2
  • the code target : when user press space, auto input a span, and then user can continue input,
  • when i trace them in the devtools,range.setEnd(lasttextnode, 0); and range.collapse() run in right way,
  • but the keyboard input is not right, i set the caret on the text, want to insert char just after the span, but input appear in the previous span that just be insert.

here is my code :

editor.onkeydown = editinput;
var sel = window.getSelection();

function editinput(e) {
  var range = sel.getRangeAt(0);

  if (e.isComposing || e.keyCode === 229) { //imk
    return;
  }
  if (e.keyCode == 32) { //space

    var tnode = range.commonAncestorContainer;
    var start = range.startOffset;
    var text = tnode.textContent;

    var span = document.createElement('span');
    span.innerHTML = '------span------';

    var firsttextnode = document.createTextNode(text.substring(0, start));
    var lasttextnode = document.createTextNode(text.substring(start));
    var fragment = new DocumentFragment();
    fragment.append(firsttextnode, span, lasttextnode);
    tnode.replaceWith(fragment);
    range.setEnd(lasttextnode, 0); // here is problem,
    range.collapse();

    e.stopPropagation(); //bubble
    e.preventDefault(); //default.
  }
}
[contenteditable=true] {
  display: inline-block;
  white-space: pre-wrap;
  width: 400px;
  height: 100%;   
}

div, textarea,   span {
  border: 1px solid rgba(122, 206, 143, 0.966);
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
<div id="editor" contenteditable="true" class="Weave" tabIndex="1">
  samelinesamelinesamelinesamelinesamelinesamelinesame
  <span>deerge span</span>oaeueouaoeu <span>disange span</span>
</div>

you can see: the keyboard input will in span that just insert.

but if i change range.setEnd(lasttextnode, 0); to range.setEnd(lasttextnode, 1), it will run right;

i have try a lot of method:

  1. range.collapse();
  2. range.setStart(lasttextnode,0)
  3. sel.removeAllRanges();
  4. sel.collapse(lasttextnode,0)
  5. range.setStartBefore(lasttextnode);
  6. range.setStartAfter(span);

all of them is not work. just insert a space before the lasttextnode can solve the question partly, but that is not my target, i want input something after the span closely.

defend orca
  • 617
  • 7
  • 17
  • You had said that (in title), "can not be out of span", and then you are saying, "you can see: the keyboard input will in span that just insert". Now, I ask: "do you want caret to be inside of span, or do you want it just after the span?". Also, you had said, "and then user can continue input". So, the question is, from where should the user continue typing input? – vrintle Apr 17 '20 at 06:30
  • thanks @RahulVerma, i have change the title, do i get the point of you? – defend orca Apr 17 '20 at 06:35
  • (In title) I think you mean "can continue input". __Also__, I had asked you, "from where should the user continue typing input? (inside the span __or__ outside the span)" – vrintle Apr 17 '20 at 06:38
  • i want to outside the span, but can not. – defend orca Apr 17 '20 at 06:52

2 Answers2

3

You can try inserting an empty character (e.g. \u200B) in between the span and the last text node. Then when you move cursor to right before the last text node, it's outside the span tag. But remember to erase the empty character from the result before inserting it into database.

editor.onkeydown = editinput;
var sel = window.getSelection();

function editinput(e) {
  var range = sel.getRangeAt(0);

  if (e.isComposing || e.keyCode === 229) { //imk
    return;
  }
  if (e.keyCode == 32) { //space

    var tnode = range.commonAncestorContainer;
    var start = range.startOffset;
    var text = tnode.textContent;

    var span = document.createElement('span');
    span.innerHTML = '------span------';
    var emptyNode = document.createTextNode('\u200B');

    var firsttextnode = document.createTextNode(text.substring(0, start));
    var lasttextnode = document.createTextNode(text.substring(start));
    var fragment = new DocumentFragment();
    fragment.append(firsttextnode, span, emptyNode, lasttextnode);
    tnode.replaceWith(fragment);
    range.setEnd(lasttextnode, 0); // here is problem,
    range.collapse();

    e.stopPropagation(); //bubble
    e.preventDefault(); //default.
  }
}
[contenteditable=true] {
  display: inline-block;
  white-space: pre-wrap;
  width: 400px;
  height: 100%;   
}

div, textarea,   span {
  border: 1px solid rgba(122, 206, 143, 0.966);
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
<div id="editor" contenteditable="true" class="Weave" tabIndex="1">
  samelinesamelinesamelinesamelinesamelinesamelinesame
  <span>deerge span</span>oaeueouaoeu <span>disange span</span>
</div>
Allen Hsu
  • 3,515
  • 3
  • 25
  • 38
  • this look like a good solution, but next time i get the doc form database, and show it on the contenteditable, i must insert the \u220b on the right position? do i got the idea? – defend orca Apr 17 '20 at 07:03
  • No, it's not necessary. The `\u220b` is just a placeholder for the editor. It's only used to move the cursor when editing. – Allen Hsu Apr 17 '20 at 07:13
  • But it's okay even if you forgot to clean up the `\u220b` tag. The only downside is that you have some invisible characters in the output HTML. – Allen Hsu Apr 17 '20 at 07:15
  • OK, i will try it, i concern when i take them back, and there is not the \u220b, and then can not input just after the span, if that is true, i will keep the \u220b always. thank your again, any way, you have solve my problem, thank you. – defend orca Apr 17 '20 at 09:54
0

You could try to add another node, with just a space, and then setEnd on that node.

var firsttextnode = document.createTextNode(text.substring(0, start));
var lasttextnode = document.createTextNode(text.substring(start));
var emptyNode = document.createTextNode(' ');
var fragment = new DocumentFragment();
fragment.append(firsttextnode, span, lasttextnode, emptyNode);
tnode.replaceWith(fragment);
range.setEnd(emptyNode, 1);
range.collapse();

https://jsfiddle.net/63s1tgyw/

It will focus out of the span. Is that what you wanted to achieve?

Maciej Kasprzak
  • 929
  • 6
  • 17
  • 1
    just input a space before lasttextnode can solute it too, but that is not i want to find. i want to input something close follow the span, not insert a no use space. any way thank you for your answer, especially that is the first answer. – defend orca Apr 17 '20 at 06:58