Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/443.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 范围对象:Webkit和基于Mozilla的浏览器之间的差异_Javascript_Webkit_Range_Mozilla - Fatal编程技术网

Javascript 范围对象:Webkit和基于Mozilla的浏览器之间的差异

Javascript 范围对象:Webkit和基于Mozilla的浏览器之间的差异,javascript,webkit,range,mozilla,Javascript,Webkit,Range,Mozilla,目前,我在为基于Mozilla和Webkit的浏览器编写抽象层以使用DOM范围对象(获取和处理用户选择)时遇到了一些困难 我也尝试过看Rangy之类的框架,但这对于我的任务来说似乎太复杂了(我不知道在代码中到底哪里可以找到我需要的信息。如果有人能给我一个提示,我将不胜感激!) 我想要的只是: 获取对选择开始所在的文本节点及其偏移量的引用 获取对选定内容结束的文本节点及其偏移量的引用 到目前为止,我的图层如下所示: var SEL_ABSTR = { get_selection: functi

目前,我在为基于Mozilla和Webkit的浏览器编写抽象层以使用DOM范围对象(获取和处理用户选择)时遇到了一些困难

我也尝试过看Rangy之类的框架,但这对于我的任务来说似乎太复杂了(我不知道在代码中到底哪里可以找到我需要的信息。如果有人能给我一个提示,我将不胜感激!)

我想要的只是:

  • 获取对选择开始所在的文本节点及其偏移量的引用
  • 获取对选定内容结束的文本节点及其偏移量的引用
到目前为止,我的图层如下所示:

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:

  • 有时,当在包含div中选择整个(如果只有一个)文本节点时,我会返回对该div的引用,而不是对文本节点的引用。现在我可以处理它并返回对div的子节点(文本节点)的引用

  • 有时,我会返回对偏移量==previsibling.length的上一个同级的引用,以及对偏移量==0的下一个同级的引用。但正确的参考是在中间。我也能处理这件事

  • 那么Mozilla还有什么呢?Webkit很好用

    我们应该假设DOM范围对象是标准的(我不是说IE,这是另一个任务…)

    欢迎


    更具体的细节如下:

    这不是对兰吉的批评。所以如果听起来像那样,我很抱歉。我可以想象,处理这些不同的API本身并不容易

    你是对的,我没有具体说明我要完成的任务。我的结构相当简单:我有一个div(属性contenteditable=true)和该div中的文本(开头有一个文本节点)

    从这个结构开始,现在可以用鼠标选择文本并添加属性;然后,该属性由包含选定文本的范围和指定给该范围的表示选定属性的类表示。现在可以再次选择一些文本和属性。如果它是相同的文本和另一个属性,则将为该范围指定另一个类,如果该属性已存在,则将删除该类。如果选择包含多个跨距的文本,它们将被拆分以表达该结构(也许你还记得我7月份的帖子)

    
    你好,我是
    但我也有下划线
    也没有颜色
    
    该算法现在在“对称”情况下运行良好:我可以构建一个复杂的结构,然后向后撤销它。它适用于Safari和Chrome。现在我当然要进一步开发算法

    但是现在我在Mozilla上遇到了问题,因为我不了解DOM范围对象的系统:startContainer、endContainer、startOffset、endOffset

    在我对仅包含textnodes和spans的div的具体情况的看法中,我假设:

    • startContainer和endContainer始终指向受鼠标选择影响的textnode(没有空跨距,它们始终包含其他跨距或textnode),标记整个选择的开始和结束
    • STARTOFSET和endOffset指示选择在textnode的开头和结尾的位置
    在上面发布的代码中,我发现了两个Mozilla行为与webkit不同的案例

    因此,如果我知道Mozilla DOM范围的规则,我可以在我的层中对其进行分解,以便webkit和Mozilla的行为相同


    非常感谢您的回答。

    没有规则规定选择边界必须用文本节点表示。考虑元素内的一个选择,该元素只包含“代码> < /Cord>元素”。所以,你在Mozilla中所说的bug根本不是bug;事实上,WebKit的选择处理非常简单。然而,您观察到浏览器在文本节点的结尾处精确地考虑选择边界时所处的位置是有效的,并且会使事情复杂化。解决这个问题的最佳方法实际上取决于你想做什么,而你的问题并不清楚这一点

    如果您希望选择边界仅以元素文本内容中的字符偏移量为依据(尽管出于链接答案中列出的原因,我通常不建议这样做)

    最后,作为Rangy的作者,我想指出,它基于浏览器实现的相同API(DOM范围和选择),因此我认为它与这些API并不复杂。参考资料:

    • (正在进行的工作)
    • (由所有主要浏览器的当前版本实现)
    • (DOM 2系列的后续产品,正在进行中)

    您注意到一个错误,Gecko/Firefox和Presto/Opera错误地选择了鼠标光标单击的节点,但没有选择。等等,什么?发生的情况是,如果点击注册的字符少于一半(虽然大于0像素),它不会被视觉选择,但是Firefox和Opera仍然选择节点本身!Trident/IE和WebKit(Chrome/Safari)不会这样做

    我已经与这个bug斗争了一段时间,在Mozilla上提交了一个bug(我不记得从去年开始我是否在Opera上这么做了),今天终于直接写信给DOM4规范的编辑,要求他们对浏览器供应商如何定义
    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);}