Подтвердить что ты не робот

Возможно ли получить числовой индекс элемента в его родительском node без цикла?

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

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

Ответ 1

Вы можете считать братьев и сестер... Список childNodes включает в себя текстовые узлы и -

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

Ответ 2

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

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

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

Ответ 3

Опция 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);
}

Ответ 4

Я думаю, что у вас есть это, но:

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

Ответ 5

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

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

Ответ 6

Если в вашей форме есть входные элементы коллекции с таким же именем (например, <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;
}

Ответ 7

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

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