Allow line break with javascript + LivePreview

I make the site in two columns, on the left, you can write, and it is displayed on the right with a special design.
The thing is, I would like to allow a line break on the right side, but it does not appear. How could I do this?
here is a preview of my design. To see the full picture, here > the script is HERE

function wordsinblocks(self) { var demo = document.getElementById("demo"), initialText = demo.textContent, wordTags = initialText.split(" ").map(function(word) { return '<span class="word">' + word + '</span>'; }); demo.innerHTML = wordTags.join(''); self.disabled = true; fitWords(); window.addEventListener('resize', fitWords); } $(function() { $('textarea.source').livePreview({ previewElement: $('p#demo'), allowedTags: ['p', 'strong', 'br', 'em', 'strike'], interval: 20 }); }); window.onload = wordsinblocks(self); function fitWords() { var demo = document.getElementById("demo"), width = demo.offsetWidth, sizes = [7.69230769230769, 23.07692307692307, 46.15384615384614, 100], calculated = sizes.map(function(size) { return width * size / 100 }), node, i, nodeWidth, match, index; for (i = 0; i < demo.childNodes.length; i++) { node = demo.childNodes[i]; node.classList.remove('size-1', 'size-2', 'size-3', 'size-4'); nodeWidth = node.clientWidth; match = calculated.filter(function(grid) { return grid >= nodeWidth; })[0]; index = calculated.indexOf(match); node.classList.add('size-' + (index + 1)); } } 
+5
source share
5 answers

You need to split the source (what you write) into new line , and then split each line into space .

Update wordinblocks as:

 function wordsinblocks(self) { var demo = document.getElementById("demo"), initialText = demo.innerText, wordTags = initialText.split(/\n/g).map(function(line) { var spanWord = line.split(/\s/g).filter(Boolean).map(function(word){ return '<span class="word">' + word + '</span>'; }); return "<span class='line-break'>" + spanWord.join("") + "</span>"; }); demo.innerHTML = wordTags.join(''); self.disabled = true; fitWords(); window.addEventListener('resize', fitWords); } 

Update fitWords as

 function fitWords() { var demo = document.getElementById("demo"), width = demo.offsetWidth, sizes = [7.69230769230769, 23.07692307692307, 46.15384615384614, 100], calculated = sizes.map(function(size) { return width * size / 100 }), lineNode, node, i, k, nodeWidth, match, index; for (k = 0; k < demo.childNodes.length; k++) { lineNode = demo.childNodes[k]; for(i = 0; i < lineNode.childNodes.length; i++) { node = lineNode.childNodes[i]; node.classList.remove('size-1', 'size-2', 'size-3', 'size-4'); nodeWidth = node.clientWidth; match = calculated.filter(function(grid) { return grid >= nodeWidth; })[0]; index = calculated.indexOf(match); node.classList.add('size-' + (index + 1)); } } } 

Add to css

next style
 #demo .line-break:after { clear: both; display: table; content: "" } 

FIDDLE DEMO HERE

Hope this helps you and let me know if I miss something.

UPDATE for multiple line breaks

Update textarea.reloadPreview as

 textarea.reloadPreview = function() { var previewString = this.val().replace(/\n/g,"<br>"); if (previewString.length > 0) { previewString = this.htmlUnencode(previewString); previewString = previewString.replace(opts.paraRegExp, "<p>$1</p><p>$2</p>"); previewString = previewString.replace(opts.lineBreakRegExp, "$1<br />$2"); previewString = previewString.replace(allowedTagsRegExp, "<$1>"); } try { // Workaround for a bug in jquery 1.3.2 which is fixed in 1.4 preview[0].innerHTML = previewString; } catch (e) { alert("Sorry, but inserting a block element within is not allowed here."); } preview.updatingPreview = false; this.bind('keyup', this.handleKeyUp); wordsinblocks(self); } 

Update worksinblocks as

 function wordsinblocks(self) { var demo = document.getElementById("demo"), initialText = demo.innerText, wordTags = initialText.split(/\n/g).map(function(line) { var spanWord = line.split(/\s/g).filter(Boolean).map(function(word){ return '<span class="word">' + word + '</span>'; }); var result = spanWord.join(""); result = result == "" ? "<span class='empty'></span>" : result; return "<span class='line-break'>" + result + "</span>"; }); demo.innerHTML = wordTags.join(''); self.disabled = true; fitWords(); window.addEventListener('resize', fitWords); } 

Add the following styles to your css

 #demo .line-break .empty { height: 25px; display: block } #demo .word { float: left; box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 5px; padding-left: 10px; padding-right: 10px; font-size: 2.9vw; height: 25px; font-family: "helvetica"; border: 1px solid black; } 

UPDATED FIDDLE HERE

+4
source

When you press Enter you can insert line breaks. One way is to use .which or .keyCode :

 $(document).keydown(function(e){ var event = e.which || e.keyCode; if (event == 13){ //do something like this return '<span class="word"><br/>' + word + '</span>'; } }); 

"13" is the character code for Enter . I tested it in your code and it works great. You just need to put it (change too) where it does not affect any of your existing codes.

The second way is to copy exactly what is in the "Record" panel before performing some actions, such as splitting words by encapsulating them at different times, etc.


[UPDATE # 1]

Just a piece of code for testing.

 function wordsinblocks(self) { var demo = document.getElementById("demo"), initialText = demo.textContent, wordTags = initialText.split(" ").map(function(word) { return '<span class="word">' + word + '</span>'; }); $(document).keydown(function(e){ var event = e.which || e.keyCode; if (event == 13){ demo.innerHTML = wordTags.join(' <br/> '); } else{ demo.innerHTML = wordTags.join(''); } }); self.disabled = true; fitWords(); window.addEventListener('resize', fitWords); } 

[UPDATE # 2]

 function wordsinblocks(self) { var demo = document.getElementById("demo"), initialText = demo.innerText.replace(/\n\r?/g,"<br/>"), wordTags = initialText.split(" ").map(function(word) { return '<span class="word">' + word + '</span>'; }); demo.innerHTML = wordTags.join(''); self.disabled = true; fitWords(); window.addEventListener('resize', fitWords); } 
+5
source

you can do this with css instead of white-space: pre;

 p { white-space: pre; } 
+3
source

Good challenge. To achieve a good fit and handling of textarea string strings:

  • Make sure that the displayed text has the same formatting as in the text field: line height, width, distance between letters, size ....
  • Replace the new lines with <br />/(?:\r\n|\r|\n)/g
  • Use separate blocks for spaces → make sure that double spaces and spaces are displayed at the beginning of the line.

Here is my approach: Screenshot

 $(function(){ var set = { hookTo : ".leftside textarea", dispIn : ".rightside .content", newline : "@#@" }; //Focus text area: $(set.hookTo).focus(); $(set.hookTo).keyup(function(){ $text = $(this); $tar = $(set.dispIn); raw = $text.val(); box = []; //Recplace tags: raw.replace(/&/g, "&amp;") .replace(/>/g, "&gt;") .replace(/</g, "&lt;") .replace(/"/g, "&quot;"); //Hadle Line breaks: raw = raw.replace(/(?:\r\n|\r|\n)/g, set.newline); //Boxes: box = raw.split(' '); $.each(box, function(i,e){ var newlines; if (e === "") { box[i] = "<div class='wordbox space'>&nbsp;</div>"; } else { newlines = e.split(set.newline); if (newlines.length > 0) { $.each(newlines,function(index,el) { if (el === "") newlines[index] = "<div class='wordbox space'>&nbsp;</div>"; else newlines[index] = "<div class='wordbox'>" + el + "</div>" + "<div class='wordbox space'>&nbsp;</div>"; }); box[i] = newlines.join("<br />"); } else { box[i] = "<div class='wordbox'>" + e + "</div>" + "<div class='wordbox space'>&nbsp;</div>"; } } }); $tar.html(box.join("")); }); }); 
 body { background-color:white; height:100%; } .wrapper { width:100%; font-size:0; box-sizing:border-box; } .leftside, .rightside { width:50%; display:inline-block; font-size:16px; vertical-align: top; font-family:arial; } .rightside .header, .leftside .header { font-size:16px; padding:10px 20px; font-weight:bold; } .rightside .header { color: black; background-color:orange; } .leftside .header { color: orange; background-color:black; } .rightside .content { width:100%; padding:10px 20px; box-sizing:border-box; font-size:0; } .rightside .content .wordbox { outline: 1px solid black; line-height:16px; letter-spacing: 1px; font-size:15px; display:inline-block; margin-bottom: 3px; } .rightside .content .wordbox.space { outline: 0; opacity:0; } .wrapper textarea { width:100%; box-sizing:border-box; border:0; overflow: auto; outline: none; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; resize: none; padding:10px 20px; font-size:15px; font-family:arial; line-height:16px; letter-spacing: 1px; min-height:400px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div class="wrapper"> <div class="leftside"> <div class="header">Write</div> <textarea placeholder="Type here please"></textarea> </div> <div class="rightside"> <div class="header">See</div> <div class="content"></div> </div> </div> 
+3
source

Short hacking solution

Change wordsinblocks to

 function wordsinblocks(self) { var demo = document.getElementById("demo"), initialText = demo.textContent.replace(new RegExp("\n", "g"), '<br>'), wordTags = initialText.split(" ").map(function(wordWithLineBreaks) { return wordWithLineBreaks.split('<br>').map(function(word, index, arr) { return (word === '' ? '' : '<span class="word">' + word + '</span>') + (index < arr.length - 1 ? '<div class="lb">&nbsp;</div>' : '') ; }).join(''); }); demo.innerHTML = wordTags.join(''); self.disabled = true; fitWords(); window.addEventListener('resize', fitWords); } 

In the for loop inside the fitWords function fitWords add after the first line in the loop:

 if (node.tagName.toLowerCase() === 'div') continue; 

Edit

 $(function() { $('textarea.source').livePreview({ previewElement: $('p#demo'), allowedTags: ['p', 'strong', 'br', 'em', 'strike'], interval: 20 }); }); 

to

 $(function() { $('textarea.source').livePreview({ previewElement: $('p#demo'), allowedTags: [], paraRegExp: new RegExp('something nobody will ever enter'), lineBreakRegExp: new RegExp('something nobody will ever enter'), interval: 20 }); }); 

Add to the end of your css:

 .lb { display: block; clear: both; } 

For a complete solution, see jsfiddle .

Some thoughts on a solution

Although this solution works, it is far from optimal.

For example, using the livePreview jQuery plugin livePreview not make much sense, because it seems that you do not need HTML support, since your code uses the textContent property after livePreview completed the task, which effectively removes all HTML.

This is also the reason that the line break insert (added by pressing the enter key) does not work in the source code. The following happened:

  • User enters text with line breaks
  • livePreview replaces these line breaks <br> by using the lineBreakRegExp option.
  • The textContent property returns only text, which means that <br> is lost again.

So @Shlomi Hassid provided a better, albeit incomplete approach. Incomplete because the size of the boxes is missing.

+3
source

All Articles