Zer*_*ity 10 javascript jquery range contenteditable
我有一个满足的div
<div id="divTest" contenteditable="true">
Run Code Online (Sandbox Code Playgroud)
我需要从插入位置得到最后一个字,在某些情况下我必须测试并删除这个特定字.以下是我的表现
$('#divTest').on('keyup focus', function (e) {
if (e.keyCode == 32) {
var lastWord = getWordPrecedingCaret(this), spanLastWord = $('#lastWord');
}
});
function getWordPrecedingCaret(containerEl) {
var preceding = "",
sel,
range,
precedingRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0).cloneRange();
range.collapse(true);
range.setStart(containerEl, 0);
preceding = range.toString();
}
} else if ((sel = document.selection) && sel.type != "Control") {
range = sel.createRange();
precedingRange = range.duplicate();
precedingRange.moveToElementText(containerEl);
precedingRange.setEndPoint("EndToStart", range);
preceding = precedingRange.text;
}
var words = range.toString().trim().split(' '),
lastWord = words[words.length - 1];
if (lastWord) {
var resultValue = 'some'; // this value is coming from some other function
if (resultValue == lastWord) {
alert('do nothing');
// do nothing
}
else
{
alert('replace word');
// delete That specific word and replace if with resultValue
}
return lastWord;
}
}
Run Code Online (Sandbox Code Playgroud)
演示:http://codepen.io/anon/pen/ogzpXV
我尝试过range.deleteContents(); 但这将删除div中的所有内容.我怎样才能替换特定单词?
要使用,Ranges我们需要记住,我们正在使用节点,而不仅仅是渲染的文本.您想要操纵的结构是:
<div id="divTest" contenteditable="true"> <-- Element Node
"some text" <-- TextNode
</div>
Run Code Online (Sandbox Code Playgroud)
但它也可能是:
<div id="divTest" contenteditable="true"> <-- Element Node
"some text" <-- TextNode
"more text" <-- TextNode
"" <-- TextNode
</div>
Run Code Online (Sandbox Code Playgroud)
为了解决你的问题更简单,只处理一个TextNode,我建议使用该normalize()函数将所有这些函数连接成一个.
然后你只需要设置Range之前的单词边界deleteContents().删除后,您可以TextNode使用替换插入新的替换insertNode().
var wordStart = range.toString().lastIndexOf(lastWord);
var wordEnd = wordStart + lastWord.length;
/* containerEl.firstChild refers to the div's TextNode */
range.setStart(containerEl.firstChild, wordStart);
range.setEnd(containerEl.firstChild, wordEnd);
range.deleteContents();
range.insertNode(document.createTextNode(resultValue));
Run Code Online (Sandbox Code Playgroud)
为此,您需要将文本放在一个单独的文本中TextNode.但经过ìnsertNode了div将包含多个文本节点.要解决此问题,只需调用normalize()即可加入所有TextNode元素.
containerEl.normalize();
Run Code Online (Sandbox Code Playgroud)
编辑:
正如Basj指出的那样,原始解决方案无法用于多线.那是因为当按下ENTER时,结构会改变:
<div id="divTest" contenteditable="true"> <-- Element Node
"some text" <-- TextNode
</div>
Run Code Online (Sandbox Code Playgroud)
类似于:
<div id="divTest" contenteditable="true"> <-- Element Node
<div>"some text"</div>
<div>"more text"</div>
</div>
Run Code Online (Sandbox Code Playgroud)
我已经更新了这个答案,但是也值得在这个问题上阅读Basj的答案:在光标前替换单词,当多个行在contenteditable
JSFiddle演示或可运行的代码片段:
document.getElementById('divTest').onkeyup = function (e) {
if (e.keyCode == 32) {
getWordPrecedingCaret(this);
}
};
function getWordPrecedingCaret(containerEl) {
var preceding = "",
sel,
range,
precedingRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0).cloneRange();
range.collapse(true);
range.setStart(containerEl, 0);
preceding = range.toString();
}
} else if ((sel = document.selection) && sel.type != "Control") {
range = sel.createRange();
precedingRange = range.duplicate();
precedingRange.moveToElementText(containerEl);
precedingRange.setEndPoint("EndToStart", range);
preceding = precedingRange.text;
}
var words = range.toString().trim().split(' '),
lastWord = words[words.length - 1];
if (lastWord) {
var resultValue = 'some'; // this value is coming from some other function
if (resultValue == lastWord) {
console.log('do nothing: ' + lastWord);
// do nothing
} else {
console.log('replace word ' + lastWord);
/* Find word start and end */
var wordStart = range.endContainer.data.lastIndexOf(lastWord);
var wordEnd = wordStart + lastWord.length;
console.log("pos: (" + wordStart + ", " + wordEnd + ")");
range.setStart(range.endContainer, wordStart);
range.setEnd(range.endContainer, wordEnd);
range.deleteContents();
range.insertNode(document.createTextNode(resultValue));
// delete That specific word and replace if with resultValue
/* Merge multiple text nodes */
containerEl.normalize();
}
return lastWord;
}
}Run Code Online (Sandbox Code Playgroud)
<div id="divTest" contenteditable="true">Write words here and hit SPACE BAR</div>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3457 次 |
| 最近记录: |