Categories
Uncategorized

JavaScript Gotchas

This just cost me and a colleague about an hour.

  var headers = mydiv.getElementsByTagName('h3');
  for (var i = 0; i < headers.length; i++) {
    // ...
  }

When run, this wasn’t going inside the for loop at all (in IE; firefox worked). So we stuck in an alert to see what headers.length came out as. [object] apparently.

After much chasing around the houses, we looked closer at the original HTML:

  <h3 id='length'>Some Header</h3>

It’s a miracle that this worked at all in firefox. What was happening is that the length property of the headers collection was being shadowed by the element with an id of length. That’s happening because the collection is an HTMLCollection, and the JavaScript DOM bindings specify that you can also index by id into that collection. And because functions and properties share the same namespace in JavaScript, disaster ensues.

So the lesson to take away from all this is that you should take great care to avoid using id’s that are the same as existing method or property names. Eric Meyer found the same things some time ago: Reserved ID Values.

Categories
Uncategorized

JSLint Backlash

Typically enough, two days after I start on something, there’s a backlash. Dean Edwards (whom I respect highly) points out that JSLint is not a silver bullet in JSLint Considered Harmful.

(aside: everybody please read ‘Considered Harmful’ Essays Considered Harmful. Thank you)

The post he links to brings up a number of valid points about where valid uses of JavaScript can be flagged up by JSLint. This is perfectly reasonable. For example, you rarely want to use eval() in JavaScript, but when you need it, it’s the only way to do what you want. In that case, JSLint provides a flag to disable the warning.

But the real point is that you can’t just blindly follow results from a tool for what are ultimately stylistic issues like these. You have to use your knowledge as a programmer to interpret the output and agree / disagree with each point as appropriate. The purpose of JSLint is to flag areas that might be of concern, or perhaps be liable to bugs. It’s not saying “this is a bug, absolutely, for sure”.

One thing which might be useful (although I have no idea how easy it would be to implement) would be to be able to specify hints in the same manner that you could for C lint. There is already one example (declaring external definitions), but there could be more.

Whilst I am sure that it has it’s flaws, I’m extremely glad to see tools like JSLint being made available. Analysis tools like these help to move JavaScript from being “toy for websites” to “useful programming language”.

Now all I want is a JavaScript equivalent of perltidy

Categories
Uncategorized

JavaScript::Lint 0.02

I’ve just put together a new version of JavaScript::Lint. The main new thing is that you can now specify options to control how the lint works. You probably want to enable the undef option, for instance.

I also fixed a problem where I was covering up errors when the lint couldn’t do anything more (e.g. nested comments). After my mailing Douglas Crockford about it, he kindly pointed out that this was mentioned in the comments. I’d entirely missed it. Ah well. Anyway, it now returns a “cannot proceed” message.

Update: after spotting something rather stupid, I’ve now uploaded JavaScript::Lint 0.03 instead.

Categories
Uncategorized

JavaScript::Lint

After whinging gratuitously about how cruddy non-browser JavaScript is, Mark Fowler kindly pointed me in the right direction to get Perl integration working: JavaScript.pm.

So now I’ve wrapped up JSLint into a small command line tool (and Perl lib), JavaScript::Lint.

It’s fairly simple at the moment. I plan to add support for the options in jslint soon.

Categories
Uncategorized

JSLint

Jeremy pointed me at an article mentioning JSLint today. It’s a fantastic idea, and even more astounding, it’s actually implemented in JavaScript. This is great for showing it off as “the little language that could”.

The only problem is that it doesn’t integrate well with my development environment. I normally use TextMate or Vim. JSLint needs a JavaScript runtime, which is conveniently loaded into my browser, but inconveniently not loaded into my command line. So I set out looking for a way to come up with a command line version of JSLint.

The JSLint web site actually points out a few options. But I don’t run windows (for WSH) or Konfabulator, so that’s no good. I could try using Rhino, but I’d rather avoid a heavyweight JVM invocation (1.5s to run is too slow).

The first port of call is Mozillas spidermonkey. Handily, this is already in my FreeBSD ports collection, so it’s a quick install. But there’s one slight problem—it provides no way to do I/O. So I can’t tell it to read stdin to get the JavaScript to check. Interestingly:

  • Rhino does provide a ReadFile() call, but not spidermonkey. How annoying.
  • Spidermonkey provides a File() constructor, but it doesn’t appear to compile when enabled (I think this is down to spidermonkey being disassociated from the main mozilla source tree).

So, let’s try another little hack. There’s another port available, lang/p5-JavaScript-SpiderMonkey. I should be able to use a small amount of Perl to complete the task. Except that the API is bizarre, baroque and hangs when I feed it jslint. Grrr.

On to njs. That fails to even parse the blasted fulljslint.js, stopping on the first line with an unexplained “syntax error”.

Oh well. I guess I’d better go and try to get SpiderMonkey working again.

It’s really depressing that it’s so hard to get JavaScript working outside of the browser.

Update: Ian Bicking is coming to much the same conclusions about this…

Categories
Uncategorized

London JavaScript Night

I’ve just gotten back from LJS. It was an excellent evening of talks (bar mine, I feel). The two talks I really wanted to see (“JavaScript Idioms” by Paul Hammond and “JavaScript Taste Testing” by Simon Willison) were superb.

Paul Hammond gave a very good overview of why things often look a bit funny in JavaScript, but are actually sensibly thought out. His idioms in other languages managed to draw puzzled looks and laughs in almost equal amount.

Simon did a whirlwind tour of Dojo, Prototype, the Yahoo UI Library and MochiKit. It was a pretty well thought out and explained piece of work. He did a good job of showing where the tradeoffs lie in each case. It’s also made me realise how much I need to try the alternate toolkits to get a feel for them… (NB: Apparently YUI makes a best effort at accessibility for its widgets, which sounds like a Good Thing™).

Of the remaining talks, I really enjoyed Dan Webb’s DOMBuilder, which strikes me a an extremely elegant solution to the verbosity of the DOM.

Tom Insam’s enthusiasm for E4X was extremely entertaining, despite the ending (“It’s hardly worth bothering”).

It was a difficult act to follow, and to be honest, I completely tanked. I had expected about 30 people, and there were around 200. Plus my topic was relatively obscure to most people. Ah well. Next time I’ll find a better subject (and practise more beforehand). Oh, and get a proper PDF presentation instead of S5. That would have been much easier to handle. BTW, the slides are up.

Hopefully the slides for the remaining talks will be up in the next day or two.

A big thanks to Greg McCarroll for organising it all in the first place. Good job, Greg.

Categories
Uncategorized

Firebug 0.4 Preview

firebug is one of the best tools I’ve seen for web development in Firefox. There’s a new version due out soon, and Encytemedia have put up a fantastic preview. I’m drooling with anticipation!

Categories
Uncategorized

Prototyping Squirrels

There’s a new article on xml.com: ExplorerCanvas: Interactive Web Apps. It’s all about chasing squirrels with a web page. So far so good.

But I noticed that the author is using Prototype. Good stuff! Great way to cut down on having to do a lot of stuff yourself.

Yet reading through the article, it seems that the only thing it’s being used for is the $() function and the Ajax bits. I base this on the fact that on page 2, the wheel (in the form of event handling) is completely reinvented. Why bother including all of Prototype if you’re going to ignore large bits of it? You can cut’n’paste $() in a few lines of code instead…

Personally, I’d spend a short amount of time reading a couple of the really good articles on Prototype:

Remember: Prototype isn’t just for Ajax.

Categories
Uncategorized

London JavaScript Night

The wonderful Greg McCarroll of london.pm is organising London JavaScript Night. If this is anything like the Perl tech meets, I expect it to be well run. I’m already looking forwards to both the full-length talks on that page, and I can’t wait to find out what the lightning talks have in store.

Categories
Uncategorized

Subclassing with Prototype

I really like Ajax.InPlaceEditor from script.aculo.us. But it doesn’t quite do what I need. Nonetheless, bending it to my will ought to be fairly simple if I can just override a method or two.

This involved getting very familiar with Prototype’s Class.create and Object.extend.

After spending a while looking at the source for those two, my big book of JavaScript, and google, I was still flummoxed. Until I scrolled down a bit in controls.js (where Ajax.InPlaceEditor) lives. I saw this example of inheritance:

  Ajax.InPlaceCollectionEditor = Class.create();
  Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
  Object.extend(Ajax.InPlaceCollectionEditor.prototype, { ... });

That is:

  1. Create a new class (or constructor function to be accurate).
  2. Copy all the template functions from the source class into the destination class.
  3. Start adding our own functions into the class.

This is a good start! But there’s a tricky problem that I need to overcome: I wanted to override the constructor and run some code after the base class constructor. There’s no easy way to do this, because there is no link between the new class and the inherited one after you have called Object.extend(). So, you just have to be very explicit about exactly what you want to do. This is what I ended up with:

  var MyInPlaceEditor = Class.create();
  Object.extend(MyInPlaceEditor.prototype, Ajax.InPlaceEditor.prototype)
  Object.extend(MyInPlaceEditor.prototype, {
      initialize: function(element, url, options) {
          Ajax.InPlaceEditor.prototype.initialize.apply(this, arguments);
          // Don't respond to events on the main element of interest.
          // Only listen to events on the externalControl.
          Event.stopObserving(this.element, 'click', this.onclickListener);
          Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
          Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
      }
  });

It’s that line at the start of initialize() that’s the interesting one. It grabs the initialize() from Ajax.InPlaceEditor, and then uses apply() to call it using the new MyInPlaceEditor object as this. So it gets treated like it’s part of MyInPlaceEditor, even though it’s really defined in Ajax.InPlaceEditor.

So now I’m in a position to start overriding the other bits that I care about.