1

I want to have a function that generates ID's on the fly for a given jquery object, if it doesn't have one already. These ID's should then be used in future requests.

I came up with the code below, but it doesn't work. The ID's are never set. The commented out alert statement below always return undefined.

I always pass code like $(this) or $(options.el) as a parameter to substitute 'el'. Initially, the elements do not have explicitly ID set in HTML.

Any help would be appreciated, here's the code:

getElementId: function(el) { if(undefined == el.attr('id')) { el.attr('id',"anim-"+Math.random().toString().substr(2)); } // alert(el.attr('id')); return el.attr('id'); }, 
12
  • What browser have you tried this in? Is your if statement evaluating to true? i.e., if you add an alert before your el.attr('id', 'anim... does it execute? you can try stepping through your code in firebug and see if it breaks on that statement Commented Feb 23, 2011 at 15:20
  • 4
    are you getting any errors? Is el a jQuery object? If it is not then .attr wont work for you. Commented Feb 23, 2011 at 15:20
  • you can also try if((typeof(el.attr('id'))).toString() == 'undefined') { Commented Feb 23, 2011 at 15:21
  • 1
    @Jaitsu: typeof is an operator, not a function, so the parentheses are unnecessary in this case. typeof always returns a string, to the toString() call is completely unnecessary. And, since you know you're always comparing strings to strings, you should be using === (the strict equality operator), not == (the type-coercing equality operator). Commented Feb 23, 2011 at 15:23
  • 1
    @Matt Ball: I personally only use == when I have a specific purpose for type coercion (usually when I'm doing x == null). My point is that it doesn't make sense to say you shouldn't use the type-coercing operator when there will be no type-coercion. In such a case, it makes no difference which you use. Commented Feb 23, 2011 at 15:42

5 Answers 5

4

Test the truthiness of the valued returned by .attr(), and make sure that el is actually a jQuery object.

getElementId: function(el) { if (!el.jquery) { el = $(el); } if(!el.attr('id')) { el.attr('id',"anim-"+Math.random().toString().substr(2)); } // alert(el.attr('id')); return el.attr('id'); }, 

Depending on the attribute you're trying to retrieve, .attr() may return undefined or "".


Other recommended cleanup:

getElementId: function(el) { if (!el.jquery) { el = $(el); } var id = el.attr('id'); if(!id) { // make sure this ID hasn't actually been used before! do { id = "anim-"+Math.random().toString().substr(2); } while (!$('#' + id).length); el.attr('id', id); } return id; }, 

You really need to make sure that you're not assigning an ID to that element which has already been used before. The above function does this. A simpler way to accomplish the same thing is to use an incrementing counter stored somewhere outside of the scope of the function:

__idCounter__: 1, getElementId: function(el) { if (!el.jquery) { el = $(el); } var id = el.attr('id'); if(!id) { id = "anim-" + (this.__idCounter__++); el.attr('id', id); } return id; }, 

Last edit (I promise)

There seems to be confusion about what .attr() returns when an element does not have the attribute requested. After running some tests, it looks like .attr() returns:

  • the empty string for at least id and class (perhaps other HTML4-spec attributes as well; didn't test)
  • undefined for other attributes not defined by the spec

Output from my tests:

<div id="myID"/> id: myID <div id="myID"/> class: <div id="myID"/> data-attr: undefined <div id="myID"/> asdf: undefined <div class="myClass"/> id: <div class="myClass"/> class: myClass <div class="myClass"/> data-attr: undefined <div class="myClass"/> asdf: undefined <div data-attr="myAttr"/> id: <div data-attr="myAttr"/> class: <div data-attr="myAttr"/> data-attr: myAttr <div data-attr="myAttr"/> asdf: undefined <div asdf="myNonSpecAttr"/> id: <div asdf="myNonSpecAttr"/> class: <div asdf="myNonSpecAttr"/> data-attr: undefined <div asdf="myNonSpecAttr"/> asdf: myNonSpecAttr 

tl;dr

Just test the truthiness of the value returned by .attr(), since that treats undefined and "" (the empty string) the same:

if (somejQueryElt.attr('someAttr')) { // it definitely has the attribute } else { // it definitely does not have the attribute } 
Sign up to request clarification or add additional context in comments.

Comments

2

Try changing:

if(undefined == el.attr('id'))

to:

if("" == el.attr('id'))

2 Comments

jQuery returns en empty string on unset attributes... Don't ask me why, even the doc says it should return undefined but a real life test shows it returns an empty string, see jsfiddle.net/d8Nmc
Thx for the investigation @Matt Ball!
1

To find any element/attribute exists in DOM you need to use length property : Proper condition is :

if (el.attr('id').length > 0 ) 

Full function:

getElementId: function (el) { return el.attr('id').length > 0 ? el.attr('id') : el.attr('id', "anim-" + Math.random().toString().substr(2)); } 

3 Comments

This is misguided advice. Yes, you use length to determine if a jQuery object is empty, but the same does not hold for attributes, which are just strings. If .attr() returns undefined (which it does in jQuery 1.5 for nonexistent attributes), then checking the length property will throw an exception.
@ Matt Ball : i assumed that he is using jquery 1.5 prior. unless only checking if(!el.attr('id')) would work.
I did a little investigating and it looks like I was wrong about when .attr() returns "" vs undefined (see my edit). You nailed it, however: just check if(!el.attr('id')).
0

Adding a simple debugging statement in your code would show you why no id is being set.

getElementId: function(el) { alert(el.attr('id')); if(console)console.log(el.attr('id')); if(undefined == el.attr('id')) { el.attr('id',"anim-"+Math.random().toString().substr(2)); } // alert(el.attr('id')); return el.attr('id'); }, 

You will see the alert does not return undefined. It returns an empty string

getElementId: function(el) { var id = el.attr('id'); if(id.length===0) { id="anim-"+Math.random().toString().substr(2); el.attr('id',id); } return id; }, 

I also hope you know that math.random is really not random. You should have some sort of counter.

Comments

-1

Maybe your condition should be like this:

if (typeof el.attr('id') === 'undefined')

3 Comments

Using jQuery, attr() on a non existent attribute will never be undefined, it will be an empty string, see @pimvdb correct answer
Aaaah, it returns an empty string in jQuery 1.4, how vicious is that?
And jQuery 1.5 returns en empty string on Fiddle. The doc is wrong or this is a bug... See jsfiddle.net/d8Nmc

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.