1) Detecting key events easily
How do we detect which key was pressed? Prototype provides set of
key event aliases so that we don’t have to remember that return is “13″
and escape is “27″. Almost all major keys are aliased: KEY_RETURN,
KEY_ESC, KEY_TAB, KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN. See full list in API docs
$(’myInput’).observe(’keyup’, function(e){ if (e.keyCode == Event.KEY_TAB) doSomethingCoolWhenTabIsPressed(); })
2) You won’t need event capturing (most likely)
Sometimes I see capturing phase being explicitly set to false in
Event’s observe method. The good thing is that it’s set to false by
default and you would rarely need to use it. The following 2 lines are
fully identical so we can just skip this last argument:
Event.observe(’productInfo’, ‘click’, displayProductInfo, false); // ‘false’ could be skipped Event.observe(’productInfo’, ‘click’, displayProductInfo);
or a short way:
$(’productInfo’).observe(’click’, displayProductInfo, false); // ‘false’ could be skipped $(’productInfo’).observe(’click’, displayProductInfo);
3) insert() wisely
Another one of those “it’s-there-by-default” values is a position
argument of Element’s insert method. Surprisingly it’s not mentioned
anywhere in the docs - I accidentally found it wondering through the
source one day. insert accepts one of four position values: top, bottom, before, and after. If we omit this argument, it defaults to bottom (and luckily this happens to be the most common case). The following lines behave identically:
new Insertion.Bottom(’blogEntry’, new Template(’<div><h2>#{name}</h2><p>#{content}</p></div>’) .evaluate({ name: blogEntry.name, content: blogEntry.content })); // Insertion class is deprecated - it’s recommended to use Element’s insert method: $(’blogEntry’).insert(new Template(’<div><h2>#{name}</h2><p>#{content}</p></div>’) .evaluate({ name: blogEntry.name, content: blogEntry.content }), ‘bottom’ ); // “bottom” can be skipped $(’blogEntry’).insert(new Template(’<div><h2>#{name}</h2><p>#{content}</p></div>’) .evaluate({ name: blogEntry.name, content: blogEntry.content }));
4) Forms gone wild
Plain form submission is quite easy but what if we want to prevent
certain elements from being serialized before submitting form via ajax?
Let’s take a look at few ways to do this:
Plain form submission using .request
$(’register’).observe(’submit’, function(e){ Event.stop(e); $(this).request(); })
Using .getInputs makes it easy to filter out elements based on type
and name attributes. In this example we’re serializing elements with
name ‘email’ and submitting result to the URI contained in form’s
“action” attribute
$(’register’).observe(’submit’, function(e){ Event.stop(e); new Ajax.Request($(this).readAttribute(’action’), { parameters: Form.serializeElements($(this).getInputs(”, ‘email’)) }) })
Using .getInputs could help most of the time but what if we want to
exclude elements that have “multiple” attribute? We might try something
like this:
$(’register’).observe(’submit’, function(e){ Event.stop(e); new Ajax.Request(this.readAttribute(’action’), { parameters: Form.serializeElements($(this).getElements() .reject(function(el){return el.hasAttribute(’multiple’)}) ); }) })
Wow, what’s going on over here?!
When submit event occurs, we prevent default submit action Event.stop(e), get all form’s elements this.getElements(), iterate over them REJECTING those that have “multiple” attribute .reject(function(el){return el.hasAttribute('multiple')}). The filtered collection is then serialized Form.serializeElements() and is submitted via ajax new Ajax.Request()
This is all very cool but here’s the reason why learning CSS3
selectors might be a good thing (the results from both - reject-based
and selector-based filtering are the same):
$(’register’).observe(’submit’, function(e){ Event.stop(e); new Ajax.Request($(this).readAttribute(’action’), { parameters: Form.serializeElements($$(’#register input:not([multiple])’)) }) })