
seen from Malaysia
seen from Malaysia
seen from Brazil
seen from Sweden

seen from Philippines
seen from Egypt

seen from Australia

seen from Brazil
seen from China
seen from China
seen from Brazil

seen from Malaysia

seen from United States
seen from United States
seen from China

seen from Türkiye
seen from United States

seen from United States
seen from China
seen from China
HelloJS is a collection of examples for Javascript libraries. Browse through source or get hands-on by deploying code to Dropbox
This book was recommended to me by a colleague. It steps into decision made during the development of backbone.js and spine.js. I look forward to receiving it next week.
There is more information on Alex MacCaw's book on his website.
Exposing Environment Variables to Static Spine.js Apps
If you're using [Spine.app](http://spinejs.com/docs/app) to build your static Spine.js app, you might run into the same problem that we did: there was some configuration (such as the host of our API) that needed to change from environment to environment. I wanted to retain the completely static compilation process that Spine affords us without doing anything terribly hacky like client-side host-based conditionals. Luckily, Spine.js apps are compiled using [hem](https://github.com/maccman/hem) and hem has a (not so well documented) way to write custom compilers! I wanted to be able to selectively expose environment variables (which are very easy to set on Heroku) and also supply sensible defaults. So I decided that I would create a `.env` compiler that would parse a JSON hash as default values and override it with any available environment variables. All you have to do is put this into `slug.js` in your project's root: var hem = new (require('hem')); var fs = require('fs'); var argv = process.argv.slice(2); hem.compilers.env = function(path) { var content = fs.readFileSync(path, 'utf8'); var envHash = JSON.parse(content); for (key in envHash) { if (process.env[key]) { envHash[key] = process.env[key]; } } return "module.exports = " + JSON.stringify(envHash); }; hem.exec(argv[0]); This simple script declares a compiler, then reads and parses a JSON file from disk, replacing any declared keys with any environment variables that are present. Now I can define a file (say `app/environment.env`) that looks like this: {"API_HOST":"https://api.divshot.com","RUNTIME":"web"} And I'm able to access and/or override those variables per-environment. For instance, in local development I can run: API_HOST=http://localhost:8080 hem server Or even better, if I'm compiling my app for offline use as a packaged app, I can pass a flag: RUNTIME=chrome hem compile All that is required to access these variables is to require the `environment` file like you would any other: window.env = require("environment") console.log(env.API_HOST) This is a simple hack that provides some powerful configurability. If you're using Spine.app, it might just come in handy! ### Bonus: Making it work on Heroku When I did this I did it with the target of deploying to Heroku using [our Spine Heroku buildpack](http://github.com/divshot/heroku-buildpack-spine). When I deployed to Heroku...it didn't work! That's because by default Heroku doesn't expose config variables to the build process. Luckily, there is a [Heroku labs feature](https://devcenter.heroku.com/articles/labs-user-env-compile) to expose config variables during the build process. Just run: heroku labs:add user-env-compile Now when the buildpack compiles your assets, it will detect and assign environment variables appropriately. We think this is a fantastic way to deploy static HTML with not-quite-static results.
Listening for Model.fetch in Spine.js
When you call `fetch` on a model to update from the server, bind to `refresh` if you want to call a select method in your handler. If you bind to `fetch`, any select method will return an empty array.
Spine.js vs Backbone.js
Spine and Backbone are two Javascript MVC frameworks that look very similar on the surface but under the hood there are key differences. The purpose of this article is to highlight these differences and hopefully make it easier to choose which framework fits your needs.
The basics
Backbone is written in Javascript and was created by Jeremy Ashkenas in the year 2010. Spine came later and was highly inspired by Backbone, it is created by Alex MacCaw and is written in CoffeeScript.
Backbone was very successful right from the start and has been used by many established companies such as 37signals, Fog Creek Software, LinkedIn and many others. Spine has gained some attraction, specially by CoffeeScript developers, but not nearly as much as Backbone.
Spine size is 7k, it aims to simplify MVC and integrates well with CoffeeScript. Backbone size is 5.6k and it depends on the utility library Underscore.js ( 4k ) that makes up for some of Javascript missing features.
Positive by default
In the beginning Spine implemented a concept called asynchronous user interfaces. The way it works is that the user interface is updated when models are saved without waiting for the server response, expecting the result to be positive. This made Spine apps snappier and is explained well by the creator of Spine in his article about async uis.
Backbone introduced the same concept in version 0.9 and the models are now also positive by default. It's still possible to turn this behavior off in Backbone by setting the wait option to true in the methods save, create and destroy.
Example:
contact.save({ wait: true });
Models vs. Collections
Backbone has Models and Collections but in Spine there are only Models.
Spine is similar to Active Record in Rails where static methods operate on the list of records while instance methods work on single record instances. This makes Spine simple for doing basic things such as adding a contact to a contact list.
Example:
var Contact = Spine.Model.sub(); Contact.configure("Contact", "name", "email"); Contact.extend( Spine.Model.Ajax ); // Usage var contact = new Contact({ name: "Sven Svensson", email: "[email protected]" }); contact.save();
The save operation in this example syncs the model to the server and adds the record to the list of contacts. Let’s next accomplish the same thing using Backbone.
Example:
var Contact = Backbone.Model.extend({}); var Contacts = Backbone.Collection.extend({ model: Contact, url: "contacts" }); // Usage var contacts = new Contacts(); var contact = new Contact({ name: "Sven Svensson", email: "[email protected]" }); contacts.create( contact );
As you can see there are differences between the two so let’s dive a bit deeper.
Attributes
Notice this line in the Spine model example.
Contact.configure("Contact", "name", "email");
Spine attributes that are synced to the server need to be configured so they are not mixed with other properties on the model that are only stored in memory.
Example:
Contact.configure("Contact", "name", "email"); contact.name = “John Johnson”; contact.email = “[email protected]”; contact.onlyInMemory = true;
In Backbone attributes are not stored directly on the model and are accessible through get and set methods.
Example:
contact.set({ name: “John Johnson”, email: “[email protected]” }); contact.onlyInMemory = true;
This means that Spine models are more static because they need to be defined beforehand but Backbone models are dynamic and can be changed on the fly. If you need models that have dynamic attributes Backbone is a better friend.
Another advantage of the setter method in Backbone is that it fires both change and change:attribute events when setting attributes. This is helpful in use cases where the user interface should be updated at the same time as attributes are changed.
Unique identifiers
Spine makes it impossible to change the name of the unique identifier to something else than id.
This is a problem for example with databases such as CouchDB and MongoDB where the name is usually _id but not id. To make this work with Spine there needs to some sort of conversion between the two names which is dirty.
Backbone has a property called idAttribute that makes it easy to switch the unique identifier name to something else than id.
Example:
var Contact = Backbone.Model.extend({ idAttribute: "_id" });
The models of Backbone also include an identifier called cid that is generated on the client before models are saved to the server and are specially useful for asynchronous user interfaces.
Strangely enough Spine models generate a client identifier that is set on the id before saving to the server and is overwritten as the model is synced for the first time. This is in my opinion very confusing and only increases the likelihood of introducing bugs.
Storing records
Spine stores records in a hash internally but Backbone uses both an array and a hash.
The Spine hash uses id as the hash key and are therefore super fast for retrieving records by id. The problem with this approach is that for most other cases the hash is slower, for example the methods count, toJSON, first, last need to convert the hash to an array before returning the result, this is slower than just using an array.
Backbone collections keeps the records array always sorted by default but that behavior is hard to reproduce using only a hash. To sort records in Spine the hash has to be converted to an array and sorted using the sort method of javascript arrays.
That brings us to the next part about helper methods.
Helpful Helpers
Backbone depends on the Underscore library as stated above. Underscore is mostly used by Backbone collections to provide many useful methods such as map, filter, pluck and many more can be quite useful.
Spine has few helper methods like select and findByAttribute but nothing as extensive as in Underscore . This is less of a problem in Spine for CoffeeScript developers as Coffee makes it easier to implement these kinds of operations.
Views vs. Controllers
Spine controllers and Backbone views serve the same purpose and bridge the gap between the HTML markup and the model layer. In a conventional server-side MVC framework this layer is most often referred to as controllers and in my mind that name makes more sense than calling it views because the markup represents the view.
Lets not get carried away and rather take a look at a simple Backbone view example.
Example:
var ContactView = Backbone.View.extend({ events: { "click li": "openContact" }, initialize: function() { contacts.bind( "reset", reset, this ); contacts.fetch(); }, reset: function() { this.contactList = this.$("#contact-list"); // Do stuff } }); // Usage new ContactView({ el: $("#view").get(0) });
Spine controllers are almost identical.
var ContactView = Spine.Controller.create({ events: { "click li": "openContact" }, elements: { "#contact-list": "contactList" }, init: function() { ContactModel.bind( "refresh", refresh ); ContactModel.fetch(); }, refresh: function() { // Do stuff }, }); // Usage new ContactView({ el: $("#view") });
In both implementation we have list of events, a constructor and methods. Spine additionally provides a way to define the elements used by the controller with the elements list, its a very much used shorthand and a nice-to-have.
Architecture
Another good thing about the Spine is that the library is broken into separate files. Spine core, ajax, local storage and routes are separate files so it’s possible to pick which one to include in our apps and avoid loading unnecessary code.
I think this is something that could be done with Backbone as its mainly one file that could be broken up to make things lean and cleaner.
Conclusion
Spine and Backbone are frameworks that provide structure to our javascript code and features that help us to focus on writing better web applications. I have used both these frameworks and been happy with the results in both cases.
As a conclusion I recommend when the key thing is simplicity or CoffeeScript integration choose Spine. In most other cases I recommend using Backbone with Underscore as the tool for the job.
spine.js contacts tutorial bugs
When working through the spine contacts tutorial, there are a few things missing (as of 4/20/2012) to get the final pretty output. 1. Edit slug.json to include spine/lib/list as a dependency. 2. Edit Main to include the following
className: 'main stack'
3. The public index should export the app in this manner:
exports.app = new App({el: $("#article")});
4. The body should contain the following:
<header id="header"> <h1>Spine Contacts</h1> </header> <article id="article"></article>
5. Finally, copy over the fancy css from the github repo!
Spine.js & creating non-blocking user interfaces
My slides from STHML.js meetup about Javascript MVC & Creating non-blocking user interfaces with Spine.js.
http://www.slideshare.net/hjortureh/spine-js-creating-non-blocking-user-interfaces