Archive for the 'JavaScript' Category

JavaScript Currying Redux

Saturday, March 10th, 2007

Currying in JavaScript is all the rage. There’s no shortage of code examples on how to do it. Regardless, currying is still a topic that many of us have a hard time truly wrapping our brains around. Let’s dig a little deeper. When we come out on the other side, we’ll have a little syntactic sugar for automagically currying functions that most of us have never seen before.

Why Should I Use Curry?

If you’re not already versed in the art of currying, you’re probably wondering why you should even bother with this technique. The main benefit of curried functions in JavaScript is for callbacks. Callbacks are used everywhere in JavaScript: event handlers, timeout handlers, Ajax oncomplete callbacks, and the very handy Array Extras methods map, filter and forEach added in JavaScript 1.6 by Mozilla. It’s often very useful to create a new function to use as a callback. Often these functions will never be used again, so they’re usually anonymous functions.

if (typeof currying == “undefined”)

The definition of currying is often vague and confusing, but the simplest explanation is this: Turning a function of two arguments into a function of one argument that returns a function of one argument. This definition comes from Higher-Order Perl by Mark Jason Dominus (MJD), a wonderful book on functional programming techniques that will change the way you think about code. The definition I just gave applies to functions of more than two arguments, but this is the simplest case. A simple example of manual currying:

// A normal version of add()
function add(x, y) { return x + y }

// Manually curried add()
function curried_add(x) {
    return function (y) {
        return x + y;
    };
}

add(1, 99);    // 100
curried_add(1)(99);    // 100

When we call curried_add() we only pass one argument. We get back another function that expects one argument, then uses the two arguments it’s received to perform its calculation.

In Higher-Order Perl, MJD shows a technique that lets you have your cake and eat it too. Using our original add() function, we can write it so that if we give it 2 arguments, it behaves as normal. But if we give it only one argument, it returns a curried function with that first argument filled in.

function add(x, y) {
    function curried(y) {
        return x + y;
    }
    return (arguments.length > 1) ? curried(y) : curried;
}

add(1, 99);    // 100
add(1)(99);    // 100

In this version of add(), we create an inner function that contains the actual function calculation. This inner function has access to the x argument of the outer function. If the add() function has been called with more than one argument, we’ll go ahead and invoke this nested function to compute the result. If only one argument has been supplied, we’ll return a function that will wait for the second argument before computing its result.

Automagical Currying

Writing this code over and over again will get tedious and be error-prone, so we’ll once again look to Higher-Order Perl for a generic solution. MJD gives us curry_n(), a function that generates a generic curried version of another function. Here it is in JavaScript:

function curry_n(f, n) {
    if (typeof n == 'undefined') n = f.length;
    return function () {
        if (arguments.length >= n) {
            return f.apply(this, arguments);
        } else {
            var a = [].slice.call(arguments,0);
            return curry_n(
                function () {
                    return f.apply(this, a.concat([].slice.call(arguments,0)))
                },
                n-a.length
            );
        }
    };
}

How does this work? It does essentially what we just did in our manually curried add(), but it’s generic. We pass a function to curry_n(). We get back a function that will check to see if it was called with the number of expected arguments. If it has, the function will return as normal. Otherwise, we’ll remember the arguments we did get, and then pass along a new function that will wait for the remaining arguments.

Now let’s return to our add() example. We’ll create a generic curried version that will work just like the manual one we created above:

var add = curry_n( function (x, y) { return x + y } );

add(1, 99);    // 100
add(1)(99);    // 100

var plus_one = add(1);
plus_one(10);    // 11
plus_one(99);    // 100

If you have your own Array extras file that uses Array.map(), this technique will come in especially handy:

[1,2,3,4,5].map(add(1));    // [2,3,4,5,6]

The curry_n() function takes an optional second parameter, which is the number of arguments your function expects. If you omit this, then the function’s length property will be used, which is the number of arguments you explicitly define during its creation. This will pose a problem for functions with explicitly defined optional arguments. In these cases, you’ll want to pass the second argument to curry_n() to include only the number of required arguments.

var map = curry_n( function (f, a, context) { return a.map(f, context) }, 2 );
Array.double = map( function (x) { return x * 2 } );
Array.double([1,2,3,4,5]);    // [2,4,6,8,10]

Because we’ve supplied the number 2 as the second argument to curry_n(), our function will return once it’s accumulated at least 2 arguments. We could still pass in the last optional argument when we make the call to Array.double() (though in this case it would be useless). If we omitted this argument, our function would not have executed until it received 3 arguments.

Caveats

I should note that this technique is not a replacement for other currying methods, such as Prototype’s Function.bind(), or even a generic curry function such as:

function curry(f) {
    var args = [].slice.call(arguments,1);
    return function () {
        return f.apply(this, args.concat([].slice.call(arguments,0)));
    };
}

What’s the difference? The difference is that curry_n() will return a function if not enough arguments have been provided, but will return the result of the function application if all its arguments have been passed. Meanwhile, curry() will always return a function, even if all arguments have been supplied. This comes into play for event callbacks or setTimeout() code. Sometimes in these situations you’ll have a function that you only call for its side effects, that you want to apply arguments to ahead of time. You might need to fill all arguments in, but you always need a function returned in these cases so it can be run by the event handler or timeout code.

curry_n() is meant strictly as a way to add implicit currying behavior to a defined function. It’s basically a form of polymorphism, or a very specific application of function overloading.

Resources:

Modify Existing JavaScript Functions

Wednesday, February 7th, 2007

I often find myself needing to tweak existing functions in JavaScript. There are a few cases of standardized native JavaScript object methods that have very useful features that some pesky browser forgot to implement. The method exists, but it doesn’t conform to the standard. How can I possibly fix that broken browser?

Other times I’m working with a useful JavaScript library and need to use one of its functions, but realize that there’s a bug in the code, or a certain edge case it doesn’t handle properly that keeps coming back to bite me. I’m tempted to just add my own hack to the library code and be done with it, but there is a better way.

Because functions are first-class objects in JavaScript, we can assign new function values to existing ones without anyone being the wiser. And thanks to the power of closures, our new function can remember the old one without any other code being able to access the original version. I’ve sometimes seen this called a Proxy Pattern, where our new function acts as a pass-through to the old one without the outside world knowing that the call has been intercepted.

If It Ain’t Broke, Don’t Fix It!

Before you go fixing things, you should make sure they’re broken in the first place. If you plan on fixing a broken browser implementation, then make sure it really is broken before you go to the trouble of changing it (and introduce new bugs to an already working version). The unobtrusive JavaScript philosophy advocates object detection over browser sniffing. This works fine for browsers that don’t implement certain methods like Array.push() or Function.call(), but you need a more thorough test for a broken function.

The solution is to create a simple test of the function that probes the issue you are trying to correct. I got the idea for this technique from Dan Webb’s Code Highlighter script. Older versions of Safari don’t support callback functions for String.replace(). Code Highlighter needs this functionality, so it does a simple test to see if it needs to be fixed:

if ('a'.replace(/a/, function () { return 'b'; }) !== 'b') {
    // Fix the String.replace method
}

In browsers that support callback functions for String.replace(), nothing will be changed. Browsers that don’t support the callback function can easily be detected with this simple test.

I was recently working on a script that needed the String.split() method to hold onto the delimiter in the returned array (this is very useful for parsing). If you use parenthesis on the regular expression delimiter, the delimiter text is supposed to be included in the final array. Internet Explorer does not include the text. I wrote a function for fixing this, but first needed to test if it was broken in the first place:

if ('a b'.split(/( )/)[1] !== ' ') {
    // Fix the String.split method
}

Testing can extend to library functions as well, unless you know for sure that the version of a library that you are using implements a function in a specific way.

Don’t Throw Away Other People’s Work

Once you’ve determined that a function needs to be modified, you don’t want to lose the existing version of it. Why? Because someone else has probably already done most of the work for you. You just need to filter input to the function, or modify its existing output slightly.

The trick is to use the powerful and often misunderstood closure. Closures allow you to access the original function from the new one without other code having access to the original. There are 2 similar syntaxes for accomplishing this, and you should use whichever suits your style. Dan Webb’s Code Highlighter uses the following syntax:

(function(){
  var default_replace = String.prototype.replace;
  String.prototype.replace = function(search,replace){
	// replace is not function, apply original and return
	if(typeof replace != "function"){
		return default_replace.apply(this,arguments)
	}

        // search string is not RegExp, apply callback once on first matched substring
	if(!(search instanceof RegExp)){
		var idx = str.indexOf(search);
		return (
			idx == -1 ? str :
			default_replace.apply(str,[search,callback(search, idx, str)])
		)
	}

        // Otherwise replace the matched expression
        // with the result of the callback function manually
  }
})();

This example creates an anonymous function and invokes it immediately. Inside the function body, the old replace() method is assigned to the local variable default_replace. Then the replace() method is redefined with a new function that still has access to the old version. The new replace() method then does a series of checks to see what arguments were passed in. If the replace argument wasn’t even a function, it simply returns the result of the original function implementation. Otherwise, it augments the result of default_replace in a manner consistent with the ECMAScript standard.

Here is an example of an alternate syntax that accomplishes the same thing with the String.split() method:

String.prototype.split = (function (old) {
    return function (delimiter, limit) {
        var result = old.apply(this, arguments);
        // If delimiter was RegExp and contained parenthesis,
        // modify the result of the original method to adhere to the standard
    };
})(String.prototype.split);

This syntax also creates an anonymous function and invokes it right away. But this version passes in the existing value of the String.split() method as an argument to the anonymous function. This argument is named old, and can be accessed throughout the function. Then the anonymous function returns the new value of the String.split() method, which retains access to the old variable. I personally find this syntax a little more elegant, but it may potentially be more confusing to anyone else reading your code.

An Everyday Example

This technique can be used in a common, everyday JavaScript problem. That problem is the window.onload conundrum. You can never be quite sure who else has attached a handler to this important event, and if you’re not using an Event abstraction layer that can implement the Delegate Pattern of the W3C and Microsoft’s implementations, then you may accidentally overwrite another onload event. When you need a quick and dirty solution, the following can get the job done:

window.onload = (function (old) {
    return function () {
        if (typeof old == 'function')    old();
        // Run new code here...
    };
})(window.onload);

Learn to Program in JavaScript’s Dialect

JavaScript is an interesting language with some very strange colloquialisms. These sayings can look like strange slang, but are very powerful when you don’t have access or time to worry about a library that abstracts away the unusual syntaxes of JavaScript. I have become a better programmer since I’ve embraced the quirky syntax that is possible yet powerful in JavaScript.

Extending DOM Nodes with Mootools

Tuesday, September 26th, 2006

One of the really useful features of JavaScript is the flexibility of its objects. Developers have spent a lot of time looking for ways to emulate the class system of most Object-Oriented Programming languages, which has been a worthwhile pursuit. Mootools itself gives us one of the most elegant solutions to the problem of defining classes in JavaScript.

But one of the unique aspects of JavaScript is the ability to assign arbitrary properties and methods to any object, regardless of how that object was created. This has led to tricks like extending JavaScript’s native Array and String objects. But did you know you can extend DOM nodes as well?

Attaching methods to Elements

The Mootools library takes full advantage of JavaScript’s ability to attach custom methods to DOM node elements. Unfortunately, because of Internet Explorer’s implementation of DOM nodes, these methods can’t be attached to Element prototypes in a cross-browser fashion. But Mootools does let you pass a reference to a DOM node through the $ function to extend that node with the library’s Element methods. This means that once you’ve called $ on an Element, you don’t have to call it again:

var h1 = $('heading');
h1.setHTML('Updated!');
document.getElementById('heading').appendText('...again.');

The third line of code is purely for demonstration purposes. There’s no need to call document.getElementById on the element, but the point is to show that even if you’re not referencing the variable returned by $, the DOM node itself has been extended.

The Element class in Mootools has been turned into a native object, so you can extend it to add to the methods that get copied onto all DOM nodes passed through the $ function, just like the Mootools system of extending objects. This is similar to extending a native JavaScript object, with the exception that it only works on DOM nodes passed through $ after calling Element.extend:

Element.extend({
  alert: function() {
    alert(this.innerHTML);
  },
  log: function() {
    try {
      console.log(this);
    } catch(e) { alert(this.outerHTML);}
  }
});

$('heading').alert();
$('heading').log();

The $ function also adds an extend method to the DOM node passed to it, allowing individual nodes to be extended with custom methods:

var h1 = $('heading');
h1.extend({
  custom: function() {
    // Custom method for only this element
  }
});

Mootools’ new Element class

The $ function in Mootools extends a DOM node with all the methods of Element.prototype. But Element is also a class that can be instantiated. This is useful for extending a reference you already have to a DOM node that may not have an ID:

var link = new Element(document.getElementsByTagName('a')[0]);

// link contains reference to DOM node that has all methods of Element

Where the Element class really shines is as a shortcut for creating new DOM nodes. If you pass a string into Element’s constructor, Mootools will call document.createElement on that string, then pass the created DOM node through the $ function. This is a very handy shortcut, and cool syntactic sugar:

var h1 = new Element('h1');
h1.appendText('Hello World');
h1.injectInside($E('body'));

Or if you’re comfortable with chaining methods:

var h1 = new Element('h1').appendText('Hello World').injectInside($E('body'));

Subclassing the Element class

This leads to a really expressive capability of Mootools: creating new DOM nodes from custom classes. Remember the old JavaScript image rollover days when the way to preload an image was to call var img1 = new Image();? Now you can use similar custom element constructors in your code to give individual element types streamlined constructors and their own unique methods.

Your first attempt at this would probably be along the lines of trying to extend the Mootools Element class. This doesn’t work, because Element is a native Mootools object. Calling Element.extend adds methods to the Element super class instead of copying the Element class to a new class. Luckily the Element constructor shows us the solution to our problem.

Look at the Element.initialize method and you’ll see that it returns an object. I’m used to thinking in terms of PHP, where class constructors can not return anything because the instantiated object is always assigned from the constructor. In a JavaScript object constructor, any object can be returned. That means we can use our custom Element class’s constructor to create our element, extend the element with the methods of the current class, and then return that element. An example will make this clearer:

var Link = new Class({
  initialize: function(options) {
    options = Object.extend({
      href: '#'
    }, options || {});

    var link = new Element('a');
    link.extend(this);

    for (var i in options) {
      link.setAttribute(i, options[i]);
    }

    return link;
  },

  disableClick: function() {
    this.onclick = function(){ this.blur(); return false; };
    return this;
  },

  enableClick: function() {
    this.onclick = Class.empty;
    return this;
  }
});

The magic happens on the line where we call link.extend(this). When a JavaScript object is instantiated via the new operator, a blank object is created from the prototype of that object’s constructor. That means this inside an object constructor refers to the blank object and contains all the methods attached to the prototype of the constructor. So extending the DOM element we just created with this copies all the methods and properties of our prototype into the DOM node.

We’re also using the Link constructor to set up some simple default parameters to help make creating links easier in the future, and giving links created via this class some simple utility functions for disabling click events. The object could be created with the following:

var link = new Link({href: 'http://www.google.com', title: 'The omnipotent one'});
link.appendText('click here').injectInside($E('body'));
link.disableClick();

This would create a new <a> element that has been extended with Mootools’ DOM node extensions, inserted into the document, and with a disabled click event.

Something else useful — sometimes you’ll have DOM nodes already created that you’d like to give the Link methods to. This can be done in one of two ways. The most direct is to call element.extend, passing in Link.prototype. The other method is to instantiate a new Link object but pass in ‘noinit’ as the parameter, which will keep the initialize method from running when creating the object. Each method performs essentially the same thing and is a matter of personal taste:

var link = new Element(document.getElementsByTagName('a')[0]);
link.extend(new Link('noinit'));

// Accomplishes the same thing:
link.extend(Link.prototype);

Go forth and experiment

Hopefully you’ve seen the expressive power that the Mootools way of handling DOM nodes can give you when writing your own code. Go on and experiment with custom DOM node classes and let me know what you find. One word of warning — be careful when using this.parent() inside a custom DOM element method. I haven’t fully tested it yet, and it seems to work in most cases, but one time it did fail in Internet Explorer while I was trying something on an <iframe> element.

Related resources

Useful Utility Functions in mootools

Thursday, September 14th, 2006

The new mootools JavaScript framework has quickly impressed me with its design and usefulness. The library was clearly written to meet real programmers’ needs while working in JavaScript. Just take a look at some of the new utility functions and methods it provides.

Note: This article covers functions and methods found in the Array.js and Function.js modules of mootools.

A cleaner array iterator

Mootools provides a Prototype-inspired each method that every JavaScript array inherits. Its syntax is a bit cleaner because it’s based on the Mozilla Array.prototype.forEach method. The mootools each method allows you to pass in a second parameter as the context in which the function will be called, allowing you to resolve the this keyword. Accomplishing this in the Prototype library involves binding the function passed to each:

var x = {sum: 0};

for (var i = 0, fixtures = []; i < 500; i++) {
  fixtures.push(i);
}

fixtures.each(function(el, i) {
  this.sum+= i
}.bind(x));

// x.sum = 124750

Accomplishing the same thing in mootools is just a small syntax change (the changed line is highlighted):

var x = {sum: 0};

for (var i = 0, fixtures = []; i < 500; i++) {
  fixtures.push(i);
}

fixtures.each(function(el, i) {
  this.sum+= i
}, x);

// x.sum = 124750

The mootools each method takes the object that will resolve to this inside the loop as the second argument.

Why should you care about this minor syntax change? Because calling bind on a function every time through a loop is going to add overhead to your code’s performance. I’ve run the previous code in Firebug with a timer and the results are very telling:

500 elements each with bind: 39ms
500 elements each: 3ms
1000 elements each with bind: 75ms
1000 elements each: 6ms

Not only is the mootools syntax cleaner, but it performs almost 10 times faster than using the bind method. Keep in mind that these examples all use mootools’ each method. If I’d used the Prototype each the code would have run even slower, but that issue has already been well-documented.

Prototype each diversion

The reason Prototype’s each loop runs so slowly is that each iteration of the loop has to run through a try/catch block in order to look for break and continue statements. If you’re using Prototype’s each and you want to break or continue in the loop, you must use the following syntax:

[1,2,3,4,5,6,7,8,9,10].each(function(el) {
  if (el > 7) throw $break;
  if (el == 4) throw $continue;
  alert(el);
});

// Will alert "1", "2", "3", "5", "6", "7"

I’m not here to bash Prototype. It’s a great library. But I think it does need to be pointed out that its each method will run slower than traditional loops because of the design decision to incorporate a workaround for break and continue statements.

What, you’re not using break and continue statements? They can really help you cut down on loop iterations. There is no way to use break or continue in an each loop in mootools, so keep that in mind. You’ll have to use the good old-fashioned for loop for that one.

Running code at time intervals

JavaScript provides the setTimeout and setInterval functions for running code after a delay or at regular intervals. This comes in very handy for animations, but also for other GUI functions, such as delaying hiding a menu after navigating away. The native syntax for this can get a little verbose sometimes, so mootools provides some utility functions as methods of every function. To run code once after a time delay you use the delay method:

(function(){ alert("Sorry I'm late."); }).delay(5000);

This will run the function after a delay of 5 seconds. You can also run code at a regular interval using the periodical method:

var annoy = (function(){ console.log('Are we there yet?'); }).periodical(5000);

The previous code will run until the window unloads unless we clear the interval returned by periodical. Mootools provides a $clear function that will clear any time interval passed to it, whether it was created with delay or periodical:

$clear(annoy);

Just be sure to assign the periodical function to a variable, or else you won’t be able to clear it! Talk about annoying…

The second parameter to delay and periodical is the context object to call the function within, just like the each method. This can come in handy when using methods of mootools’ objects:

var xhr = new Ajax('url', {update: ajaxElement});
var $req = xhr.request.periodical(60000, xhr);

This code will create an Ajax object that calls its request object every minute. You need to pass the Ajax object as the second argument to periodical so the request method will run in the right context.

Cleaner object detection

Sometimes checking the type of a JavaScript object can get confusing. Everything is actually an Object, so running [1,2,3] instanceof Object returns true, even though we were checking against an array. But curisouly, running 'string' instanceof Object returns false! There’s also the typeof function, so things can get rather confusing and frustrating in a hurry when trying to detect object types. Mootools provides a function called $type that will do the proper checks behind the scenes and return a lowercase string type of the element you passed into the function. If the type of object is not matched, $type will return false.

The types returned by $type are:

  • function
  • textnode
  • element
  • array
  • object
  • string
  • number
  • false

Try it out:

$type(function(){});
// Returns 'function'

$type(document.createElement('div'));
// Returns 'element'

$type([]);
// Returns 'array'

$type({});
// Returns 'object'

$type('hello world');
// Returns 'string'

$type(4);
// Returns 'number'

Mootools just continues to amaze me. I’m digging through the source code and running lots of tests to see just how the library works, so stay tuned for more articles about this new library’s features.

Extending Objects and Classes with mootools

Tuesday, September 12th, 2006

I love the moo libraries. Despite my passion and knowledge of the Prototype JavaScript libary, I’ve never used it in a commercial project. I have used moo.fx (and the included prototype.lite) for actual client work and been very satisfied with the results. The moo libraries are very lightweight, organized and clean. They are well thought-out and extendable, and you won’t find any bloatware within.

Now Valerio Proietti has decided to grace us all with his new library, mootools. mootools is like a cross between Prototype and jQuery, with an emphasis on clean, Object-Oriented code and lean, modular design. The library has the most inspired download feature of all libraries — it allows you to pick and choose modules and automatically figures out the dependencies and compresses the code for you.

In this article we’ll take a look at one of the library’s coolest features: extending JavaScript and the library’s functionality.

Extending objects

On the surface, extending objects in mootools works just like Prototype. There is an Object.extend function that takes two arguments: destination and source.

var test = {hello: 'world'};
Object.extend(test, {animal: 'sloth'});

// test now contains "{hello: 'world', animal: 'sloth'}"

At this point mootools diverges from Prototype and adds some nice functionality to help you extend the libary and JavaScript itself.

Class inheritance

mootools implements a class inheritance scheme that is inspired by Dean Edwards’ wonderful Base class. Creating a class is similar to Prototype, but now you don’t ever have to think about the prototype object when you define the class:

var Shape = new Class({
  initialize: function(width, height) {
    this.width = width;
    this.height = height;
  },
  draw: function() {
    console.log('starting to draw...');
  }
});

Now we’ll probably never use the Shape class because it’s abstract, so let’s see how mootools lets us extend the class:

var Square = Shape.extend({
  draw: function() {
    this.parent();
    console.log('drawing square');
  }
});

Some of you may be wondering where the extend() method on Shape came from. You can breathe a sigh of relief, because it’s not coming from Object.prototype (whew!). Any class created with new Class() gets an extend method. When you use the extend method to define a child class, the parent class remains untouched. The child class inherits all of its parents’ properties and methods. Each of the child’s methods also has access to the parent’s method of the same name, accessed by calling this.parent() within a method.

To see this in action, let’s instantiate a new Square object:

var square = new Square(150, 150);
square.draw();

// Logs "starting to draw...", then "drawing square" to the console

Finally, an easy way to define classes and inheritance schemes in JavaScript!

Multiple inheritance with Class.implement()

mootools supports multiple inheritance in a Ruby mixin style with the Class.implement() method. Using the implement method of an existing class, that class can inherit methods and properties from another class or object. Unlike Class.extend(), the implement method is called on the class you are modifying, not on the object being copied. This method can be used to support multiple inheritance:

var UsefulGlobalObject = {
  inspect: function() {
    var results = [];
    for (var i in this) {
      results.push(i + ': ' + this[i]);
    }
    return results.join(",n");
  }
};

var Circle = Shape.extend({
  draw: function() {
    this.parent();
    console.log('drawing circle');
  }
});

Circle.implement(UsefulGlobalObject);

Let’s assume UsefulGlobalObject really is a useful global object. Passing this object to Circle.implement() copies all properites of the object to Circle’s prototype, so any circle object will now have the method inspect(). If we were copying from a parent class instead of an object, the syntax would use the new keyword:

Shape.ThreeDimensional = new Class({
  rotate: function(degrees, plane) {
    console.log('rotating by ' + degrees + ' on the ' + plane + ' plane');
  }
});

var Sphere = Shape.extend({
  draw: function() {
    this.parent();
    console.log('drawing sphere');
  }
});

Sphere.implement(new Shape.ThreeDimensional);

Sphere has inherited from both the Shape class and the Shape.ThreeDimensional class.

Extending library classes and native objects

Another use for the implement() method is for modifying a library class in a different code module, or even dynamically adding to a class at runtime. This is similar to Ruby, where you can reopen a class definition at any time to add new methods. We can use the implement() method to add or overwrite any method in a mootools class in our own code so that we don’t have to modify the library itself:

Ajax.implement({
  // add a new method
  newMethod: function() {
    // new method code
  },

  // overwrite an existing method
  request: function() {
    // overwrite the original request method
  }
});

This code will add a new method newMethod and overwrite the request method for the Ajax object.

One last feature of the mootools library is the concept of Native Objects. String, Function and Array have been turned into mootools native objects, which essentially means their extend() method is an alias for the implement() method. Calling extend() on these objects adds properties and methods to them just like Class.implement() does. It makes the syntax for extending a native object even sweeter:

Array.extend({
  map: function(fn) {
    for (var i = 0, a = []; i < this.length; i++) {
      a[i] = fn(this[i]);
    }
    return a;
  }
});

Any method you extend a JavaScript native object (String, Function, Array) with will have the new methods attached, even if it was created before the call to extend(). Note that the Number object is not a native object in mootools, but you can easily change that by calling Object.Native():

new Object.Native(Number);

Number.extend({
  isOdd: function() {
    return !!(this % 2);
  }
});

mootools also provides the Element and Elements classes as native objects, so they can easily be extended just as JavaScript native objects:

Element.extend({
  visible: function() {
    return this.style.display != 'none';
  },

  toggle: function() {
    this[this.visible() ? 'hide' : 'show']();
    return this;
  },

  hide: function() {
    this.style.display = 'none';
    return this;
  },

  show: function() {
    this.style.display = '';
    return this;
  }
});

The Element class in mootools contains all the methods that get bound onto any DOM node passed through the $() function. Note that if you call Element.extend(), any methods or properties you add to the Element class won’t automatically be added to any elements that have already been run through the $() function. We’ll cover extending DOM nodes in an upcoming post.

Plugin friendly

The mootools library is brand new, but it has a solid codebase that stands on the shoulders of giants like Prototype and Dean Edwards. It provides a lot of great features right out of the box, but it’s also been written to make class inheritance and object extension very simple. This encourages traditional use of class inheritance schemes, as well as adding your own extensions and plugins to the library on an as-needed basis, without having to modify the original source code.

Using Prototype’s New String Functions

Tuesday, August 29th, 2006

After years of extensive research and study, I’ve come to a profound conclusion — working with strings sucks. It’s even more difficult when you’re doing it in JavaScript. Lucky for us, the Prototype JavaScript framework provides several shiny new String object functions to make our lives easier. Sounds like a perfect chance to be lazy — let’s get to work!

Note: I’m working with the new String methods in Prototype 1.5.

Let’s create a simple string we can run some manipulations on:

var string = 'Laziness always pays off now.';

String.gsub

The gsub method is similar to the native replace method, but it’s even more powerful. It accepts 2 arguments, the first one being the pattern to search for. This can be a simple string or a regular expression. The second argument is what to replace the matched pattern with.

Let’s start with something easy. I’m tired of spaces, so let’s replace them with underscores.

string.gsub(' ', '_');

// Returns "Laziness_always_pays_off_now."

Not very exciting, and we could have accomplished the same thing with string.replace(/\s/g, '_'). Where gsub really starts to shine is when you realize that the second argument can be a function. This function will run on each match found in the string. The function receives one argument, an array of matches against the pattern. You then return a manipulated version of the string. Sound confusing? Follow the bouncing code:

string.gsub(/\s\w/, function(match){ return match[0].toUpperCase(); });

// Returns "Laziness Always Pays Off Now."

Each match is passed to the function, which can then manipulate the match and return the version to replace. We needed to reference the match as match[0] because the matches of a regular expression are returned as an array. Index 0 is the entire match, and each numeric index after that corresponds to a parenthesis group in the regular expression. If we had used parenthesis in the regular expression, we could have accessed other elements of the match array:

string.gsub(/(s|f)(\s)/, function(match){ return match[1].toUpperCase() + '-' + match[2]; });

// Returns "LazinesS- alwayS- payS- ofF- now."

String.sub

String.sub is almost identical to String.gsub, but it accepts an additional argument. Instead of replacing each match in the string, sub replaces the number of matches that you pass in as the optional 3rd argument (which defaults to 1). Let’s return to our original example:

string.sub(' ', '_');

// Returns "Laziness_always pays off now."

This time, only the first match was replaced. If we run it again and pass in the 3rd parameter we’ll see something different:

string.sub(' ', '_', 3);

// Returns "Laziness_always_pays_off now."

Otherwise String.sub is identical to String.gsub.

String.scan

The scan method simply calls the String’s gsub method with the pattern and iterator function provided. This lets you loop through each match and do something with it:

string.scan(/\w+/, alert);

// Produces 5 alerts: "Laziness", "always", "pays", "off", "now"

Another use would be to get an array of all the items that matched:

var results = [];
string.scan(/\w+/, function(match){ results.push(match[0].toUpperCase()); });

// results = ['LAZINESS', 'ALWAYS', 'PAYS', 'OFF', 'NOW']

For some reason, the scan method returns the String object split into an array of its characters.

String.truncate

This method works almost like you’d expect, with a slight quirk (in my opinion). The truncate method chops a string off to the number of characters you supply as the first argument:

string.truncate(15);

// Returns "Laziness alw..."

That’s almost what I expected to get, except there are only 12 characters from the original string instead of 15. That’s because there’s an optional second argument to truncate to append to the end of the string, and it counts as part of the returned string’s length. It defaults to ‘…’, but the following will yield the result I expected to see:

string.truncate(15, '');

// Returns "Laziness always"

Template Class

Last we have a new Template class, which I think is a work of beauty. This class lets you set up a string template with variables to replace later, much like a PHP template or the server technology of your choice. The default variable substitution pattern is: #{variable_name}. Here’s how to create an object with the class:

var linkTemplate = new Template('<a href="#{href}">#{text}</a>');

You render the template by calling its evaluate method and passing in an object with property names matching the variables you used in the template:

linkTemplate.evaluate({href: 'http://www.google.com', text: 'The omnipotent one'});

// Returns "<a href="http://www.google.com">The omnipotent one</a>"

It also works with an array:

var arrayTemplate = new Template('Original: #{0}, Sequel: #{1}');
arrayTemplate.evaluate(['Naked Gun', 'Naked Gun 2 1/2']);

// Returns "Original: Naked Gun, Sequel: Naked Gun 2 1/2"

Customizing the Template Variable Pattern

Just because we can, let’s customize the Template class even further. Say you’ve already got a nice template, but it’s written in PHP using a short tag syntax. Being the lazy programmer you are, you can’t be bothered with rewriting this. Don’t worry, your hard work now will pay off with the potential for laziness later!

The second parameter to Template’s constructor is the regular expression pattern to use for the variable substitution. This parameter is optional and defaults to the Template.Pattern constant, which allows for the very nice #{variable} syntax. We can create our own regular expression to use for template variable substitution. Try the following:

Template.PhpPattern = /(^|.|\r|\n)(<\?=\s*\$(.*?)\s*\?>)/;

Now we can pull in a typical PHP template and let Prototype work its magic:

var phpTemplate = new Template('<div id="<?= $id ?>" class="<?= $class ?>"><?= $content ?></div>', Template.PhpPattern);
phpTemplate.evaluate({id: 'news', class: ['updated', 'arbitrary'].join(' '), content: '<p>No news is good news...</p>'});

// Returns "<div id="news" class="updated arbitrary"><p>No news is good news...</p></div>"

This might be useful if you are doing Ajax calls and returning JSON data a lot. You could create a Template class when the page loads using a small PHP template from your own site, then pass the JSON object you got from the Ajax request into the template’s evalute method. Of course, only do this if the PHP template file does not have any business/application logic that you don’t want prying eyes to see. Just remember that anything you give to JavaScript can be viewed by everyone. I recommend it only for simple templates that have simple variables, if you use it at all. You have been warned.

Even though I personally prefer to use simple PHP templates, I’ll give you a Smarty pattern to play with as well:

Template.SmartyPattern = /(^|.|\r|\n)(\{\$(.*?)\})/;

One important thing to note is that you should follow the existing Template.Pattern regular expression pattern’s structure of parenthesis. This structure follows one group to match before the variable, one group to match around the variable name, and the variable name itself. If you don’t follow the (beforePattern)(varSyntax(varName)) pattern, the template won’t replace your variable properly, because it relies on these parenthesis for the 1, 2, and 3 indexes.

Coming Full Circle

Now that I’ve shown you the Template class, I can put a nice cherry on top by showing you one more trick with String.gsub and String.sub. The second argument to these methods can also be a Template string:

string.gsub(/\s/, '#{0}_');

// Returns "Laziness _always _pays _off _now."

When using a template string as the second parameter, keep in mind that the match’s index works just like the index of the array that would be passed if the second argument was a function. Here’s an example:

'Cory Hudson'.gsub(/(\w+) (\w+)/, '#{2}, #{1}');

// Returns "Hudson, Cory"

Note that this Template pattern cannot be customized like it can be when you create an object from the Template class, so you’ll have to stick to the Ruby syntax when using gsub and sub. But emulating Ruby’s not such a bad thing, is it?

Strings Can Be Fun!

Even I had fun using Prototype’s latest additions to the native String object. They can save you some time while coding, and the fact that they are so flexible with their arguments is a nice bonus!