Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with line Breaks on contentEditable DIV

I have a problem with contenteditable line breaks on SAFARI/CHROME. When I press "return" on a contentEditable <div>, instead of creating a <br> (like Firefox), they create a new <div>:

<div>Something</div> <div>Something</div> 

That looks like (on the contentEditable DIV):

Something Something 

But after sanitization (removing <div>), I get this:

SomethingSomething 

In Firefox, the contenteditable is:

Something <br> Something 

And that after sanitization looks the same:

Something Something 

Is there any solution to "normalize" this across browsers?

I've found this code on Make a <br> instead of <div></div> by pressing Enter on a contenteditable

$(function(){    $("#editable")    // make sure br is always the lastChild of contenteditable   .live("keyup mouseup", function(){     if (!this.lastChild || this.lastChild.nodeName.toLowerCase() != "br") {       this.appendChild(document.createChild("br"));      }   })    // use br instead of div div   .live("keypress", function(e){     if (e.which == 13) {       if (window.getSelection) {         var selection = window.getSelection(),           range = selection.getRangeAt(0),           br = document.createElement("br");         range.deleteContents();         range.insertNode(br);         range.setStartAfter(br);         range.setEndAfter(br);         range.collapse(false);         selection.removeAllRanges();         selection.addRange(range);         return false;       }     }   }); }); 

This works, but (in SAFARI and CHROME) I have to press two times the "return" key to get a new line...

Any idea?

Edit: With the code I found ( at the bottom of this question) is working fine except the function that "makes sure a <br> element is always the lastChild... Any idea on how to fix this?

Edit 2: I'm getting this error on the console: Uncaught TypeError: Object #<HTMLDocument> has no method 'createChild'

Edit 3: Ok, I changed the document.createChild("br"); to document.createElement("br"); and I think I got it working in FF/Safari/Chrome... All return <br> for new lines...

The problem is now that when I'm inside an Ordered or Unordered List, I need to get a new line without <br>...

Edit 4: If anyone interested in the solution of the last edit: Avoid createElement function if it's inside a <LI> element (contentEditable)

like image 903
Santiago Avatar asked May 16 '11 20:05

Santiago


People also ask

Does div cause a line break?

It is an inline-level element and does not break to the next line unless its default behavior is changed. To make these examples easier to use and understand for all types of computer users, we're using the style attribute in the div.

How do I stop Enter key in Contenteditable?

To prevent contenteditable element from adding div on pressing enter with Chrome and JavaScript, we can listen for the keydown event on the contenteditable element and prevent the default behavior when Enter is pressed. to add a contenteditable div. document. addEventListener("keydown", (event) => { if (event.

How do you focus on Contenteditable?

Changing your tabIndex to >= 0 will let you focus on the elements. If you need to do it dynamically, you can just add a tabindex >= 0 to your element in the event listener.

What is Contenteditable div?

Definition and Usage The contenteditable attribute specifies whether the content of an element is editable or not.


2 Answers

This technique appears to avoid the Chrome bug that does show BRs the first time (with the code you mentionned you need to push two times the Enter key).

It's not a perfect hack but it works: it adds a whitespace after your BR so it show properly. However, you will see that adding only a whitespace " " will NOT change anything, it works with other letters. The browser will not show it, probably because it is like a blank space inside an html page, it simply does not mean anything. To get rid of that bug I created a div with jQuery that includes a &nbsp; tag, and I take the text() property to put it in the textnode otherwise it doesn't work.

$editables = $('[contenteditable=true]');  $editables.filter("p,span").on('keypress',function(e){  if(e.keyCode==13){ //enter && shift    e.preventDefault(); //Prevent default browser behavior   if (window.getSelection) {       var selection = window.getSelection(),           range = selection.getRangeAt(0),           br = document.createElement("br"),           textNode = document.createTextNode("\u00a0"); //Passing " " directly will not end up being shown correctly       range.deleteContents();//required or not?       range.insertNode(br);       range.collapse(false);       range.insertNode(textNode);       range.selectNodeContents(textNode);        selection.removeAllRanges();       selection.addRange(range);       return false;   }     } }); 
like image 149
Micaël Félix Avatar answered Sep 17 '22 12:09

Micaël Félix


Listening to keystrokes seems like a lot of work. Would something as simple as this be feasible:

var html = $('.content').html().replace(/<div>/gi,'<br>').replace(/<\/div>/gi,''); 

JSFiddle demo here.

Also, it looks like sanitize.js allows a custom configuration. Have you tried adding div as an allowed element?

Allowing HTML/CSS is dangerous, so ensure you are being extra cautious.

EDIT: Removed server side comments. Sanitising occurs at time of usage- if the client wants to bypass this locally it can be done so at their own risk. Thanks Vincent McNabb for pointing this out.

like image 25
Kurt Avatar answered Sep 20 '22 12:09

Kurt