RSS
 

Scoping with HTML and inline event attributes

12 Dec

Just the other day on Stack Overflow, I saw a seemingly uninteresting question with the following code:




The user’s problem was that the call to click() wasn’t executing correctly, but if he changed the name of the function it did. I’ll admit that I wasn’t really in the mood for this type of question, so I brushed it off and moved on. The subject arose again in the JavaScript chat room where Pointy, a frequent flyer in the JS tags, was attempting to get to the root of the problem. My initial thought was that the user had made a mistake, but at the same time I thought it couldn’t hurt to check it out. So I fired up jsFiddle and pasted in the code. It failed silently, so I checked a couple of other browsers with the same result.

It was obvious what was going on at this point – the <button> element has a method on it named click() and the browsers were forcing the lexical scope of the function to include properties of the current object. I made a quick and dirty change to verify this:

    <button onclick="console.log(tagName)">try it</button><br />

Sure enough, the console output was BUTTON. I’m sure many experienced developers will be unsurprised at this, knowing this is the expected behaviour all along but, honestly, I’ve never encountered this before (probably due to how I like to attach my events via JS in the first place) and I don’t remember reading it in any specification. Pointy was able to find this portion of the HTML5 spec, however:

Lexical Environment Scope
  1. Let Scope be the result of NewObjectEnvironment(the element’s Document, the global environment).
  2. If the element has a form owner, let Scope be the result of NewObjectEnvironment(the element’s form ownerScope).
  3. Let Scope be the result of NewObjectEnvironment(the element’s object, Scope).


This indicates that the JavaScript equivalent for an element contained within a form would be something like this:

element.onclick = new Function(
    "event", 
    "with (document) { with (this.form) { with (this) { /* function code */ }}}"
);

I verified this by quickly testing getElementById without referencing the document object first. It worked just fine.

Now, after seeing all this, I’m left with several questions in my head all revolving around one important question — why? — why does anyone feel like it is necessary to do all this? I can’t think of any positive reasons for it to be this way, only reasons for it not to be this way:

  • The document object and the host element for the event are both very easily accessible from within the function’s scope.
  • NewObjectEnvironment() has taken a lot of flak over the years, the only thing that uses it is the with statement and Crockford likes to remind us that with statements are harmful, like in this example, we might not know if click() belongs to the element, the form containing it, the document or the window. It’s also very inefficient.


The only reason I can think of that this is in the HTML 5 specification is for backwards compatibility. This might be the way the coding dinosaurs wrote their HTML and JavaScript 15 years ago and this feature has survived since Netscape Navigator 2.0. In my opinion, this isn’t an excuse and it should have been deprecated and removed long ago. I don’t feel so badly about it for myself, though, I’ve got by for years without even encountering this behaviour and I’m sure it will never affect me in the future, unless I’m working with someone else’s code. Just one more reason to attach your event handlers using script, I suppose.

 
 

Tags: , ,

Leave a Reply

 

 
  1. Zach

    January 7th, 2011 at 4:16 pm

    Hey, totally unrealted, but I saw you posted on another blog talking about the comodo code signing cert. I’m also having trouble getting my cert (bought it in chrome, now i cant retrieve it.) Did you have any luck in getting this resolved? Please shoot me an email to the address on this comment.

    Thanks!
    Z

     
    • Andy

      January 14th, 2011 at 1:33 pm

      Hi Zach, sorry for the late reply.

      After looking around for a Chrome based solution for a while, I realized there wasn’t one. Eventually, I gave in and filed a ticket on https://support.comodo.com/. They got back to me quickly enough, and I had to go through the purchase process again – right up to the checkout part, but closing the browser before giving payment details – in Internet Explorer.

      Yes, it’s horrendous that Chrome doesn’t support this but it’s even worse that there’s no feature detection that stops you from actually buying a certificate in Chrome.

       
  2. vick

    April 12th, 2013 at 6:49 pm

    HTML Attributes are property of the elements which may have values and these attribute values are always enclosed in quotes. It’s providing to the browser with some additional information about an elements how the elements should appear or behave. HTML elements can contain one or more attributes, attribute names and attribute values are case-insensitive and separated by an equals (=) sign.

    [HTML Attributes](http://www.willvick.com/HTML/HTMLAttribute.aspx)

    [HTML Attributes Examples](http://www.willvick.com/HTML/HTMLExampleAttribute.aspx)

    [Youtube - HTML Tutorial - Attributes](http://www.youtube.com/watch?v=ucOXvaCEZgg)