JavaScript DOM: найти индекс элемента в контейнере
Мне нужно найти индекс элемента внутри его контейнера по ссылке на объект. Как ни странно, я не могу найти легкий путь. Нет jQuery пожалуйста-только дом.
UL
LI
LI
LI - my index is 2
LI
Да, я мог бы назначить идентификаторы каждому элементу и перебирать все узлы, чтобы соответствовать идентификатору, но это кажется плохим решением. Разве нет чего-нибудь получше?
Итак, скажем, у меня есть ссылка на объект третьего LI, как в примере выше. Как узнать, что это индекс 2?
спасибо.
12 ответов:
вы могли бы использовать
Array.prototype.indexOf. Для этого нам нужно несколько "бросить"HTMLNodeCollectionистинноArray. Например:var nodes = Array.prototype.slice.call( document.getElementById('list').children );тогда мы могли бы просто позвонить:
nodes.indexOf( liNodeReference );пример:
var nodes = Array.prototype.slice.call( document.getElementById('list').children ), liRef = document.getElementsByClassName('match')[0]; console.log( nodes.indexOf( liRef ) );<ul id="list"> <li>foo</li> <li class="match">bar</li> <li>baz</li> </ul>
обновление 2017
исходный ответ ниже предполагает, что OP хочет включить непустой текстовый узел и другие типы узлов, а также элементы. Теперь мне не кажется ясным из вопроса, Является ли это допустимым предположением.
предполагая, что вместо этого вы просто хотите индекс элемента,
previousElementSiblingтеперь хорошо поддерживается (чего не было в 2012 году) и является очевидным выбором сейчас. Следующее (что совпадает с некоторыми другими ответами здесь) будет работать во всем главном, кроме IEfunction getElementIndex(node) { var index = 0; while ( (node = node.previousElementSibling) ) { index++; } return index; }оригинальный ответ
просто использовать
previousSiblingдоnull. Я предполагаю, что вы хотите игнорировать только текстовые узлы с пробелами; если вы хотите фильтровать другие узлы, то соответствующим образом отрегулируйте.function getNodeIndex(node) { var index = 0; while ( (node = node.previousSibling) ) { if (node.nodeType != 3 || !/^\s*$/.test(node.data)) { index++; } } return index; }
Вы можете использовать это, чтобы найти индекс элемента:
Array.prototype.indexOf.call(yourUl, yourLi)Это например регистрирует все показатели:
var lis = yourList.getElementsByTagName('li'); for(var i = 0; i < lis.length; i++) { console.log(Array.prototype.indexOf.call(lis, lis[i])); }
только для элементов это может быть использовано, чтобы найти индекс элемента среди его родственных элементов:
function getElIndex(el) { for (var i = 0; el = el.previousElementSibling; i++); return i; }отметим, что
previousElementSiblingНе поддерживается в IE
вот как я делаю (версия 2018 ?):
const index = [...el.parentElement.children].indexOf(el);Тадаааам. И, если вы когда-нибудь захотите рассмотреть необработанные текстовые узлы, вы можете сделать это вместо этого :
const index = [...el.parentElement.childNodes].indexOf(el);я распространяю детей в массив, поскольку они являются HTMLCollection (таким образом, они не работают с indexOf).
будьте осторожны, что вы используете Babel или что покрытие браузера достаточно для того, что вам нужно достичь (размышления о операторе распространения, который в основном является Матрица.из-за кулис).
пример создания массива из HTMLCollection
<ul id="myList"> <li>0</li> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <script> var tagList = []; var ulList = document.getElementById("myList"); var tags = ulList.getElementsByTagName("li"); //Dump elements into Array while( tagList.length != tags.length){ tagList.push(tags[tagList.length]) }; tagList.forEach(function(item){ item.addEventListener("click", function (event){ console.log(tagList.indexOf( event.target || event.srcElement)); }); }); </script>
Если вы хотите написать это компактно все, что вам нужно:
var i = 0; for (;yourElement.parentNode[i]!==yourElement;i++){} indexOfYourElement = i;мы просто перебираем элементы в Родительском узле, останавливаясь, когда находим ваш элемент.
вы также можете легко сделать:for (;yourElement.parentNode.getElementsByTagName("li")[i]!==yourElement;i++){}если это все, что вы хотите просмотреть.
вы можете перебирать
<li>s в<ul>и остановитесь, когда найдете правильный.function getIndex(li) { var lis = li.parentNode.getElementsByTagName('li'); for (var i = 0, len = lis.length; i < len; i++) { if (li === lis[i]) { return i; } } }
современный собственный подход может использовать ' массив.из ()', например: `
const el = document.getElementById('get-this-index') const index = Array.from(document.querySelectorAll('li')).indexOf(el) document.querySelector('h2').textContent = `index = ${index}`<ul> <li>zero <li>one <li id='get-this-index'>two <li>three </ul> <h2></h2>'
другой пример просто с помощью базового цикла и проверки индекса
HTML
<ul id="foo"> <li>0</li> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>JavaScriptзапускает onload / ready или после визуализации ul
var list = document.getElementById("foo"), items = list.getElementsByTagName("li"); list.onclick = function(e) { var evt = e || window.event, src = evt.target || evt.srcElement; var myIndex = findIndex(src); alert(myIndex); }; function findIndex( elem ) { var i, len = items.length; for(i=0; i<len; i++) { if (items[i]===elem) { return i; } } return -1; }Пример Работает
просто передайте ссылку на объект следующей функции, и вы получите индекс
function thisindex(elm) { var the_li = elm; var the_ul = elm.parentNode; var li_list = the_ul.childNodes; var count = 0; // Tracks the index of LI nodes // Step through all the child nodes of the UL for( var i = 0; i < li_list.length; i++ ) { var node = li_list.item(i); if( node ) { // Check to see if the node is a LI if( node.nodeName == "LI" ) { // Increment the count of LI nodes count++; // Check to see if this node is the one passed in if( the_li == node ) { // If so, alert the current count alert(count-1); } } } } }
Comments