var d = document.querySelector("#d"); var ds = document.querySelector("#d-source"); var p = document.querySelector("#p"); var ps = document.querySelector("#p-source"); // Show html setInterval(function() { ds.textContent = d.innerHTML; ps.textContent = p.innerHTML; }, 1000 / 30); // ---------------------------------------------- // Main // ---------------------------------------------- new ParagraphEditor(p); function ParagraphEditor(el) { this.el = el; this.el.addEventListener("keyup", this); this.el.addEventListener("paste", this); } ParagraphEditor.prototype.handleEvent = function(evt) { if (this['on' + evt.type]) { this['on' + evt.type](evt); } else { console.log(this.toString() + " cannot handle " + evt.type); } }; ParagraphEditor.prototype.onpaste = function(evt) { event.preventDefault(); var text = event.clipboardData.getData("text/plain"); // remove trailing newlines text = text.replace(/[\r\n]+$/, "") // convert \n\n to paragraph // foo\n\nbar\nfoobar -> <p>foo</p><p>bar\nfoobar</p> var html = text.split(/[\r\n][\r\n]+/g).map(function(p) { return '<p>' + p + '</p>'; }).join(""); // convert \n to br // <p>foo</p><p>bar\nfoobar</p> -> <p>foo</p><p>bar<br>foobar</p> html = html.replace(/[\r\n]/g, "<br>"); document.execCommand('insertHTML', false, html); }; ParagraphEditor.prototype.onkeyup = function(evt) { if (this.el.children.length === 0) { document.execCommand('formatBlock', false, 'p'); } if (evt.keyCode === 13 && !evt.shiftKey) { document.execCommand('formatBlock', false, 'p'); } };
<div class="container"> <div class="half-column"> <h2>Default</h2> <div id="d" contenteditable></div> </div> <div class="half-column"> <h2>HTML in Default</h2> <div id="d-source" class="source"></div> </div> </div> <div class="container"> <div class="half-column"> <h2>ParagraphEditor</h2> <div id="p" contenteditable></div> <dl> <dt>Enter</dt><dd>new paragraph</dd> <dt>Shift Enter</dt><dd>new line</dd> </dl> </div> <div class="half-column"> <h2>HTML in ParagraphEditor</h2> <div id="p-source" class="source"></div> </div> </div>
[contenteditable], .source { box-sizing: border-box; width: 300px; height: 100px; border: 1px solid #CCC; border-radius: 0.4rem; padding: 0.4rem; } dl { width:100%; overflow: hidden; } dt, dd { float:left; margin:0; padding:0; } dt { width: 30%; } dd::before { content: "..."; margin-right: 0.5rem; } dd { width: 70%; } p { margin-top: 0; margin-bottom: 1em; } .container { overflow: hidden; } .half-column { width: 50%; float: left; }