JavaScript DOM:在容器中查找元素索引
我需要通过对象引用在其容器内find元素的索引。 奇怪的是,我找不到一个简单的方法。 没有jQuery请 – 只有DOM。
UL LI LI LI - my index is 2 LI
是的,我可以为每个元素分配ID,并遍历所有节点来匹配ID,但这似乎是一个不好的解决scheme。 没有更好的东西吗?
所以,说我有一个对象引用第三个LI,如上面的例子。 我怎么知道它是索引2?
谢谢。
你可以使用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想要包含非空文本节点和其他节点types以及元素。 从现在的问题来看,这是否是一个有效的假设呢?
假设你只想要元素索引,那么previousElementSibling
现在可以得到很好的支持(在2012年情况并非如此),而且现在是明显的select。 以下(与其他一些答案相同)将在除IE <= 8之外的所有主要内容中工作。
function 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; }
你可以用它来find一个元素的索引:
Array.prototype.indexOf.call(yourUl, yourLi)
这例如logging所有的指标:
var lis = yourList.getElementsByTagName('li'); for(var i = 0; i < lis.length; i++) { console.log(Array.prototype.indexOf.call(lis, lis[i])); }
的jsfiddle
对于只是元素,这可以用来find它的兄弟元素中的一个元素的索引:
function getElIndex(el) { for (var i = 0; el = el.previousElementSibling; i++); return i; }
请注意,IE <9中不支持previousElementSibling
。
Array.prototype.indexOf.call(this.parentElement.children, this);
或者使用let
语句。
从HTMLCollection创build数组的一个示例
<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>
另一个例子只是使用基本的循环和索引检查
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; }
运行示例
的jsfiddle
只需将对象引用传递给以下函数,即可获得索引
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); } } } } }
如果你想写这个紧凑的所有你需要的是:
var i = 0; for (;yourElement.parentNode[i]!==yourElement;i++){} indexOfYourElement = i;
我们只是遍历父节点中的元素,当我们find你的元素时停下来。
你也可以轻松做到:
for (;yourElement.parentNode.getElementsByTagName("li")[i]!==yourElement;i++){}
如果这只是你想要通过。
您可以遍历<ul>
的<li>
,并在find正确的时候停止。
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; } } }
演示