Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian...
-
Upload
nguyenthuan -
Category
Documents
-
view
217 -
download
0
Transcript of Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian...
Essential Backbone.js
Ian Chursky
Contents
Preface .......................................................................................................................................................... 1
History ...................................................................................................................................................... 1
What is Backbone.js? ................................................................................................................................ 1
Benefits of Using Backbone.js .................................................................................................................. 2
Who This Book Is For ............................................................................................................................... 2
Errata ......................................................................................................................................................... 3
Feedback ................................................................................................................................................... 3
Chapter 1: Routers ........................................................................................................................................ 4
New Routes ............................................................................................................................................... 5
Parameters & Splats .................................................................................................................................. 5
Better Code Organization ......................................................................................................................... 7
Navigate .................................................................................................................................................... 8
Summary ................................................................................................................................................... 8
Chapter 2: Views........................................................................................................................................... 9
Setup ......................................................................................................................................................... 9
Events ...................................................................................................................................................... 10
Templates ................................................................................................................................................ 12
Summary ................................................................................................................................................. 13
Chapter 3: Models ....................................................................................................................................... 14
Model Default Values ............................................................................................................................. 14
Initialize .................................................................................................................................................. 15
Get & Set ................................................................................................................................................ 15
Clone ....................................................................................................................................................... 15
Summary ................................................................................................................................................. 16
Chapter 4: Collections ................................................................................................................................. 17
Add, Remove, & Reset ........................................................................................................................... 17
Get & Set ................................................................................................................................................ 18
Summary ................................................................................................................................................. 18
Chapter 5: Using Templates in Backbone.js ............................................................................................... 19
Underscrore Templates ........................................................................................................................... 19
Handlebars .............................................................................................................................................. 20
Summary ................................................................................................................................................. 22
Chapter 6: APIs and Backbone.js ............................................................................................................... 23
What is an API? ...................................................................................................................................... 23
API Integration with Backbone.js ........................................................................................................... 24
Creating Our Own API With Slim PHP Framework .............................................................................. 25
Client Side: Backbone.js ......................................................................................................................... 27
Summary ................................................................................................................................................. 30
Chapter 7: Module Loading Backbone.js with RequireJS .......................................................................... 31
Why Use RequireJS? .............................................................................................................................. 31
Using RequireJS...................................................................................................................................... 33
Loading Our Own JavaScript With RequireJS ....................................................................................... 34
Shims ...................................................................................................................................................... 36
Summary ................................................................................................................................................. 37
Chapter 8: Additional Concepts: Data Binding .......................................................................................... 38
Chapter 9: Additional Concepts: Specialized Notification Views .............................................................. 41
Options .................................................................................................................................................... 43
Chapter 10: Extending Backbone.js ............................................................................................................ 44
Extending Classes ................................................................................................................................... 44
Creating New Classes ............................................................................................................................. 44
Conclusion .................................................................................................................................................. 47
Appendix A: Code Samples & Repos ......................................................................................................... 48
Acknowledgements
Big thanks to all of my family and friends for their continued love and support over the years.
Big thanks to all of the teachers and colleagues who have invested their time, effort (and patience) with me in so
many ways. I would not be where I am today without all of your help.
Biggest thanks of all to my wife Lauren and my 2 daughters: Mia and Calista. Love you all so much.
1
Preface Have you ever fired up your favorite web browser and gone to purchase airline tickets? Perhaps there was a visual
model of a plane where you could click on the exact seat and aisle that you wanted (of those that were available). Or
maybe you've signed in to your favorite photo-sharing or music-streaming website and you used a UI to create a
photo album or a playlist of songs by dragging and dropping elements on to different containers. If you have done so
at any time in the second decade of 21st century (the 2010s) you have likely noticed that a lot of these services
incorporate a high degree of interactivity. You click things, you drag and drop things and a lot of interesting things
happen in response. What's more, things that you do in the application in the present will remain reflected in the
application the next time you return to it in the future. Your data is somehow saved and persisted on the server
behind the scenes.
However you use the web, chances are you have used an application built with technology that implements this
interactive functionality. Backbone.js is part of the technologies that make these sorts of applications possible. That's
what this book is about. But first, a little bit of history on how we got here.
History Beginning at around 2009 - 2010 web pages on the modern Internet started undergoing rapid evolution in many
significant ways. While the web has always been a dynamic ever-changing environment, one of the more noticeable
developments was the rise of websites and web applications making use of more open technologies such as HTML5
and JavaScript to bring interactivity and 2-way communication between clients (usually browsers) and servers. In
the early 2000s when it came to interactive applications within browsers Adobe Flash dominated the Internet
landscape. Flash, however, was ultimately a problematic implementation for the open nature of the web in a number
of ways. Many of the problems that Flash brought about were summarized by the co-founder and CEO of Apple
Steve Jobs in an open letter called "Thoughts on Flash" published on April 29, 2010. Jobs explained why Apple
would not allow Flash on the iPhone, iPod touch and iPad. He cited the rapid energy consumption (Flash had always
been a bit of a resource hog), poor performance on mobile devices, abysmal security, lack of touch support, and
desire to avoid "a third party layer of software coming between the platform and the developer" (Flash runs as a
browser plugin). He touched on the idea of Flash being "open", claiming that "By almost any definition, Flash is a
closed system". This spelled the beginning of the end of the dominance of Flash on the web.
So with Flash on the way out, something had to fill the void. A lot of organizations returned to just the regular old
HTML website, but there was definitely a place for web applications especially with the ever accelerating growth of
the mobile web. And this is where the "single page application" (SPA) built using open technologies (HTML5 and
JavaScript) entered the fray. A single-page application, could be described as web application or web site that fits on
a single page. All the necessary code -- usually HTML, JavaScript, and CSS -- is retrieved with a single page load
and any additional resources that are needed are dynamically loaded and added to the page, usually in response to
user actions. The page does not reload at any point in the process, nor does control transfer to another page.
Interaction with the single page application often involves dynamic communication with the web server behind the
scenes. There is a diverse and flourishing ecosystem of JavaScript libraries that drive the functionality of these
single page applications. Backbone.js is part of this ecosystem.
What is Backbone.js? Backbone.js was created by Jeremy Ashkenas (who is also the creator of CoffeeScript and Underscore.js) and was
first released in 2010. It quickly gained popularity along with a number of other JavaScript libraries that were
emerging around that time. These included Ember.js, AngularJS, Knockout.js, and a number of others. These
JavaScript libraries could be loosely described as client-side "model-view-whatever" frameworks for creating single-
page applications. They all loosely follow the popular model-view-controller design pattern and they all seem to
have model component for storing data and a view component for displaying data, but the component in between
varies from framework to framework... Backbone has collections, Angular has directives, Knockout has view
models, and so on. This is where the "whatever" term comes from. It is sometimes abbreviated MVW or MV*, with
the * being a wildcard.
2
Regardless of what they name the various parts of their structure they all attempt to solve similar problems. But even
though the end goals are similar they're also often quite different in their respective approaches and what kinds of
things they focus on.
Backbone.js describes itself as follows on the Backbone.js homepage...
Backbone.js gives structure to web 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 API over a RESTful
JSON interface.
The following is a list of a few popular applications that at some point within their history were built in Backbone.js
on the whole or in part...
Airbnb, BitTorrent.com, Diaspora, Digg, DocumentCloud, Flixster, Foursquare, Grooveshark, Hulu, LinkedIn
Mobile, NewsBlur, Pandora Radio, Pinterest, Sony Entertainment Network, Soundcloud
Trello
...among others.
Benefits of Using Backbone.js So which one of these to choose? Why would one choose Backbone.js over other frameworks like AngularJS or
Ember.js? Why would one choose any of these others over Backbone? The answer to this question is probably
always going to be subjective on some level and there will always be many arguments on the Internet about which
of these is "better" or "best" but I believe there are some aspects of Backbone.js that can be seen as an overall
positive...
Backbone.js is small and simple -- Backbone is quite a bit smaller in terms of number of lines of code (and
therefore size) in relation to AngularJS and Ember.js. Some argue that this is a determinant because you end up
having to write more lines of boilerplate code in your application, but on the flip-side of this one of the criticisms of
these larger libraries is that there is "too much magic" going on where a lot more is being done for you. When
something goes wrong and you have a bug that you are trying to track down, there are a lot fewer lines of code to
step through with Backbone.js. Smaller might be a bit better in terms of control.
Non-cryptic syntax -- Although it has its own style, Backbone still feels very much like writing native JavaScript.
By contrast AngularJS is much more of an abstraction from JavaScript in the same manner that jQuery is. So the
learning curve for Backbone is probably smaller for those who have written JavaScript prior to coming to these
frameworks.
There may be others to discuss, but well save those all for another day because you are probably more interested in
diving into some code rather than arguing over personal preferences.
Who This Book Is For This book is for the developer who maybe has some experience with writing a bit of JavaScript or jQuery code but
has not yet ventured into the waters of SPA MVW (model-view-whatever) frameworks. This book will provide you
the essential basics of creating a Backbone application and in the process you hopefully will be able to get a grasp of
the concepts of building within this sort of framework. This knowledge is definitely helpful when moving to other
frameworks of similar type.
This book is also for the intermediate or seasoned JavaScript application developer who has maybe worked with
other frameworks but has been tasked with working on a Backbone application and need a quick reference of
working code and a high-level overview of the common components therein. This book will give you the essentials
to get up and going (hopefully as fast as possible).
3
Please note that this book will not cover a basic introduction to HTML and JavaScript. The content in this book
assumes that you have had at least some experience working with HTML, JavaScript, and jQuery – though,
honestly, you really do not need all that much. If you do not really know these technologies at all, it would be of
great benefit for you to take a few online tutorial courses before returning to what is presented here. W3Schools is a
very popular choice, but there are many others as well. All you really have to do these days is go to Google or
YouTube and type in "learn X," where X is whatever subject you want to learn.
This book also assumes that you have a basic understanding of how the web operates and that web pages and
resources (CSS files, images, cookies, etc.) are sent from server to client over HTTP(S) and the client (i.e. browser)
can send data back to the server (e.g. submitting forms) via the same protocol.
It is also assumed that you have at least a very basic understanding of how AJAX works using JSON as a data-
exchange format.
Errata While I and others have done our best to have proofread the content that is to follow, it is likely that there are a fair
number of mistakes that still exist within. You can send me any notifications of such errors via e-mail:
[email protected]. Errors found will be fixed with future updates of the book, which I will try to churn out as
fast as possible.
Feedback Also, feel free to send additional feedback of any kind via email: [email protected]. Just make sure to
reference in the subject line your e-mail has to do with this book. I will do my best to respond to all those who make
the effort to contact me. I am also on the Twitters @ianchursky and @9bitStudios so if you want to leave 140
characters of feedback (or just say hi) you can contact me there as well.
So, without further ado, let's jump right in. We'll start with something all web frameworks have to do. Handle
requests in the browser and route them to the proper place. So we will begin with Backbone.js routers.
4
Chapter 1: Routers In what follows, we are going to look at Backbone.js routers. Routers are a great place to start whenever you begin
developing a Backbone application (or any application for that matter) because you can figure out what URLs and
sections your app will need and you can then add hooks in your code to respond to them. On some levels it helps
define application structure, much like a flow chart would.
Backbone.js uses routers to execute certain actions when a user goes to a certain URL / hash location within a
Backbone application. Backbone applications all use routes that follow a # character in the URL. The # might be
familiar to you if you've ever used it as a named anchor to link to part of the current document without going to a
new URL. This is very prevalent in pages that have tables of content at the top (e.g. like in Wikipedia articles),
where the links at the top take you to a place on the same page further down. That's what's going to happen with
Backbone. We're going to stay on our same page, but we're going to set up our JavaScript such that Backbone listens
for the user going to these hash locations. When the user clicks on different links within the application, instead of
going to a different place on the page, we'll be executing different components of JavaScript in our code. That's how
a "client-side JavaScript application" essentially behaves.
So let's say we have the following HTML page where we've loaded up Backbone. Note that we're also going to want
to load Backbone's dependency library Underscore.js. What that means is, Undersocre.js is required for Backbone.js
to work properly. We also want to load jQuery (even though it’s actually not a dependency for Backbone) because
jQuery has a really nice on method that is useful for catching events thrown by Backbone. If that seems little unclear
to you at this point, you'll see what we mean a bit later on...
We're going to be adding code in the <script> section at the bottom. In a larger scale Backbone application, you'd
probably have all of your routers in a separate file called "routers.js," but for now we'll just do everything within our
HTML file.
So we'll set things up as the following...
<!DOCTYPE html> <html> <head> <script src="js/jquery.js" type="text/javascript"></script> <script src="js/underscore.js" type="text/javascript"></script> <script src="js/backbone.js" type="text/javascript"></script> </head> <body> <script type="text/javascript"> </script> </body> </html>
What we need to do first is define some routes. In the <script> section add the following code...
var Router = Backbone.Router.extend({ routes: { "": "home", // url:event that fires } }); var router = new Router;
What we have done here is create a new router and have given it a routes property. The "routes" object follows the
following format...
url : Name of event that fires
5
What does this mean? Well the string on the left is the URL hash that a user of your application is going to navigate
to and the string on the right is the name of the event that is fired off when that hash location is accessed.
So let's look at our first example. This "" is a blank string. This means you are going to the root URL of your
Backbone.js application. So, for example, if you had a BackboneJS application hosted at
http://www.yourwebsite.com/. This event would fire when the user went to http://www.yourwebsite.com/ (the home
page with no additional parameters or sub-page locations). The event would not fire if they went to
http://www.yourwebsite.com/#/newUser or http://www.yourwebsite.com/#/somethingElse because the strings
following the hash character would not be empty.
Next we want to add the following right after the code we added in the previous step...
router.on('route:home', function() { alert('We have loaded the home view'); }); Backbone.history.start();
Backbone.history.start(); is just a method that backbone uses to say "Start listening for routes." Before routers will
work in Backbone, you have to add this method. Just something to remember.
Now in your browser, go to your home URL. If you had this application hosted at http://www.yourwebsite.com/,
you'd just go to http://www.yourwebsite.com/. If you are developing locally you would want to go to http://localhost
or http://127.0.0.1. If we do this, you should see the alert fire meaning we are responding to the event "route:home".
New Routes Now let's add another route so that our code looks like the following...
var Router = Backbone.Router.extend({ routes: { "": "home", // url:event that fires "new": "createNew" } }); var router = new Router;
Now in the location where we added the previous "on" method, place the following code below that (but before the
Backbone.history.start(); statement) ...
router.on('route:createNew', function() { alert('We are going to create something new here...') });
Now in your browser, after your home URL add the following...
/#/new
Such that your URL will be something like http://www.yourwebsite.com/#/new, if you go to it, you can see that the
code in our method fires. What if you go to http://www.yourwebsite.com/#/createSomething. You'll see that the
code does not fire? Backbone has not matched either of the routes we have defined so no code is being executed.
Parameters & Splats If you've ever done web development utilizing dynamic pages of any kind, you know that the content on pages are
populated depending on the parameters that get passed in. So, for example, if you had a social profile of some sort,
you might have something like http://www.9bitSocialNetwork.com/profile?id=2345&view=all. In that case, the
parameters "id" and "view" would be used by the website to determine who's profile to show and how to show it.
6
You'd have one view that defined the layout and what you'd show in that view would depend on the specific
parameters. Backbone.js applications have the ability for you to pass in parameters as well.
Let's add yet another route such that our code looks like the following...
var Router = Backbone.Router.extend({ routes: { "": "home", // url:event that fires "new": "createNew" "edit/:id": "editItem", } }); var router = new Router;
And in the place where we have added our "on" methods add the following (but, again, before the
Backbone.history.start(); statement)...
router.on('route:editItem', function(idParam) { alert('We are going to edit entry number ' + idParam); });
So obviously we are going to try to catch an event when the user goes to http://www.yourwebsite.com/#/edit, but
what is that :id thing? This is how Backbone defines a parameter. Backbone is looking for a specific item to follow
the http://www.yourwebsite.com/#/edit. What happens if we go to the following URL?
http://www.yourwebsite.com/#/edit
Nothing happened. Why is that? It's because Backbone is expecting a parameter as we defined in our route. So now
try this...
http://www.yourwebsite.com/#/edit/1
Now we see that backbone is catching the id parameter and it's getting passed into the function. This is how we can
populate a single view in Backbone and have variable content passed in. What if we went to the following URL...
http://www.yourwebsite.com/#/edit/1/steve
Again nothing happens because this is passing in 2 parameters. To catch it we'd have to add another route
var Router = Backbone.Router.extend({ routes: { "": "home", // url:event that fires "new": "createNew" "edit/:id": "editItem", "edit/:id/:name": "editItemAndName", } }); var router = new Router; And catch the event here... router.on('route:editItemAndName', function(idParam, nameParam) { alert('We are going to edit entry number ' + idParam + 'and name ' + nameParam); });
Now if we go to the URL http://www.yourwebsite.com/#/edit/1/steve we can see that the event gets caught.
Backbone also has a special variable type of parameter called a "splat." A splat looks like the following...
7
var Router = Backbone.Router.extend({ routes: { "": "home", // url:event that fires "new": "createNew" "edit/:id": "editItem", "edit/:id/:name": "editItemAndName", "download/*anything": "downloadItem" } }); var router = new Router;
A spat basically means "match anything and everything," so as a result if you were going to use a splat you'd want to
set it as the last item in your defined route.
So if put a place to respond to this event...
router.on('route:downloadItem', function(anythingParam) { alert('What is stored in anything is ' + anythingParam); });
If we pass anything after "/#/download/" all of it (slashes and all) will get passed to the anythingParam argument. If
we go to http://www.yourwebsite.com/#/download nothing happens because Backbone is still expecting a
parameter. However if we go to something like http://www.yourwebsite.com/#/download/path/to/my/file we can see
that path/to/my/file gets passed into the parameter (slashes and all)
Now that we have defined some routes (and can easily add as many more as we want to) we are well on our way to
creating a nice Backbone.js application!
Better Code Organization Now that we have a good introductory baseline on what is happening with Backbone routers, we should take a quick
look at an alternate way of organizing Backbone routes in code. We can actually respond to the events within our
router and don't need separate jQuery "router.on" for each route outside of router. For example....
var Router = Backbone.Router.extend({ routes: { "": "home", // url:event that fires "new": "createNew" "edit/:id": "editItem", "edit/:id/:name": "editItemAndName", "download/*anything": "downloadItem" }, home: function() { alert('We have loaded the home view'); }, createNew: function() { alert('We are going to create something new'); } editItem: function(idParam) { alert('We are going to edit entry number ' + idParam); } }); var router = new Router;
8
Notice here that we have named some properties with the exact same string names defined in our routes. You can
use this approach as well if you prefer. This implementation tends to make the code a bit cleaner because everything
is nicely encapsulated within our router definition.
Navigate A Backbone.js router discussion would be incomplete if we didn't look at the very important Backbone router
method called navigate. The navigate method is basically how you redirect to other locations in your Backbone
application when you need to. This becomes very important when you are saving, updating, or deleting data. Often
times when you, say, add a new user by filing out a form in an application and hitting the "Submit" button, the
application will redirect back to the list of all users with a message that says "User Added" or something of the sort.
If you didn't do this, the person using your application would still be on the form page after hitting "Submit" which
is not the best user experience because they would have to then manually navigate themselves back to the home
screen.
Take a look at the implementation below. This is how navigate is called.
router.navigate('', { trigger:true });
What does this mean? This means navigate to the homepage (i.e. the "" route). Navigate by itself does not actually
execute the code that we have defined in our router. All it will do is update the URL. That is why we have to pass in
the { trigger: true } option to trigger the code we have defined in our route based on the path we have given. We
could direct users to any location in our application that we want using navigate. The code below would navigate to
the edit form for a user with ID #4...
router.navigate('edit/4', { trigger:true });
Where would you use something like this in an actual Backbone application? For a brief demo of this take a look at
the code below. In this example we are deleting an artist inside of a Backbone View. After the artist is deleted we
navigate back to the homepage on successful deletion.
var ArtistDeleteView = Backbone.View.extend({ el: '.deletePage', events: { 'click .delete': 'deleteArtist' }, deleteArtist: function (ev) { this.artist.destroy({ success: function () { console.log('Artist Deleted'); router.navigate('', {trigger:true}); } }) }, });
Summary We have only just scratched the surface of the components of Backbone.js but we have learned how to handle
different routes in this section. We now have the foundation to do more sophisticated things such as load up views,
get data from a server, or anything else that we want when the parts of our code for route changes fire. For more info
on Backbone routers, see the documentation on the official Backbone.js site here where you can expand upon the
knowledge you have learned here.