Right to Left jQuery Selectors not working - javascript

In reading post on StackOverflow about jQuery Selector performance, I keep reading the same thing over and over saying jQuery uses a Bottom up or Right to Left approach to selectors.
Take this example...
$("#dnsTitle a.save").removeClass("disabled");
According to what I have been reading it is better performance to use this instead...
$("a.save #dnsTitle").removeClass("disabled");
The problem I am running into is this does not even work at all! Can someone clarify the real best method for doing selectors?
I am working on an existing project that has some really long selectors and I am trying to improve them where I can but it seems I am getting bad information or outdated. I am using jQuery 2.0

The concept of "Bottom Up/Right to Left/Leaf to Root" is only related to the implementation of the selector parser and not the order of the selectors in usage.
Usage:
From the usage standpoint, selectors are "read" left to right, where your first selector is your root, and the succeeding selectors your descendants. The elements that match the last selector are returned. And so:
#dnsTitle a.save - looks for an element that has an id of dnsTitle and from there, looks for a decendant a element with class save. You end up with the a elements with the class save.
a.save #dnsTitle - looks for an a element with class save and from that, finds a decendant with an id of dnsTitle. You end up with whatever elements with the id dnsTitle
Parsing:
Now from the parsing point of view, there's 2 common ways you approach parsing a selector string, and they're the "Top-down" and the "Bottom-Up":
Top-down / Root to Leaves / Left to Right
If you've been through a Data Structures course, then this is how you normally parse a tree. You find the node where you want to start, which would be your first selector. Then you work your way down in finding the succeeding nodes.
A problem in this approach is that it uses a recursive approach and uses a lot of memory, especially if your tree is huge. Also, the issue of back-tracking is a problem since the succeeding selectors are descendants, and matches may vary in depth. The next selector might match a great^N grandchild. Recursion goes N steps deep to find that great^N child and take N steps to return back up.
Bottom-Up / Right to Left / Leaves to Root
With this approach, the parser looks for all elements that match the last selector and you end up with an array of matches. With that array of matches, you filter them if they match the succeeding previous selectors.
The advantage of this approach is that you have a fixed array to work on, and not a variable-depth tree. Also, you are filtering linearly since a node, in this case, can only have one parent in contrast to top-down which deals with multiple children. This also means you only need loops to do the job, not recursion. One loop can go over each result, and the other, nested, to go through each ancestor if it matches the succeeding previous selectors.

Related

jQuery class selector vs cached element + find

I have a situation where I'm wondering what the best approach is performance-wise.
I have a class name, let's call it .class-test.
I also have a cached element, $body.
I can either retrieve the .class-test element by:
$('.class-test')
or by
$body.find('.class-test')
In a worst-case scenario, does one of these approaches win out over the other? Also, if someone could describe what is being done under the hood by the second approach that would be great (i.e. I know that .find defers to Sizzle, but if the element is cached does it already have a tree of its DOM elements stored, then it only needs to traverse that sub-tree to find the class? or is that tree only built as-needed?).
The difference is how many times you dip in the DOM pool so to speak. In the first query, jQuery will search from within the document( top level ) and travel down in to the DOM tree checking every level till it gets to the very end and then returns all of the matching elements.
In the second option, you specify the starting point, so instead of starting at the very top and working its way down you are starting at the body element. In this particular case you are only going one level lower but here is the real plus, since you have the body cached, jquery doesn't have to find that it can just reference the cached element.
When you get deeper into the DOM tree this can be a big time saver. You can save 10s to 100s of level checks. And although you wont notice this much for small sites, one day you may be working with enterprise level code bases where these performance gains will be very beneficial to you.

Determine the character index of DOM element inside its owner document's html?

Primarily, I need to convert selection ranges to indices in the source HTML. I was thinking there's a couple ways to do it manually, but is there a built in way to do it?
Some ideas:
Clone the document. Remove the element and its subsequent siblings, and remove all the subsequent siblings of each of its ancestors. Then you just get the document HTML and get its length. o_O
render the tags, text, etc to HTML myself, walking down the DOM tree. Also o_O
The performance could be improved by caching results. Then, if an ancestor already knows its position, it's a bit faster to compute the childs. But then maintaining the cache is another thing.
What about adding a unique ID or class to it and then search for that in the whole document string?

Is there an efficiency difference between finding by id and finding by class with JavaScript/jquery?

Is there an efficiency difference between finding by id and finding by class with JavaScript/jquery?
Is one better than the other? If so is it because indexes of ID or Class are made in the DOM somewhere?
Does it end up not mattering much?
Finding by ID is always faster, no matter where (getElementById(), $('#id'), or even in regular CSS).
Since ID's are unique per page, they're much faster to find.
In addition, when using $('#id'), jQuery will map that back to the built-in getElementById(), which is the fastest way to query the DOM.
Well, logically speaking, an ID would be more efficient, as there is (should be) only one of it, so once it finds it, it will stop searching. However I am not familiar with the jQuery source, I don't know how it actually works, that's from a logic perspective.
For most browsers, the difference in speed between searching by id and searching by class name depends on how many elements have a given class. At best, there will be only one such element, and the search speed ought to be the same. At worst, there are a bazillion elements with a given class. Typically, though, you shouldn't have to worry about the speed of searching through 10-20 elements containing the same class.
A critical caveat, though: MSIE <= 8 has no native getElementsByClassName, so jQuery has to fall back to a full DOM tree search unless, e.g., the element name of the wanted element is also provided. Even then. $('div.myclass') may not be much help if your document is large and exceedingly div-happy. Benchmarking is really the only way to find out.

Speed difference between very similar jQuery expressions in IE

In IE, compare the speed of execution of an expression along the lines of
$('div.gallery div.product a");
to the very similar
$('div.gallery').find("div.product").find("a");
Sometimes the second variant runs faster, sometimes slower. Often the speed difference is a factor of 2 or more. What is going on?
The first variant will do the following:
Find all anchor tags in the page
Only leave the ones with ancestor div.product
Only leave the ones with ancestor div.gallery
The second one
Find elements with class .gallery and tag div
Search for div.product in their descendants
Search for anchor tags in their descendants
So the first one will search for elements from right to left, while the second one will search them from left to right.
Which is faster depends on your site structure but the first one is the recommended way, because browsers match CSS selector the same way.
If you want to increase speed make sure that the rightmost selector is as specific as possible.
e.g.: in this case you can add a special class for your anchor tags like .gallery-link and then your query will become a simple a.gallery-link which in IE will invoke a getElementsByTagName function for the anchor tags then they will be filtered by their class name. Notice that because you don't have to traverel up the DOM tree your query becomes significantly faster. The cost is a bit more complex markup. For costly queries it may worth it.

optimizing jQuery Selectors - Which is faster?

Are selectors or functions faster in jQuery? Example:
$('#something div.else'); // find multiple divs with class .else
or
$('#something').children('div.else');
I'm trying my best to optimize a page with hundreds of returned elements that seems to hang on a certain crappy computer here in the office (that must use Internet Explorer ::shudder::).
Well in this case, the second's faster, but, they're not equivalent. The first finds any descendant div.else, the other finds only direct children that are div.else.
It depends on your DOM as to which is faster, the equivalent of the second would be this:
$('#something > div.else');
This uses the child selector. They should be very, very close, and in any case, I doubt a selector descending from an ID is your problem area, I think you'll find the vast majority of your time in JS is spent elsewhere.
For diagnosing speed issues, get a profiler, for IE specifically there's a fantastic free one called dynaTrace AJAX Edition. Grab it, follow the short tutorials on their site...you'll find where your pain areas in IE are pretty quickly.
Although I haven't checked with the jQuery code, I think the difference should be negligable between your two examples - although the first one should run a little faster.
The problem with old IE versions is that they do not support a native way to fetch items based on class names. In this case, jQuery has to execute a regulra expression on each class attribute of each element contained.
If it is possible in your case, you might gain quite a lot performance when being able to select on an unusual tagname:
$("#container blockquote.else")
and ideally,leave away the class name.
EDIT: just saw the answer from Nick and he's right, the scond one only has to check the direct children. The equivalent first one would be:
$("#container > div.else")
In your specific example, your first example of
$('#something div.else');
gets optimized through Sizzle (which is delivered within the jQuery lib) into
$('#something').find('div.else');
without that optimization, it would be slower, since the selector engine sizzle does work from right to left. So, it would match all divs with the class else and would then check which of those has #something as parent.
edit
The Sizzle optimazation is slower
anyway, since it took a while until
that task is completed and some
functions are called on the way
In general, using jQuery functions is a lot faster. For instance jQuerys .eq() function will use an array slice to reduce a wrappet set of jQuery objects, whereas :eq() selector will invoke sizzle.
If in your example, div.else elements are direct children of #something, .children() will beat .find() since .find() will also lookup all descendants (and their childs).
If I understand correctly you need the fastest way to get #something div.else in IE6. Since jQuery uses Sizzle, the way it will find that is first find all div's, then filter by the ones with the else class, and has an ancestor with the #something id.
Your second example will be faster if it contains few children, slower if it contains many.
A suggestion you could try would be to use another tag type instead of div, one that isn't used in your page, say blockquote. Just reset it's styles with css so it looks like a normal div, then change your selector to #something blockquote.else which should be tons faster.

Categories

Resources