A Flurry of Prototype Updates

—Wednesday, August 30 2006

With so much discussion happening recently about the state of Prototype, it’s great to see some updates finally rolling in. Hopefully this is only the beginning of what’s to come.

Here is the changelog as of around 7:00 CST:

  • Make destructive Element, Form, and Form.Element methods return their first argument, so that multiple calls can be chained together. [sam]
 $("sidebar").addClassName("selected").show(); 

The following methods now return their first argument: Element.toggle, Element.hide, Element.show, Element.remove, Element.update, Element.replace, Element.addClassName, Element.removeClassName, Element.observe, Element.stopObserving, Element.cleanWhitespace, Element.scrollTo, Element.setStyle, Element.makePositioned, Element.undoPositioned, Element.makeClipping, Element.undoClipping, Form.reset, Form.disable, Form.enable, Form.focusFirstElement, Form.Element.focus, Form.Element.select, Form.Element.clear, Form.Element.activate, Form.Element.disable, Form.Element.enable.

  • For consistency, Element.toggle, Element.show, and Element.hide no longer take an arbitrary number of arguments. [sam]

    !! BACKWARDS COMPATIBILITY CHANGE !!

    If you have code that looks like this:

Element.show('page', 'sidebar', 'content');

You need to replace it with code like this:

['page', 'sidebar', 'content'].each(Element.show); 
  • Mix in Form and Form.Element methods to forms and form field elements with $() and $$(). Closes #4448. [Dan Webb, sam]
  • Add Object.clone [sam]
  • Add Form.Element.disable and Form.Element.enable. Closes #4943. [jan@prima.de]
  • Field is now simply an alias for Form.Element. [sam]
  • Add Element.Methods.getElementsByClassName and Element.Methods.getElementsBySelector. Closes #4669. [Andrew Dupont, DHH, sam]
  • Avoid race condition when stopping an Ajax.PeriodicalUpdater. Closes #4809. [e98cuenc@gmail.com]
  • Improve support for synchronous requests. Closes #5916. [sam, jthrom@gmail.com]
  • Add serialization and observation support for input type=search. Closes #4096. [rpnielsen@gmail.com]
  • Properly decode query components in String.prototype.toQueryParams. Closes #3487. [sam]
  • Add Array.prototype.reduce [sam]:
  [1, 2].reduce()   // [1, 2]
  [1].reduce()      // 1
  [].reduce()       // undefined
  
  • Add Object.keys and Object.values [sam]
  • Simulate non-GET/POST requests by POSTing with a _method parameter set to the actual verb [DHH]
  • Make Element.update() handle TABLE-related elements with the DOM API because of IE’s missing .innerHTML property on them [Thomas Fuchs, thx to Rick Olson]
  • Sync to script.aculo.us unittest.js library as of 2006/08/29 [Thomas Fuchs]
  • Add additional unit tests to test/unit/dom.html for testing Element.update and $().update in various enviroments [Thomas Fuchs]
  • Prevent possible exceptions on unloading the page in IE [Thomas Fuchs]

Object.keys and Object.values

New to Prototype is Object.keys and Object.values. There are a couple things to be aware of however. These methods won’t work on Prototype classes the way you might expect. So for instance, this will not work:

   var Foo = Class.create();
  Foo.prototype = {
    intialize: function(str) {
      console.log(str);
    },

    bar: function(str) {
      console.log(str);
    }
  }

  console.log(Object.keys(Foo));
  // ["prototype","bind","bindAsEventListener"]

The reason for this is that Foo is a Function and you’ll get the keys for the Function object. A relatively easy work around for this is ask for the keys on Foos prototype object:

console.log(Object.keys(Foo.prototype)); //["intialize","bar"]

Of course, you don’t get the class methods with this so you can use something like this. Not a particularly useful class, but you get the idea:

  var Inspector = Class.create();
  Inspector.prototype = {
    initialize: function(obj) {
      var instanceMethods = Object.keys(obj.prototype);
      var classMethods = Object.keys(obj).reject(function(method) {
        return ['bind', 'bindAsEventListener', 'prototype'].include(method);
      });
      console.log(instanceMethods, classMethods);
    }
  }

Form and Form.Element methods mixed in to $ and $$

This is great and well help put an end to some of those very verbose Form operations. Now you can do stuff like:

  <form action="/search" id="searchform">
    <input type="text" value="this is text" name="q" id="search" />
    <input type="submit" value="submit" />
  </form>
  console.log($('searchform').getElements());

Shorter syntax for Event Observing

Dan Webb’s very old patch for event observing went in. This means we can now do:

$('element').observe('click', function(e) {  alert(e); });

Full support for chainability

All the methods listed in the CHANGELOG overview above now return their first argument.

  $('sweet').observe('click', function(e) {
    console.log("%s was clicked", Event.element(e));
  }).setStyle({color: 'red'});

This is just a quick overview of what is going into Prototype as we speak. It seems Sam is on the move today and there is a flurry of activity so we’ll likely see more before the day is over with. I’ll try to update this post as soon as I learn more.