Javascript 范围对象:Webkit和基于Mozilla的浏览器之间的差异
目前,我在为基于Mozilla和Webkit的浏览器编写抽象层以使用DOM范围对象(获取和处理用户选择)时遇到了一些困难 我也尝试过看Rangy之类的框架,但这对于我的任务来说似乎太复杂了(我不知道在代码中到底哪里可以找到我需要的信息。如果有人能给我一个提示,我将不胜感激!) 我想要的只是:Javascript 范围对象:Webkit和基于Mozilla的浏览器之间的差异,javascript,webkit,range,mozilla,Javascript,Webkit,Range,Mozilla,目前,我在为基于Mozilla和Webkit的浏览器编写抽象层以使用DOM范围对象(获取和处理用户选择)时遇到了一些困难 我也尝试过看Rangy之类的框架,但这对于我的任务来说似乎太复杂了(我不知道在代码中到底哪里可以找到我需要的信息。如果有人能给我一个提示,我将不胜感激!) 我想要的只是: 获取对选择开始所在的文本节点及其偏移量的引用 获取对选定内容结束的文本节点及其偏移量的引用 到目前为止,我的图层如下所示: var SEL_ABSTR = { get_selection: functi
- 获取对选择开始所在的文本节点及其偏移量的引用
- 获取对选定内容结束的文本节点及其偏移量的引用
var SEL_ABSTR = {
get_selection: function(window_object) {
return window_object.getSelection();
},
get_range: function(selection) {
return (selection.getRangeAt) ? selection.getRangeAt(0) : selection.createRange();
},
get_range_info: function(range, div_ele) {
var first_node, start_offset;
var last_node, end_offset;
if (range.startContainer == div_ele) {
// selections affects the containing div
first_node = div_ele.childNodes[0];
last_node = first_node;
start_offset = 0;
end_offset = first_node.nodeValue.length;
} else if (range.startOffset == range.startContainer.nodeValue.length && range.endOffset == 0) {
// known bug in Firefox
alert('firefox bug');
first_node = range.startContainer.nextSibling.childNodes[0];
last_node = first_node;
start_offset = 0;
end_offset = first_node.nodeValue.length;
} else {
first_node = range.startContainer;
last_node = range.endContainer;
start_offset = range.startOffset;
end_offset = range.endOffset;
}
return {
first_node: first_node,
start_offset: start_offset,
last_node: last_node,
end_offset: end_offset,
orig_diff: end_offset - start_offset
};
},
};
目前我已经发现了两个Mozilla bug:
更具体的细节如下: 这不是对兰吉的批评。所以如果听起来像那样,我很抱歉。我可以想象,处理这些不同的API本身并不容易 你是对的,我没有具体说明我要完成的任务。我的结构相当简单:我有一个div(属性contenteditable=true)和该div中的文本(开头有一个文本节点) 从这个结构开始,现在可以用鼠标选择文本并添加属性;然后,该属性由包含选定文本的范围和指定给该范围的表示选定属性的类表示。现在可以再次选择一些文本和属性。如果它是相同的文本和另一个属性,则将为该范围指定另一个类,如果该属性已存在,则将删除该类。如果选择包含多个跨距的文本,它们将被拆分以表达该结构(也许你还记得我7月份的帖子)
你好,我是
但我也有下划线
也没有颜色
该算法现在在“对称”情况下运行良好:我可以构建一个复杂的结构,然后向后撤销它。它适用于Safari和Chrome。现在我当然要进一步开发算法
但是现在我在Mozilla上遇到了问题,因为我不了解DOM范围对象的系统:startContainer、endContainer、startOffset、endOffset
在我对仅包含textnodes和spans的div的具体情况的看法中,我假设:
- startContainer和endContainer始终指向受鼠标选择影响的textnode(没有空跨距,它们始终包含其他跨距或textnode),标记整个选择的开始和结束
- STARTOFSET和endOffset指示选择在textnode的开头和结尾的位置
非常感谢您的回答。没有规则规定选择边界必须用文本节点表示。考虑元素内的一个选择,该元素只包含“代码> < /Cord>元素”。所以,你在Mozilla中所说的bug根本不是bug;事实上,WebKit的选择处理非常简单。然而,您观察到浏览器在文本节点的结尾处精确地考虑选择边界时所处的位置是有效的,并且会使事情复杂化。解决这个问题的最佳方法实际上取决于你想做什么,而你的问题并不清楚这一点 如果您希望选择边界仅以元素文本内容中的字符偏移量为依据(尽管出于链接答案中列出的原因,我通常不建议这样做) 最后,作为Rangy的作者,我想指出,它基于浏览器实现的相同API(DOM范围和选择),因此我认为它与这些API并不复杂。参考资料:
- (正在进行的工作)
- (由所有主要浏览器的当前版本实现)
- (DOM 2系列的后续产品,正在进行中)
startContainer
进行明确的澄清
var sc = window.getSelection().getRangeAt(0).startContainer;
var an = window.getSelection().anchorNode
var fn = window.getSelection().focusNode
if (sc!==an && sc!==fn) {alert('startContainer bug encountered!');}
可以修改代码来处理这个问题,但是我没有时间为您写出所有代码
下面是我们将使用的方法列表
window.getSelection().getRangeAt(0).startContainer;
window.getSelection().anchorNode
window.getSelection().focusNode
非常重要的一点是要记住,锚点节点并不是通过初始单击明确地位于左起始位置。如果用户单击装备
var sc = window.getSelection().getRangeAt(0).startContainer;
var an = window.getSelection().anchorNode
var fn = window.getSelection().focusNode
if (sc!==an && sc!==fn) {alert('startContainer bug encountered!');}
window.getSelection().getRangeAt(0).startContainer
window.getSelection().getRangeAt(0).startContainer.parentNode
window.getSelection().getRangeAt(0).startContainer.previousSibling
window.getSelection().getRangeAt(0).startContainer.nextSibling
window.getSelection().getRangeAt(0).startContainer.childNodes[]
.nextSibling.firstChild
.nextSibling.firstChild.nodeValue
<em>textNode here</em>
for (i in window.getSelection())
{
document.getElementById('textarea_example').value = document.getElementById('textarea_example').value+'\n'+i;
}
var e1 = scp.nodeName;
if (scp.nextSibling) {var e2 = scp.nextSibling.nodeName;} else {var e2 = 'null';}
var e3 = sc.nodeName;
if (sc.nextSibling) {var e4 = sc.nextSibling.nodeName;} else {var e4 = 'null';}
alert(
'startContainer = '+window.getSelection().getRangeAt(0).startContainer.nodeName
+'\n\n'+
'startContainer = '+window.getSelection().getRangeAt(0).startContainer.nodeValue
+'\n\n'+
e1
+'\n\n'+
e2
+'\n\n'+
e3
+'\n\n'+
e4
+'\n\nanchorNode = '+
window.getSelection().anchorNode.nodeName
+'\n\n'+
window.getSelection().anchorNode.nodeValue
+'\n\nfocusNode = '+
window.getSelection().focusNode.nodeName
+'\n\n'+
window.getSelection().focusNode.nodeValue
);
if (e2=='#text') {alert('e2 = '+scp.nextSibling.nodeValue);}
if (e4=='#text') {alert('e4 = '+scp.nextSibling.nodeValue);}