Sammy 0.5: Something for Everyone

Something for everyone

I’m pleased to announce the next major release of Sammy.js, 0.5.0. I’ll go over what I think are the most import changes, but you can check out the HISTORY or just cut to the chase and download it.

jQuery 1.4.1

One of the big events I was waiting for in order to release this new version was the release of jQuery 1.4.1. Besides being a good leap and jump faster then previous versions, the latest jQuery added support for cross-browser bubbling of the submit event. This might not sound like a big deal, but Sammy handles post/put/delete routes by binding to forms and their submit events. In previous versions of Sammy, if a form was dynamically added to the page (i.e. by a partial or get route), you (or the app) would fire a changed event, which would tell the app to search for all newly added forms and bind to their submit events. Using the power of jQuery 1.4.1, Sammy can now just listen for submit events that will bubble up to the applications element and from their dispatch the route. In general this is a lot cleaner and will make it easier for beginners as it just works.

Chain of fools

From user requests, and to fulfill my own desires, I’ve tried make Sammy more adaptable to different styles of coding/app creation. The first thing I realized why not make Sammy app definitions chain-able? It’s a style of development that jQuery developers are already used to, and it looks pretty swanky, too. With 0.5, all the app modifying methods are now chain-able:

  

// classic style:
$.sammy(function() {
this.use(Sammy.Mustache);
this.use(Sammy.Session);

this.before(function() {
// …
});

this.get('#/', function() {
// …
});

this.bind('run', function() {
// …
});

})

// New chain style:
$.sammy()
.use(Sammy.Mustache)
.use(Sammy.Session)
.before(function() {
// .
})
.get('#/', function() {
// …
})
.bind('run', function() {
// …
});

Sammy()

Once just a namespace, Sammy() is now a function (and its aliased to $.sammy). The Sammy() method provides access to the new Sammy.apps object and hence allows you to access the different Sammy applications you’ve added to the page without having to define additional global vars. Finding and extending is all based on @element_selector@s so those should be unique per-application. It also provides a quicker syntax for defining an app bound to an element_selector.

// Old way
// we're forced to make app a global so we can access it
// outside of this closure
app = $.sammy(function() {
this.element_selector = '#myapp';
//…
})
// equivalent to
app = new Sammy.Application(function() {
this.element_selector = '#myapp';
//…
});

// NEW WAY
$.sammy('#myapp', function() {
//…
});
// equivalent to Sammy('#myapp', function() {})

// No need to assign it, the app can be looked up by element selector
$.sammy('#myapp') //=> Sammy.Application

There are some cool use-cases for this, including being able to iterate over all the Sammy apps in play and extend them.

any way you want it

Sammy 0.5 adds the new any pseudo-verb which allows you to easily add a route that will match against any verb:

  
$.sammy(function() {

this.any('#/', function() {
this.log("I'm up for anything");
});

// also equivalent
this.route('#/', function() {});

});

This was actually the first step of another way to define Sammy applications. The new mapRoutes() method allows you to define any number of routes as 2D Array.

$.sammy(function() {

this.runIndex = function() {
this.partial('index.template');
};

this.mapRoutes([
// each element in the array represents the arguments sent to route()
['get', '#/user', function() {
this.partial('user.template');
}],
// leaving out the verb assumes the verb is 'any'
[/\/alert$/, function() {
alert(this.params['alert']);
}],
// passing a string instead of a callback assigns the method with that
// name from the application.
['get', '#/', 'runIndex']
]);

});

I personally like the method syntax better, but there are some cool uses for this – You could even load your routes from multiple files and add them to the application using JSON.

Filters

before filters are very useful for extracting common functionality out of your routes. However, I’ve found myself writing this pretty often:

$.sammy(function() {

this.before(function() {
// only run if the path is not the index
if (this.path != '#/') {
//… do something
}
})

});

Taking some hints from Rails, I’ve added options to before filters. The above example could be rewritten:

$.sammy(function() {

this.before({except: '#/'}, function() {
//… do something
})

});

The filters can match against path (as a string or RegExp) and verb and you can define them in the positive (only) or negative (except). The method that does the matching is exposed as contextMatchesOptions so you can use it outside of before()

I’ve also found myself doing a lot of wrapping entire route callbacks in an asynchronous check for something (usually a login). The new around filters make this easy. around takes a single argument which is a neatly packed function that contains the full execution path of the route being accessed. This includes additional filters and the route callback itself. This also means you can entirely halt the execution by never running the passed callback.

$.sammy(function() {

this.around(function(callback) {
// `this` here is the Sammy.EventContext
// just like before, etc
$.get('/session', function() {
callback();
});
});

})

Lots more

Theres actually a fair amount more to cover in Sammy 0.5, but I think I’ll be doing more short ‘Whats new’ posts soon. Check the HISTORY for a full rundown of changes.

Thanks

Special thanks goes out to everyone who helped with ideas, commits and testing for this release including Lena Herrmann, Jinzhu, dpree, Jeff O’Connell, Todd Willey, Tim Caswell, and Frank Prâßdorf (endor).

3 Responses to “Sammy 0.5: Something for Everyone”

Really interesting… I’m gonna try it. Thanks!
P.S. The download link, “http://github.com/quirkey/sammy/tarball/v0.5.0”, is broken. I downloaded from “http://github.com/quirkey/sammy/tarball/0.5.0” (no ‘v’ before “0.5.0”). Bye!

AQ Says: #

Thanks for the catch! that was my mistake. I’ve re-pushed the tag as v0.5.0.

I love this library!

One suggestion for the next tutorial: how to do a set of tabs, such that each tab page is a Sammy route so tab changes get into the history – and can jQuery tabs be used for this?

About

QuirkeyBlog is Aaron Quint's perspective on the ongoing adventure of Code, Life, Work and the Web.

twitter/@aq.

instagram/@quirkey.

github/quirkey.

QuirkeyBlog is proudly powered by WordPress

Categories