contentEditable field to maintain newlines upon database entry

nonshatter picture nonshatter · Dec 7, 2012 · Viewed 8.5k times · Source

I have a div with the attribute contentEditable set.

This allows me to have a free-form editable textarea, without the need for any form input fields: http://jsfiddle.net/M8wx9/8/

However, when I create a couple of new lines and click save button, I grab the content with the .text() method which goes on to remove the line feeds I just entered. I need to maintain the newline characters if at all possible and store the content as plain text in the database.

I could store the HTML directly to the database by using .html() instead of .text() but I don't like that idea as I may need to extract this data as plain text in the future. Furthermore, pressing enter in Firefox breaks new lines with <br>, Chrome and Safari are breaking with <div>...</div> and Internet Explorer and Opera are using paragraphs <p>...</p> for new lines, so it doesn't sound very easy to be able to parse the html.

How can I preserve these line feeds and store the content as plain text in the database (Similar to the way a textarea does)?

Best Regards, ns

Answer

steveukx picture steveukx · Dec 7, 2012

jQuery uses textContent on a Node to return the text value of an element, which will compress white space. If you want the line breaks to be maintained, you need to use innerText which means accessing the element directly rather than through jQuery.

From your jsfiddle:

console.log($(Comments)[0].innerText);

http://jsfiddle.net/M8wx9/10/

==== update:
As a caveat to this (as Tim Down has pointed out), using innerText will only work in webkit and microsoft browsers. If your application also supports Firefox, you will need to use regular expressions on the innerHTML in order to maintain line breaks. As an example:

$(Comments).html().trim()
.replace(/<br(\s*)\/*>/ig, '\n') // replace single line-breaks
.replace(/<[p|div]\s/ig, '\n$0') // add a line break before all div and p tags
.replace(/(<([^>]+)>)/ig, "");   // remove any remaining tags

http://jsfiddle.net/M8wx9/12/

As mentioned in the comment, the previous is not working in Chrome. Here is a working solution:

$(Comments).html().trim()
.replace(/<br\s*\/*>/ig, '\n') 
.replace(/(<(p|div))/ig, '\n$1') 
.replace(/(<([^>]+)>)/ig, "");

http://jsfiddle.net/M8wx9/81/