Coding with Jesse

Free eBook: Unobtrusive Ajax

October 22nd, 2010

Great news! O'Reilly has been kind enough to let me distribute my eBook Unobtrusive Ajax to readers of my blog, so now you can download and read it for free!

Download "Unobtrusive Ajax" eBook

From the book's cover:

Unobtrusive Ajax is about making web applications that work for everyone all the time, even if you have JavaScript turned off, or you're using a mobile phone or a screen reader, or however you happen to be using the Web. It's about the separation of behavior (JavaScript), content (HTML), and presentation (CSS).

This short cut will focus on the practical benefits of using Ajax and JavaScript unobtrusively and show you that unobtrusive web development and progressive enhancement benefit both web developers and users of the Web. You'll get to see many simple examples of building web interfaces that are unobtrusive. You'll quickly see that it is actually very easy to make web applications that everyone can use.

When you're finished reading this book, you will be able to convince anyone why developing unobtrusively is the best way to build a site with JavaScript and Ajax.

I wrote this book back in 2007, before I'd discovered jQuery, so writing unobtrusive JavaScript has become even easier than ever. That said, the principals of writing web pages that work without JavaScript remain the same: keep your content in the HTML, use real links and forms, and avoid depending on JavaScript or Flash for any critical functionality.

Nowadays, I would also suggest bearing different user interfaces in mind. Not every visitor to your website has a mouse and a keyboard, some are using their handheld touchscreen phones, and if your shopping cart requires people to drag and drop, you may end up losing customers. Be careful not to make assumptions about your visitors. If you stick with basic HTML, you can't go wrong.

Official jQuery Templating Plugin

October 11st, 2010

jQuery announced that they are now officially supporting jQuery Templates, thanks in big part to Microsoft.

Templating cleans up the job of generating HTML with jQuery. It also gives you the opportunity of keeping HTML code out of your JavaScript completely, if you wish.

Let's say you have a block of data like this:

var fruits = [
    { name: 'apples', color: 'green' },
    { name: 'oranges', color: 'orange' },
    { name: 'bananas', color: 'yellow' },
    { name: 'tomatoes', color: 'red' }
];

You want to display the data in a nice table with some color effects:

namecolor
apples green
oranges orange
bananas yellow
tomatoes red

Without templates, your code might look like this:

// create a table
var $table = $('<table class="fruit-table">');

// append a header to the table
$('<tr><th>name</th><th>color</th></tr>').appendTo( $table );

// append a row for each fruit
for (var i in fruits) {
    // create a row, and set the background to the color of the fruit
    var $row = $('<tr/>', { css: { background: fruits[i].color } });

    // create a column and append to the row
    // we use text here so all HTML is escaped, to prevent hacking
    $('<td/>', { text: fruits[i].name }).appendTo( $row );

    // do the same for the color
    $('<td/>', { text: fruits[i].color }).appendTo( $row );

    // append the row to the table
    $row.appendTo( $table );
}

// all done, stick the table on the page
$table.appendTo('body');

Unfortunately, code like this usually ends up looking kludgy, and it's often hard to visualize what the final HTML will look like.

Templates let us turn the HTML/JavaScript relationship inside-out by putting the looping right in the HTML:

// define a template for the fruit table
// we'll use slashes at the end of each line to escape the line break
// this way we don't have to concatenate strings.
$.template('fruit-table', '\
    <table class="fruit-table"> \
        <tr><th>name</th><th>color</th></tr> \
        {{each rows}} \
            <tr style="background: ${color}"> \
                <td>${name}</td> \
                <td>${color}</td> \
            </tr> \
        {{/each}} \
    </table> \
');

// instantiate the template with the fruit array passed in as 'rows'
var $table = $.tmpl('fruit-table', { rows: fruits });

// that's it. stick it on the page.
$table.appendTo('body');

Now there's no question what the HTML will look like. It's in plain view.

If you'd like to jump on the chance to take the HTML out of your JavaScript completely, you can stick the same block on the page, in a special <script> block:

<script id="fruit-table" type="text/x-jquery-tmpl">

    <table class="fruit-table">
        <tr><th>name</th><th>color</th></tr>
        {{each rows}}
            <tr style="background: ${color}">
                <td>${name}</td>
                <td>${color}</td>
            </tr>
        {{/each}}
    </table>

</script>

Now we're down to a single line of code. Beautiful, isn't it?

$('#fruit-table').tmpl({ rows: fruits }).appendTo('body');

Now that we've gotten that taken care of, let's take it to the next level, and make a template that will dump any tabular data we give it:

<script id="table" type="text/x-jquery-tmpl">

{{if !data || data.length == 0 }}
    <p>No data.</p>
{{else}}
    <table class="${className}">
        <tr>
            {{each(key) data[0]}}
               <th>${key}</th>
            {{/each}}
        </tr>
        {{each(i, row) data}}
            <tr>
                {{each(key, value) row}}
                    <td>${value}</td>
                {{/each}}
            </tr>
        {{/each}}
    </table>
{{/if}}

</script>

$('#table').tmpl({
    data: fruits,
    className: 'fruits-table'
}).appendTo('body');

Want more? Check out the documentation and official announcements for lots more information:

jQuery Live Events

February 16th, 2009

jQuery 1.3 came out on January 14th, jQuery 1.3.1 on the 21st, and with them we now have live events built into jQuery.

Live events are pretty magical at first glance. They allow you to set events only once, and they work forever in the future, even as you're creating new elements and adding them to the page.

Normally if you ran:

$('a.wizard').click(function(){
    // do some wizardry
});

and then later you added wanted to add some more <a class="wizard">s to the page, you would have to re-attach this event handler over and over.

Live events allow you to add an event that will work forever. This means you only have to add each type of event once. You would only have to write:

$('a.wizard').live('click', function(){
    // do some wizardry
});

And your wizard links will work forever, even after you add 100 new wizard links to the page dynamically.

This magic trick works by attaching the click event to the document. Whenever you click anywhere on the page, the document click event gets called. jQuery compares the target element to your wizard links and triggers your click event if the click came from inside the link.

You can also do this yourself using the new closest() function. It allows you to do something like this:

// listen for clicks on the document
$(document).click(function(e){
    // look for a possible parent element matching a.wizard
    $(e.target).closest('a.wizard').each(function(){
        // wizard it up
    });
});

These live events can really help with performance. If you're attaching events to 100s of similar elements, like photos in an album, you can also save a lot of memory and speed things up by using live events, or using the example above and checking for events on a common parent element, either document or any element.

If you're used to using closures to use data within click handlers, you will find they won't work anymore which is probably a good thing. Instead, you can use data() to store any amount of data with that element and get it out later:

// maybe this is some JSON data you got using Ajax or something
var wizards = [
   { name: 'Merlin', skill: 'magic' },
   { name: 'Mr. Wizard', skill: 'science' }
];

$.each(wizards, function(i, wizard){
    // create a new link, change the text, add the data and append to the body
    $('<a class="wizard"/>')
        .text(wizard.name)
        .data('wizard', wizard)
        .appendTo(document.body);
});

then you only need to attach the click handler once:

$(document).ready(function(){

    $('a.wizard').live('click', function(){
        // fetch the data back out
        var wizard = $(this).data('wizard');

        // get the stuff you need out of the object
        var name = wizard.name;
        var skill = wizard.skill;

        // do your thing
        alert(
            "Hello my name is "
            + name
            + "and I'm better than you at "
            + skill
            + "!!!"
        );
    });

});

And you can actually do these things in reverse, the order doesn't matter because of the magic and universality of live events.

Pretty cool, eh? This way of developing has always been possible using JavaScript, but after learning about this with jQuery 1.3, it changed the way I look at programming with data and events.

What do you think? Any questions, corrections or suggestions? Leave a comment.

<< older posts newer posts >> All posts