Determine absolute or global z-index?

2019-05-11 12:44发布

OK guys, here's a tricky one (perhaps): is there any to get a sort of "global z-index" of an element? here is an example of what i'd like to do:

given two element references, how would you determine which one is hiher in the z order (given that they may not have assigned z-indices or are in separated containers)

Elaborate hacks welcome! Not-so elaborate methods more than welcome.

1条回答
Root(大扎)
2楼-- · 2019-05-11 13:07

This was an interesting problem. The following code may not be bug free. I just put it together right now and haven't tested it entirely. Its purpose is to demonstrate an approach.

It compares two elements and tests them on three criteria:

  • Looking through the ancestor tree of each element, if the first ancestor for element A to have a z-index has a greater z-index than the first ancestor of element B to have a z-index (if one exists for element B at all), then element A is higher in the z-order.

  • Otherwise, if element B is a descendent of element A then element B has a higher z-order.

  • Otherwise, looking at the siblings of the last ancestor that element A and element B had in common, if an ancestor of element A comes first in the array of children of that common ancestor then element B has a higher z order.

There may be an simpler way of describing of the logic above and the algorithm can be improved. (For example, the second check above could be done first.) However, here's the code:

<html>
<head>
<script language="javascript">

function getAncestorsAsArray(element){
    var arr = new Array();
    arr.unshift(element);
    while (arr[0].parentNode){
        arr.unshift(arr[0].parentNode);
    }

    return arr;
}

function highestInitialZIndex(elementArr){
    for (var i=0; i<elementArr.length; i++){
        if (elementArr[i].style == undefined) continue;
        var r = elementArr[i].style.zIndex;
        if (!isNaN(r) && r!="") {
            return r;
        }
    }

    return undefined;
}

function findCommonAncestor(elementArr1, elementArr2){
    var commonAncestor;
    for (var i=0; i<elementArr1.length; i++){
        if (elementArr1[i] == elementArr2[i]) {
            commonAncestor = elementArr1[i];
        }
    }

    return commonAncestor;
}

function findHighestAbsoluteIndex(element1, element2){
    var arr1 = getAncestorsAsArray(element1);
    var arr2 = getAncestorsAsArray(element2);

    // Does an ancestor of one elment simply have a higher z-index?
    var arr1Z = highestInitialZIndex(arr1);
    var arr2Z = highestInitialZIndex(arr2);
    if (arr1Z > arr2Z || (!isNaN(arr1Z) && isNaN(arr2Z))) return element1;
    if (arr2Z > arr1Z || (!isNaN(arr2Z) && isNaN(arr1Z))) return element2;

    // Is one element a descendent of the other?
    var commonAncestor = findCommonAncestor(arr1, arr2);
    if (commonAncestor == element1) return element2;
    if (commonAncestor == element2) return element1;

    // OK, which has the oldest common sibling? (Greater index of child node for an element = "older" child)
    var indexOfCommonAncestor;
    for (var i=0; i<arr1.length; i++){
        if (arr1[i] == commonAncestor) {
            indexOfCommonAncestor = i;
            break;
        }
    }

    for (var j=commonAncestor.childNodes.length; j>=0; j--){
        if (arr1[indexOfCommonAncestor+1] == commonAncestor.childNodes[j]) return element1;
        if (arr2[indexOfCommonAncestor+1] == commonAncestor.childNodes[j]) return element2;
    }   
}

function doTest(){
    var e1 = document.getElementById("myDiv1");
    var e2 = document.getElementById("myDiv2");

    highest = findHighestAbsoluteIndex(e1, e2);
    alert(highest.id);
}

</script>

</head>
<body onload="javascript:doTest();">

<div>
<div>
<div style="position:absolute; z-index:20;" id="myDiv1">
</div>
</div>
</div>

<div>
</div>

<div style="position:absolute; z-index:10;" id="myDiv2">
</div>

</body>
</html>

Play around with the nested divs in the body to test it working.

查看更多
登录 后发表回答