Search code examples
javascriptrangenodeskeydowncaret

how can i insert element on caret by the keydown event?


this function is not work, but if i set breakpoint in devtools, it will work success, why? so strange......

function insertHtmlAtCursor() {
  var range=window.getSelection().getRangeAt(0);
  var node = range.createContextualFragment("<div>this is not show</div>");
  range.insertNode(node);
}

but if i change code to this, it always run in right way.

  var node = document.createTextNode('this is ok.'); 

i use chrome in macos, here is the demo:

editor.onkeydown=editinput;
function editinput(e) {
  if(e.isComposing||e.keyCode===229) {
    return;
  }
  if(e.keyCode==32) {//space
  var range=window.getSelection().getRangeAt(0);
    var node=range.createContextualFragment('ttttttttttt');
    range.insertNode(node);
  }
}
<div id="editor" contenteditable="true" class="knowleadge" tabIndex="1">
</div>

this is the demo, when i key in space, it will not insert fragment, but when i debug in chrome, it will insert the fragment.

now thanks @Dekel, i know keyup replace keydown is a solution , but because i need deal with tab, and keyup can not really catch the tab key, so i need deal the code in keydown, how can i do it?

and i find settimeout can deal these problem, but is there any other solution? here is the set time out:

if(e.keyCode==32) {//space
    setTimeout(dealpace,0);
    e.stopPropagation(); 
    e.preventDefault();  
}
function dealpace() {
    var range=window.getSelection().getRangeAt(0);
    var node=range.createContextualFragment('ttttttttttt');
    range.insertNode(node);
}

thanks @Dekel, settimeout is not key, the key is e.preventDefault(); like @Dekel say, keydown insert the text, but keyup replace the text with space. so we need e.preventDefault(); like this:

 if(e.keyCode==32) {//space
    dealpace();
    e.stopPropagation(); 
    e.preventDefault();  
    }
 function dealpace() {
    var range=window.getSelection().getRangeAt(0);
    var node=range.createContextualFragment('ttttttttttt');
    range.insertNode(node);
 } 

Solution

  • Looks like both work just fine:

    function insertHtmlAtCursor1() {
      var range=window.getSelection().getRangeAt(0);
      var node = range.createContextualFragment("<div>this is not show</div>");
      range.insertNode(node);
    }
    function insertHtmlAtCursor2() {
      var range=window.getSelection().getRangeAt(0);
      var node = document.createTextNode('this is ok.'); 
      range.insertNode(node);
    }
    .container {
      border: 1px solid black;
      background: #fefefe;
    }
    <div class="container">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>
    
    <button onClick="insertHtmlAtCursor1()">Function 1</button>
    <button onClick="insertHtmlAtCursor2()">Function 2</button>

    Are you sure you are using it correctly?
    What exactly is the issue?