вставить промежуток в contenteditable, и тогда пользователь не может продолжить ввод после и из промежутка, который только что был вставлен - PullRequest
2 голосов
/ 14 апреля 2020
  • цель кода: когда пользователь нажимает пробел, автоматически вводит диапазон, а затем пользователь может продолжить ввод,
  • , когда я отслеживаю их в devtools, range.setEnd (lasttextnode, 0); и range.collapse () выполняется правильно,
  • , но ввод с клавиатуры неправильный, я установил курсор на текст, хочу вставить символ сразу после диапазона, но ввод появляется в предыдущем диапазоне, который просто вставьте.

вот мой код:

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>

Вы можете видеть: ввод с клавиатуры будет в диапазоне, который только что вставлен.

но если я изменю range.setEnd(lasttextnode, 0); на range.setEnd(lasttextnode, 1), он будет работать правильно;

Я попробовал много методов:

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

все они не работают. просто вставьте пробел, прежде чем последний текстовый узел сможет частично решить вопрос, но это не моя цель, я хочу что-то вводить после интервала.

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Вы можете попробовать вставить пустой символ (например, \u200B) между диапазоном и последним текстовым узлом. Затем, когда вы перемещаете курсор вправо перед последним текстовым узлом, он выходит за пределы тега span. Но не забудьте стереть пустой символ из результата, прежде чем вставить его в базу данных.

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>
0 голосов
/ 17 апреля 2020

Вы можете попытаться добавить другой узел, используя только пробел, и затем установить EndEnd на этом узле.

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/

Он будет фокусироваться вне диапазона. Это то, чего вы хотели достичь?

...