Another little piece of DocumentCloud is now available: Backbone supplies structure to JavaScript-heavy applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.

We make heavy use of Backbone to create the DocumentCloud workspace. Your documents, notes, projects, and collaborators are all represented by Backbone models, and almost everything you see in the interface is created by a Backbone view. Hopefully the library will prove helpful to other folks dealing with JavaScript-heavy applications.

17 Responses to 'Code Drop: Backbone.js'

Backbone and Underscore are very nice. I started prototyping with them to build an MVC in Javascript. Its lightweight beats everything I tried before. Way to go!

One thing however, the fetch, save and sync functions are not flexible enough. Only four methods are supported but our Back-end has a much richer set. Plus the URLs are built making too many assumptions. It would be better if I could define the methods and their URLs explicitly. To get around that, I found myself rewriting some of that code.

Despite this, I will continue using Backbone – it suits well my needs.

The four basic REST/CRUD methods are supported out of the box by Backbone — naturally, you’ll need to extend your models with more than that (we certainly do). That said, I don’t think that Backbone *should* support more than REST, by default. Are there particular methods you think should be added to all models?

In our case the URL is directly tied to the method we use (i.e. /get_task, /update_task, /complete_task, etc). They go hand in hand. Currently the url function isn’t aware of the method. Plus the GET/POST arguments are built inside the Backbone.sync function.

I don’t think the solution is for Backbone to support more methods out of the box, but instead to offer means for developers to register their own. And to let developers attach those to functions instead of imposing. For example, the Collection’s create function calls the Model’s save function. What if I want to do further processing before saving?

You can use “extend” to make a subclass of Model, View, or Collection, overriding as many of the existing methods as you see fit. If you want to perform additional processing before saving, override Model#save, and insert the processing there.

While writing my first prototype with Backbone, I struggled finding where to put Controller logic. In the end, I established a convention that it should always be in the View – never in the Model. That way, the model can remain generic and could be used by multiple views.
With a little perspective, it even seems that Views are in fact Controllers and they could be renamed as such. What do you think?

I’m curious if anyone has implemented both a localstorage + ajax solution with Backbone? I’m just getting started with Backbone, but would like to be able to download data from the server via ajax, save it to localstorage, and then update the views.

I haven’t seen a LocalStorage + Ajax plugin yet. Unfortunately, LocalStorage is significantly different from a real database, and it’s a little tricky to make the same model representations work well when stored on the server as well as the browser.

I don’t see a destroy/delete method on a view. How are they removed from memory? This is my scenario: I have a collection of models that can be filtered. I only want to have views for unfiltered models. So at any time, I would like to create/delete views on the fly.
Thoughts or suggestions?

However it would be nice it events supported namespaces like jQuery. Because I now have multiple views looking at one same model. When I destroy one, I have to call unbinds on all the events and handlers I passed to bind. It is a pain to maintain…

And a one() bind function like jQuery would also be nice. But that’s a nice to have.

“trigger” does assume that the length of the events array does not change while it is being iterated over. However, your fix will cause undefined behavior in the case where you “unbind” events during a trigger — causing some events that should be fired to be skipped over.

If you have a piece of real-world code that caused an issue with “trigger”, please open a ticket here:

You are indeed right. I have hit some issues.
I opened a ticket. However the live code I have is too big to share. So in my ticket I presented a scenario where Events in Backbone break. I hope you can fix it. It is currently a blocker for me.

Hi,
I’m working on a project where we use intensively Backbone.
Just a little thing you should add to the documentation : “_changed” is a sort of reserved keyword that one must not use as a callback function. I’ve lost hours trying to find out why I had the following error :
TypeError: func.apply is not a function
This exception is raised in the trigger() function by this line :
list[i].apply(this, Array.prototype.slice.call(arguments, 1));
when it tries to invoke the _changed callback but gets mixed up with the Backbone _changed property.
Hope this helps others to not loose as much time as I have !
Regards,
Christophe