15

Preface

  • Please note, I'm not looking for a code solution, but rather insight into why this may occur.
  • The error occurs in IE (tested 7 & 8), but not Firefox, Chrome, Safari.

Description

When manually calling a function assigned to onclick, IE with throw a Error: Object doesn't support this action if all of the following conditions are met:

  1. You call the method directly via the element's on[event] property.
  2. You do not use .call() or .apply().
  3. You pass an argument (any argument, even undefined).
  4. You attempt to assign the return value to a variable.

Violate any one of those rules, and the call succeeds.

The function itself appears to have nothing to do with it. An empty function gives the same result.

Code

var elem = document.getElementById('test');  // simple div element.
var result;               // store result returned.

function test_func(){};   // function declaration.
                          // function expression behaves identically.

elem.onclick = test_func; // assign test_func to element's onclick.

// DIRECT CALL
test_func();                 // works
test_func( true );           // works
result = test_func();        // works
result = test_func( true );  // works

// DIRECT CALL, CHANGING THE CONTEXT TO THE ELEMENT
test_func.call( elem );                  // works
test_func.call( elem, true );            // works
result = test_func.call( elem );         // works
result = test_func.call( elem, true );   // works ******** (surprising)

// CALL VIA ELEMENT, USING .call() METHOD, CHANGING THE CONTEXT TO THE ELEMENT
elem.onclick.call( elem );                  // works
elem.onclick.call( elem, true );            // works
result = elem.onclick.call( elem );         // works
result = elem.onclick.call( elem, true );   // works ******** ( very surprising)

// CALL VIA ELEMENT
elem.onclick();                 // works
elem.onclick( true );           // works
result = elem.onclick();        // works
result = elem.onclick( true );  // Error: Object doesn't support this action

Summary

Again, I don't need a code solution. Rather I'm curious if anyone has insight into why IE is implemented this way.

Many thanks.


EDIT: To clarify one thing, nothing with the actual function seems to make any difference. Naming parameters, not naming them, returning the argument, returning a literal value, returning undefined, all of these have no effect.

This is likely because the function seems to never actually get called. As I noted in a comment below, the code leading up to this call runs fine, so it isn't a parsing issue either. But when the interpreter gets to this one, it sees:

Variable + AssignmentOperator + DOMElement + EventHandler + CallOperator + Argument

...and throws the Error. No manipulation I do seems to make any difference. A valid removal of any one of those, and the Error disappears.

If I place add a variable to the middle of it that stores the handler, then fire it from the variable it works.

var temp = elem.onclick;
result = temp( true );    // works

...but this shouldn't be much of a surprise, since it is effectively the same as the fourth version above.

user113716
  • 318,772
  • 63
  • 451
  • 440
  • 3
    Can you elaborate on your "surprising" and "very surprising" annotations? To me, none of them are surprising. The last snippet surprises me, though. Assigning the return value of a function to a variable should not yield "doesn't support this action". – August Lilleaas Nov 09 '10 at 20:50
  • @August Lilleaas - Surprising only when you compare them to the one that receives the `Error:`, since like that one, they are called from the context of the element, are passing an argument, and are assigning the return value. Otherwise, not surprising at all. – user113716 Nov 09 '10 at 20:57
  • Haven't got an idea yet about the other conditions, but clearly .apply and .call create a new copy of the function. That's why it works in that case. – MartinodF Nov 09 '10 at 22:13
  • If I had a nickel for every time I asked IE "why"... – Josh Stodola Nov 09 '10 at 22:46
  • @MartinodF - That's an interesting thought, although looking at the spec, it seems as though the Function object's `.call()` method calls the object's own internal `[[Call]]` method instead of creating a new object. Of course, we're talking about IE, so who knows. :o) – user113716 Nov 09 '10 at 23:07
  • @Josh - Yeah, I've got a feeling that I'll have to be satisfied with the old *"it's IE, what do you expect"* answer. Although part of me is holding out that CMS or someone may stop by with a brain-melting explanation. :o) – user113716 Nov 09 '10 at 23:11
  • Without seeing the source of IE there is probably no definitive answer. Maybe just calling the event through the default function happens to invoke a bit of code that, contrary to what you'd expect from JavaScript, checks the arguments before forwarding call to the actual event handler. Have you tried assigning a one-arg function as the event handler? – Georg Fritzsche Nov 09 '10 at 23:14
  • @patrick dw - Yep, you're right. I wouldn't be surprised if this issue was one of the major memory leak causes in IE though ;) – MartinodF Nov 09 '10 at 23:19
  • @Georg Fritzsche - If you mean assigning a function that has one parameter defined, then yes I tried that. Same result. I can't seem to find anything with the function itself that affects the behavior. – user113716 Nov 09 '10 at 23:20
  • @MartinodF - Wouldn't surprise me. I wish I had access to a machine with IE9 beta. If anyone can test it, I'd be curious to know the result. – user113716 Nov 09 '10 at 23:22
  • @patrick dw - Wait a sec, I'll be back with the results – MartinodF Nov 09 '10 at 23:24
  • @Georg Fritzsche - The really strange thing is that it works when passing an argument, or when attempting to assign the return value to a variable, but when *both* of those circumstances exist, it fails. – user113716 Nov 09 '10 at 23:27
  • 3
    @patrick dw - Works just fine in IE9 beta, no error. Seems they did something good after all ;) – MartinodF Nov 09 '10 at 23:28
  • @MartinodF - Thanks so much for taking the time to test it for me. Doesn't surprise me too much that it is fixed, since it seems from what I've read that IE9 is making some great progress. – user113716 Nov 09 '10 at 23:32
  • 3
    Where's [EricLaw](http://stackoverflow.com/users/126229/ericlaw-msft) when you need some insight into a strange IE bug? :-p – Andy E Nov 09 '10 at 23:54
  • @MartinodF: No, calling a `Function` object's `call()` or `apply()` method do not create a new function. They merely call the function with a set of parameters (if you consider `this` to be a kind of implicit parameter, which is quite a useful way to think of it). – Tim Down Nov 10 '10 at 00:54
  • @Tim Down - Thanks, patrick dw already pointed that out ;) – MartinodF Nov 10 '10 at 01:00
  • Wow, a down-vote and a vote to close? How could a specific behavior in IE be considered *"an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet"* ? – user113716 Nov 10 '10 at 12:58
  • @patrick: I reckon the question's going to be safe from closing. It's much more interesting (to me) than the daily grind of near-duplicates and beginner questions. – Tim Down Nov 10 '10 at 13:30
  • Thanks @Tim. It consumed a few of my hours yesterday. Hate to see it go away. Not sure if I'll get any answer beyond *"it's a bug"*, but the information could be useful to someone else. – user113716 Nov 10 '10 at 13:51
  • @patrick: This is exactly the kind of question I'd suggest asking in comp.lang.javascript (http://groups.google.com/group/comp.lang.javascript/topics). The regulars in there are seriously knowledgeable about this kind of thing. – Tim Down Nov 10 '10 at 14:03
  • @Tim The regulars in there are selling Air Jordans, Ugg boots, and Viagra! – Josh Stodola Nov 10 '10 at 16:01
  • @Josh: ... and sometimes promises of naked videos of lady celebrities. A combination of spam, Stack Overflow and a somewhat hostile tone (in that order) has seriously diminished that newsgroup, but it's still where I'd go for this kind of question. – Tim Down Nov 10 '10 at 16:17
  • @Tim - Thanks for the suggestion, but I'll probably just let it ride here for a while. If at some point I feel up to the apparent aggravation I'll experience there, I may give it a shot. :o) – user113716 Nov 10 '10 at 16:51

3 Answers3

3

As to "why" it was implemented this way, there's probably no answer from the outside. A good example is when former IE developer, the inventor of innerHTML, faces problems with innerHTML itself.

Asking why is also unnecessary because

  1. You don't often call event handlers with parameters explicitly
  2. You can work around the issue (as you stated in your question)

Another thing to note is that your analogy is too specific. The issue is not restricted to the assignment expression, you can reproduce it with other types of expressions:

undefined === elem.onclick( true )
typeof elem.onclick( true )
elem.onclick( true ) - 1
alert(elem.onclick( true ))
gblazex
  • 49,155
  • 12
  • 98
  • 91
  • +1 For good points and the link to very interesting article. Yes, I do have workarounds and you're right that this is not a common use of event handlers in the first place. It's just that it was such an odd situation, working fine with the argument until you decide to do an assignment (or other expression as you noted), that I thought I must have been missing something obvious, or at least knowable. Anyway, thanks for your input. I'm going to let this one stand out there for a little while longer, but you're probably right that it will take just the right insider to actually explain it. – user113716 Nov 14 '10 at 13:28
0

Have you tried using the instructions found here? He suggests using code like this:

var fireOnThis = document.getElementById('someID');
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent( 'click', true, true, window, 1, 12, 345, 7, 220, false, false, true, false, 0, null );
fireOnThis.dispatchEvent(evObj);
Anthony Corbelli
  • 877
  • 4
  • 10
  • 3
    IE 7 and 8 don't support `document.createEvent` or `.initMouseEvent` or `.dispatchEvent`. – Andy E Nov 09 '10 at 23:07
0

Try some function that actually has one parameter and actually returns something. See if it produces an error too. It may have something to do with parameters and a function default return value. Try it and post the results back, please.

EDIT

If the function does not get called, the problem could be in the resolution of the property onclick. It may be somehow you are not actually calling your defined function, but the code finds some other build in IE object when you pass true as parameter. In any case this behavior is out of any specifications and so we may call it bug. Of those IE has plenty as you can see from my own questions.

IE 8 absolute positioned element outside its parent clipping problem

IE8 bottom:0 in position:absolute behaves like position:fixed

Community
  • 1
  • 1
Boris Hamanov
  • 3,085
  • 9
  • 35
  • 58
  • 1
    Good point, but I had tried that. I attempted all variations of the actual function that I could think of. Nothing I did to it seemed to make a difference. This is probably because the function doesn't seem to get called at all. If I just put a simple `.alert()` in there, it doesn't fire. It isn't a parsing issue, since code leading up to it fires. But when the interpreter gets to that one, it's like it sees *Variable + Assignment + Element + HandlerProperty + CallOperator + Argument* and says nope. :o) Every one of those is required for the failure. – user113716 Nov 10 '10 at 02:03
  • Regarding your edit, it doesn't mind the argument (any argument), and it doesn't mind the assignment. But having both causes it to freak out. I've just been trying to find some way to rationalize it. I guess IE is the wrong place to try to be rational. ;o) – user113716 Nov 10 '10 at 13:07