获取从节点到另一个节点的DOM路径

时间:2015-10-27 12:57:11

标签: javascript dom path

我需要一种方法,将两个节点(node1node2)作为参数,从node2返回导致node1的最小路径。 理想情况下,它返回一个节点数组,但目前它对一个字符串是可以的。例如:

        P
      /   \
  #text    U
         /   \
        B     I
        |     |
     #text   #text

function foo(node1, node2) {
    ...
}

当我以这种方式运行时,例如在节点P(根)和B上运行:

var res = foo(P, B);
console.log(res);

我获得:

res = Array[3] {
    0: P (class=..., id=...)
    1: U (class=..., id=...)
    2: B (class=..., id=...)
}

或者,以字符串的形式:

res = "P(class=..., id=...) > U(class=..., id=...) > B(class=..., id=...)";

如果节点具有属性(例如idclass),则返回那些(如示例中所示)。 我搜索了类似的东西的互联网方法,但我发现只有方法返回整个文档的完整路径而不是两个节点之间。 例如,我试过这个方法对我不起作用,因为它返回单个节点的完整路径。

function getDomPath(el) {
  var stack = [];
  while ( el.parentNode != null ) {
    console.log(el.nodeName);
    var sibCount = 0;
    var sibIndex = 0;
    for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
      var sib = el.parentNode.childNodes[i];
      if ( sib.nodeName == el.nodeName ) {
        if ( sib === el ) {
          sibIndex = sibCount;
        }
        sibCount++;
      }
    }
    if ( el.hasAttribute('id') && el.id != '' ) {
      stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
    } else if ( sibCount > 1 ) {
      stack.unshift(el.nodeName.toLowerCase() + ':eq(' + sibIndex + ')');
    } else {
      stack.unshift(el.nodeName.toLowerCase());
    }
    el = el.parentNode;
  }

  return stack.slice(1); // removes the html element
}

另一件事,我会使用纯JavaScript,没有jQuery。 我不知道如何做我需要的,非常感谢你的帮助。

谢谢

1 个答案:

答案 0 :(得分:0)

<!DOCTYPE html>

<html>
<script>

window.onload = function() {
    console.log(min_path(
        document.getElementById("4"),
        document.getElementById("9")
    ));
};

function min_path(node1, node2) {
    if(node1 === node2) {
        return node1;
    }

    var node_1_ancestors = get_ancestors(node1);
    var node_2_ancestors = get_ancestors(node2);

    var divergent_index = 0;
    while(node_1_ancestors[divergent_index] === node_2_ancestors[divergent_index]) {
        divergent_index++;
    }

    var path = [];
    for(var i = node_1_ancestors.length - 1; i >= divergent_index - 1; i--) {
        path.push(node_1_ancestors[i]);
    }
    for(var i = divergent_index; i < node_2_ancestors.length; i++) {
        path.push(node_2_ancestors[i]);
    }

    return path;
}

function get_ancestors(node) {
    var ancestors = [node];
    while(ancestors[0] !== null) {
        ancestors.unshift(ancestors[0].parentElement);
    }
    return ancestors;
}

</script>
</head>
<body>
<div id="0">
    <div id="1">
        <div id="2">
            <span id="3"></span>
            <span id="4">node1</span>
        </div>
        <div id="5">
            <p id="6"></p>
            <span id="7">
                <div id="8">
                    <div id="9">node2</div>
                    <div id="10"></div>
                </div>
            </span>
        </div>  
    </div>
    <div id="11"></div>
</div>
</body>
</html>

编辑:当节点相等时,它会进入无限循环,所以我添加了一个检查。