Issue
I'm trying to create a minimal queue editor. I have two panels: one where i write the text/code and it colors in relation to the word, and then i have another panel with the preview function (views the output of the html code). Then the code panel
and the preview panel
.
Previously to build the code panel
, i used a <textarea>
. Using textarea, the text was NOT colored, but the preview panel
worked correctly. Now i'm using a div
and contenteditable. With them, the text is colored correctly, but the preview panel
doesn't work and undefined
is printed inside.
PROBLEM: The problem will probably be that the preview panel
is unable to recover the html code from the code panel (div with contenteditable), because the html text is not printed formatted (unlike the textarea which printed the formatted text). So, mistakenly, the output is printed in the code panel and not the html code
How can i display formatted text in the panel code and consequently display the output in the panel code?
WHAT WOULD I WANT? As you can see, if i write <h1>This is a Heading</h1>
and <p>This is a paragraph</p>
in the code panel
, the formatted text is not printed, but the output is printed directly. I don't want this.
Instead, i would like to get this:
index.html
<div id="editor" contenteditable="true" oninput="showPreview()">
<!-- HTML CODE TO PRINT -->
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
<!-- -->
</div>
<h3>PREVIEW</h3>
<div class="preview-area">
<iframe id="preview-window"></iframe>
</div>
style.css
#editor {
width: 400px;
height: 100px;
padding: 10px;
background-color: #444;
color: white;
font-size: 14px;
font-family: monospace;
}
.statement {
color: orange;
}
javascript.js
//PREVIEW
function showPreview() {
var editor = document.getElementById("editor").value;
// var cssCode =
// "<style>" + document.getElementById("cssCode").value + "</style>";
// var jsCode =
// "<scri" + "pt>" + document.getElementById("jsCode").value + "</scri" + "pt>";
var frame = document.getElementById("preview-window").contentWindow.document;
frame.open();
//frame.write(htmlCode + cssCode + jsCode);
frame.write(editor);
frame.close();
}
// CHANGE COLOR TEXT
var keywords = ["DIV", "DIV", "H1", "H1", "P", "P", "HELLO", "<", ">", "/"];
// Keyup event
document.querySelector('#editor').addEventListener('keyup', e => {
// Space key pressed
if (e.keyCode == 32) {
var newHTML = "";
// Loop through words
str = e.target.innerText;
chunks = str
.split(new RegExp(
keywords
.map(w => `(${w})`)
.join('|'), 'i'))
.filter(Boolean),
markup = chunks.reduce((acc, chunk) => {
acc += keywords.includes(chunk.toUpperCase()) ?
`<span class="statement">${chunk}</span>` :
`<span class='other'>${chunk}</span>`
return acc
}, '')
e.target.innerHTML = markup;
// Set cursor postion to end of text
// document.querySelector('#editor').focus()
var child = e.target.children;
var range = document.createRange();
var sel = window.getSelection();
range.setStart(child[child.length - 1], 1);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
this.focus();
}
});
Solution
Use <
to "escape" the less-than characters in the contenteditable
. This will make the code appear in the editor:
<div id="editor" contenteditable="true" oninput="showPreview()">
<!-- HTML CODE TO PRINT -->
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
<!-- -->
</div>
Then to have the line breaks reflected in the editor, apply white-space: pre
to the contenteditable
. We'd also need to reformat the text inside the contenteditable
to ensure it shows as desired.
#editor {
/* … */
white-space: pre;
}
<div id="editor" contenteditable="true" oninput="showPreview()"><h1>This is a Heading</h1>
<p>This is a paragraph.</p></div>
The <iframe>
result will not show in the snippet below due to browser security but the editor behavior can be previewed:
//PREVIEW
function showPreview() {
var editor = document.getElementById("editor").innerText;
// var cssCode =
// "<style>" + document.getElementById("cssCode").value + "</style>";
// var jsCode =
// "<scri" + "pt>" + document.getElementById("jsCode").value + "</scri" + "pt>";
var frame = document.getElementById("preview-window").contentWindow.document;
document.getElementById("preview-window").srcdoc = editor;
frame.open();
//frame.write(htmlCode + cssCode + jsCode);
frame.write(editor);
frame.close();
}
// CHANGE COLOR TEXT
var keywords = ["DIV", "DIV", "H1", "H1", "P", "P", "HELLO", "<", ">", "/"];
// Keyup event
document.querySelector("#editor").addEventListener("keyup", (e) => {
// Space key pressed
if (e.keyCode == 32) {
var newHTML = "";
// Loop through words
str = e.target.innerText;
(chunks = str
.split(new RegExp(keywords.map((w) => `(${w})`).join("|"), "i"))
.filter(Boolean)),
(markup = chunks.reduce((acc, chunk) => {
acc += keywords.includes(chunk.toUpperCase())
? `<span class="statement">${chunk}</span>`
: `<span class='other'>${chunk}</span>`;
return acc;
}, ""));
e.target.innerHTML = markup;
// Set cursor postion to end of text
// document.querySelector('#editor').focus()
var child = e.target.children;
var range = document.createRange();
var sel = window.getSelection();
range.setStart(child[child.length - 1], 1);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
this.focus();
}
});
#editor {
width: 400px;
height: 100px;
padding: 10px;
background-color: #444;
color: white;
font-size: 14px;
font-family: monospace;
white-space: pre;
}
.statement {
color: orange;
}
<div id="editor" contenteditable="true" oninput="showPreview()"><h1>This is a Heading</h1>
<p>This is a paragraph.</p></div>
<h3>PREVIEW</h3>
<div class="preview-area">
<iframe id="preview-window"></iframe>
</div>
Answered By - Wongjn
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.