Обычно я делаю так:
for(i=0;i<elem.parentNode.length;i++) {
if (elem.parentNode[i] == elem) //.... etc.. etc...
}
Обычно я делаю так:
for(i=0;i<elem.parentNode.length;i++) {
if (elem.parentNode[i] == elem) //.... etc.. etc...
}
Вы можете считать братьев и сестер... Список childNodes включает в себя текстовые узлы и -
function whichChild(elem){
var i= 0;
while((elem=elem.previousSibling)!=null) ++i;
return i;
}
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
выполняет цикл, только внутри вызова функции. Это невозможно сделать без цикла.
Вы можете использовать метод 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);
}
Вы можете использовать метод .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);
}
Вы также можете использовать оператор распространения:
function getElementIndex (element) {
return [...element.parentNode.children].indexOf(element);
}
function getNodeIndex (element) {
return [...element.parentNode.childNodes].indexOf(element);
}
Я думаю, что у вас есть это, но:
var
===
вместо ==
в сравненииНевозможно получить индекс node внутри своего родителя без какого-либо цикла, будь то for
-loop, Array
, например indexOf
или forEach
, или что-то еще остальное. Индекс-операция в DOM является линейным, а не постоянным.
В более общем плане, если возможны мутации списка (и DOM, безусловно, поддерживает мутацию), как правило, невозможно обеспечить индекс-операцию, которая выполняется в постоянное время. Существуют две общие тактики реализации: связанные списки (обычно вдвое) и массивы. Поиск индекса с помощью связанного списка требует прогулок. Поиск индекса с использованием массива требует сканирования. Некоторые двигатели будут кэшировать индексы, чтобы сократить время, необходимое для вычисления node.childNodes[i]
, но это не поможет вам, если вы ищете node. Не задавать вопрос - это лучшая политика.
Если в вашей форме есть входные элементы коллекции с таким же именем (например, <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;
}
Попробуй это:
let element = document.getElementById("your-element-id");
let indexInParent = Array.prototype.slice.call(element.parentNode.parentNode.children).indexOf(element.parentNode));