views:

1573

answers:

5

Is there a built in method or defacto default plugin that will let you automatically assign an unique ID to an element in jQuery, or do you need to implement something like this yourself? I'm looking for the jQuery equivalent to Prototype's identify method

Here's an example. I have some HTML structure on a page that looks like this

<span id="prefix_1">foo bar</span>
...
<div id="foo">
   <span></span>
   <span></span>
   <span></span>
</div>

I want to assign each of the spans an ID that will be unique to the page. So after calling something like this

$('#foo span').identify('prefix');   //fake code, no such method

The rendered DOM would look something like this

<span id="prefix_1">foo bar</span>
...
<div id="foo">
   <span id="prefix_2"></span>
   <span id="prefix_3"></span>
   <span id="prefix_4"></span>
</div>

Is there anything official-ish/robust for jQuery, or is this something most jQuery developers roll on their own?

+3  A: 

Not that I know of, but you could do this yourself by adding the id attribute and supplying a GUID.

To add the attribute:

$(foo).attr( "id", createGuid() );

For the createGuid() implementation, see this question.

Note that you could easily turn this into a jQuery plug-in so that this function (you could even name it identify()) is available on any $-expression.

Jason Cohen
Yeah, it's not *too* difficult a concept to implement. Another approach would be to store a reference count on the plugin function and increment it each time it was called. I was/am hoping for something more official that will catch any edge cases I haven't thought of.
Alan Storm
Understood and agreed about getting a more "native" method! I'm interested in a better answer too...
Jason Cohen
(The info/code is appreciated, and worth an up-vote, in case that wasn't obvious)
Alan Storm
A: 

Maybe try

$("#foo span").each(function(){
   $(this).attr("id", "prefix_" + $(this).parent().index($(this)));
});
Birk
Those won't be globally-unique, which you typically want in an ID.
Jason Cohen
+12  A: 
jQuery.fn.identify = function(prefix) {
    var i = 0;
    return this.each(function() {
        if($(this).attr('id')) return;
        do { 
            i++;
            var id = prefix + '_' + i;
        } while($('#' + id).length > 0);            
        $(this).attr('id', id);            
    });
};

$('span').identify('test');

Tested this on:

<span id='test_2'></span>
<span>test1</span>
<span>test2</span>
<span>test3</span>

Turned it to:

<span id="test_2"></span>
<span id="test_1">test1</span>
<span id="test_3">test2</span>
<span id="test_4">test3</span>
Paolo Bergantino
The code works and is appreciated, but I'm still looking for something that's been around a while and proven itself in the wild (which is in no way a criticism on your provided code)
Alan Storm
I poked around the jQuery website before writing this and I couldn't find anything, but I get it where you're coming from. I think I covered everything, though.
Paolo Bergantino
Well done Paolo.
Prestaul
+2  A: 

Based on Paolo's solution:

jQuery.fn.identify = function(prefix) {
    var i = 0;
    return this.each(function() {
        if($(this).attr('id')) return;
        do { 
            i++;
            var id = prefix + '_' + i;
        } while($('#' + id).length > 0);            
        $(this).attr('id', id);            
    });
};

$('span').identify('test');

A small change that will avoid to re-count already used ids.

gizmo
This is how I had it originally, but if there is only element named 'test_2', it will jump straight to 'test_3' without ever doing 'test_1' - I am not sure if that is desired or not.
Paolo Bergantino
Yep, that's because of the "i" argument in the "each" call. I've remove it to avoid this issue.
gizmo
Yup. Arrived at it too.
Paolo Bergantino
+1  A: 

I'd modify the given function slightly and make it:

jQuery.fn.identify = function(prefix) {
    var i = 0;
    return this.each(function() {
        if($(this).attr('id')) return;
        do { 
            i++;
            var id = prefix + '_' + i;
        } while(document.getElementById(id) != null);            
        $(this).attr('id', id);            
    });
};

ID's could contain special characters that would require escaping in order to work properly with jQuery's CSS selector engine--like ".". So instead of finding them and escaping them, it's simpler and faster to replace it with the document method.

Andy Edinborough