Поиск индекса узла DOM

Я хочу найти индекс данного узла DOM. Это как обратное действие

document.getElementById('id_of_element').childNodes[K]

Вместо этого я хочу извлечь значение K, учитывая, что у меня уже есть ссылка на дочерний узел и родительский узел. Как мне это сделать?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
60
0
50 559
7

Ответы 7

Я думаю, что единственный способ сделать это - перебрать потомков родителя, пока не найдешь себя.

var K = -1;
for (var i = myNode.parent.childNodes.length; i >= 0; i--)
{
    if (myNode.parent.childNodes[i] === myNode)
    {
        K = i;
        break;
    }
}

if (K == -1)
    alert('Not found?!');

Ответ Роборга работает ... или вы можете попробовать ...

var k = 0;
while(elem.previousSibling){
    k++;
    elem = elem.previousSibling;
}
alert('I am at index: ' + k);

Разве вы не можете заменить while(elem.previousSibling){k++;elem = elem.previousSibling;} на while(elem=elem.previousSibling){k++;}?

user66001 11.03.2013 06:35

Немного короче, ожидает, что элемент будет в элементе, возвращает k.

for (var k=0,e=elem; e = e.previousSibling; ++k);

После комментария от Джастин Диринг я просмотрел свой ответ и добавил следующее:

Или, если вы предпочитаете «пока»:

var k=0, e=elem;
while (e = e.previousSibling) { ++k;}

Первоначальный вопрос заключался в том, как найти индекс существующего элемента DOM. В обоих моих примерах выше в этом ответе ожидается, что элем будет элементом DOM и что этот элемент все еще существует в DOM. Они потерпят неудачу, если вы дадите им нулевой объект или объект, у которого нет предыдущий. Более надежный способ будет выглядеть примерно так:

var k=-1, e=elem;
while (e) {
    if ( "previousSibling" in e ) {
        e = e.previousSibling;
        k = k + 1;
    } else {
        k= -1;
        break;
    }
}   

Если е - это ноль или если предыдущий отсутствует в одном из объектов, k равно -1.

@some, мне пришлось изменить пример, и похоже, что вам нужно переместить e = e.previousSibling в замешательство цикла for и выполнить нулевую проверку в firefox 3.5.

Justin Dearing 27.08.2009 00:55

@Justin: "e = e.previousSibling" находится посередине ... Цикл for объявляет k = 0 и e = elem. Затем он выполняет e = e.previousSibling до тех пор, пока e === null. Для каждого успешного цикла он увеличивает k на единицу. И это работает в FF3.5.2. Пожалуйста, объясните, что вы считаете неправильным.

some 27.08.2009 22:05

@Justin: Добавил еще несколько примеров.

some 27.08.2009 23:06

some - Если я могу предложить, поскольку выше / ниже являются относительными спецификаторами, вы можете подумать о том, чтобы вставить «Оба приведенных выше примера (1 & 2) ожидают элем» вместо аналогичного текста в вашем ответе, поэтому, если это когда-либо актуально, кто-то знает, о каких двух предыдущих примерах (если я прав) вы говорите.

user66001 08.03.2013 03:07

К вашему сведению, самый быстрый способ сделать это, по-видимому, - использовать цикл for. Источник: jsperf.com/fastest-way-to-get-index-of-element-in-a-nodelist

brunoais 27.04.2013 13:37

@brunoais В примере for вы используете previousElementSibling и получаете результат 24, но в while вы используете previousSibling с результатом 49. Я создал новый прецедент, где они оба используют previousElementSibling, и тогда не так уж много разница больше в моем ограниченном тестировании по крайней мере. На самом деле while был немного быстрее в FF20 на Win7.

some 28.04.2013 07:12

@brunoais, а в IE10 for и while примерно на 40% медленнее, чем indexOf ... Вы получаете элементы в живом HTMLCollection. Преобразуя это в массив вместо Array.prototype.slice.call(main.children,0), который также является самым быстрым в FF20.

some 28.04.2013 07:28

@ user66001 Извините, что я не заметил вашего комментария до сих пор. Собственно, в своем ответе я имел в виду свои собственные примеры, где они находятся над примечанием. Извините, если это было непонятно.

some 28.04.2013 07:34

@brunoais Для справки в будущем: на машинном уровне нет почти никакой разницы между циклом for и циклом while. Если вы сравните две функции, одна из которых использует для, а другая пока, и получите значительную разницу во времени, вы, вероятно, делаете что-то не так.

some 28.04.2013 18:47

@some На самом деле это неверно для любого языка сценариев, потому что перевод в машинный код отличается, и компиляция также может быть другой. «За», подобное тому, что я сделал, можно рассматривать как единый «блок», который распознается внутренними компонентами и уже имеет алгоритмы, оптимизирующие его. Пока это можно рассмотреть в 2 этапа. Создание переменной и время. Итак, в C или java, или C# и т. д. Это точно так же, но для php или javascript это совсем другое.

brunoais 28.04.2013 19:59

@some - НП. Для меня это было непонятно, учитывая, что в начале предложения говорилось об исходном вопросе. Спасибо за разъяснение :)

user66001 29.04.2013 09:49

@some - Спасибо. Намного лучше i.m.o, но, надеюсь, это поможет другим :)

user66001 02.05.2013 23:34

используя фреймворк, такой как прототип, вы можете использовать это:

$(el).up().childElements().indexOf($(el))

Как и в случае с оригинальным плакатом, я пытался

find the index of a given DOM node

но тот, на котором я просто использовал обработчик кликов, и только по отношению к своим братьям и сестрам. Я не смог заставить вышеуказанное работать (несомненно, из-за noobness, я попытался подставить 'this' для elem, но это не сработало).

Мое решение заключалось в использовании jquery и использовании:

var index = $(this).parent().children().index(this);

Он работает без указания типа элемента, например: 'h1', идентификатора и т. д.

Кратчайший путь, без каких-либо фреймворков, во всех версиях Safari, FireFox, Chrome и IE> = 9:

var i = Array.prototype.indexOf.call(e.childNodes, someChildEl);

Тоже был бы мой ответ :) +1!

Van Coding 16.02.2012 21:36

Примечание: замените e.childNodes на e.children, чтобы найти индекс элемента в его родственном элементе элементы - в отличие от родственного элемента узлы, который включает текстовые узлы и узлы комментариев.

Matthew 17.02.2012 06:39

аналогичный пример приведен в MDN: developer.mozilla.org/en-US/docs/DOM/NodeList#Workarounds

Lloyd 21.08.2012 20:12

Почему мы не можем сделать что-то вроде e.parentNode.childNodes.indexOf(e)? Обновлено: я только что это проверил. NodeList не является настоящим Array, поэтому мы должны использовать имплант Array для indexOf через его прототип. Меня удивляет, что ArrayindexOf функционирует на NodeList, и было ли это намеренно или случайно.

Steven Lu 16.01.2013 03:44

@StevenLu Ваш первый вопрос: indexOf в NodeList не определен в спецификации DOM, даже в DOM4. Ваш последний пункт: это предназначено. Методы массива достаточно универсальны, чтобы работать практически с чем угодно, имеющим свойство length.

Matthew 16.01.2013 21:13

@StevenLu Это сделано намеренно. См. ECMA-262, издание 5 стр. 244 (145 в pdf), последнее примечание к разделу 15.4.4.14: «Функция indexOf намеренно общая; она не требует, чтобы ее значение это было объектом Множество. объекты для использования в качестве метода. Возможность успешного применения функции indexOf к объекту хоста зависит от реализации ".

some 28.04.2013 07:43

За счет распределения массива его можно сократить до [].indexOf.call(children, el), если только это не выполняется с заявлением о совместимости браузера (хотя это меня удивит).

JMM 05.05.2016 17:02

В настоящее время можно использовать [... e.childNodes].indexOf(elem).

user2467065 09.06.2016 06:34

@pat Ты мог ... Однако там проблема как в Комментарий JMM.

yckart 11.03.2017 20:34

Итак, вы также можете сделать Array.from(e.childNodes).indexOf(elem)

yckart 11.03.2017 20:43

Обратите внимание, что [].indexOf.call выделяет новый пустой массив, который после этого удаляется. [ ...e.childNodes].indexOf(elem) выделяет весь новый массив дочерним узлам, который затем отбрасывается. Оригинальное решение, напротив, не выделяет явно какие-либо новые данные где-либо, оно применяет существующую функцию к существующим данным.

hijarian 28.07.2017 13:26

Современный нативный подход может включать Array.from(e.children).indexOf(theChild)

Нет поддержки IE, но Edge работает: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Другие вопросы по теме