tags:

views:

150

answers:

3

Hi

I would like to insert multible sliders in one page. I have a block of code I would like to reuse but it will insert 2 DIV's with id=slider...

Is it possible to find second element with id=slider and rename to id=slider01?

BR. Anders

+3  A: 

Try

$('div[id="slider"]:eq(1)').attr("id", "slider01");

http://jsfiddle.net/rYyA7/ - Tested in IE6/8, Firefox, Safari, Chrome and Opera.

Andy E
Was about to suggest that, too. +1
Boldewyn
That would assume he already inserts an element with an identical id into the DOM, which would be really bad karma.
jAndy
Have you tested that? I was wondering whether jQuery/Sizzle doesn't optimize out the attribute selector in favor of `getElementById` (which *may* be faster on some implementations). I'd be hesitant to rely on it not doing so...
T.J. Crowder
@T.J.: Was just in the process. I fixed one facepalm with my code that was unrelated to that. I made the assumption that Sizzle would optimize "#id" strings, but not attribute equals selectors (which makes sense, really). Tested in Chrome and IE so far, http://jsfiddle.net/rYyA7/.
Andy E
@jAndy: that depends on what the "block of code" is. Of course, nobody should be using duplicate IDs on a page but if they're inserted programmatically then this is one potential fix. Another potential fix might be to have jQuery parse the code first and change the ID before adding it to the DOM.
Andy E
@Andy E's head: Cool. May be worth spelunking in the Sizzle source to see if they explicitly allow for this case (since, sadly, people end up with duplicate `id` s a lot). I'd just be...nervous in terms of future-proofing. :-)
T.J. Crowder
@Andy E's head: That's what I'm saying. That should be in your answer. First and best way should be `.clone()` that element, modify the id and then append it to the DOM.
jAndy
i have inspired my self on your example to make a version that works with more then one duplicate.
meo
@jAndy: It makes little difference which way around you do it unless you're changing the HTML code (which won't validate). If the line that follows the code that creates the second div fixes the ID, there's no way that it could have any adverse effects. A single line of code is easy to read and maintain, so your definition of "best way" is subjective. If I were to denounce my answer, I would do it for the reasons provided by @T.J., that the Sizzle library might be changed at some point to stop this selector from working, but I really don't think that's likely because of `querySelectorAll`.
Andy E
@Andy E's head: well, the question at stake is still what the OP means with `a block of code`. If that is javascript, you should totally avoid putting a cloned object with an identical id into the DOM and change that id afterwards. Same thing is for creating a DOM element with a duplicate id. It may work, to change the id attribute afterwards, but it's just bad karma to me.
jAndy
@jAndy: But there really is no difference. Sure, I totally understand where your argument is coming from - it's absolutely wrong to have a duplicate ID in the document, but the point is that it's only there until the next line of code runs - no other code will be able to interact with this in the meantime. It might seem like bad karma to you, but your concerns have no real validity to them. But maybe we should agree to disagree on this one :-) I do agree that an alternative solution might be to change the `id` before appending, but I think whether this is a better method or not is subjective.
Andy E
Hi. I tried it right after your post but could not make it work. Tried from scratc again today and it worked first time :-) Thanks a lot. Have looked up references and understand what is beeing done. Great. An xtra plus for posting link to a page with example code!
Tillebeck
To those who wonder. It is a module that returns the id="slider". I would like to use the module twice, but then I will need to change the ID.
Tillebeck
+5  A: 

You'd be best off doing this by assiging a new id before you append the second slider to the page. You haven't shown the code for how you're doing that so it's hard to advise on how to do that, but it would be best.

It's possible to find the second slider afterward, when your document is temporarily invalid, but it may be awkward. Again it depends on your code. If you already have a reference to a jQuery object containing the second slider, as a by-product of how you're creating it, it's easy (just use yourvar[1].id = newavlue). If not, you may be best off searching on the basis of other things the sliders have in common, like say if they're both divs with the class slider:

var sliders, ids;
sliders = $("div.slider");
if (sliders.length > 1) {
    ids = {};
    sliders.each(function() {
        if (ids["x" + this.id]) {
            // This ID has already been used, grab a new one
            this.id = 'newslider' + new Date().getTime();
        }
        else {
            // This ID hasn't been used yet; flag that we're using it
            ids["x" + this.id] = true;
        }
    });
}

That code walks through all of the matching elements and ensures that there are no duplicate IDs (with a couple of caveats, mainly that there aren't already IDs in the form "newsliderNNNNNNNNNN" where the Ns are the number returned by new Date().getTime()). (The "x" prefix on the property names in the ids object is just to defend against accidental collisions with pre-existing properties, like toString. Hey, it's a valid id, someone might use it. :-) )

Andy E's head's answer provides a much shorter way of doing it and may be a way to go, but it assumes that searching on the basis of the id attribute won't get optimized at some stage such that it stops finding multiple elements. That assumption may well be valid, but I'd be uncomfortable relying on the selector implementation not changing down-the-line and introducing an issue in my code. (There's been a lot of work on selectors the last few years; the current jQuery engine, Sizzle, is brand-new for instance.) But again, it may be fine.

T.J. Crowder
Lol my answer all of a sudden became rather controversial :-) You make a valid point, although I think it makes sense that attribute equals selectors work exactly as they do, and I would put money on the fact that they are not optimized for reasons such as this. Many other selectors are optimized and it would make you wonder why they left out attribute equals selectors.
Andy E
A further argument would be that in many situations Sizzle relies on a browser's `querySelectorAll` implementation if available. This would likely remain the case in the future too. BTW - +1 for a good answer :-)
Andy E
@Andy E's head: Yeah, it's probably fine to do it that way, and it's wonderfully direct, and short (short ~= less code to maintain ~= good). I've just been bitten by things like that enough times that I'm pretty cautious.
T.J. Crowder
@T.J. Amen to that.
Andy E
+2  A: 

i would do it like that:

$('div[id="slider"]').not(':eq(0)').each(function(i){ //selects all divs with the id slider but not the first one
    var $that = $(this),
    newID = $that.attr('id') + (i + 1) // adds a incising number to the ID's 

    $that.attr('id', newID) // sets the new id
})

check the example here: http://jsfiddle.net/nuW34/

meo
+1 for being inspired :-)
Andy E
+1 for being my inspiration, oh andy would you like to marry me :-P
meo
Super! That is really some great lines of code!
Tillebeck