I want to find the index of the child div that has the id \'whereami\'
.
-
I added two tests to the jsPerf test. Both use previousElementSibling
, but the second includes compatibility code for IE8 and lower.
Both of them perform extremely well in modern browsers (which is most browsers in use today), but will take a small hit in older browsers.
Here's the first one that doesn't include the compatibility fix. It'll work in IE9 and higher, as well as pretty much all of Firefox, Chrome and Safari.
function findRow6(node) {
var i = 1;
while (node = node.previousElementSibling)
++i;
return i;
}
Here's the version with the compatibility fix.
function findRow7(node) {
var i = 1,
prev;
while (true)
if (prev = node.previousElementSibling) {
node = prev;
++i;
} else if (node = node.previousSibling) {
if (node.nodeType === 1) {
++i;
}
} else break;
return i;
}
Because it automatically grabs element siblings, there's no test needed for nodeType
, and the loop is shorter overall. This explains the large performance increase.
I also added one last version that loops the .children
, and compares the node
to each one.
This isn't quite as fast as the previousElementSibling
versions, but is still faster than the others (at least in Firefox).
function findRow8(node) {
var children = node.parentNode.children,
i = 0,
len = children.length;
for( ; i < len && children[i] !== node; i++)
; // <-- empty statement
return i === len ? -1 : i;
}
Going back to the previousElementSibling
version, here's a tweak that may bump up the performance just a bit.
function findRow9(node) {
var i = 1,
prev = node.previousElementSibling;
if (prev) {
do ++i;
while (prev = prev.previousElementSibling);
} else {
while (node = node.previousSibling) {
if (node.nodeType === 1) {
++i;
}
}
}
return i;
}
I haven't tested it in the jsPerf, but breaking it out into two different loops based on the presence of a previouselementSibling
would only help I would think.
Maybe I'll add it in a bit.
I went ahead and added it to the test linked at the top of this answer. It does help a little bit, so I think it's probably worth doing.
讨论(0)
-
A little improvement over Jack's solution, 3% improvement. Little weird indeed.
function findRow5(node)
{
var i = 2;
while (node = node.previousSibling)
i += node.nodeType ^ 3;
return i >> 1;
}
As there are only two possible nodeType
s in this case (and in most cases):
Node.ELEMENT_NODE == 1
Node.TEXT_NODE == 3
So xor 3 with nodeType
, will give 2
and 0
.
http://jsperf.com/sibling-index/4
讨论(0)
-
Try this:
function findRow(node) {
var i = 1;
while ((node = node.previousSibling) != null) {
if (node.nodeType === 1) i++;
}
return i; //Returns 3
}
讨论(0)
-
Year 2020 - A solution if you're using Tables - Clean Vanilla JS approach
Credit goes to: Alain Cruz
Source: https://stackoverflow.com/a/58845058/3626361 (leave him an Up vote if it helped you)
Question: How to return the row and column index of a table cell by clicking?
const cells = document.querySelectorAll('td');
cells.forEach(cell => {
cell.addEventListener('click', () =>
console.log("Row index: " + cell.closest('tr').rowIndex + " | Column index: " + cell.cellIndex));
});
<table>
<tr>
<td>0:0</td>
<td>0:1</td>
<td>0:2</td>
<td>0:3</td>
</tr>
<tr>
<td>1:0</td>
<td>1:1</td>
<td>1:2</td>
<td>1:3</td>
</tr>
<tr>
<td>2:0</td>
<td>2:1</td>
<td>2:2</td>
<td>2:3</td>
</tr>
</table>
Cheers! Stefano
讨论(0)
-
By co-opting Array
indexOf
you could use :
var wmi = document.getElementById ('whereami');
index = [].indexOf.call (wmi.parentNode.children, wmi);
[Tested on Chrome browser only]
讨论(0)
-
Generally speaking, a small difference in performance has a negligible effect unless the code is run in a loop. Having to run the code once instead of every time will be significantly faster.
Do something like this once:
var par = document.getElementById('parent');
var childs = par.getElementsByTagName('*');
for (var i=0, len = childs.length;i < len;i++){
childs[i].index = i;
}
Subsequently finding the index is as easy as:
document.getElementById('findme').index
It sounds like whatever you're doing could be benefited by having a cleaner relationship between the DOM and the javascript. Consider learning Backbone.js, a small javascript MVC library which makes web applications much easier to control.
edit: I've removed the jQuery I used. I do normally avoid using it, but there's quite a preference for it on SO, so I assumed it would end up being used anyway. Here you can see the obvious difference: http://jsperf.com/sibling-index/8
讨论(0)