Perfection Kills

by kangax

Exploring Javascript by example

← back 401 words

Common mistakes and how to avoid them

Here’s another list of things that tend to confuse unexperienced “prototypers”:

1) Preventing default event behaviour:

All-famous return false; is good for inline snippets but doesn’t give the desired effect when used in Event#observe‘s callback. To prevent default event behavior we should call event.stop() (Event.stop(event) in 1.5.1 and earlier) method. Don’t forget to pass the actual event object as a first argument to callback function.

Wrong:


$('someLink').observe('click', function(){ doSomething(); return false; })

Right:


$('someLink').observe('click', function(e){ e.stop(); doSomething(); }) // Event.stop(e) in v1.5.1 and earlier

2) Extending element and IE issues

Internet Explorer unfortunately does not allow to touch its HTMLElement.prototype object, so elements can not be extended at the top level. We can still make IE behave nicely by extending them explicitly (usually wrapping with Element.extend or $). Doing that before using prototype’s syntactic sweetness will make your code bullet-proof.

Wrong:


document.body.insert(new Element('div', {className: 'loginPopup'}));

Right:


$(document.body).insert(new Element('div', className: 'loginPopup'));

Wrong:


var link = document.createElement('ul');
link.addClassName('ratingWidget'); // IE throws error: "Object does not support this property or method"

Right:


var link = Element.extend(document.createElement('ul'));
link.addClassName('ratingWidget');

As an alternative to Element.extend we can just wrap element with $ (automatically extending it)


var link = document.createElement('ul');
$(link).addClassName('ratingWidget');

or to make it more concise (using new 1.6+ goodie)


new Element('ul', {className: 'ratingWidget'}); // new Element() extends element automatically

3) Unnecessary constructions or how to “keep it simple”

This one is obvious, yet I see it all the time.
Function, specified as a callback for Ajax requests, is being passed a response object automatically (so we don’t have to pass it explicitly).
The only thing we need to do is make sure to reference that object as a first argument when defining a callback function:

Wrong:


new Ajax.Request('get.php', {
  onSuccess: function(json) {
    populateLocations(json)
  }
});

Right:


new Ajax.Request('get.php', {
  onSuccess: populateLocations
});
...
var populateLocations = function(json) {
  // here we have our json object even without passing it explicitly to onSuccess callback
  // it can now be used to insert/interpolate some template into some container
  $('locationsContainer').insert(locationsTemplate.interpolate(json));
};

Did you like this? Donations are welcome

comments powered by Disqus