如果两个相邻的可编辑范围和光标在中间,html 如何决定我写的是哪一个?
In case of two adjacent editable span and the cursor being in the middle, how html decide on which one i'm writing?
每次用户在输入文本中输入一个点时,我都会让这个脚本在可编辑的 div 中添加一个新的跨度,尝试根据是否存在分隔文本的点来分隔不同跨度中写入的文本.
(我使用自定义标签 '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。
那么,如果我的光标位于两个相邻的跨度之间,html 如何决定下一个输入是放在一个跨度中还是另一个跨度中?
有办法强制执行预期的行为吗?
编辑: 很明显,只有在以下 div 为空的情况下才会发生这种情况,因为存在歧义。如果您在下面的 div 中放置一个字符并将插入符号移动到位置“1”,它就像一个魅力。 (只是说这个问题不直接依赖于这个特定的代码,它在不同的条件下完美运行)
这也意味着问题可以通过添加像 &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);
您必须设置为可编辑,这样当您输入时,它会创建一个带有新 ID 的新对象,但不会为新对象提供可编辑选项,并且由于它不可编辑,因此鼠标指针保持在同一位置.
我所做的更改:添加了一些边框和边距,使其可见
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);
<!-- begin snippet: js hide: false console: true babel: false -->
mytag {
border: 1px solid black;
}
<div id='editor-container'>
<mytag id="0" contenteditable="true">test</mytag>
</div>
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);
}
每次用户在输入文本中输入一个点时,我都会让这个脚本在可编辑的 div 中添加一个新的跨度,尝试根据是否存在分隔文本的点来分隔不同跨度中写入的文本. (我使用自定义标签 '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。
那么,如果我的光标位于两个相邻的跨度之间,html 如何决定下一个输入是放在一个跨度中还是另一个跨度中? 有办法强制执行预期的行为吗?
编辑: 很明显,只有在以下 div 为空的情况下才会发生这种情况,因为存在歧义。如果您在下面的 div 中放置一个字符并将插入符号移动到位置“1”,它就像一个魅力。 (只是说这个问题不直接依赖于这个特定的代码,它在不同的条件下完美运行)
这也意味着问题可以通过添加像 &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);
您必须设置为可编辑,这样当您输入时,它会创建一个带有新 ID 的新对象,但不会为新对象提供可编辑选项,并且由于它不可编辑,因此鼠标指针保持在同一位置.
我所做的更改:添加了一些边框和边距,使其可见
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);
<!-- begin snippet: js hide: false console: true babel: false -->
mytag {
border: 1px solid black;
}
<div id='editor-container'>
<mytag id="0" contenteditable="true">test</mytag>
</div>
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);
}