I've been struggling with this for a while, and have tried many searches, but haven't found the right solution, nor words for the issue I have.
I wish to traverse the <tr>'s in <table id="Listeners"> with jQuery, and set the rows to either Even or Odd class.
The is yet saved in a variable and passed to the function, as follows:
<table id="Listeners">
<tr><td>1</td></tr>
<tr><td>2</td></tr>
</table>
And my jQuery:
var Element = $("#Listeners");
$(Element+" tr").each(function(index) {
if (index%2 == 0) {
$(this).addClass("Even");
}
});
But that doesn't work, any thoughts on how to solve this?
You can use find() method and :even selector:
Selects even elements, zero-indexed.
var $element = $("#Listeners");
$element.find("tr:even").addClass("Even");
// or $element.find("tr").filter(':even').addClass("Even")
There are many ways to do this. This should work:
$('#Listeners tr:nth-child(even)').addClass("Even");
See: http://api.jquery.com/nth-child-selector/
Even this:
$('#Listeners tr:even').addClass("Even");
See it working here: http://jsfiddle.net/zm2nN/
Related
I tried using this statement:
$("td", calendar).getElementsByClassName("today")
but I kept getting the error that getElementsByClassName is not a function.
$("td", calendar)
gives back an array of "td"'s. Is it possible to access the "today" "td" only using one line, or is a some kind of iteration necessary?
jQuery is a wrapper for DOM elements and has its own helper functions.
To filter a collection of elements, use .filter like so:
$( 'td', calendar ).filter( '.today' );
If you are only going to use tds with the today class, then it is better to alter your selector:
$( 'td.today', calendar );
You could achieve this with built in JS functions as well, like this
const tdCollection = document.querySelectorAll( 'td.today' );
console.log( tdCollection );
<table>
<tr>
<td>yesterday</td>
<td class="today">today</td>
<td>tomorrow</td>
</tr>
</table>
You are mixing vanilla Javascript with jQuery.
Javascript
var x = document.getElementsByClassName("today")
this returns all elements with this classname in an array
jQuery
var x = $('.today');
when selecting an element with jquery you need to prepend a "#" for ids and a "." for classes
good luck and have fun learning javascript :)
[EDIT] Sorry, apparently I over read the real problem here. In your specific case you would best go with a solution similar to what #lumio suggested in his answer.
Apologies if this is a duplicate. It probably is, but I've searched for this specific question and haven't been able to find it.
Let's say I have HTML like so:
<tr>
<td>
<input id="hello">
</td>
<td>
Hello
</td>
</tr>
Using JQuery or Javascript, I want to select the <tr> that contains an input with id="hello".
Here's my attempt so far:
var id = "hello";
var tr = $("tr:has('#" + id + "')");
However, this neither searches for inputs specifically nor seems to work. If you can shed some light on this I'd be very grateful.
Jasper, as haxxxton mentioned in the comments, the .closest() jQuery method is the quickest and simplest method to acheive this.
$('#hello').closest('tr');
$('input[id="hello"]').closest('tr'); // more efficient method than escaping dots if say, your id attribute had periods.
This can be done using the parents() method:
var tr = $('#hello').parents('tr');
Take a look at JQuery's closest() method here.
It traverses up the DOM tree (starting at the current element) until it hits a element which matches the given selector.
Example for your case:
$("#hello").closest("tr")
You can try to get the element by id and then closest() the parent of that element. This seems to be the prefered way in the documentation. Be aware that there can only be one id per page.
Here's an example and a link to the documentation:
var yourElement = $("#hello").closest("tr");
If you browse through the documentation you will find multiple ways of achieving the same result. Hope it helps.
This question is the root cause for my question.
Hide all next tr td until next tr th
As already two answers being posted , I thought of trying something different
Javascript:
$(function(){
var thList = $('td');
$('td').click(function(){
for( i =0; i < thList.length;i++){
// What to do here
}
});
});
HTML:
<table border="2">
<tr>
<td> 1 </td>
<td> 2 </td>
<td> 3 </td>
</tr>
<table>
What am doing here is
Assigning click event to <TH> element. And on load , am getting all the <TH> in the DOM in an Array.
Now, my logic is. Iterate the for loop and if the clicked TH is not the one in the for loop, then hide it.
What i tried is
if ( thList[i] != $(this)) { thList[i].style.display = 'none' }
But this does not seem to be working. what code I need to put there to compare the object
Besides the fact, that you example markup does not contain any th-elements, you could try the following:
$('td').click(function(){
var $tdList = $('td').not(this); // <- get all th's and exlude the clicked element
$tdList.each(function(){this.style.display = 'none'; });
});
or even better, use jQuery, you don't need a each wrapper then:
$tdList.hide();
Since jQuery saves you a lot of work, try to use it whenever you can - use the each() instead of for-loops and use .css() (or even more dedicated methods like .hide()) instead of the native .style - this should shorten your code significantly.
You can use:
thList.click(function() {
thList.not(this).css("display", "none");
});
For performance reason you could delegate the event instead:
$("#yourtable").on("click", "th", function(event) {
thList.not(event.target).css("display", "none");
});
I didn't test it, but should works.
However I'm curious about the UI: if the TH are hidden in this way, they can't be displayed anymore after the first click of any of them.
1-You $(this) is diferent of this once is a jquery object
2-You dont have a TH element here is the code similar that you want but whit td's
$(function(){
var tdList = $('td');
$('td').click(function(){
tdList.hide();
$(this).show();
//OR tdList.not(this).hide();
});
});
When you are accessing the items in a jQuery object, you get them as DOM elements, not as new jQuery objects. So, you should compare it to the element reference directly, not wrap the element reference in a jQuery object:
for (i = 0; i < thList.length; i++) {
if ( thList[i] != this) { thList[i].style.display = 'none' }
}
You can also use the not method to get a collection without the current element:
thList.not(this).each(function(){ this.style.display = 'none'; });
Of course, using the css method it becomes even simpler:
thList.not(this).css('display', 'none');
Word of caution: The cells in tables are not really separate elements that you can just hide without affecting the other cells in the table. The table can show unexpected behaviour when you hide cells in it.
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.
I'm looking to grab a group of tables that have more than X rows with jQuery. Currently, I'm doing something similar to:
$("table").each(function(){
if($(this).find("tr").length > x){
tableArray[tableArray.length] = $(this);
}
});
and then acting on the members of the tableArray.
Is there a better way of getting these tables, perhaps a nice selector I've missed?
Thanks
Try using the :has selector:
$('table:has(tr:eq('+x+'))');
That would only grab tables that have a row x. Note that :eq() takes a zero-based index as its parameter, meaning if x is 1, tables containing 2 rows or more would be selected.
EDIT :has is falling over for me, with :nth-child and :eq. .has() (the method equivalent of the selector) works though:
alert($('table').has("tr:nth-child(2)").length)
Although, note that the parameter passed to nth-child is not zero-based like :eq is.
Example - alerts the number of tables found with 2 rows or more.
Check this one
http://api.jquery.com/nth-child-selector/
$("table tr:nth-child(" + (x + 1) + ")").parent();
Didn't test it, but should be close. Note, you may need two ".parent()" calls, depending on your table structure.
I think your way is fine, frankly.
One alternate way would be to use the :has selector in conjunction with nth-child: ask jQuery for $("tbody:has(:nth-child(4))).... This says "find all tables whose tbody elements have 4 or more children". Since the children of a tbody are typically tr elements, this will do the trick.