Find next cell contained in sibling string using querySelector
I am trying to use querySelector
to find the first cell in a NEXT row of a table. So, starting at ROW 1, find the next TR element and then find the first TD child inside that TR element.
However, when I write a CSS selector, it returns null
.
CSS syntax syntax:
"tr.row ~ tr td"
Here's a complete working example:
<!DOCTYPE html>
<html>
<head>
<script>
function findRow()
{
var row1 = document.querySelector("tr.row");
var targetCell = row1.querySelector("tr.row ~ tr td");
alert(targetCell);
}
</script>
</head>
<body>
<table>
<tr class = "row">
<td class = "cell"></td>
</tr>
<tr class = "row">
<td class = "cell"></td>
</tr>
</table>
<script>
findRow();
</script>
</body>
</html>
So the selector ".row1
successfully gives me a TR element with id row1
.
However, the second selector ".row1 ~ tr td"
returns null
.
Now if instead of calling querySelector
with an element, TR
I call document.querySelector
, it works. I can even call row1.parentNode.querySelector
and then it works. This indicates that the actual item being called querySelector
is not in the item set to search.
Unfortunately this is not a solution. This is just a simplified example: in my actual use case, I cannot call querySelector
from the parent element above row1
, because then I will lose the context I am in (in my real use case I have a lot of dynamically generated strings, so if I call document.querySelector
or even row1.parentNode.querySelector
, I will lose my context).
I realize I can just do this with simple DOM looping workarounds, but I'm trying to get used to using it querySelector
here as it is obviously better for the future. (Also, I am not using jQuery here.) I also suspect the selector :scope
will help here, but unfortunately not yet widespread.
So is it possible to do what I want using querySelector
?
source to share
Difficult to use querySelector
. The problem with element.querySelector is that these are leaf nodes only. Better to use something like
var targetCell = row1.nextElementSibling.cells[0];
var row1 = document.querySelector("tr.row"),
targetCell = row1.nextElementSibling.cells[0];
alert(targetCell);
<table>
<tr class="row">
<td class="cell"></td>
</tr>
<tr class="row">
<td class="cell"></td>
</tr>
</table>
If you really want to use it, you can use the :nth-child(k)
parent to reference the k
th element .
var parent = row1.parentElement,
index = [].slice.call(parent.children).indexOf(row1) + 1,
targetCell = parent.querySelector(":nth-child("+index+") ~ tr td");
var row1 = document.querySelector("tr.row"),
parent = row1.parentElement,
index = [].slice.call(parent.children).indexOf(row1) + 1,
targetCell = parent.querySelector(":nth-child("+index+") ~ tr td");
alert(targetCell);
<table>
<tr class="row">
<td class="cell"></td>
</tr>
<tr class="row">
<td class="cell"></td>
</tr>
</table>
source to share
Yes, you can target #cell2
on querySelector
, but you will need to do this with document.querySelector
, and do not element.querySelector
.
The problem with element.querySelector
is that these are only child nodes of targets, hence sibling nodes and their children. From MDN :
Returns the first element that is a descendant of the element it is invoked on that matches the specified selector group.
Here's a script showing the change: http://jsfiddle.net/usho2t63/
var targetCell = document.querySelector("#row1 ~ tr td");
source to share
Since a CSS selector cannot travel to parents, your best approach would be to use DOM methods, as Oriol already answered.
Alternatively, using only querySelector
if you make sure to give each element an ID, you should do something like this:
document.querySelector("#" + row1.getAttribute("id") + " ~ tr td");
to make sure you always target the reference string
source to share