Edw*_*ith 14 html javascript dom contenteditable rangy
我有一个contenteditable div,其中包含典型的所见即所得编辑器html(粗体,锚点,列表).
我需要确定当前光标是否为onKeyDown,在div的开头和结尾.原因是,基于光标位置和按下的键,我可能想要将此div与退格上的前一个div合并,或者在输入时创建一个新的跟随div.
我一直在摆弄范围,但是当你在元素中使用html时,事情变得相当复杂.
我希望我必须忽略一些简单的解决方案.
是否有一种相对简单的方法来确定这一点 - 我愿意使用像Rangy这样的库.
谢谢!
编辑:我正在考虑以下几点:
$('.mycontenteditable').bind('keydown', handle_keydown)
handle_keydown = function(e) {
range = window.getSelection().getRangeAt(0)
start_range = document.createRange()
start_range.selectNodeContents(this.firstChild)
start_range.collapse(true) // collapse to start
is_start = start_range.compareBoundaryPoints(Range.START_TO_START,range)
end_range = document.createRange()
end_range.selectNodeContents(this.lastChild)
end_range.collapse(false)
is_end = end_range.compareBoundaryPoints(Range.END_TO_END,range)
}
Run Code Online (Sandbox Code Playgroud)
我会遇到类似这样的奇怪问题吗?
Tim*_*own 20
我会使用类似的方法,除了使用对象的toString()方法,Range而不是cloneContents()避免不必要的克隆.另外,在IE <9(其不支持范围),可以使用类似的方法与所述text的属性TextRange.
请注意,当内容中存在前导和/或尾随换行符时,这会出现问题,因为toString()范围的方法就像textContent节点的属性一样,只考虑文本节点,因此不考虑<br>或隐含的断行元素.此外,不考虑CSS:例如,display: none包含隐藏的元素内的文本.
这是一个例子:
现场演示:http://jsfiddle.net/YA3Pu/1/
码:
function getSelectionTextInfo(el) {
var atStart = false, atEnd = false;
var selRange, testRange;
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount) {
selRange = sel.getRangeAt(0);
testRange = selRange.cloneRange();
testRange.selectNodeContents(el);
testRange.setEnd(selRange.startContainer, selRange.startOffset);
atStart = (testRange.toString() == "");
testRange.selectNodeContents(el);
testRange.setStart(selRange.endContainer, selRange.endOffset);
atEnd = (testRange.toString() == "");
}
} else if (document.selection && document.selection.type != "Control") {
selRange = document.selection.createRange();
testRange = selRange.duplicate();
testRange.moveToElementText(el);
testRange.setEndPoint("EndToStart", selRange);
atStart = (testRange.text == "");
testRange.moveToElementText(el);
testRange.setEndPoint("StartToEnd", selRange);
atEnd = (testRange.text == "");
}
return { atStart: atStart, atEnd: atEnd };
}
Run Code Online (Sandbox Code Playgroud)
Edw*_*ith 15
这就是我最终解决这个问题的方法.我上面提出的解决方案有时会工作但有很多边缘情况,所以我最终考虑了光标前后有多少文本,如果是0个字符,那么我就在开始或结束时:
handle_keydown = function(e) {
// Get the current cusor position
range = window.getSelection().getRangeAt(0)
// Create a new range to deal with text before the cursor
pre_range = document.createRange();
// Have this range select the entire contents of the editable div
pre_range.selectNodeContents(this);
// Set the end point of this range to the start point of the cursor
pre_range.setEnd(range.startContainer, range.startOffset);
// Fetch the contents of this range (text before the cursor)
this_text = pre_range.cloneContents();
// If the text's length is 0, we're at the start of the div.
at_start = this_text.textContent.length === 0;
// Rinse and repeat for text after the cursor to determine if we're at the end.
post_range = document.createRange();
post_range.selectNodeContents(this);
post_range.setStart(range.endContainer, range.endOffset);
next_text = post_range.cloneContents();
at_end = next_text.textContent.length === 0;
}
Run Code Online (Sandbox Code Playgroud)
仍然不完全确定还有其他边缘情况,因为我不完全确定如何对其进行单元测试,因为它需要鼠标交互 - 可能有一个库来处理这个问题.
Yuv*_* A. 10
我发现了这个非常一致且简短的方法:
function isAtTextEnd() {
var sel = window.getSelection(),
offset = sel.focusOffset;
sel.modify ("move","forward","character");
if (offset == sel.focusOffset) return true;
else {
sel.modify ("move","backward","character");
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
关键:尝试强制向前移动一个字符 - 如果它确实移动了:不在末尾(向后移动一个字符),如果没有 - 它在末尾(不需要向后移动,它没有移动)。
文本开头的实现是相反的,并且“留给读者作为练习”......
空洞:
MDN 标记modify为“非标准”,尽管兼容性表显示了相当广泛的支持(根据该表测试可在最新的 Chrome 和 Firefox 上运行 - Edge 不支持)。
我尝试使用对其支持更多的内容extend()- 然而,奇怪的是,即使在文本末尾,扩展也确实有效。
如果您在用户启动插入符号移动后进行检查(例如在键盘或鼠标事件处理程序中),则应该处理检查强制插入符号以意外方式移动的情况。
| 归档时间: |
|
| 查看次数: |
5710 次 |
| 最近记录: |