Reputation: 57
I am building a web tool for authors that follows a format we need for our backend. I didn't like a number of pre-made solutions for rich text editors as they were having way more features than I would need so I decided to parse my text through a function to detect bold using ** in the text.
I came across a regex solution here and when I used it, it detected the bold text and substituted * for <b>
but displayed the tags instead of making the text between <b>
and </b>
bold.
I am new to HTML, CSS and JS so probably this is a simple error, but I couldn't find out how to deal with it myself...
// Tracks number of current textareas i.e. paragraphs
var element_counter = 0;
// Add Paragraph on button press
document.getElementById("addParagraph").addEventListener("click", function() {
var textarea = document.createElement("textarea");
var text = "Here goes your new paragraph.";
var node = document.createTextNode(text);
textarea.setAttribute("id", element_counter);
//textarea.setAttribute("class", "flow-text");
//textarea.setAttribute("oninput", "this.style.height = '';this.style.height = this.scrollHeight + 'px'");
textarea.append(node);
var section = document.getElementById("editor");
section.appendChild(textarea);
element_counter++;
reloadPreview();
});
// Add Image on button press
document.getElementById("addImage").addEventListener("click", function() {
var image = document.createElement("input");
image.setAttribute("type", "file");
image.setAttribute("id", element_counter);
image.setAttribute("accept", "image/*");
image.setAttribute("class", "file-field input-field");
var section = document.getElementById("editor");
section.appendChild(image);
element_counter++;
});
// Remove paragraph with confirmation step on button press
var confirm = false;
document.getElementById("removeLastItem").addEventListener("click", function() {
// Ensure there is an object to remove and wait for confirmation
if (document.getElementById(element_counter-1) != null) {
if (confirm === false) {
confirm = true;
document.getElementById("removeLastItem").innerHTML = "Confirm";
} else {
document.getElementById("removeLastItem").innerHTML = "Remove last item";
var element = document.getElementById(element_counter-1);
element.parentNode.removeChild(element);
confirm = false;
element_counter--;
reloadPreview();
}
}
});
// Remove all with confirmation step on button press
var confirmRemoveAll = false;
document.getElementById("removeAll").addEventListener("click", function() {
// Ensure there is an object to remove and wait for confirmation
if (document.getElementById(element_counter-1) != null) {
if (confirmRemoveAll === false) {
confirmRemoveAll = true;
document.getElementById("removeAll").innerHTML = "Confirm";
} else {
document.getElementById("removeAll").innerHTML = "Remove all";
var element = document.getElementById("editor").innerHTML = ""
confirmRemoveAll = false;
element_counter = 0;
reloadPreview();
}
}
});
// Preview on button press
document.getElementById("previewButton").addEventListener("click", reloadPreview);
// Preview current document status
function reloadPreview() {
// Clear previous preview
document.getElementById("preview").innerHTML = "";
// Add elements iteratively
var section = document.getElementById("preview");
const id = "preview";
for (var counter = 0; counter < element_counter; counter++) {
var type = document.getElementById(counter).nodeName;
// If text element
if (type === "TEXTAREA") {
var paragraph = document.createElement("p");
var text = document.getElementById(counter).value;
var richtext = boldText(text);
paragraph.setAttribute("id", id + counter);
paragraph.setAttribute("class", "flow-text");
paragraph.innerHTML = richtext;
section.appendChild(paragraph);
}
// If image element
if (type === "INPUT") {
// This weird structure allows to render item by item into preview and not mix up the order as onload is otherwise too slow
(function() {
var file = document.getElementById(counter).files[0];
var reader = new FileReader();
var image = document.createElement("img");
image.setAttribute("id", id + counter);
image.setAttribute("class", "materialboxed responsive-img");
section.appendChild(image);
reader.onload = function(e) {
image.setAttribute("src", e.target.result);
}
reader.readAsDataURL(file);
}())
}
}
}
function boldText(text){
var bold = /\*\*(\S(.*?\S)?)\*\*/gm;
var richtext = text.replace(bold, '<b>$1</b>');
return richtext;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Climate Science</title>
<!--Used to unify web page appearance and this preview appearance-->
<link type="text/css" href="/css/materialize.css" rel="stylesheet">
<link type="text/css" href="/css/styles.css" rel="stylesheet">
<link type="text/css" href="/css/mystyles.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons&display=swap" rel="stylesheet">
<script href="text/javascript" src="/js/materialize.js"></script>
<link rel="manifest" href="/manifest.json">
<!-- IOS Support -->
<link rel="apple-touch-icon" href="/img/icons/icon-96x96.png">
<link rel="apple-touch-icon" href="/img/icons/icon-152x152.png">
<meta name="apple-mobile-web-app-status-bar" content="#5368ff">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="theme-color" content="#5368ff">
</head>
<body class="grey lighten-5">
<header>
<!-- top nav -->
<div class="navbar-fixed">
<nav class="z-depth-2">
<div class="nav-wrapper">
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li><a href="pages/test" class="waves-effect">Log out</a></li> <!--TODO needed?-->
</ul>
</div>
</nav>
</div>
</header>
<div class="container">
<h3>Editor Area</h3>
<p><b>Linebreaks</b> within paragraphs are currently <b>ignored</b> to follow our internal database format.</p> <!--TODO check if accurate, \n possible integratable?-->
<!--
<h6>Safety switch</h6>
<div id="safetyswitch" class="switch">
<label>
Off
<input type="checkbox">
<span class="lever"></span>
On
</label>
</div>
<p>You can only remove paragraphs while the switch is deactivated!</p>
<h6>Auto-preview</h6>
<div id="safetyswitch" class="switch">
<label>
Off
<input type="checkbox">
<span class="lever"></span>
On
</label>
</div>
<p>The preview will load automatically while you edit your text</p>
<br>
-->
<button id="addParagraph" class="waves-effect waves-light btn">Add new paragraph</button>
<button id="addImage" class="waves-effect waves-light btn">Add new image</button>
<button id="removeLastItem" class="waves-effect waves-light btn">Remove last item</button>
<button id="removeAll" class="waves-effect waves-light btn">Remove all</button>
<div id="editor">
<!-- Here go all the content the author creates-->
</div>
<button id="previewButton" class="waves-effect waves-light btn">Update Preview</button>
<h3>Preview</h3>
<div id="preview">
<!-- Here will be the preview elements when clicking the button -->
<!--
<form action="#">
<p class="flow-text">What changes do you think we're already experiencing? Tap as many that apply</p>
<p>
<label>
<input type="checkbox" />
<span>Raising Sea Levels</span>
</label>
</p>
<p>
<label>
<input type="checkbox" />
<span>Fewer Heat Waves</span>
</label>
</p>
<p>
<label>
<input type="checkbox" />
<span>Worse Droughts</span>
</label>
</p>
<p>
<label>
<input type="checkbox" />
<span>Hotter heat waves</span>
</label>
</p>
<button class="btn waves-effect waves-light btn-large" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
</form>
-->
</div>
</div>
<script href="text/javascript" src="js/preview.js"></script>
<script href="text/javascript" src="js/ui.js"></script>
</body>
</html>
Upvotes: 1
Views: 1374
Reputation: 1960
Hi so perhaps use innerHTML
to insert HTML into the tag body? So instead of paragraph.append
:
paragraph.innerHTML = richtext;
Upvotes: 2