How can I directly select classes, etc using a variable?
var $tbody = $(".tbl-locations-body");
$(".tbl-locations-body a.collapse").hide();
$(".tbl-locations-body tr.child-row").hide();
$(".tbl-locations-body .container").first().hide();
$(".tbl-locations-body .tab-content").hide();
I want to use $tbody to perform the methods. What is the syntax?
You could use the find() method from the $tbody jQuery object. Note that you can apply multiple selectors as well to make the calls a one-liner:
var $tbody = $(".tbl-locations-body");
$tbody.find('a.collapse, tr.child-row, .container:first, .tab-content').hide();
var $tbody = $(".tbl-locations-body");
$("a.collapse", $tbody).hide();
// etc...
Explanation:
If you pass $tbody as second parameter into jquery function, you will search only in a scope of that element($tbody), rather than in whole document.
You can use the find() method - see code below:
var $tbody = $(".tbl-locations-body");
$tbody.find("a.collapse").hide();
$tbody.find("tr.child-row").hide();
$tbody.find(".container").first().hide();
$tbody.find(".tab-content").hide();
I've been reading up on this and although
var $tbody = $(".tbl-locations-body");
$("a.collapse", $tbody).hide();
looks cleaner, under the hood it's changed to $tbody.find() anyway. So the better answer is to use the find method to start with - and as Rory pointed out, you can select multiple too.
Related
I'm working on an app where I need to clone a table, then access the td and tr independently, depinding on their attributes or classes within this table.
Is there an easy way to accomplish this with the classical jQuery selector or do I need to write a whole new function ?
Code :
JS
var grid = $("table").clone();
console.log($(grid).$("td"));
Assuming you're starting with just one table, the following selector string will find all the rows in that table (as you know).
$("table tr")
but if you're referencing your table with a variable you have to use the find operator with the remainder of the original selector string instead, e.g.
var $table = $("table");
$table.find("tr")
I'm prefixing my variable with a $ as a note-to-self that it's already a jQuery object, i.e. there's no need to $($table).
You can work with the clone in exactly the same way:
var $clone = $("table").clone();
$clone.find("tr")
Yes you can use the clone just like a regular jQuery selector. For your example it would be
var grid = $("table").clone();
console.log($(grid).find("td"));
or even
console.log(grid.find("td"));
I need to get the number of rows in a table using a variable as the table selector. I get the table with this:
var table_element = $(this).prev('table.w2bw2c-with-artists-table');
I tried this from a previous post but got an error that length was undefined.
var new_with_artist_index = $(table_element).rows.length;
I have seen these methods used to find the number of rows in a table:
var rowCount = $("#tblEmployee td").closest("tr").length;
var rowCount = $('#myTable tbody tr').length;
How can I use one of these methods where the table selector is a variable instead of an ID? Or is there a better way?
You can just use .find() method on jQuery object.
var rowCount = table_element.find('tbody tr').length;
Or, You could get the native table using [] or .get() then use .rows property
var rowCount = table_element[0].rows.length;
var row = $("#tblEmployee td").find("tr");
var rowCount = row.length;
Many ways to do this:
1. jQuery find method
$(tableElement).find('tr').length
2. jQuery context parameter (i call it that way)
$('tr', tableElement).length
3. Plain Javascript
tableElement.querySelectorAll('tr').length
As you see the shortest would be the second variant, i think its also very clear, so if you can utilize jQuery, go for that variant. If you dont have jQuery in your library yet you should probably use the third variant.
querySelectorAll is defined for all DOM Elements and returns a NodeList. There is also a querySelector function, that will return the first match of the selector (so a single Element or null if nothing matches).
NodeList does not extend Array, so if you want to iterate the list, you need to do it that way:
[].forEach.call(tableElement.querySelectorAll('tr'), function(element) {
doSomething();
});
I found an answer from Ricky G at
jQuery: count number of rows in a table
Here's my code:
//Helper function that gets a count of all the rows <TR> in a table body <TBODY>
$.fn.rowCount = function() {
return $('tr', $(this).find('tbody')).length;
};
To use:
var table_element = $(this).prev('table.w2bw2c-with-artists-table');
var new_with_artist_index = $(table_element).rowCount();
Thanks and a tip of the hat to Ricky G!
If you execute in the console on this page
var cloned = $(".question").clone(true);
$(".question").addClass("first");
var clonedStr = cloned[0].outerHTML || new XMLSerializer().serializeToString(cloned[0]);
$(".question").after(clonedStr);
you will clone the question (there will be two questions on the page, but the first one will be with the .first class). That's what is needed.
Is there any simpler way to do this with jQuery? I'm confused of the third string in the code above and believe it could be simpler. Any ideas?
Thank you.
If you don't use the HTML as string, then don't get it. Just use the jQuery object:
var cloned = $(".question").clone(true);
$(".question").addClass("first").after(cloned);
Also, you can do it one line:
$(".question").after($(".question").clone(true)).first().addClass("first");
You could use insertAfter to insert the cloned element after changing the class. You don't need to convert the element in the jQuery object to a string, you can use that object within the function itself:
var $question = $('.question');
var $cloned = $question.clone(true).insertAfter($question);
$question.addClass('first');
I'm using a jquery plugin which fixes the headers on a html table that I generate. Unfortunately the performance of the plugin is very slow and I've narrowed it down to the following code:
var $tbl = $(this);
var $tblhfixed = $tbl.find("thead");
$tblhfixed.find("th").each(function ()
$(this).css("width", $(this).width());
});
This is taking about 40 seconds on a table with 2,000 rows in ie. Does anyone know why it's so slow and more importantly how can I make this faster? I've tried many other plugins and this is the only one which works how I want it to. Thanks for any help
I guess you faced with the same problem that I had some time ago. It called a "Recalculate layout" or something.
Try to separate this script onto two loops, like this:
var $tbl = $(this);
var $tblhfixed = $tbl.find("thead");
var widths = [];
// 1.
$tblhfixed.find("th").each(function ()
widths.push($(this).width());
});
// 2.
$tblhfixed.find("th").each(function (index, element)
$(this).css("width", widths[index]);
});
First one will calculate all the widths. Second one will apply them to TH's
UPD:
You may increase performance by placing this code between 1. and 2.:
$tblhfixed.hide();
and show it again after 2.:
$tblhfixed.show();
the culprit is probably the .each.
The reason is that when you iterate using .eachinstead of a normal loop, you call a function for each iteration. a function call has a pretty big overhead in this case, since a new callstack has to be created for each iteration.
To make it faster change
$tblhfixed.find("th").each(function ()
$(this).css("width", $(this).width());
});
to
var elms = $tblhfixed.find("th");
for(var i=0, elm;elm = elms[i];i++) {
elm.css("width", elm.width());
}
First, you should use find() only when you need to pass through all nested nodes. Right here you can use children().
Second, each time $(this) creates new instance of jQuery object, while you can create it once:
var $this = $(this);
Each time $(this).width() is recalculated. Make sure that you need it to be recalculated. Or do:
var tableWidth = $this.width();
And third, according to #Martin Jespersen, each iteration the function object is created.
Also you don't need jQuery here at all. You can access DOM directly:
var tableWidth = ...; // get the table width the way you want
var thead = this.tHead;
var thRow = thead.rows[0];
for (var i = 0; i < thRow.length; ++i) {
thRow.cells[i].style.width = tableWidth + "px";
}
you should not repeat $(this) inside your function passed into .each(). wrapping an element has non-trivial overhead, which is not ok when you have 20k elements. you want to eliminate as much work as possible inside the .each() call, or eliminate it altogether.
Also, why query find() twice, when you can do this instead, which should give you the same results:
$ths = $('table thead th'); //or tableid, or something
$ths.css('width', $ths.width());
it appears that $.width() is 99 times slower than the native get(0).clientWidth, check out this test: http://jsperf.com/jq-width-vs-client-width
I'm looping through cells in a table row. each cell has a text box in it, and I want to take the value of the text box and push it onto an array.
function dothing() {
var tds = $('#'+selected+' td');
var submitvals = new Array();
tds.each(function(i) {
var val = $(this).children('input')[0].val();
submitvals.push(val);
});
}
Theres more to the function, but this is all that is relevant. For some reason, when I run this code, I get "HTMLInputElement has no method 'val'." I thought that input elements were supposed to have a val() method in jQuery that got the value so this makes no sense. Am I missing something, or doing it wrong?
val() is a jQuery method. .value is the DOM Element's property. Use [0].value or .eq(0).val()....
.val() is a jQuery function, not a javascript function. Therefore, change:
var val = $(this).children('input')[0].val()
To:
var val = $(this).children('input:eq(0)').val()
function dothing() {
var tds = $('#'+selected+' td');
var submitvals = new Array();
tds.each(function(i) {
var val = $($(this).children('input')[0]).val();
submitvals.push(val);
});
}
.val() is a jquery method. Using [0] returns the DOM element, not the jquery element
var val = $(this).children('input:first').val();
What I don't understand, is why none of the suggested syntaxes on this or other questions similar to this seem to work for me. I had to do trial and error and eventually had to use:
MySelectElement.value = x;
It also didn't help that the Visual Studio Intellisense suggestions offer a whole other range of unworking method names, such as ValueOf().