Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cross browser compare document position

DOM4 compareDocumentPosition

I want to implement compareDocumentPosition. Resig has made a great start at doing just this. I've taken his code and neatened it up

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;
}

This works for Element but does not for Text or DocumentFragment. This is because IE8 does not give .sourceIndex on those nodes. (It doesn't give .contains either but I've fixed that problem already)

How do I efficiently write the +=4 and +=2 bit which correspond to DOCUMENT_POSITION_FOLLOWING and DOCUMENT_POSITION_PRECEDING.

For extra reference those two are defined by tree-order which DOM4 defines as

An object A is preceding an object B if A and B are in the same tree and A comes before B in tree order.

An object A is following an object B if A and B are in the same tree and A comes after B in tree order.

The tree order is preorder, depth-first traversal.

Most modern browsers implement this (including IE9). So you only need something that works in IE8 (I don't care about IE6/7, but if it works awesome!)

like image 247
Raynos Avatar asked Nov 30 '11 23:11

Raynos


People also ask

What is meant by cross browser compatibility?

Cross-browser compatibility is the ability of a website or web application to function across different browsers and degrade gracefully when browser features are absent or lacking.

What is a cross browser bug?

Cross browser compatibility issues is when your website doesn't display or function as intended across different browsers or browser versions.

What is cross browser web development?

Introduction. Cross-browser development is making a web page look and behave the same on different desktop and mobile browsers. Five years ago, this was a real challenge for front-end developers. Thankfully, it's has gotten much easier now with the support for modern CSS tools like Grid and Flexbox.


1 Answers

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;
    }
}

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

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

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

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

    var children = reference.childNodes;
    var ret = recursivelyWalk(
        children,
        testNodeForComparePosition.bind(null, other)
    );
    if (ret) {
        return Node.DOCUMENT_POSITION_CONTAINED_BY +
            Node.DOCUMENT_POSITION_FOLLOWING;
    }

    var children = other.childNodes;
    var ret = recursivelyWalk(
        children, 
        testNodeForComparePosition.bind(null, reference)
    );
    if (ret) {
        return Node.DOCUMENT_POSITION_CONTAINS +
            Node.DOCUMENT_POSITION_PRECEDING;
    }

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

I wrote it myself. I thought this implementation was bugged but it was a bug in some other code of mine. Seems pretty solid.

like image 113
Raynos Avatar answered Oct 16 '22 05:10

Raynos