开发者

Is it possible to get element's numerical index in its parent node without looping?

Normally I'm doing it this way:

for(i=0;i<elem.parentNod开发者_JAVA技巧e.length;i++) {
  if (elem.parentNode[i] == elem) //.... etc.. etc...
}


function getChildIndex(node) {
  return Array.prototype.indexOf.call(node.parentNode.childNodes, node);
}

This seems to work in Opera 11, Firefox 4, Chromium 10. Other browsers untested. It will throw TypeError if node has no parent (add a check for node.parentNode !== undefined if you care about that case).

Of course, Array.prototype.indexOf does still loop, just within the function call. It's impossible to do this without looping.


Note: If you want to obtain the index of a child Element, you can modify the function above by changing childNodes to children.

function getChildElementIndex(node) {
  return Array.prototype.indexOf.call(node.parentNode.children, node);
}


Option #1

You can use the Array.from() method to convert an HTMLCollection of elements to an array. From there, you can use the native .indexOf() method in order to get the index:

function getElementIndex (element) {
  return Array.from(element.parentNode.children).indexOf(element);
}

If you want the node index (as oppose to the element's index), then replace the children property with the childNodes property:

function getNodeIndex (element) {
  return Array.from(element.parentNode.childNodes).indexOf(element);
}

Option #2

You can use the .call() method to invoke the array type's native .indexOf() method. This is how the .index() method is implemented in jQuery if you look at the source code.

function getElementIndex(element) {
  return [].indexOf.call(element.parentNode.children, element);
}

Likewise, using the childNodes property in place of the children property:

function getNodeIndex (element) {
  return [].indexOf.call(element.parentNode.childNodes, element);
}

Option #3

You can also use the spread operator:

function getElementIndex (element) {
  return [...element.parentNode.children].indexOf(element);
}
function getNodeIndex (element) {
  return [...element.parentNode.childNodes].indexOf(element);
}


You could count siblings... The childNodes list includes text and element nodes-

function whichChild(elem){
    var  i= 0;
    while((elem=elem.previousSibling)!=null) ++i;
    return i;
}


There is no way to get the index of a node within its parent without looping in some manner, be that a for-loop, an Array method like indexOf or forEach, or something else. An index-of operation in the DOM is linear-time, not constant-time.

More generally, if list mutations are possible (and the DOM certainly supports mutation), it's generally impossible to provide an index-of operation that runs in constant time. There are two common implementation tactics: linked lists (usually doubly) and arrays. Finding an index using a linked list requires a walk. Finding an index using an array requires a scan. Some engines will cache indexes to reduce time needed to compute node.childNodes[i], but this won't help you if you're searching for a node. Not asking the question is the best policy.


I think you've got it, but:

  • make sure that variable "i" is declared with var
  • use === instead of == in the comparison


If you have a collection input elements with the same name (like <textarea name="text_field[]"…) in your form and you want to get the exact numeric index of the field that triggered an event:

function getElementIdxFromName(elem, parent) {
    var elms = parent[elem.name];
    var  i = 0;
    if (elms.length === undefined) // there is only one element with this name in the document
        return 0;
    while((elem!=elms[i])) i++;
    return i;
}

Getting numeric id of an element from a collection of elements with the same class name:

function getElementIdxFromClass(elem, cl) {
    var elems = document.getElementsByClassName(cl);
    var  i = 0;
    if (elems.length > 0) {
        while((elem!=elems[i])) i++;
        return i;
    }
    return 0;
}


Try this:

let element = document.getElementById("your-element-id");
let indexInParent = Array.prototype.slice.call(element.parentNode.parentNode.children).indexOf(element.parentNode));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜