While Jesse operates on the next version of Red, his never-quite-ready Ruby runtime built on top of Javascript, I’ve been playing with RedShift, our Ruby DOM manipulation library by exploring Ruby idioms that would make common tasks more elegant.
We already have a ready? method on the Document class that is called when the DOM has been parsed and is ready. It’s the equivalent of jQuery’s $(document).ready(fn), Prototype’s document.observe("dom:loaded", fn), and MooTools’ window.addEvent('domready', fn) functions.
I was playing with this concept of meta-events and had the idea of using them for scoping code based on selectors. When you combine all your javascript into a single file to reduce the number of HTTP requests for a page, you need a nice way of trigger certain behavior only for a subset of pages. I usually have a few classes and ids attached to the body tag of any page:
<body id='show' class='people admin-viewing'>
This presence of these identifiers will trigger a subset of all possible document behavior. To replacing many if statements I extended our DOM-selection method to encapsulate this behavior in an optional block.
Document['#show.people'] do
end
Although succinct, this fails aesthetically because it doesn’t obviously announce what the hell the block is for. I moved the block behavior to a specific found? method to mirror the syntax of Document.ready? as a kind of meta-event:
Document['#show.people'].found? do
# code here only takes place if the selector is found
Document['#show.people']['a'].add_class('whatever')
end
Missing from this example was the ability to do sub-selects from within the block (which gives a nice speed boost and reduces duplication). I updated it to take a block argument.
Document['div#navigation'].found? do |page_nav|
# find all the links inside the navigation div
page_nav['a'].add_class('whatever')
end
I’m eager to try pattern on existing projects, so I extended jQuery to accomplish the same goals:
$('div#navigation').found(function(){
// only execute if the selector finds elements
this; // is the jQuery object of $('div#navigation')
});