Any shorter way to add attributes to specified elements using jQuery? - javascript

Assuming I have a wide table with many columns, and I want to add colspan=2 to:
td#2, td#10, td#15
td#3, td#11, td#16
Do I have to do it specifically:
$("table td").eq(2).attr('colspan','2')
$("table td").eq(10).attr('colspan','2')
$("table td").eq(15).attr('colspan','2')
Or should I use filter()?
Is there any shorter way?

You can do:
$("td:eq(2), td:eq(10), td:eq(15)", "table").prop('colspan',2);
is i think the shortest possible way.

You could do
$('table').find('td:eq(2), td:eq(10), td:eq(15)').prop('colspan', 2);
(I'd use .prop() instead of .attr() I think, but I need to make sure :-) (edit yup it's a real property)
Note that the above would work, but those jQuery extended search qualifiers like :eq() can slow down the selection process. It might be faster to use a separate filter step after selecting just the cells.
Also note that that selection (like your original code) finds the 2nd, 10th, and 15th cells in the whole table. If you wanted to set the property of the 2nd, 10th, and 15th cells on each row, you'd probably want something different.

$("table td").filter(':eq(2), :eq(10), :eq(15)').attr('colspan',2);

As an alternative to multiple selectors, you can invoke the form of attr() that takes a function and write:
$("table td").attr("colspan", function(index) {
return index == 2 || index == 10 || index == 15 ? "2" : undefined;
});
(You can use prop() equally well here, since its setter form also supports taking a function and the colspan attribute directly maps to the DOM property of the same name.)

You can optimise your code as below. Rather than jumping into DOM and searching $("table td") 3 times cache the it into a variable and use it.
var td = $("table td");
td.eq(2).attr('colspan',2);
td.eq(10).attr('colspan',2);
td.eq(15).attr('colspan',2);
Else you can do something like
$("td:eq(2), td:eq(10), td:eq(15)", "table").attr('colspan',2);
Else
$("table").filter('td:eq(2), td:eq(10), td:eq(15)').attr('colspan',2);

Related

How to get value of child element in table cell with jquery?

I added jQuery to an older application. This is causing some syntax errors so I need to update the older code to be compatible with jQuery. For clarification, once I include jQuery, myTable.rows.length returns "undefined." The reason I am including jQuery is because I want to use DatePicker elsewhere on the page.
Once I changed myTable.rows.length to $('#myTable tr').length; that part worked correctly, which led me to believe I need to update the following snippets as well.
What is the equivalent of the following code, in jQuery?:
myTable.rows[i].cells[0].children[0].value;
If what you are doing works, why change it?
I am not a fan of this, but the same idea would be
$("#myTableId")find("tbody tr").eq(i).find("td").eq(0).children().eq(0).val();
You would probably be better off with having a class on the item you are trying to select.
If it will be the first input in the first cell it would just be
var i = 0;
var rows = $("#myTableId")find("tbody tr");
var inputVal rows.eq(i).find("td :input").val();
It would be
$($("td:first", ($("#myTable tr")[i])).children()[0]).val();
To select the k-th td:
$($($("td", ($("#myTable tr")[i]))[k-1]).children()[0]).val();
Somewhat simpler ( i-th row, j-th cell ):
$("#myTable tr:nth-child("+i+") td:nth-child("+j+")").children()[0].val();

CSS not updated when hiding rows with jQuery

I have a table with the odd and even rows with a different CSS style tr:nth-child(2n){...}, and when I filter them with a textbox and jQuery, I hide() all the rows except the ones that match my criteria.
The problem is that now the rows remain with the current style (as I assume they keep the position despite they can't be seen), so the new odd and even rows doesnt match the CSS pattern.
How could I fix it?
Try to follow this example:
jQuery('tr:visible').filter(':odd').css({'background-color': 'red'});
jQuery('tr:visible').filter(':even').css({'background-color': 'yellow'});
Check here:
http://jsfiddle.net/KSL7j/1/
Hope it helps
Update
You can check this other example with odd and row CSS classes.
As CAbbott suggested in this fiddle: http://jsfiddle.net/KSL7j/21/
nth-child checks for the nth-child, not for the nth visible child or th nth whatever-styled child (hide() just adds display:none and nothing more...) and will never do.
I see two possible solutions:
1.add classes even/odd after filtering, just asking for the visible ones and then use your css on those classes
untested code:
var rows = $(tr[#display=block]);
rows.each(function(){
var index = rows.index(this);
if(index%2==0){
$(this).addClass('even');
}
else{
$(this).addClass('odd');
}
}
2.really remove the rows, not just hiding them
when you use hide() it is just set the display to none.
the structure of the dom is not modify so the nth-child do not work as you expected
you need to remove the even tr to get the effect you want.
if you want reset the rows. you can hold them in a variable and restore them back
var rows = $("tr");
var even = rows.filter(":even");
$("#trigger").click(function () {
even.hide();
even.remove();
});
http://jsfiddle.net/R2gBt/

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.

Is there a better way to select tables based on how many rows they have via jQuery?

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.

How can I jump to the next cell in a table?

I have a table wherein the first column is a checkbox and the second one has a text.
Whenever, the checkbox is checked, I want to know the corresponding value which is in the next cell.
Please tell me how to do.
If I use the getelementsbytagname function, it returns from the start of the document.
This is quite simple to do without jquery. We have a input inside a td so we can go up a level and get the next sibling:
var nextTd = myInput.parentNode.nextSibling;
Because some browser insert empty text nodes between tds we can do the following to make sure we're on the right node:
if (nextTd.tagName != "TD")
nextTd = nextTd.nextSibling;
Also, FWIW, getElementsByTagName can be called from any Node. Thus, if I have a table, I can call
myTable.getElementsByTagName("tr");
To return all rows inside of myTable.
Assuming you're using jQuery (or some other civilized framework), it's pretty easy:
$('table#yourTableId input:checkbox').click(function(ev) {
if (this.checked) {
// not sure what you mean by "want to know" ...
console.log($(this).closest('tr').find('td:nth-child(2)').html());
}
});
You could do it with the jQuery "live" event facility similarly, which'd be cheaper if there are a lot of checkboxes.
The simplest way would be yo use jQuery or a similar library, that implements CSS3 selectors.
$('table input:checked').parent().parent().find('td.nth-child(2)').text():
You could also bind onto the change events of the checkboxes
$('input:checkbox').change = function(){
val = $(this).parent().parent().find('td.nth-child(2)').text():
}

Categories

Resources