views:

416

answers:

2

I'm trying to set the "onclick" attribute of a link generated with jQuery.

While other attributes work without problem (eg. href, but also other custom attrs), setting "onclick" seems to only work in FireFox. On other browsers the attribute just gets ignored.

Any hint? Is this behaviour correct? And why?

<html><head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
<script type="text/javascript">
  jQuery(function(){
    var obj = $('<a/>');
    obj.html('click me');
    obj.attr({'href':'#test', 'onclick':'alert("o hai"); return false;'});
    $('body').append(obj);
  });
</script>
</head><body /></html>

EDIT: I know about the .click() jQuery method; but that's not the point, I just want to set the attribute and can't figure out why it doesn't work like any other attr does.

+2  A: 

try it jQuery way....

<script type="text/javascript">
  jQuery(function(){
    var obj = $('<a/>');
    obj.html('click me')
       .attr('href','#test')
       .click(function() {
            alert("o hai");
            return false;
        })
    $('body').append(obj);
  });
</script>

edit: try changing onclick to onClick, note the capital "C"

jQuery(function(){
    var obj = $('<a/>');
    obj.html('click me');
    obj.attr({'href':'#test', 'onClick':'alert("o hai"); return false;'});
    $('body').append(obj);
  });
Reigel
I know "the jQuery way". I need to set the attribute though, and I can't figure out why it isn't working.
Patonza
please see edit...
Reigel
Using "onClick" with the capital C does work on both FF and Chrome. Thank you. It's fairly odd, though, that Chrome DOM inspector shows an attribute with the lowercase "c". And anyway it's still broken on IE, but that may be another problem.
Patonza
All event handler attributes are explicitly lower-case-only as DOM properties. Passing `onClick` to jQuery only makes it work in more browsers because it side-steps an internal optimisation where jQuery sets existing properties directly instead of using `setAttribute` (see jQuery 1.4.2 line 1486), which is case-insensitive in non-XHTML HTML. It still won't work in IE, and it's inadvisable anyway.
bobince
+3  A: 

Is this behaviour correct?

In as much as attr('onsomeevent', ...) has never been the way to add event listeners, has never been supported, and only works on Firefox due to coincidence, yes.

And why?

Because IE before version 8 can't directly get/set HTML attributes. Calling setAttribute() only sets a DOM property of the same name. And the onclick property isn't a string property so you can't write a string to it. It only accepts a function value.

jQuery's attr() muddies the issue by being called attr but actually writing to DOM properties and not HTML attributes... but using HTML attribute names (like eg. class) rather than DOM property names (like className).

(Except when it doesn't, because for some cases it tries to hide the difference by using attributes. Except that still doesn't work all the time in IE for the reason above. This is not one of jQuery's proudest moments.)

Anyhow, in general having JavaScript in a string is a code smell. The best way forward for jQuery and modern JavaScript in general is to use function objects (possibly inline function() { ... } expressions) instead.

bobince
Not an answer, issue existed even on Google Chrome, and I was not trying to set an event handler, just the DOM attribute.Thank you anyway.
Patonza
As I said, `attr()` sets a DOM property. It's exactly the same as saying `element.onclick= 'alert()';`, which is obviously invalid. Event handler properties require a function value, not string.
bobince
Well thanks, then. I though that DOM properties could contain any object type and then eventually fail when called as en event handler if not of the 'function' type.
Patonza
@Patonza: It is an answer, just clearly not the answer you wanted to hear. In fact, this is the only answer here that directly targets your specific questions, `is this behaviour correct?` and `And why?`. @bobince: +1 for going into the detail for `attr` that I couldn't be bothered to ;-)
Andy E
Yes, it is an answer. I didn't understand the concept of "onclick property isn't a string property". I thought javascript object properties could accept any object type. Now I learn that DOM is strongly typed. Thanks again for the clarification :)
Patonza
Well, *relatively* strongly. JavaScript will do some kinds of conversion for you, eg. if you write an integer to a string property it'll `toString()` it. But there's no built-in coercion from string to function (nor could there be, at a language level). HTML attributes are a different case, but `attr()` isn't talking about attributes. Except when it is. (Argh!)
bobince