use*_*521 11 html javascript php jquery
我有一个contenteditable div如下(| =光标位置):
<div id="mydiv" contenteditable="true">lorem ipsum <spanclass="highlight">indol|or sit</span> amet consectetur <span class='tag'>adipiscing</span> elit</div>
Run Code Online (Sandbox Code Playgroud)
我想得到当前的光标位置,包括html标签.我的代码:
var offset = document.getSelection().focusOffset;
Run Code Online (Sandbox Code Playgroud)
偏移量返回5(最后一个标签的全文)但我需要它来处理html标签.预期的返回值是40.代码必须与所有最近的浏览器一起使用.(我也检查了这个:带有HTML标签的window.getSelection()偏移量?但它没有回答我的问题).有任何想法吗 ?
Alv*_*oro 10
编辑:这是一个旧的答案,不适用于OP要求具有相同文本的节点.但如果你没有这个要求,它会更清洁,更轻巧.
这是您可以使用的一个选项,适用于所有主流浏览器:
document.getSelection().anchorOffset)document.getSelection().anchorNode.data)#mydiv通过使用获取该文本的偏移量indexOf()对于您的特定情况,代码看起来像这样:
var offset = document.getSelection().anchorOffset;
var text = document.getSelection().anchorNode.data;
var textOffset = $("#mydiv").html().indexOf( text );
offsetCaret = textOffset + offset;
Run Code Online (Sandbox Code Playgroud)
您可以在此JSFiddle上查看工作演示(查看控制台以查看结果).
一个更通用的函数版本(允许传递div作为参数,因此它可以与不同的一起使用contenteditable)在另一个JSFiddle上:
function getCaretHTMLOffset(obj) {
var offset = document.getSelection().anchorOffset;
var text = document.getSelection().anchorNode.data;
var textOffset = obj.innerHTML.indexOf( text );
return textOffset + offset;
}
Run Code Online (Sandbox Code Playgroud)
关于这个答案
另一种方法是在DOM中添加一个临时标记并计算该标记的偏移量.该算法在感兴趣outerHTML的内部序列化(the innerHTML)中查找标记(其)的HTML序列化div.重复文本不是此解决方案的问题.
为此,标记的序列化在其div中必须是唯一的.您无法控制用户键入字段的内容,但您可以控制放入DOM的内容,因此这不难实现.在我的示例中,标记是静态唯一的:通过选择不太可能导致冲突的类名.通过检查DOM并更改类直到它是唯一的,它也可以动态地完成.
我有一个小提琴(源自Alvaro Montoro自己的小提琴).主要部分是:
function getOffset() {
if ($("." + unique).length)
throw new Error("marker present in document; or the unique class is not unique");
// We could also use rangy.getSelection() but there's no reason here to do this.
var sel = document.getSelection();
if (!sel.rangeCount)
return; // No ranges.
if (!sel.isCollapsed)
return; // We work only with collapsed selections.
if (sel.rangeCount > 1)
throw new Error("can't handle multiple ranges");
var range = sel.getRangeAt(0);
var saved = rangy.serializeSelection();
// See comment below.
$mydiv[0].normalize();
range.insertNode($marker[0]);
var offset = $mydiv.html().indexOf($marker[0].outerHTML);
$marker.remove();
// Normalizing before and after ensures that the DOM is in the same shape before
// and after the insertion and removal of the marker.
$mydiv[0].normalize();
rangy.deserializeSelection(saved);
return offset;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,代码必须补偿将标记添加到DOM中并将其删除,因为这会导致当前选择丢失:
Rangy用于保存选择并在之后恢复.请注意,保存和恢复可以使用比Rangy更轻的东西来完成,但我不想用minutia加载答案.如果您决定使用Rangy执行此任务,请阅读文档,因为可以优化序列化和反序列化.
为了让Rangy工作,DOM必须在保存之前和之后处于完全相同的状态.这就是normalize()我们在添加标记之前和删除标记之后调用的原因.这样做是将紧邻的文本节点合并为单个文本节点.问题是向DOM添加标记可能会导致文本节点被分成两个新的文本节点.这会导致选择丢失,如果没有通过规范化撤消,将导致Rangy无法恢复选择.再一次,比调用更轻松的东西normalize可以做到这一点,但我不想用minutia加载答案.
| 归档时间: |
|
| 查看次数: |
551 次 |
| 最近记录: |