Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<br> inserted in contenteditable span fails to move cursor

I want all text and breaks to be in spans, which the following code does. Works perfectly in IE11 and chrome but has a serious issue in FF. To wit, if the first key entered is < enter >, the cursor fails to move to after the inserted < br >. The caret position seems to move as the next key entered is on the next line but the flashing cursor doesn't. Furthermore, if backspaced to remove the character, the cursor goes back up to the first line.

Easiest way to demonstrate :http://jsfiddle.net/jd2d7n3L/20/

  1. Make the first character entered < enter >
  2. Expected result (which is what happens in chrome and IE10+) is for the flashing cursor to move down one line.
  3. Enter 'a' and then backspace. Expected result is flashing cursor is leftmost on 2nd line

I have read many similar questions and answers relating to this on SO but none specifically deal with this situation. How can I make FF behave?

HTML

<div id=bE contenteditable="true"><br></div>

JS

bE.addEventListener("keypress",KP);
bE.addEventListener("keypress",KU);

function getContainer()
  {
  var eC=window.getSelection().getRangeAt(0).endContainer;
  while(eC&&eC.nodeType==3)eC=eC.parentNode;
  return eC
  }

function insertElement(E)
  {
  var sel=window.getSelection(),range=sel.getRangeAt(0);
  range.deleteContents(); 
  range.collapse(true);
  range.insertNode(E);
  range.setStartAfter(E);
  range.collapse(true);
  sel.removeAllRanges();
  sel.addRange(range);     
  }

function KP(e)
  {
  var kc=e.which||e.keyCode;
  if(e.charCode||e.which===13)
    {
    var sel=window.getSelection(),range=sel.getRangeAt(0);
    var eC=getContainer();
    if(eC===bE)
      {
      eC=document.createElement("span");
      range.insertNode(eC);
      range.selectNodeContents(eC);
      sel.removeAllRanges();
      sel.addRange(range);
      }
    if(kc===13)insertElement(document.createElement("br"));
    else       insertElement(document.createTextNode(String.fromCharCode(kc)));

    e.preventDefault();
    }
  }

function KU(e) //ensures last element is br
  {
  if(!bE.lastChild||bE.lastChild.nodeName.toLowerCase()!=="br")bE.appendChild(document.createElement("br"))
  }
like image 250
poby Avatar asked Oct 20 '22 23:10

poby


1 Answers

Ok I finally nailed it. It seems Firefox doesn't like having < br > as the last childnode of any parent. If you append an empty textnode to every trailing < br >, it works! Firefox will not move the caret after a < br > if it's the last childNode.

like image 94
poby Avatar answered Oct 30 '22 01:10

poby