How to get nested js selectors like td? - javascript

I need to get all selector that match the condition so I can iterate thru it later on. My code does not return any values. Probably syntax is wrong so I would appreciate if you help me (haven't written lots in js).
Here is the html
function restore_hp(){
var percent_restore = document.querySelectorAll("table.table.table-condensed.table-top-spacing > tr > td[2]");
percent_restore.forEach((td)=>{
console.log(td.innerText)
});
}

You are probably looking for td:nth-child(2) at the end of your selector.
Your current td[2] would select such a table cell: <td 2="some-attribute-value">...</td>. Notice that this would be invalid HTML because a) 2 is an invalid attribut identifier (cannot start with a number) and b) even if it in general would be valid syntax it wouldn't be known for HTMLTableCellElement, and thus again, invalid HTML.
2nd issue:
> selects direct children only. tr is not a direct child of your table (it never is, missing tbody is auto-inserted by all browsers).

What you want is something called :nth-child pseudo selector. Learn more from the below link-
https://www.w3schools.com/cssref/sel_nth-child.asp
SO your function may be like-
function restore_hp(){
var percent_restore = document.querySelectorAll("table.table.table-condensed.table-top-spacing tr td:nth-child(2)");
percent_restore.forEach((td)=>{
console.log(td.innerText)
});
}
Codepen: https://codepen.io/ashfaq_haq/pen/WNNOYRR

You can add a HTML class to the elements you want to manipulate and simply query on the class :
...
<tr>
<td>Some text</td>
<td class="my-custom-class">Some other text</td>
</tr>
...
var percent_restore = document.querySelectorAll(".my-custom-class");
percent_restore.forEach((td)=>{
console.log(td.innerText)
});
That way you're not lost in your HTML tree.

Related

Removing <tr> from table without :contains()

Okay,
This may sound easier than it is, I need to use either Javascript or jQuery to remove a <tr> from a table, I don't know what row this <tr> will be, nor do i know which <tr> I will be removing and the only way I can find out which <tr> to remove is from the text inside the child's <td>.
I cannot use the :contains() selector from jQuery as I'm using ajax to get the elements and it just seems broken.
$("td:contains(var)").parent().remove();
just gives me a DOMexception error.
Is there a way I can loop through all the <td>'s in a table and check the text contents of them?
This will check the text of each one:
$('tr').each(function() {
var $tds = $(this).find('td');
$tds.each(function() {
if ($(this).text() === "some text") {
$(this).parent().remove()
}
});
})

How to use each() for all td in tr, except for the last one?

I have a 3 tables that every row have 2 \ 4 \ 6 columns , and the last column contains a edit button.
When I press the edit button, I want all the other td's will turn into a textboxes.
The script:
$(".icon-pencil").click(function () {
var row = $(this).parent('td').parent('tr');
row.find('td').each(function () {
$(this).html("hi");
});
});
a row example:
<tr>
<td>1</td>
<td>
<img src="img/couponimg.png" alt="" />
</td>
<td>1</td>
<td>A coupon for ..</td>
<td><i class="icon-pencil"></i>
</td>
<td><i class="icon-remove"></i>
</td>
</tr>
It works as I want, but it applies the change to all the <td> , and I don't want to change the last one.
How to prevent to affect to the last one?
I recommend event delegation.
$(document).on('click', '.icon-pencil', function () {
$(this).closest('tr').find('td:not(:last)').html("hi");
});
Also,
$('something').each(function() {
$(this).html("hi");
});
is equivalent to
$('something').html("hi");
Try this:
row.find('td').each(function() {
$(this).not('td:last-child').html("hi");
});
Try this and use :not(:nth-last-child(-n+2)) which will EXCLUDE the last 2 columns.
$(".icon-pencil").click(function() {
var row = $(this).closest('tr');
row.find('td:not(:nth-last-child(-n+2))').each(function() {
$(this).html("hi");
});
});
example :
http://jsbin.com/oyUvAhi/2/edit
2 changes :
closest instead of .parent('td').parent('tr')
when finding the TR - select only the relevant TD's for change.
Edit
please read #François Wahl comment - which helps shorten the code :
row.find('td:not(:nth-last-child(-n+2))').html("hi");
Since your HTML is well formed, in this particular situation, the :last CSS selector works nicely, so you can use that. I will give you a more general solution, when the element is not the last node in the parent, or perhaps not even the last node of its type in the parent (:last-of-type).
jQuery objects are collections of elements. The CSS selector usually used to create such a collection is matched on the DOM, but once you have a jQuery object you can manipulate it any way you want. If you want to eliminate the last element, you can do something like this:
var myJQueryObject = $('mySelector');
Array.prototype.splice.call(myJQueryObject, myJQueryObject.length-2, 2); // removed the last two elements
This relies on the fact that jQuery objects are Array-like objects (have a length property and numeric-like keys) and Array.prototype.* methods work on Array-like objects.

Getting total length of an index in each()

I want to get an unknown (changing) # of rows from a table, between the 1st cell and the last 3. I'm using jQuery's each and don't know why $(this).length doesn't give the total length of the index.
jQuery:
$("#parent table:first tr").each(function(i){
var goodlng = $(this).parent().children("tr").length -1; //this works
var badlng = $(this).length -1; //this doesn't! (always == -1)
});
Is the goodlng good practice? it seems like a hack to have to go to parent and then back to children.
Here is a jsfiddle (have console.log()) open.
Example HTML:
<div id="parent">
<table>
<tr>
<td>unwanted 1</td>
</tr>
<tr>
<td>wanted!</td>
</tr>
<tr>
<td>unwanted2</td>
</tr>
</table>
</div>
tl;dr: Why doesn't $(this).length == $(this).parent().children("tr").length inside of an each function. and is there another better way of doing this.
Your question says "cells", but it seems like you're trying to get the number of rows.
If you really want it inside the .each(), you could use the siblings()[docs] method and the andSelf()[docs] method.
$(this).siblings().andSelf().length
But if the rows aren't changing, why do it repetitively?
Or if they are changing, I'd just use the native rows property on the table to get the length.
var table = $("#parent table:first");
table.find('tr').each(function() {
var len = table[0].rows.length;
});
Actually, this $(this).parent().children("tr").length is the correct way of handling things. this, in the context above is a reference to the tr node itself. tr.length = the length of the tr. tr.parent().children("tr"), on the other hand is a list of the node's siblings, so tr.parent().children("tr").length is the number of siblings.
This is the context of EACH element, not all of them. Therefore, this is only ONE tr at a time. That is why the length does not have all the elements.
The each() function is unaware of the collection of elements that it is working on. It is dealing with a single element at all times. Thats why when you go to the parent and ask for all children you get the right answer.
$(this)
simply refers to the current tr element that you are dealing with, not a collection of them.

How can I elegantly select a parent including its set of direct descendents?

I'm working with a mess of HTML markup. In order to get reliable matches I have resorted to explicitly querying a chain of elements using the '>' operator.
For this question I am attempting to select the parent of an explicit chain of descendents.
For example, I'd like to select the table element with class 'toolbar' in the following HTML:
<table class='toolbar'>
<tbody>
<tr>
<td class='button'>
...
</td>
</tr>
</tbody>
</table>
Here is what I've tried:
1. Use 'has'
$("table.toolbar:has(tbody > tr > td.button)")
Here elements are matched even if tbody isn't a direct descendent of table so this doesn't reliably work.
2. Use '>' and parent()
$("table.toolbar > tbody > tr > td.button").parent().parent().parent()
This works but is messy. Also have to make sure the correct number of parent() calls are included.
3. ???
Due to the crap HTML, it is critical that elements are explicitly given in the query as one direct descendent beneath another.
Can anyone please help with the nicest way of doing this? Thanks!
$("table.toolbar > tbody > tr > td.button").closest("table.toolbar")
Still a bit messy but should work.
closest(expr) documentation
$("td.button").parents("table.toolbar")
seems the easiest way.
I think:
$("td.button").closest("table.toolbar")
Updated:
you can use:
$("table.toolbar:has(tbody:has(td.button))")

jQuery: I have a class, I'm iterating it with each. The result is different each turn. How to use the this and access the value?

I'm a beginner and this is my first time encountering problem like this.
I'm iterating a class using the each method provided by jQuery. The page have many class with the same name. So we can expect that it may be 15 iterations.
Each iteration have different value.
$(".book").each(function(n) {
var result = $(this
I have to get the last TD with the value List. So my option is to use
$(".book tbody tr:last")
But I think this thing wouldn't work in the each environment because it won't know which context it is currently processing.
The $(this tbody tr:last) wouldn't work also. How can I devised a selector that will work?
<div class = "book">
<p class = "chapter">
<table>
<tbody>
<tr>
<td>General</td>
<td>
<b>Buck</b>
</td>
</tr>
<tr>
<td>General</td>
<td>List</td>
</tr>
</tbody>
</table>
</p>
</div>
Assuming the HTML you posted there is a single book and there are many others exactly like it, and you want access to the last <tr> in each one of them, this should work:
$('div.book tbody tr:last-child').each(function() {
var value = $(this).find('td').eq(1).text();
});
value would then be "List" with the HTML above, and if you have several <div>s it would iterate as you might expect through the last <tr> of each one of them.
The key here is that we are using last-child instead of simply last. The last documentation says that it will match the last selected element; we don't want that. What we want instead is what last-child describes: Matches all elements that are the last child of their parent. This distinction is important in this particular case as we only want the last child of the particular table we're currently in, we don't want the last result overall.
If you wanted the last <td> in each last <tr>, we could even do this:
$('div.book tbody tr:last-child td:last-child').each(function() {
var value = $(this).text();
});
This selector would select each last child <tr> and select its appropiate last-child <td>. This would be best if you don't care what the value of the first <td> is. If you do then you want to use the first one.
If you're only looping over the tr:last elements, Paolo's answer should work for you. However, if you're need to run more than one query against each div.book, try this instead:
$("div.book").each(function() {
$("tbody tr:last", this).doStuff();
$("p.chapter", this).doOtherStuff();
}
The second argument to the dollar function is the "context node" and defaults to document (i.e. it "searches" the entire DOM).

Categories

Resources