tags:

views:

49

answers:

1

I have a span tag in html and this <span> can appear multiple times on the page.

I want to select only the first span tag. I am doing it like this

var $myvar= $(".mydiv .indiv .myspan:first");

For now its working fine.

I think my code will prevent the browser from traversing the whole DOM, as I am using :first, which will improve performance. Am I correct?

One more question:

HTML:

<div class="mydiv">
    <div class="indiv">
        <span>myspan</span>
        <a href="#" class="anc1">a1</a>
        <a href="#" class="anc2">a2</a>
    </div>
    <table>
    ..................
    </table>
</div>

This html is having 2 anchor tags.I want to write a function on click of this 'a' tag.For that I can try something like $(".mydiv .indiv a").click(function(e) and it will work.but lets say, there is a same repeating structure in HTMl , so it will work for repeating set 'a' tags also, which i dont want.I want only the first set of 'a' tags to work. The functionality of 'a' tag is , onload 2 nd one will be in hide state, so on click of 1st, the 2nd one will be dispalyed and first one will be in hide state,and on click of 2 nd reverse action will happen, hope this time i have made myself clear :-)

+5  A: 

Answer to first question

I'm sorry to tell you but using :first won't make your selection any quicker. It's not the browsers fault though. It's how jQuery works. (BTW. if your page isn't super large e.g. several hundred matches for e.g. mydiv it doesn't really matter what your selector looks like)

$(".mydiv .indiv .myspan:first");
  1. jQuery first selects all elements in the DOM which have the class mydiv set.
  2. it loops over all(!) elements found in step 1 and finds all their descendants with class indiv set.
  3. it loops over all(!) elements found in step 2 and finds all their descendants with class myspan set
  4. finally it loops over all(!!!) elements found in step 3 and determines if it is the first element

Especially step 4 is not what you normally would expect. As only returning the first found .myspan element would suffice, but that's not how the Sizzle selector library that jQuery uses works.

So the only way to improve this selector is to use

$(".mydiv .indiv .myspan").eq(0);

Which at least spares you the loop in step 4

Or to find a more concise selector


Answer to second question

If I understood you correctly you hide the second <a> similar to this

$(".indiv > a").eq(1).hide();

Then the following should do what you want. Hides second link in first indiv. Appends click handler only to the first two links. Which show/hide each other.

$(document).ready(function(){
    $(".indiv").eq(0).children("a").eq(1).hide();
    $(".indiv").eq(0).children("a").each(function(i,e) {
        var x = $(e);
        if(i==0) {
            x.click(function(){
                x.hide();
                x.next().show(); 
            });
        } else {
            x.click(function(){
                x.hide();
                x.prev().show(); 
            });
        }
    }); 
});


A few comments to your question:

The <span> doesn't have set a class myspan but only contains the text myspan. Is the class attribute just missing or is you selector wrong.

Assuming you really have the spans like this <span class="myspan">....</span>. Are there any spans on the page which also have this class set but shouldn't be selected? If not you could rewrite your selector to

$(".myspan").eq(0);
jitter
is there any way to find more concise selector?what abt the 2nd qs?
Wondering
check expanded answer + comment to question about 2nd question
jitter
Edited the post, pls take a look at it.
Wondering
You can also do $(".myspan:eq(0)"). I'm not sure if Sizzle (jQuery's selector engine) is optimized to stop its search after it finds the first element. I'd check for you but Sizzle is advanced beyond my understanding.
David Murdoch
@Wondering check expanded answer. Btw. as long as your page is of reasonable size (e.g. <100 matches for any of the selector parts) it doesn't really matter what the selector looks like.
jitter
@jitter: AFAIK Sizzle is a right-to-left selector engine. Meaning that in $(".mydiv .indiv .myspan") it first finds ".myspan" then checks to see if it has a parent with class "indiv" with a parent with class "mydiv".
David Murdoch
@David Murdoch: AFAIK only `.eq(x)` gets you a little speedup as the pseudo `:eq(0)` selector also would be evaluated using loop over all elements.
jitter
for hiding anchor tag I have used $(".anc1").eq(0).css("display", "none")
Wondering
one last comment. The situation is also different for browsers which support the `querySelectorAll` method http://www.w3.org/TR/selectors-api/. Sizzle uses this method when available and then you might not see no speedup anymore as the browser will handle the whole selector and as you can imagine. The browser should be fast then the javascript-emulation
jitter
@Wondering: you could you use $(".anc1").eq(0).hide();
David Murdoch
@David Murdoch: wow. You actually are right about the right-left evaluation order. Didn't know about that. Also found a few nice jQuery performance tip after searching for this right-left thinghttp://jonraasch.com/blog/10-advanced-jquery-performance-tuning-tips-from-paul-irish#more-382
jitter
But one day I will have to step through a selection to verify this
jitter