Quick Tip: An Introduction to Sammy.js

Quick Tip: An Introduction to Sammy.js

Tutorial Details
  • Program: Sammy.js
  • Version: 0.5.4
  • Difficulty: Intermediate
  • Estimated Completion Time: 15 Minutes

You’ve been seeing it for a while now with Google’s Reader, Gmail, and most recently, on Facebook. Probably, you, too, would like to write RESTful evented JavaScript applications. Well, fellow developers, meet Sammy.js, a tiny JavaScript framework built on top of jQuery. Sammy utilizes the URL hash (#) to allow you to create single page AJAX applications that respond to your browser’s back button. Interested?

In this article, I’ll be providing a short overview of the framework, and then a brief demonstration of what it’s like working with Sammy.js, with the hope of enticing you enough to consider it for your projects.


Setting the Stage

“Sammy.js is light both in size (<20kb) and footprint. Pull it into your already started applications.”

Sammy.js is being put together by Aaron Quint, a web developer out of Brooklyn, NY. Its API is modeled on the popular ruby framework, Sinatra, and is great for both simple and complex applications. It’s easy to get into, and can be pulled into your existing projects. It’s not an all or nothing proposition; so let’s take a look.

Sammy.js allows you to write single page apps, much like Gmail. You can maintain the state of your app with the url, without having to refresh or change the page. There are other MVC JavaScript frameworks, like SproutCore, which tend to be all encompassing. But with Sammy, you have a light (~20kb) framework, capable of invoking several instances simultaneously (ie. running multiple apps in the same document).


Opening Act

Installing Sammy.js is pretty straightforward. Head on over to the download page, grab a copy and move, sammy-0.5.4.min.js to where you store your project’s libraries (typically /js for me). For the purpose of this article, I will be using version 0.5.4, but you may be inclined to try sammy-latest.min.js. You’ll also need a copy of jQuery, at least v. 1.4.1. As with most jQuery plugins, order is important: jQuery, before Sammy.js, before your JavaScript. I tend to put my JavaScript at the bottom of the page, because it blocks other items from loading in parallel, giving the impression of a slower loading page. So far we have:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    	<title>Sammy.js Example</title>
    </head>
    <body>

        <div id="content"></div>

        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
        <script type="text/javascript" src="js/sammy-0.5.4.min.js"></script>
        <script type="text/javascript">

            // your script goes here

        </script>

    </body>
    </html>

Now to start coding our app. To keep things simple, I’m working inline, which isn’t the best practice. Adding a Sammy.js application is as simple as assigning it to a variable, which I’m calling ratPack. On our page we’ve defined a div with the id “content” upon which our application will be acting. We indicate this as follows:


    var ratPack = $.sammy(function() {

        this.element_selector = '#content';

        // routes will go here

    });

The importance of the element selector is that we can have multiple instances of Sammy.js running in our document, affecting different elements.


Main Attraction

Sammy.js uses the path, as defined in the URL hash, and the common HTTP methods (get, post, put, delete) to determine a callback function to invoke. These are typically known as “routes”. Some examples from around the web would be:

As an example, we’ll sketch up a mailbox application. Let’s first setup the default route of our app, which will land on #/inbox.

    this.get('#/inbox', function(context) {
        context.app.swap('');
        context.$element().append('<h1>inbox</h1>');
    });

Here, you can make the callback function do whatever you’d like. Since I’m displaying an inbox, I’d probably want to make an ajax call and retrieve a list of messages. However, for the sake of simplicity, I’m just going to return a h1 tag. The context.app.swap('') tells Sammy to replace what’s in my content div, rather than just appending to it.

In order to get this working in the browser, we’ll want to run the app using jQuery’s document ready function and pass it to our starting URL, as defined in the above route.


    $(function() {
      ratPack.run('#/inbox');
    });

And that’s it. We should now be able to load our document in a browser, the app should launch and navigate us to our inbox.

Next, we can create another route to handle labeled messages:

    this.get('#/label/:name', function(context) {
        context.app.swap('');
        context.$element().append('<h1>' + this.params['name'] + '</h1>');
    });

Sammy uses the colon var syntax (:var) to return parameters for us to filter our messages. Again, I’m just displaying the name of the label.

To this point, we’ve only been using the “get” HTTP method. Say we were to create a form and route it to #/compose:

    this.get('#/compose', function(context) {
        context.app.swap('');
        context.$element().append('<h1>say hello to?</h1>'
          + '<form action="#/compose" method="post">'
          + '<input type="text" name="to" />'
          + '<input type="submit" name="submit" />'
          + '</form>');
    });

Now we can setup a route to accept the posted data and have Sammy parse it for us.

this.post('#/compose', function(context) {
    context.app.swap('');
    var to = this.params['to'];
    context.$element().append('<h1>hi ' + to + '</h1>');
});

That’s the basics. A simple API, powerful enough for projects both big and small. If you are following along with the code, we can add some navigation for ease of clicking.

    <div id="nav">
        <ul>
            <li><a href="#/inbox">inbox</a></li>
            <li><a href="#/compose">compose</a></li>
            <li><a href="#/label/drafts">drafts</a></li>
        </ul>
    </div>

Encore

Of course, Sammy.js has a lot more to offer than simply defining routes in the app. More advanced users can explore custom events and namespaces, for event-driven applications. Aaron is trying to keep the core of Sammy.js as tight as possible, but it also comes with a lot of plugins. There’s a title plugin, that allows you to easily set the document’s title for different routes. There are several templating systems, including haml and mustache. There’s a nice-looking form builder and Sammy.Store, “an abstract adapter class that wraps the multitude of in browser data storage into a single common set of methods for storing and retreiving data.”

I hope you’ve enjoyed this quick look at Sammy.js and are ready to consider using it in your applications. Let’s hear your thoughts on Sammy.js in the comments!

Add Comment

Discussion 42 Comments

  1. yamilurbina says:

    Sounds cool. I’m trying it as I write this. The fact that uses URL’s atracts me the most.

  2. Dan says:

    This looks nice for small widgets.

  3. Sahan says:

    User-friendly ajax :)

  4. Christopher says:

    freakin sweet! Damn its been a good day on nettuts.

  5. Zlatan Halilovic says:

    I have to agree on that one :)

  6. Andy King says:

    Simply awesome. Search-engine-indexable, bookmarkable, back-button friendly AJAX in a lightweight script. Joyous! Thanks to Aaron Quint for developing it, and to Arlo Breault for sharing this.

    • Jonas says:

      Sammy.js and similar scripts do not make your pages search-engine-indexable, so they’re mostly suited for apps that you log in to (because search engines wouldn’t normally index those pages anyway).

  7. elkaz says:

    I think Hotmail needs to get on board this bandwagon already.

  8. I read long back that # is a good tool in url to use it for preserving state and tracking pages. but reading about it will be a good journey. I was not aware of that sammy is in use on so many sites. even i was not aware of sammy. oh! need to get good knowledge of JQuery. I know only basic of it.

  9. hyperlexic says:

    greatest article photo ever.

  10. Johan says:

    Nice! Came like a letter in the mail. Love the back button support, and the fact that it’s built upon jQuery. Thanks!

  11. Codeforest says:

    Nice technique, Back button support is really sweet . Thanks for sharing

  12. Stefan says:

    Cool but nothing new, since SWFAddress have done this for years. But Sammy might be better and faster because it’s build on top of jQuery?

  13. Rory C says:

    I’d read a few articles on how to do this from scratch, but had no idea there was a framework already. Great trick, and one that I’ll definitely use. Thanks!

  14. w1sh says:

    Looks pretty cool. Does anyone know of any Sammy.js demos out there so I can see some more things it brings to the table?

  15. Jens Scherbl says:

    Thanks for sharing.

    While I’m generally not a big fan of unnecessary overuse of Ajax all over the place (see Facebook for a pretty good example how NOT to use Ajax), this might actually come in handy in some very specific situations.

    I also recommend reading “The Overuse of Ajax and How to be a good Ajax developer” by Cory Mawhorter:

    http://www.mawhorter.net/web-development/the-overuse-of-ajax-and-how-to-be-a-good-ajax-developer

  16. Lehi Sanchez says:

    I’ve been looking for a js-based solution for implementing routes. I’ll be looking forward to testing this with my iPad Web App. Thanks for posting!

  17. Perfect timing! Yesterday I was talking about implementing this on project and today I get a nice tutorial from nettuts!

  18. Daniel S says:

    WAIT! That sounds interesting – but your User will see NOTHING if he disables JavaScript – and thats a big disadvantage to usability. We need to develop a workaround for the guys who switched of javascript, man!

    Greetings from Germany,

    Daniel

  19. Alexander says:

    What about an analog for mootools? Is there smth?

  20. Jamal Mohamed says:

    Nice script. It sound cool and I’m gonna bookmark in case I need some functionality like that in the future.

    The name is ‘orrible though. Wasn’t it Samy’s script that went from profile to profile in MySpace several years ago, that added “but most of all, Samy is my hero” statement in every profile it went trough… A villain’s namesake indeed.

  21. VanThien says:

    Thanks it. This can help me.

  22. adrian says:

    there was a post in jquery for designers not long ago that promoted an virtually identical plugin BBQ (http://benalman.com/projects/jquery-bbq-plugin/) and chris posted something on css tricks on how to do it yourself

  23. xRommelx says:

    this is really awesome!

  24. Xarren says:

    Anyone tried this with CodeIgniter? How does it work together with CI segmented links? I’m going to try it out once I’ve finished my current projects, however I’m a bit worried that CI might treat the extra segment as an argument.

  25. Thanks :) It was very useful for me :)

  26. Dima says:

    To my mind, Xarren is right, tough there is nothing to worry about

    Wonderful post !

  27. Jehnee says:

    very nice thanks!

  28. Jonas says:

    Good idea, but keep in mind that this does NOT make your Ajax-driven page search engine friendly. It does, however, ensure that the states of your app can be bookmarked.

    • Jonas says:

      As far as I can see, search engines still cannot read JavaScript, so if you want to use the hash mark, you still have to provide the content to the search engines as HTML, not JavaScript. That’s more complicated than what’s been shown above.

  29. Blagoevgrad says:

    Great information! Thanks for posting

  30. Ed says:

    Xarren,

    Yes this does work with codeigniter.

    it works pretty much the same way as described in this tutorial.

    I love sammy.js so I’m glad that it does work with codeigniter.

  31. alex says:

    how i can load another file by sammerjs?

    for exemple, in php i write:

    ps. I just start styding JS

    thans, wmag

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.