您如何获取和设置内容编辑器中的插入符号位置?
How do you get and set the caret position in a contenteditable?
这个问题有一些答案here,但还有一些问题。
基本上我想做以下事情:
- 获取插入符位置
- 设置 contenteditable 的 innerHTML(这会重置插入符号位置)
- 将插入符号位置设置为在步骤 1 中获得的值。
许多现有的答案似乎因跨浏览器支持而变得复杂,但我只需要它在现代 chrome 上工作。它还需要与 html 配合使用。理想情况下,它看起来完全像这样:
var index = getCaretPosition(contentEditableDiv);
onEdit(contentEditableDiv); // <-- callback function that manipulates the text and sets contentEditableDiv.innerHTML = theManipulatedText
setCaretPosition(contentEditableDiv, index);
我已经尝试浏览 documentation 但它并不简单,我认为这个问题无论如何都应该得到更精简的答案。
这似乎对我有用,但我只针对我的用例对其进行了测试。
GET
function getCaretIndex(win, contentEditable) {
var index = 0;
var selection = win.getSelection();
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
var isSelectedNode = node === selection.focusNode;
if(isSelectedNode) {
index += selection.focusOffset;
break;
}
else {
index += node.textContent.length;
}
}
return index;
}
设置
function setCaretIndex(win, contentEditable, newCaretIndex) {
var cumulativeIndex = 0;
var relativeIndex = 0;
var targetNode = null;
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
if(newCaretIndex <= cumulativeIndex + node.textContent.length) {
targetNode = node;
relativeIndex = newCaretIndex - cumulativeIndex;
break;
}
cumulativeIndex += node.textContent.length;
}
var range = win.document.createRange();
range.setStart(targetNode, relativeIndex);
range.setEnd(targetNode, relativeIndex);
range.collapse();
var sel = win.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
需要帮助
function textNodesUnder(node) { //
var all = [];
for (node=node.firstChild;node;node=node.nextSibling){
if (node.nodeType==3) {
all.push(node);
}
else {
all = all.concat(textNodesUnder(node));
}
}
return all;
}
TEST(调用这个函数即可)
它循环遍历 contenteditable 中的文本,设置插入符号索引,然后读取它。控制台输出为:(setIndex | getIndex)
function testContentEditable() {
document.body.innerHTML = "<div contenteditable></div>"
var ce = document.querySelector("[contenteditable]");
ce.focus();
ce.innerHTML = "HELLO <span data-foo='true' style='text-decoration: underline;'><span style='color:red;'>WORLD</span> MY</span> NAME IS BOB";
var i = 0;
var intv = setInterval(function() {
if(i == ce.innerText.length) {
clearInterval(intv);
}
setCaretIndex(window, ce, i);
var currentIndex = getCaretIndex(window, ce);
console.log(i + " | " + currentIndex);
i++;
}, 100);
}
FIDDLE
function getCaretIndex(win, contentEditable) {
var index = 0;
var selection = win.getSelection();
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
var isSelectedNode = node === selection.focusNode;
if(isSelectedNode) {
index += selection.focusOffset;
break;
}
else {
index += node.textContent.length;
}
}
return index;
}
function setCaretIndex(win, contentEditable, newCaretIndex) {
var cumulativeIndex = 0;
var relativeIndex = 0;
var targetNode = null;
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
if(newCaretIndex <= cumulativeIndex + node.textContent.length) {
targetNode = node;
relativeIndex = newCaretIndex - cumulativeIndex;
break;
}
cumulativeIndex += node.textContent.length;
}
var range = win.document.createRange();
range.setStart(targetNode, relativeIndex);
range.setEnd(targetNode, relativeIndex);
range.collapse();
var sel = win.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
function textNodesUnder(node) { //
var all = [];
for (node=node.firstChild;node;node=node.nextSibling){
if (node.nodeType==3) {
all.push(node);
}
else {
all = all.concat(textNodesUnder(node));
}
}
return all;
}
function testContentEditable() {
document.body.innerHTML = "<div contenteditable></div>"
var ce = document.querySelector("[contenteditable]");
ce.focus();
ce.innerHTML = "HELLO <span data-foo='true' style='text-decoration: underline;'><span style='color:red;'>WORLD</span> MY</span> NAME IS BOB";
var i = 0;
var intv = setInterval(function() {
if(i == ce.innerText.length) {
clearInterval(intv);
}
setCaretIndex(window, ce, i);
var currentIndex = getCaretIndex(window, ce);
console.log(i + " | " + currentIndex);
i++;
}, 100);
}
testContentEditable();
这个问题有一些答案here,但还有一些问题。
基本上我想做以下事情:
- 获取插入符位置
- 设置 contenteditable 的 innerHTML(这会重置插入符号位置)
- 将插入符号位置设置为在步骤 1 中获得的值。
许多现有的答案似乎因跨浏览器支持而变得复杂,但我只需要它在现代 chrome 上工作。它还需要与 html 配合使用。理想情况下,它看起来完全像这样:
var index = getCaretPosition(contentEditableDiv);
onEdit(contentEditableDiv); // <-- callback function that manipulates the text and sets contentEditableDiv.innerHTML = theManipulatedText
setCaretPosition(contentEditableDiv, index);
我已经尝试浏览 documentation 但它并不简单,我认为这个问题无论如何都应该得到更精简的答案。
这似乎对我有用,但我只针对我的用例对其进行了测试。
GET
function getCaretIndex(win, contentEditable) {
var index = 0;
var selection = win.getSelection();
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
var isSelectedNode = node === selection.focusNode;
if(isSelectedNode) {
index += selection.focusOffset;
break;
}
else {
index += node.textContent.length;
}
}
return index;
}
设置
function setCaretIndex(win, contentEditable, newCaretIndex) {
var cumulativeIndex = 0;
var relativeIndex = 0;
var targetNode = null;
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
if(newCaretIndex <= cumulativeIndex + node.textContent.length) {
targetNode = node;
relativeIndex = newCaretIndex - cumulativeIndex;
break;
}
cumulativeIndex += node.textContent.length;
}
var range = win.document.createRange();
range.setStart(targetNode, relativeIndex);
range.setEnd(targetNode, relativeIndex);
range.collapse();
var sel = win.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
需要帮助
function textNodesUnder(node) { //
var all = [];
for (node=node.firstChild;node;node=node.nextSibling){
if (node.nodeType==3) {
all.push(node);
}
else {
all = all.concat(textNodesUnder(node));
}
}
return all;
}
TEST(调用这个函数即可)
它循环遍历 contenteditable 中的文本,设置插入符号索引,然后读取它。控制台输出为:(setIndex | getIndex)
function testContentEditable() {
document.body.innerHTML = "<div contenteditable></div>"
var ce = document.querySelector("[contenteditable]");
ce.focus();
ce.innerHTML = "HELLO <span data-foo='true' style='text-decoration: underline;'><span style='color:red;'>WORLD</span> MY</span> NAME IS BOB";
var i = 0;
var intv = setInterval(function() {
if(i == ce.innerText.length) {
clearInterval(intv);
}
setCaretIndex(window, ce, i);
var currentIndex = getCaretIndex(window, ce);
console.log(i + " | " + currentIndex);
i++;
}, 100);
}
FIDDLE
function getCaretIndex(win, contentEditable) {
var index = 0;
var selection = win.getSelection();
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
var isSelectedNode = node === selection.focusNode;
if(isSelectedNode) {
index += selection.focusOffset;
break;
}
else {
index += node.textContent.length;
}
}
return index;
}
function setCaretIndex(win, contentEditable, newCaretIndex) {
var cumulativeIndex = 0;
var relativeIndex = 0;
var targetNode = null;
var textNodes = textNodesUnder(contentEditable);
for(var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
if(newCaretIndex <= cumulativeIndex + node.textContent.length) {
targetNode = node;
relativeIndex = newCaretIndex - cumulativeIndex;
break;
}
cumulativeIndex += node.textContent.length;
}
var range = win.document.createRange();
range.setStart(targetNode, relativeIndex);
range.setEnd(targetNode, relativeIndex);
range.collapse();
var sel = win.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
function textNodesUnder(node) { //
var all = [];
for (node=node.firstChild;node;node=node.nextSibling){
if (node.nodeType==3) {
all.push(node);
}
else {
all = all.concat(textNodesUnder(node));
}
}
return all;
}
function testContentEditable() {
document.body.innerHTML = "<div contenteditable></div>"
var ce = document.querySelector("[contenteditable]");
ce.focus();
ce.innerHTML = "HELLO <span data-foo='true' style='text-decoration: underline;'><span style='color:red;'>WORLD</span> MY</span> NAME IS BOB";
var i = 0;
var intv = setInterval(function() {
if(i == ce.innerText.length) {
clearInterval(intv);
}
setCaretIndex(window, ce, i);
var currentIndex = getCaretIndex(window, ce);
console.log(i + " | " + currentIndex);
i++;
}, 100);
}
testContentEditable();