Perfect conversion from <div> to <br> in a WYSIWYG editor - javascript

I need to sanitize HTML in a WYSIWYG editor. The output must not contain any <div>s. All <div> elements must be replaced with <br> elements. This original text MUST render the same as the sanitized text.
This is my attempt so far (notice the unwanted extra whitespace in the output) – thanks to Nimit for the rendering containers:
let text = `<div>aoeu</div><div><ul><li>eu</li><li>a</li></ul><div><br></div></div><div>eu</div>`;
// let text = 'aoeu<ul><li>aoeu</li><ul><li>aoue</li></ul></ul><div><br></div></div></div><div><br></div><div><br></div><div><br></div><div>oe</div><div><ul><li>u</li></ul></div>'
document.getElementById("pre1").innerHTML = "<strong>With Div</strong> </br>" + text;
text = text
.replace(/<div><div>(.*)<\/div><\/div>/g, '<div>$1</div>') // meaningless directly double wrapped divs
.replace(/<div><br><\/div>/g, '<br>') // div with a br is only one newline
.replace(/<div>(?!<div>)(.*?)<\/div>/g, '$1<br>') // divs always make a newline after
document.getElementById("pre2").innerHTML = "<strong>Without Div</strong> </br>" + text;
.preContainer {
display:inline-block;
width:200px;
vertical-align:top;
}
.preContainer:first-child{
border-right:1px solid black;
}
<div class="preContainer"><pre id="pre1"></pre></div>
<div class="preContainer"><pre id="pre2"></pre></div>
So basically I can't seem to figure out how to perfectly convert from <div> to <br>. Any help much appreciated.

I think you can achieve your result with below replace script.
.replace("<div>", "<br>").replace("</div>", "");
Check below snippet, you can inspect both pre, second pre doesn't have any div tag:
function showItInPre(text){
//let text = `aoeua<div><ul><li>oe</li><li>a</li><li>oeu</li></ul><div><br></div></div><div><br></div><div><br></div><div>aoe</div><div><ul><li>u</li></ul><div><br></div></div><div><br></div><div>u</div><div><div><br></div></div><div>o</div><div><ul><li>o</li><li>o</li><li>a</li><li><br></li></ul></div>`;
document.getElementById("pre1").innerHTML = "<strong>With Div</strong> </br>" + text;
text = text
.replace(/<div><br><\/div>/ig, '<br>')
.replace(/<\/div><\/div>/ig, '<br>')
.replace(/<div>/ig, "").replace(/<\/div>/ig, "<br>");
document.getElementById("pre2").innerHTML = "<strong>Without Div</strong> </br>" + text;
}
document.getElementById("testit").addEventListener("click", function(){showItInPre(document.getElementById("textarea").value)});
.preContainer {
display:inline-block;
width:200px;
vertical-align:top;
}
#pre1{
border-right:1px solid black;
}
#textarea {
width:500px; height:50px;
}
<div><textarea id="textarea"></textarea><button id="testit">Test</button></div>
<div class="preContainer"><pre id="pre1"></pre></div>
<div class="preContainer"><pre id="pre2"></pre></div>

Related

Adding a newline character and display input from a textarea

I have a text are in a form. I used this code
$('textarea').keypress(function (event) {
if (event.which == 13) {
event.preventDefault();
var s = $(this).val();
$(this).val(s + "<br />");
}
});
to allow users to go the next line using the enter button. I tried using both and \n
In the form, the user is able to go to a new line. However, when the input is displayed on a page, the new line doesn't show, and any text after the new line does not appear. However, it is still there- if you go to edit the form it stills shows the text typed after you click enter. I added
white-space: pre-wrap;
into the css for text boxes in my css file trying to resolve the issue. However, it still did not work. Any suggestions/ input on how to resolve this?
You don't want to insert the <br/> tag as they type. You really don't want to do anything to their text as they type. If you want to maintain their line breaks, you can convert them to <br/> tags before you inject them into an element.
$('#text').keyup(function(event) {
var text = $("#text").val();
text = text.replace(/(?:\r\n|\r|\n)/g, '<br />');
$("#result").html(text);
});
textarea {
min-width: 200px;
min-height: 200px;
float: left;
}
#result {
float: left;
border: 1px solid red;
padding: 10px;
margin-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="text" placeholder="Type in here"></textarea>
<div id="result"></div>

append strange behaviour

I have some application that adds elements to contentEditable div.
Something like this:
<div id="div" contentEditable="true"></div>
<button id='appendBtn'>append</button>
<style>
.bracket {
color: blue;
}
.template-content {
color: green;
}
#div {
border: solid 1px gray;
margin-bottom: 10px;
}
</style>
<script>
function appendContent() {
var content = "<span class='template-block'>" +
"<span class='bracket'>{</span>" +
"<span class='template-content'>param</span>" +
"<span class='bracket'>}</span>" +
"</span>";
$("#div").append(content);
}
document.getElementById ("appendBtn").addEventListener ("click", appendContent, false);
</script>
I wrote a working example in jsfiddle.
The problem is that when I click append and continue typing after added element all next text comes green. It happens because all next text pasts into last span tag (of class bracket with green color)...
<span class="bracket">}some text</span>
The solution is adding a after last closing span tag. Like this:
var content = "<span class='template-block'>" +
"<span class='bracket'>{</span>" +
"<span class='template-content'>param</span>" +
"<span class='bracket'>}</span>" +
"</span> ";
But it brings a lot of unwanted staff I have to do with the text after. How can I solve this?
Thats a default behaviour of content editable setting the pointer behind the last character inside. In Your case the pointer is set
<span class='bracket'>}--> pointer <--</span>
You could try a workaround with ​ entity (zero width space)
if you dont want the

using a div contentEditable innerText and innerHTML neither have newlines to and from database

I'm using a div for people to enter text and then I tried saving
div.innerText
and
div.innerHTML
to my database but when I bring it back from the database and put it back into the div all of the carriage returns or newlines are gone
innerHTML to database
a
b
c
//in database like this <div>a</div><div></div><div>b</div><div></div><div>c</div>
innerText to database
a
a
a
a
a
a
//how it stored in database aaaaaa
if you could tell me how to handle this situation I would appreciate it greatly thank you for your time
div.innerHTML creates an HTML output of your new lines using <div> containers.
Therefore the line breaks will be "replaced".
div.innerText uses the "invisible" character \n or \r\n to mark new lines and it is possible that they are not shown in your database. You can however replace them by <br> tags to see if they are there.
document.getElementById("output").addEventListener("click", function() {
console.log("HTML:");
console.log(document.getElementById("text").innerHTML);
console.log("Text:");
var text = document.getElementById("text").innerText;
console.log(text.replace(/(?:\r\n|\r|\n)/g, '<br>'));
});
#text {
background-color:#FAFAFA;
border: red solid 1px;
height:150px;
width: 200px;
}
<button id="output">
Show in console
</button>
<div id="text" contenteditable>
</div>
console.log(text.replace(/(?:\r\n|\r|\n)/g, '<br>')); replaces all different kinds of possible new lines into <br> tags.
You can substitute <textarea> element for <div> with contenteditable attribute set. Encode, decode .value of textarea using encodeURIComponent(), decodeURIComponent() or format data as JSON utilizing JSON.stringify(), JSON.parse()
var button = document.querySelector("button")
var textarea = document.querySelector("textarea");
button.onclick = function() {
var value = textarea.value
console.log(encodeURIComponent(value)
, decodeURIComponent(value)
, JSON.stringify(value)
, JSON.parse(JSON.stringify(value))
);
}
textarea {
border: 1px solid navy;
width: 300px;
height: 200px;
}
You can use
<button>click</button><br>
<textarea></textarea>

Show html tags as a text

I'm making small html editor for my website.
My editor
<textarea class="editor"></textarea>
Example window
<div class="results"></div>
Javascript and JQuery
function textarea_post(){
var text = $(".editor").val();
text = text.replace(/<code>/g,"<pre>").replace(/<\/code>/g,"</pre>");
$(".results").html(text);
}
$(".editor").on("keydown keyup paste",function(e){
textarea_post();
});
My code replace <code></code> tags from editor with <pre></pre> tags.
The problem is that you can't do html code snippet between <pre></pre>.
Html code needs to be shown as a text not as html itself between <pre></pre>.
Outside <pre></pre> other tags needs to be shown as a html
I think most of what you are you are trying to do can be accomplished through css; your javascript seems to be fine; but your html needs slight adjustment as center tags are deprecated and not supported in html.
Have a look at this snippet or fiddle (just press enter at the end of the textarea)
EDIT: updated to include better script from Mohit, but note the center tags!
function textarea_post() {
var text = $(".editor").val();
text = text.replace(/<code>/g,"<pre>").replace(/<\/code>/g,"</pre>");
$(".results").html(text);
$(".results pre").each(function(){
var escapedText = $(this).html();
$(this).text( escapedText );
});
}
$(".editor").on("keydown keyup paste", function(e) {
if (e.which==13){
textarea_post();
}
});
textarea, .editor {
width: 80vw;
height: 150px;
overflow-y:scroll;
}
h2 {
text-align: center;
background-color:white;
color:darkblue;
margin-top:0;
border-bottom:1px #000 dashed;
}
.results{background-color:lightgrey;
width:80vw;
border:1px solid;
overflow-y:scroll;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="editor">
<h2>Example 1</h2>
<code>
function MyFunction(a, b){
return a+b;
}
MyFunction(5, 10)
<h1>hello</h1>
</code>
</textarea>
<div class="results"></div>
Hope this helps - post a comment if this is not the desired effect/if i have misunderstood.
Try using this:
function textarea_post(){
var text = $(".editor").val();
text = text.replace(/<code>/g,"<pre>").replace(/<\/code>/g,"</pre>");
$(".results").html(text);
$(".results pre").each(function(){
var escapedText = $(this).html();
$(this).text( escapedText );
});//
}
$(".editor").on("keydown keyup paste",function(e){
textarea_post();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<textarea class="editor" rows="15"></textarea>
<div class="results"></div>
Try adding the following line:
text = text.replace(/</g,"<").replace(/>/g,">");
This replaces the < characters with < that is the HTML variant for the less-than sign. It also replaces the > characters with > that is the HTML variant for the greater-than sign

contentEditable div replace url links

I have a contentEditable DIV where I would like to replace any user typed URL (by matching the string with regular expression) with blue color text wrapped inside a span tag.
However, different browsers return different results. Besides, replacing the matched text with span puts cursor at the beginning of the text.
Here is the link: jsfiddle
CSS
.class{
position:relative;
outline:none;
border:5px solid #96C;
font-size:16px;
width:500px;
height:60px;
padding:0px 2px;
word-wrap:break-word;
}
HTML
<div class='class' id='div' contentEditable='true'></div>
JavaScript
var regExUrl = /https?:\/\/([\w\d-\.]+)?[\w\d-\.]+\.{1}[\w]{1,4}(\/{1})?([a-zA-Z0-9&-#_\+.‌​~#?\/=]*)?/gi;
var div = document.getElementById('div');
div.onkeyup = function () {
if (div.innerHTML.match(regExUrl)) {
st = div.innerHTML.match(regExUrl);
div.innerHTML = div.innerHTML.replace(regExUrl, "<span style='color:blue;text-decoration:underline'>" + st[0] + "</span>");
}
}
How can I set the cursor at the end of the replaced text and continue typing with the default color (black)?
Not a direct answer but a suggestion of another way of achieving the same user experience in a simpler way:
http://jsbin.com/EZizIge/1/
var regExUrl = /https?:\/\/([\w\d-\.]+)?[\w\d-\.]+\.{1}[\w]{1,4}((\/{1})?)([a-zA-Z0-9&-#_\+.‌​~#?\/=]*)?/gi;
var div = document.getElementById('div');
div.onkeyup = function(){
if(div.innerHTML.match(regExUrl)){
$("div").addClass("link");
} else {
$("div").removeClass("link");
}
}
With css:
.link{
text-decoration: underline;
color: blue;
}

Categories