Helping ordinary people create extraordinary websites!
GET OUR NEWSLETTER
Your Email:
 

Higher Order Programming in JavaScript

By Sjoerd Visscher
2006-08-18


Generating HTML

Using functions as arguments

If you have generated HTML from arrays before, this code will look familiar:

var s='';

for (var i=0;i<arr.length;i++) {
var item=arr[i];
s+=...generate some HTML...
}
document.write(s);

We will now create a reduce method, that will make this a bit more readable, and make the code more modular. The above code will then look like this:

function prettyTemplate(item) {

return ...generate some HTML...
}
document.write(arr.reduce(prettyTemplate));

To create the reduce method, we can use much of the previous example. We'll extend the array prototype, so all arrays will have the reduce method available:

Array.prototype.reduce=function(templateFunction) {

var l=this.length;
var s='';
for (var i=0;i<l;i++) s+=templateFunction(this[i]);
return s;
}

Using a function as return value

The template function will often be simple: It will just wrap each item in the array with one HTML element. F.e. when creating a table, the template function won't do much more than: return '<TD>'+item+'</TD>';. Let's create a function that generates these simple element wrappers:

function wrap(tag) {

var stag='<'+tag+'>';
var etag='</'+tag.replace(/s.*/,'')+'>';
return function(x) {
return stag+x+etag;
}
}

// examples:

document.write(wrap('B')('This is bold.'));
var B=wrap('B');
document.write(B('This is bold too.'));

document.write(
'<TABLE><TR>'+
arr.reduce(wrap('TD class="small"'))+
'</TR></TABLE>'
);

In the first example you can see that you can immediately call the returned function, which results in a somewhat unusual syntax of two argument lists next to eachother. There's another special thing happening here: the returned function referes to the stag and etag variables. That this works outside of the wrap function is because of the closure like behaviour of functions in Javascript. When a function is defined, it stores a pointer to the current scope. This scope is restored when the function is called.

Using functions as objects

In the last example, an array is converted to a table, each item in the array is wrapped with a <TD> element. If we want a vertical table layout, instead of horizontal, each item must be wrapped with both a <TR> element and a <TD> element. So we must create a new function again:

var TABLE=wrap('TABLE');var TR=wrap('TR');var TD=wrap('TD');

document.write(TABLE(arr.reduce(
function (item) {
return TR(TD(item));
}
)));

TR(TD(item)) is like function composition, written as 'TR o TD', and pronounced as 'TR after TD'. So we'd like to write this as:

document.write(TABLE(arr.reduce(TR.after(TD))));

In Javascript functions are objects too, and they can also have methods. So we can extend the function prototype so that the after method is available to all functions.

Function.prototype.after=function(g) {

var f=this;
return function(x) {
return f(g(x));
}
}


Tutorial Pages:
» Introduction
» Generating HTML
» Using methods as functions
» When should you use this?


This article is licensed under the Creative Commons


 | Bookmark
Related Tutorials:
» JavaScript Debugging Techniques with Firebug
» Striped Tables Using JavaScript
» Opening PDFs in a New Window with JavaScript
» Essential Javascript -- A Javascript Tutorial
» Submit Forms Conditionally using JavaScript
» How to Setup a Randomising Function

Advertise with Us!


Tutorials Scripts Web Hosting Developer Manuals
Resources