Javascript 跨浏览器比较文档位置

Javascript 跨浏览器比较文档位置,javascript,internet-explorer-8,shim,dom4,Javascript,Internet Explorer 8,Shim,Dom4,我想实现ComparedDocumentPosition。雷西格做了一个决定。我已经把他的密码整理好了 function compareDocumentPosition(other) { var ret = 0; if (this.contains) { if (this !== other && this.contains(other)) { ret += 16; } if (this !=

我想实现ComparedDocumentPosition。雷西格做了一个决定。我已经把他的密码整理好了

function compareDocumentPosition(other) {
    var ret = 0;
    if (this.contains) {
        if (this !== other && this.contains(other)) {
            ret += 16;
        }
        if (this !== other && other.contains(this)) {
            ret += 8;
        }
        if (this.sourceIndex >= 0 && other.sourceIndex >= 0) {
            if (this.sourceIndex < other.sourceIndex) {
                ret += 4;
            }
            if (this.sourceIndex > other.sourceIndex) {
                ret += 2;
            }
        } else {
            ret += 1;
        }
    } 
    return ret;
}
功能比较文档位置(其他){
var-ret=0;
if(this.contains){
if(this!==other&&this.contains(other)){
ret+=16;
}
如果(this!==other&&other.contains(this)){
ret+=8;
}
如果(this.sourceIndex>=0&&other.sourceIndex>=0){
if(this.sourceIndexother.sourceIndex){
ret+=2;
}
}否则{
ret+=1;
}
} 
返回ret;
}
这适用于
元素
,但不适用于
文本
文档片段
。这是因为IE8没有在这些节点上提供
.sourceIndex
。(它也不提供
。contains
,但我已经解决了这个问题)

如何有效地编写与and相对应的
+=4
+=2

作为额外参考,这两个由DOM4定义为的树顺序定义

如果A和B在同一棵树中,且A按树的顺序排在B之前,则对象A在对象B之前

如果A和B在同一棵树中,且A按树的顺序排在B之后,则对象A在对象B之后

树的顺序是预顺序,深度优先遍历

大多数现代浏览器都实现了这一点(包括IE9)。因此,您只需要在IE8中工作的东西(我不关心IE6/7,但如果它工作得很好的话!)

函数recursivelyWalk(nodes,cb){
对于(var i=0,len=nodes.length;i

我自己写的。我认为这个实现有缺陷,但这是我的其他代码中的一个缺陷。看起来很可靠。

雷诺斯的答案是最好的开始,但不是开箱即用<代码>节点。*
无法找到,并且IE8中没有
.bind

以下是可在Internet Explorer 8中使用的代码:

function recursivelyWalk(nodes, cb) {
    for (var i = 0, len = nodes.length; i < len; i++) {
        var node = nodes[i];
        var ret = cb(node);
        if (ret) {
            return ret;
        }
        if (node.childNodes && node.childNodes.length) {
            var ret = recursivelyWalk(node.childNodes, cb);
            if (ret) {
                return ret;
            }
        }
    }
}

function testNodeForComparePosition(node, other) {
    if (node === other) {
        return true;
    }
}

var DOCUMENT_POSITION_DISCONNECTED = 1;
var DOCUMENT_POSITION_PRECEDING = 2;
var DOCUMENT_POSITION_FOLLOWING = 4;
var DOCUMENT_POSITION_CONTAINS = 8;
var DOCUMENT_POSITION_CONTAINED_BY = 16;

function compareDocumentPosition(thisNode, other) {
    function identifyWhichIsFirst(node) {
        if (node === other) {
            return "other";
        } else if (node === reference) {
            return "reference";
        }
    }

    var reference = thisNode,
        referenceTop = thisNode,
        otherTop = other;

    if (this === other) {
        return 0;
    }
    while (referenceTop.parentNode) {
        referenceTop = referenceTop.parentNode;
    }
    while (otherTop.parentNode) {
        otherTop = otherTop.parentNode;
    }

    if (referenceTop !== otherTop) {
        return DOCUMENT_POSITION_DISCONNECTED;
    }

    var children = reference.childNodes;
    var ret = recursivelyWalk(
        children,
        function(p) {
            (function() {
                var localOther = other;
                return testNodeForComparePosition(localOther, p);
            })();
        }
    );
    if (ret) {
        return DOCUMENT_POSITION_CONTAINED_BY +
            DOCUMENT_POSITION_FOLLOWING;
    }

    var children = other.childNodes;
    var ret = recursivelyWalk(
        children,
        function(p) {
            (function() {
                var localOther = reference;
                return testNodeForComparePosition(localOther, p);
            })();
        }
    );
    if (ret) {
        return DOCUMENT_POSITION_CONTAINS +
            DOCUMENT_POSITION_PRECEDING;
    }

    var ret = recursivelyWalk(
        [referenceTop],
        identifyWhichIsFirst
    );
    if (ret === "other") {
        return DOCUMENT_POSITION_PRECEDING;
    } else {
        return DOCUMENT_POSITION_FOLLOWING;
    }
}

(这就像调用
sourceElement.compareDocumentPosition(elementToTest)

哦,雷诺斯,你太棒了。谢谢你回答我的问题question@TimDown我睡得不够。
function recursivelyWalk(nodes, cb) {
    for (var i = 0, len = nodes.length; i < len; i++) {
        var node = nodes[i];
        var ret = cb(node);
        if (ret) {
            return ret;
        }
        if (node.childNodes && node.childNodes.length) {
            var ret = recursivelyWalk(node.childNodes, cb);
            if (ret) {
                return ret;
            }
        }
    }
}

function testNodeForComparePosition(node, other) {
    if (node === other) {
        return true;
    }
}

var DOCUMENT_POSITION_DISCONNECTED = 1;
var DOCUMENT_POSITION_PRECEDING = 2;
var DOCUMENT_POSITION_FOLLOWING = 4;
var DOCUMENT_POSITION_CONTAINS = 8;
var DOCUMENT_POSITION_CONTAINED_BY = 16;

function compareDocumentPosition(thisNode, other) {
    function identifyWhichIsFirst(node) {
        if (node === other) {
            return "other";
        } else if (node === reference) {
            return "reference";
        }
    }

    var reference = thisNode,
        referenceTop = thisNode,
        otherTop = other;

    if (this === other) {
        return 0;
    }
    while (referenceTop.parentNode) {
        referenceTop = referenceTop.parentNode;
    }
    while (otherTop.parentNode) {
        otherTop = otherTop.parentNode;
    }

    if (referenceTop !== otherTop) {
        return DOCUMENT_POSITION_DISCONNECTED;
    }

    var children = reference.childNodes;
    var ret = recursivelyWalk(
        children,
        function(p) {
            (function() {
                var localOther = other;
                return testNodeForComparePosition(localOther, p);
            })();
        }
    );
    if (ret) {
        return DOCUMENT_POSITION_CONTAINED_BY +
            DOCUMENT_POSITION_FOLLOWING;
    }

    var children = other.childNodes;
    var ret = recursivelyWalk(
        children,
        function(p) {
            (function() {
                var localOther = reference;
                return testNodeForComparePosition(localOther, p);
            })();
        }
    );
    if (ret) {
        return DOCUMENT_POSITION_CONTAINS +
            DOCUMENT_POSITION_PRECEDING;
    }

    var ret = recursivelyWalk(
        [referenceTop],
        identifyWhichIsFirst
    );
    if (ret === "other") {
        return DOCUMENT_POSITION_PRECEDING;
    } else {
        return DOCUMENT_POSITION_FOLLOWING;
    }
}
compareDocumentPosition(sourceElement, elementToTest)