jquery select all children after nth-child - javascript

I am working with jquery and creating show hide lists, I need hide all the child list items that follow the 6th child in the ul. Normally I would do this by setting the height and then changing the height on click of a click, but for this to work I need to add overflow:hidden to my css, and this is not an option.
How would I get all the child list elements that are greater than the 7th child?
Something like,
$("ul li:6n").domeSomething()

How would I get all the child list elements that are greater than the 7th child?
Select the element index = 7+
$("ul li:gt(6)").domeSomething()
:gt selector
The selector uses the zero base index:
Note that since JavaScript arrays use 0-based indexing, these selectors reflect that fact. This is why $('.myclass:gt(1)') selects elements after the second element in the document with the class myclass, rather than after the first. In contrast, :nth-child(n) uses 1-based indexing to conform to the CSS specification.

I wanted to write my answer only to discuss two previous answers: the answer from gdoron and the answer from neu-rah. If we would see on voting count one can see that the most reader find doron's answer better. I disagree and I try to explanation why.
The explanation you would find the documentation of :gt() Selector (see "Additional Notes:" here):
Because :gt() is a jQuery extension and not part of the CSS
specification, queries using :gt() cannot take advantage of the
performance boost provided by the native DOM querySelectorAll()
method. For better performance in modern browsers, use
$("your-pure-css-selector").slice(index) instead.
You can test the code with here or better here (with non-minimized code of jQuery 1.7.2). The code use just the statement $("ul li:gt(6)").css("color", "red");. You will better understand the problem if you start the demo in Developer Tools of Chrome with activated button "Pause on exceptions". You will see the following exception (it will be not the first one):
So you can see that the current implementation of jQuery try to use native querySelectorAll() of the web browser to get the best performance. After that the function $.makeArray will be used to make jQuery wrapper from the NodeList. In case of exception the line
return oldSizzle(query, context, extra, seed);
So you will have the best performance if you would use selectors supported by querySelectorAll(). For example
$("ul li").slice(7)
is better as
$("ul li:gt(6)")
I would you recommend to use more exact selectors whenever it's possible. For example if the parent <ul> element has id="menu1" then you can use
$("#menu1 >li").slice(7)
for the best results. It will help additionally in case of multiple <ul> elements on your page.
Someone can mention: the selector "ul li:gt(6)" works quickly enough. It's correct, but you should don't forget, that you use sometime selectors inside of loop or use it inside of functions which will be called inside of loops. So the difference between 10ms and 30ms can be much more clear if the execution time will be multiplicate to 100.
Moreover it somebody ask yourself the question how to implement some selection and get the answer, he/she will use the code pattern permanently. I think that it would be better to use the pattern which has performance advantage. Isn't so.
UPDATED: To clear the difference in performance of $("ul li:gt(6)"), $("ul li").slice(7) and $("#menu1 >li").slice(7) selectors I made additionally the demo. Everybody can test the difference in the web browser which he uses. You should additionally not forget, that in case of page having many other elements the id selector will work better.
On my computer the execution time of $("ul li").slice(7) and $("#menu1 >li").slice(7) are about the same (the page have very little elements) and is about 2.5-4.5 time better as the for $("ul li:gt(6)"). The results can depend on the number of li items, the number of elements on the page and many other things, but I hope that the test do clear shown that the usage of slice has performance advantage compared with the usage of :gt (exactly like we can read in the jqGrid documentation referenced before).

use slice to reduce a set
.slice(start[,end])
http://api.jquery.com/slice/
example (edited)
$("ul li").slice(6).doSomething(...)

Try this:
$('ul li:eq(6)').nextAll().domeSomething()

Related

Jquery traversing and using selectors

I'm reading a book and they show a couple of examples of how to select elements on the DOM, but they advise to always use Jquery trasversing methods over the selectors, for example if you have a list inside a div instead of using
$("#myList > li")
You should use
$("#myList").children("li")
Most of the time I use the first over the latter, the author says the 2nd is prefered and more efficient but he does not address why, can anyone explain the reason behind this?
I think the difference in performance in that particular case comes down to this:
document.querySelectorAll('#myList > li');
// VS
document.getElementById('myList').children;
And the performance test here: http://jsperf.com/ae-d2-56-2a-e2-36-a3-d3-52-74
jQuery might check to see if it's a li given the selector but that's still going to be faster than querySelectorAll or Sizzle.

jQuery selector for finding the first element after a given element that matches a selector

Let's say I have this HTML:
<textarea>blah</textarea>
<br>
<div class="select_this">hello!</div>
How can I select the DIV with class "select_this" when I already have the textarea identified? I don't want to use a class selector on the entire document because I'm working with a large document and class lookups are slow in older browsers.
jQuery .next() doesn't seem to do the trick, closest() only looks up the DOM tree, and .nextUntil() qualifies on everything I need except for the "select_this" div. Any other options out there?
There are two ways to do it.
Use this if you only have a few siblings:
$('textarea').nextAll('div.select_this').first();
The downside of this is that it test every subsequent element to see if it matches the selector, even after it's found the first one. Use this if you have many, many siblings, to save on evaluation:
$('textarea').nextUntil('div.select_this').andSelf().last().next();
Note also that it's better to use the first and last methods, rather than their corresponding selectors (:first, :last), because browsers don't natively understand the selectors, which slows the expression down considerably.
Edited to incorporate andSelf per comment below.
You want nextAll:
jQuery(yourTextarea).nextAll('.select_this:first');

When removing a class with jQuery, is it better to include the class in the selector?

Probably this will not result in any noticable performance difference, but I was just interested. If I am removing a class on a list of elements using jQuery, is it better practice or performance to include the class in the selector?
So either include it:
$('#myList li.classToRemove').removeClass('classToRemove');
or don't include it:
$('#myList li').removeClass('classToRemove');
So basically is there any difference to narrowing the list in the selector and in the removeClass method.
Selectors are matched backwards (last to first), meaning it will first find "all elements with "classToRemove" which are also "li" which are also children of "#mylist" ".
It's done that way to narrow down the list as much as possible, as soon as possible.
Therefore, you should go with
$('#myList li.classToRemove').removeClass('classToRemove');
Less items to match means a faster, more efficient script.
Assuming that not all the <li> elements have that class, then I'd say that it's better to run .removeClass() on the filtered set.
But overall, there will be other things that will have an impact on the performance, like...
The number of elements matched by '#myList li' vs '#myList li.classToRemove'
The way different environments optimize their DOM selection
The actual performance difference of the innards of the .removeClass() method between different environments
So unless you're talking about unnecessarily running .removeClass() on a large subset of elements, I wouldn't worry about it too much.
Using the more specific selector will improve performance but it won't affect the result of .removeClass().
Think of each addition to a selector like a drill down. Given the html below:
<div id="myList">
<ul>
<li id="li1"></li>
<li id="li2"></li>
<li id="li3" class="classToRemove"></li>
</ul>
</div>
//In order of fastest to slowest:
//Selecting the exact li and calling removeClass once
$('#li3').removeClass('classToRemove');
//In this one we are skipping 2 li's and then calling removeClass once
$('#myList li.classToRemove').removeClass('classToRemove');
//In this one we have to call removeClass 3 times
$('#myList li').removeClass('classToRemove');
Sorry to bump an old post.
The test at this page seems to suggest that NOT including the class selector is around 10-15% quicker. So, if you want to use jQuery, the best approach is just:
$('#myList li').removeClass('classToRemove');
Note - this page does appear to use jQuery 1...

Performance in jQuery with selectors

i was wondering things...
If i need to get the content or append an click function to an div, as the structure of the selectors it's something like that:
$('body #content #sidebar .modalwindow #global-content')
i want to target #global-content, the final id of the selectors.
what its better?
Just target it as $('#global-content') and do what i wanna or give to it all the path?
$('#global-content') is the best selector to use, altough maybe the whole selector will be executed the same way (if jQuery starts from right to left, which I'm not sure it does). ID should be unique and getElementById() is the fastest native browser method, so $('#global-content') is the fastest possible selector.
Keep in mind also, that when you are searching for something exactly 1 level lower in the DOM tree, you can put > in the selector. Example:
$('body .content') is equialent to $('body').find('.content')
$('body > .content') is equialent to $('body').children('.content')
The second one is faster.
You can experiment and try out your selectors here
a similar question was asked in
jQuery Selectors, efficiency
the answer is that
$('#global-content')
is faster
if you know the id of your element and if your id is really unique (as it should be). It is faster to call directly the id >> $('#global-content').
Thus, it is interpreted by jquery to one of the fastest selector getElementById() instead of filtering the DOM.
Note: I know jquery 1.5 and higher (maybe even since 1.4) were optimized to select by id even if the jquery code was adding too much information but that's not the best way to rely on the framework to correct a bad coding

Fastest selector method in jquery and CSS - ID or not?

What is fastest in jquery/javascript?
$('#myID .myClass')
or
$('.myClass')
What is best to use in CSS?
#myID .myClass{}
or
.myClass{}
I see now that I should have explained better. Sorry!
Ofceauce ID is a faster selector in both CSS and JavaScript. But some times you need to use class since there are multiple selectors.
Say forexample that I have i BIG html document. In the middle of the page I have:
<div id="myID">
<a class="myClass">link1</a>
<a class="myClass">link1</a>
<a class="myClass">link1</a>
</div>
If I want to target all "myClass". Would it then be better to target the ID before targeting the classes? (then I wouldn't have to do domtravel of the entire HTML document) Eg.:
Would this:
$('#myID').find('.myClass')
Be faster than:
$('.myClass')
My testing on modern browsers suggests that you should go with either,
$('#id').find('.class') // or
$('.class')
but not,
$('#id .class')
Reason being that all modern browsers implement getElementsByClassName resulting in almost-constant time lookups by class name (assuming a hash implementation). Which browsers are modern is another subjective question.
They're roughly the same in most modern browsers since class-names are hashed internally. The difference is that older browsers don't have a .getElementsByClassName or equivalent method, so .myClass is parsed internally to jQuery and EVERY element in the dom is walked and checked for the classname (or it uses XPath when possible).
Always try to use #myID .myClass when possible as it allows jQuery to jump directly to #myID and traverse from there when necessary.
Let's just think logically about this for a second, and pretend that you didn't know anything about how a browser is built internally or how it accesses the DOM, but you assume that whatever it does is logical.
Therefore, doesn't it stand to reason that out of two selectors, the narrowest one would find you results faster?
You have two selectors, which translate to rough english as
Any element of the class myClass that is a child of the element with ID of myID
Any element of the class myClass
As for "What is best to use in CSS", this is completely subjective as it depends if you are intending to target all instances of .myClass or just those that are children of #myID.
Good question actually.
Say you have parsed DOM of N elements of max depth of D and CSS of S number of rules. Then the task of finding styles for all elements has computational complexity of roughly O(N*D*S).
Obviously not all of CSS selectors has the same computation complexity.
For example li.item selector and li[class ~= "item"] require exactly the same CPU resources as they are equivalents. li[class = "item"] can be computed faster as it does not require scan of white spaces.
#1 selector here:
#myID .myClass{} /* #1 */
.myClass{} /* #2 */
require more CPU resources as you need to do exactly the same amount of work as in case #2 plus you will need to scan parent/child chain (of max D elements) to find the element with "myID".
That is all about pure CSS selectors.
In jQuery & friends situation can be a bit different. Theoretically jQuery engine can use document.getElementById() to minimize the lookup set (so reduce the N number) but that will not match CSS behavior. Here is an example: http://jsfiddle.net/dnsUF/ . Here jQuery reports one element with #foo but there two such elements in fact.
Resume:
In CSS case #2 is faster
In jQuery case #1 can be faster (but technically may not be correct in CSS sense).
Here is my article about CSS selector complexity:
http://www.terrainformatica.com/2008/07/csss-and-computational-complexity-of-selectors/
And this one of how to improve it by using style sets:
http://www.terrainformatica.com/2010/09/style-sets-in-h-smile-core/
IDs will always be the fastest way to access an element, since they are unique.
Yeah, id is one of the fastest method to access element. Check it out this test http://mootools.net/slickspeed/.
#myID .myClass is definitely a better way to access the element assuming you have many elements to which the .myClass is applied.
Update - 2015 - Check yourself here
https://jsperf.com/id-vs-class-vs-tag-selectors/2
TL;DR;
Using ID $("#foo") is almost 4x faster than CSS $(".bar") on my chrome 41 on linux 64bits

Categories

Resources