如果两个相邻的可编辑范围和光标位于中间,那么html如何确定我在写哪个?

Sas*_*vus 7 html javascript contenteditable

每当用户在输入文本中输入一个点时,我都会在此脚本中向可编辑div中添加一个新跨度,并尝试根据是否存在以点分隔它们的点来分隔以不同跨度编写的文本。(我使用自定义标签“ mytag”,但其行为实际上像跨度一样)

<div style="border:1px solid black;" id='editor-container' contenteditable="true"><mytag id="0">test</mytag></div>
Run Code Online (Sandbox Code Playgroud)

JS:

var divContainer = document.getElementById("editor-container");
var nodeIdIncrement = 0;
var htmlBefore = divContainer.innerHTML; 
var html;
var editedCharIndex;

moveCursorOnDiv("0");

divContainer.addEventListener("input", function(e) {
    html=divContainer.innerHTML;

    editedCharIndex=findFirstDiffPos(htmlBefore,html);
    console.log("html[editedCharIndex]: "+html[editedCharIndex]);

    if(html[editedCharIndex]=="."){
        nodeIdIncrement++; 
      htmlBefore=html.substring(0, editedCharIndex+1)+'</mytag><mytag id="'+nodeIdIncrement+'">'+html.substring(editedCharIndex+1);

      divContainer.innerHTML = htmlBefore;
      moveCursorOnDiv(nodeIdIncrement);
    }else{
        htmlBefore = divContainer.innerHTML;
    }

}, false);

// Find index of newly added character making a diff between previuos situation and present one
function findFirstDiffPos(a, b) {
   var shorterLength = Math.min(a.length, b.length);

   for (var i = 0; i < shorterLength; i++){
       if (a[i] !== b[i]) return i;
   }

   if (a.length !== b.length) return shorterLength;

   return -1;
}

function moveCursorOnDiv(divId){
    console.log("divId: "+divId);
  var el = document.getElementById(divId);
  console.log("inner: "+el.innerHTML);
  var range = document.createRange();
  var sel = window.getSelection();
  range.setStart(el, 0);
  range.collapse(true);
  sel.removeAllRanges();
  sel.addRange(range);
}
Run Code Online (Sandbox Code Playgroud)

这是JSFIDDLE

假设我在可编辑的div“编辑器-容器”中输入了一个字符'A',结果将是:

<div style="border:1px solid black;" id="editor-container" contenteditable="true">
   <mytag id="0">A</mytag>
</div>
Run Code Online (Sandbox Code Playgroud)

然后我加一个点。结果将是:

<div style="border:1px solid black;" id="editor-container" contenteditable="true">
   <mytag id="0">A.</mytag>
   <mytag id="1"></mytag>
</div>
Run Code Online (Sandbox Code Playgroud)

当添加点时,我以编程方式(功能moveCursorOnDiv)强制光标在新的div上移动。预期结果将是输入另一个字符“ B”将导致以下情况:

<div style="border:1px solid black;" id="editor-container" contenteditable="true">
   <mytag id="0">A.</mytag>
   <mytag id="1">B</mytag>
</div>
Run Code Online (Sandbox Code Playgroud)

相反,它实际上导致Chrome进入:

<div style="border:1px solid black;" id="editor-container" contenteditable="true">
   <mytag id="0">A.B</mytag>
   <mytag id="1"></mytag>
</div>
Run Code Online (Sandbox Code Playgroud)

尽管在Firefox中,Firefox的行为符合预期的90%,但有时还是会在Chrome中随机出现。

因此,如果我在两个相邻跨度之间有光标,那么html如何确定下一个输入将被置于跨度还是另一个?有一种方法可以强制预期的行为?

编辑:很明显,这仅在以下div为空的情况下才存在歧义。如果在下一个div中放置一个char并将插入号移动到位置“ 1”,则它就像一个超级按钮。(只说问题不直接取决于此特定代码,该特定代码在不同条件下可以完美工作)

JSFIDDLE 2

这也意味着可以通过添加&nb sp;之类的东西来解决该问题。添加新的div时,但这不是一个干净的解决方案。

小智 1

第一:您设置<div id="editor-container".....> </div>为可编辑,因此当您键入时,它会用新的.创建一个新的,但它不会为新的提供可编辑选项,并且由于它不可编辑,因此鼠标指针保持在相同的位置。<mytag>Id<mytag>

这里我做了一些更改:添加了一些边框和边距,使其可见

var divContainer = document.getElementById("editor-container");
var nodeIdIncrement = 0;
var htmlBefore = divContainer.innerHTML; 
var html;
var editedCharIndex;

moveCursorOnDiv("0");

divContainer.addEventListener("input", function(e) {
    html=divContainer.innerHTML;

    editedCharIndex=findFirstDiffPos(htmlBefore,html);
    console.log("html[editedCharIndex]: "+html[editedCharIndex]);

    if(html[editedCharIndex]=="."){
        nodeIdIncrement++; 
      htmlBefore=html.substring(0, editedCharIndex+1)+'</mytag><mytag id="'+nodeIdIncrement+'" contenteditable="true" style="margin: 10px;">'+html.substring(editedCharIndex+1);

      divContainer.innerHTML = htmlBefore;
      moveCursorOnDiv(nodeIdIncrement);
    }else{
        htmlBefore = divContainer.innerHTML;
    }

}, false);

// Find index of newly added character making a diff between previuos situation and present one
function findFirstDiffPos(a, b) {
   var shorterLength = Math.min(a.length, b.length);

   for (var i = 0; i < shorterLength; i++){
       if (a[i] !== b[i]) return i;
   }

   if (a.length !== b.length) return shorterLength;

   return -1;
}

function moveCursorOnDiv(divId){
    console.log("divId: "+divId);
  var el = document.getElementById(divId);
  console.log("inner: "+el.innerHTML);
  var range = document.createRange();
  var sel = window.getSelection();
  range.setStart(el, 0);
  range.collapse(true);
  sel.removeAllRanges();
  sel.addRange(range);
}
Run Code Online (Sandbox Code Playgroud)
mytag {
  border: 1px solid black;
}
Run Code Online (Sandbox Code Playgroud)
<div id='editor-container'>
    <mytag id="0" contenteditable="true">test</mytag>
</div>
Run Code Online (Sandbox Code Playgroud)

在 JS 中进行了更改:

htmlBefore=html.substring(0, editedCharIndex+1)+'</mytag><mytag id="'+nodeIdIncrement+'" contenteditable="true" style="margin: 10px; border: 1px solid black;">'+html.substring(editedCharIndex+1);
Run Code Online (Sandbox Code Playgroud)