javascript - 如果两个相邻的可编辑范围和光标在中间,html 如何决定我正在写哪一个?

标签 javascript html contenteditable

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

<div style="border:1px solid black;" id='editor-container' contenteditable="true"><mytag id="0">test</mytag></div>

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);
}

这是JSFIDDLE

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

<div style="border:1px solid black;" id="editor-container" contenteditable="true">
   <mytag id="0">A</mytag>
</div>

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

<div style="border:1px solid black;" id="editor-container" contenteditable="true">
   <mytag id="0">A.</mytag>
   <mytag id="1"></mytag>
</div>

添加点后,我以编程方式(函数 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>

相反,它实际上导致 Chrome:

<div style="border:1px solid black;" id="editor-container" contenteditable="true">
   <mytag id="0">A.B</mytag>
   <mytag id="1"></mytag>
</div>

虽然在 Firefox 中 90% 的时间都按预期运行,但有时会像在 Chrome 中那样随机运行。

那么,如果我的光标位于两个相邻的 span 之间,html 如何决定下一个输入是放在一个 span 还是另一个? 有办法强制执行预期的行为吗?

编辑: 很明显,只有在以下 div 因含糊不清而为空的情况下才会发生这种情况。如果你在下面的 div 中放置一个 char 并将插入符号移动到位置“1”,它就像一个魅力。 (只是说问题不直接依赖于这个特定的代码,它在不同的条件下完美运行)

JSFIDDLE 2

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

最佳答案

首先:你设置<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);
}
mytag {
  border: 1px solid black;
}
<div id='editor-container'>
    <mytag id="0" contenteditable="true">test</mytag>
</div>

在 JS 中在这里做了修改:

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

关于javascript - 如果两个相邻的可编辑范围和光标在中间,html 如何决定我正在写哪一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56441839/

相关文章:

iphone - 以编程方式在 contenteditable UIWebView 中显示键盘

javascript - jQuery - 使用发布数据重定向

html - 在多个 div 内水平对齐 H4 标签

javascript - Jquery-使用 'show' 和 'hide' on click 函数

javascript - 在 p 元素内的 span 内设置圆盘样式

javascript - window.getSelection() for contenteditable div *点击*

jquery - 当插入符位于内容可编辑的 div 中时插入 html

javascript - jQuery:嵌套框架集中的访问框架

javascript - 如何触发底层图片的onClick?

javascript - 通过推文拉取 Twitter 头像