Можно ли получить числовой индекс элемента в его родительском узле без зацикливания? - PullRequest
30 голосов
/ 10 января 2011

Обычно я делаю это так:

for(i=0;i<elem.parentNode.length;i++) {
  if (elem.parentNode[i] == elem) //.... etc.. etc...
}

Ответы [ 7 ]

37 голосов
/ 10 января 2011
function getChildNumber(node) {
  return Array.prototype.indexOf.call(node.parentNode.childNodes, node);
}

Это похоже на работу в Opera 11, Firefox 4, Chromium 10. Другие браузеры не тестировались. Он выдаст TypeError, если у узла нет родителя (добавьте проверку для node.parentNode !== undefined, если вы заботитесь об этом случае).

Конечно, Array.prototype.indexOf по-прежнему зацикливается, только внутри вызова функции. Это невозможно сделать без зацикливания.

22 голосов
/ 10 января 2011

Вы могли бы считать братьев и сестер ... Список дочерних узлов содержит текстовые и узлы элементов-

function whichChild(elem){
    var  i= 0;
    while((elem=elem.previousSibling)!=null) ++i;
    return i;
}
14 голосов
/ 20 февраля 2017

Вариант № 1

Вы можете использовать метод Array.from() для преобразования HTMLCollection элементов в массив. Оттуда вы можете использовать собственный .indexOf() метод для получения индекса:

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

Если вам нужен индекс узла (в отличие от индекса элемента), то замените свойство children на свойство childNodes :

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

Вариант № 2

Вы можете использовать метод .call() , чтобы вызвать собственный метод .indexOf() типа массива. Вот как метод .index() реализован в jQuery, если вы посмотрите на исходный код.

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

Аналогично, используя свойство childNodes вместо свойства children:

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

Вариант № 3

Вы также можете использовать оператор распространения :

function getElementIndex (element) {
  return [...element.parentNode.children].indexOf(element);
}
function getNodeIndex (element) {
  return [...element.parentNode.childNodes].indexOf(element);
}
2 голосов
/ 20 ноября 2011

Нет способа получить индекс узла в его родительском элементе без циклического некоторого подхода, будь то for -петл, Array метод, такой как indexOf или forEach, или что-то другое. Индекс работы в DOM - это линейное время, а не постоянное время.

В более общем случае, если возможны мутации списка (и DOM, безусловно, поддерживает мутацию), обычно невозможно обеспечить операцию индексации, которая выполняется в постоянное время. Существует две распространенные тактики реализации: связанные списки (обычно двойные) и массивы. Поиск индекса с использованием связанного списка требует прогулки. Поиск индекса с использованием массива требует сканирования. Некоторые движки кэшируют индексы, чтобы сократить время, необходимое для вычисления node.childNodes[i], но это не поможет вам, если вы ищете узел. Не задавать вопрос - лучшая политика.

2 голосов
/ 10 января 2011

Я думаю, что вы его получили, но:

  • убедитесь, что переменная "i" объявлена ​​с var
  • , используйте === вместо ==в сравнении
0 голосов
/ 08 апреля 2019

Если в вашей форме есть входные элементы коллекции с таким же именем (например, <textarea name="text_field[]"…), и вы хотите получить точный числовой индекс поля, вызвавшего событие:

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

Получение числового идентификатора элемента из коллекции элементов с одинаковым именем класса :

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;
}
0 голосов
/ 11 июля 2018

Попробуйте это:

let element = document.getElementById("your-element-id");
let indexInParent = Array.prototype.slice.call(element.parentNode.parentNode.children).indexOf(element.parentNode));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...