skip to Main Content

I would like to insert a new line in a contenteditable when the user press Ctrl+Enter.

Based on the following questions, I wrote the code below:

Here is my HTML:

<span id="myInput" contenteditable="true" style="white-space: pre;"></span>

Here is the JavaScript:

let myInput = document.getElementById('myInput');

myInput.addEventListener('keypress', (event) => {
    if (event.key == 'Enter' && event.ctrlKey == true) {
    event.preventDefault();
    this.insertNewLine();     
   }
})


function insertNewLine(text) {

    var sel, range, html;
  sel = window.getSelection();
  range = sel.getRangeAt(0);
  range.deleteContents();
    
  // Do not always works
  var textNode = document.createTextNode("n");
  
  // Always works
  //var textNode = document.createTextNode("nu200b");
    
  range.insertNode(textNode);
  range.setStartAfter(textNode);
  range.collapse(false);
  sel.removeAllRanges();
  sel.addRange(range);
}

When the user press Ctrl+Enter, the behavior is a bit weird:

  • On Chrome, the new line is not always inserted
  • On Firefox, the new line is inserted, but the caret does not jump to the next line

I noticed that the above code always works when an zero-width space (u200b) is added after the n character.

I made a JSFidle: https://jsfiddle.net/Alphonsio/atr7e2uw/27/

Of course, I’d prefer not to insert the second character. But I can’t figure out why the new line is not inserted in the first case (n only). Can anyone help?

2

Answers


  1. Use < BR /> instead of n

    document.querySelector("button").addEventListener("click", function() {
      let s = document.querySelector("span");
      console.log("text: " + s.innerHTML);
      //s.textContent = "<br/>" + s.textContent;
      s.innerHTML = "<br/>" + s.innerHTML;
    });
    span {
      contenteditable: true;
      whitespace: pre;
    }
    <button>Click me</button>
    <p contenteditable=false>ZZZ
    <span contenteditable=true>ABC</span>
    </p>
    Login or Signup to reply.
  2. ive looked into your problem a bit

    //js
    
            set(6);
            myInput.focus();
            
            myInput.onkeyup   = e=>{
            
                    if(!(e.key=='Enter'&&e.ctrlKey))return;
                
                  e.preventDefault();
                  
                  var pos               = get();
                  
                  var str               = myInput.textContent;
                  var newstr            = str.slice(0,pos)+'n'+str.slice(pos);
                  myInput.textContent   = newstr;
                  
                  set(pos+1);
                  
            }//onkeyup
            
            function get(){
              
                  return window.getSelection().focusOffset;
                  
            }//get
            
            function set(pos){
              
                  var txt               = myInput.firstChild;
                  var range             = document.createRange()
                  range.setStart(txt,0);
                  range.setEnd(txt,pos);
                  range.collapse(false);
                  
                  var selection         = window.getSelection();
                  selection.removeAllRanges();
                  selection.addRange(range);
                  
            }//set
            
            
            
    /*css*/
            
            #myInput {
                  display       : block;
                  border        : 1px solid black;
                  padding       : 5px;
                  width         : 300px;
                  height        : 200px;
                  white-space   : pre;
            }
            
    <!--html-->            
            
            <p>Type some characters and press Ctrl+Enter</p>
            
            <span id=myInput contenteditable=true>12345678</span>
            

    i use chrome mainly, it all works

    except when the cursor is at the end of the string, then the newline is inserted at the end but the browser doesnt seem to pick it up in the ui, seems to be a browser bug, ive tried it with various elements and all are the same

    ive just noticed, if you delete a character it starts working, try playing around with it

    if you chose to use a textarea, then it does work and you can just use

        var pos                 = myInput.selectionEnd;
        var str                 = myInput.value;
        myInput.value           = str.slice(0,pos)+'n'+str.slice(pos);
        myInput.selectionEnd    = pos+1;
    

    now i come to think about it, browsers have always been a bit funny about white space at the end of contents, even with white-space set to pre, they just love to collapse whitespace

    its fine to use newlines in any element in html, theyre a fundamental part of the html specification, a span is just an inline element

    you use a span and then set its display to be block, which effectively renders it as a div as far as i can tell

    i’ll post this for now so i dont lose my edits, i do have some more to suggest on the subject …

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search