More Ruby in Prototype
It’s obvious that Ruby has been a big influence to Prototype. We’ve already talked about Enumerables, Arrays, and Hashes, and how powerful they are. Now, lets look at some new tools: inGroupsOf and eachSlice.
Convenience matters
Have you ever tried to build a table programatically with a certain number of cells per row? The resulting code can look a bit ugly and certainly leaves something to be desired. Back in March, the Rails team introduced in_groups_of to Ruby. Since that time, I’ve put it to good use. Here is an RHTML snippet that we use in the Mephisto admin:
<table id="files">
<% @assets.in_groups_of(5) do |assets_line| -%>
<tr>
<% assets_line.each do |asset| %>
<td>
<%= render :partial => 'asset', :object => asset if asset %>
</td>
<% end %>
</tr>
<% end %>
</table>
The code above builds a table of assets in rows of 5. So basically, it takes 5 assets at a time and passes them to the block. When inside the block, each individual asset is looped over creating the columns for the tables.
in_groups_of goes Javascript
In the latest SVN version of Prototype, Sam introduced inGroupsOf. It’s similar to it’s Ruby counterpart, with the exception that you don’t pass an iterator to it. Instead you have to run it through each. Assuming we were doing the same thing–building a table, how would we accomplish that with inGroupsOf? Lets see.
<table>
<thead>
<th>First</th>
<th>Second</th>
<th>Third</th>
</thead>
<tbody id="numbers"></tbody>
</table>
We’re gonna take the HTML above, and programatically build the table from a group of numbers. Here is a look at the Javascript:
var tbody = $('numbers');
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
numbers.inGroupsOf(3, 0).each(function(group) {
var tr = document.createElement('tr');
group.each(function(num) {
var td = document.createElement('td');
td.innerHTML = num;
tr.appendChild(td);
});
tbody.appendChild(tr);
});
When you run the code above, it will spit out a table like this:

Basically we’re taking the numbers array, and dividing it into groups of 3. The 0 passed as the second argument is a filler string that is used to fill the final group if it doesn’t contain enough entries. Next, we create a tr element, and then do an inner loop which creates the td elements with the correct number, and appends it to the tr. Finally, we break out of the inner loop and append our tr onto our tbody element.
each_slice goes Javascript
inGroupsOf uses eachSlice to do some of it’s dirty work. Both of the methods are very similar, with the exception that eachSlice takes an iterator, and doesn’t pad the last slice. If we had an ObjectRange object (better known at $R in Prototype) and wanted to divide it up into slices of two, we’d do this:
$R(0, 10).eachSlice(2, function(slice) {
console.log(slice);
});
//Output
[0,1]
[2,3]
[4,5]
[6,7]
[8,9]
[10]
The first argument is the size of the slices, and the second one is the iterator, or block. Note how the last slice isn’t padded? Finally, the iterator function can also pass the loop index if you need it:
$R(0, 10).eachSlice(2, function(slice, index) {
console.log(slice, index);
});
//Output
[0,1] 0
[2,3] 1
[4,5] 2
[6,7] 3
[8,9] 4
[10] 5
And there you have it, the new features freshly baked into Prototype.
Related note
I also want to mention that I spoke to soon about XPath in Prototype. While no one has concocted a solution for IE (which was my main opposition to XPath support), document.getElementsByClassName now uses XPath in browsers that support it and it’s significantly faster than before.
Sorry, comments are closed for this article.



Discussion
Which version of Prototype includes this feature? I keep reading, both here an other places, about some great new stuff, but none of the articles or blog posts indicate which version includes them.
It looks like 1.4.0 is the latest “production” version, but the features I’m reading about sure aren’t in what I have. If the features are in the next version, is there any timeline for when that might get certified as production-ready?
Thanks.
Rob,
Later on in the article I state that it’s the SVN version of Prototype. You can check out the source here: http://dev.rubyonrails.org/svn/rails/spinoffs/prototype
When you check out the source, you’ll need to build it running `rake dist` from the command line in the root dir.
You can also get a very recent compiled version from Edge Rails: http://dev.rubyonrails.org/browser/trunk/railties/html/javascripts/prototype.js?format=txt
Justin, any news on the formation and organiztion of the Prototype core team that you mentioned in an earlier posting? I’d like to know how that’s coming along.
Phew! Thanks, Justin, for the coverage of the bleeding Edge of Prototype. Again!
Always a pleasure reading these reports. I almost always download latest Prototype because of them.
Most of these convenient Prototype tools look and feel like refactorings of “general use”, for Javascripters hard at work. Not like shiny gadgets.
@Rey: I’m told there’ll be an official announcement about Prototype Core once 1.5.0 goes final.
Hi Justin,
As ususal, great article and great add-ons to Prototype.
Your new design looks great BTW.
Anyone in particular we should contact to help with Prototype docs, etc?
Regards,
Tobie
@Andrew: Thanks for the heads. Just trying to stay informed. :o)
@Tobie: At the moment me and Andrew have taken the reigns on the documentation project. We’re still waiting on some initial setup of the system and a few other things before we start taking contributions, hopefully it’s not to much longer.
Wow, your new design is really nice. I’m always slightly nervous when designing websites with dark backgrounds but good job here. Don’t worry, I won’t ask you to add some AJAX.
On a sidenote, is your book going to be about writing rails apps with Protoype or general Javascript programming with Prototype?