Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian...

13

Transcript of Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian...

Page 1: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give
Page 2: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

Essential Backbone.js

Ian Chursky

Page 3: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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

Page 4: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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

Page 5: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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.

Page 6: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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.

Page 7: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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).

Page 8: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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.

Page 9: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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

Page 10: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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.

Page 11: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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...

Page 12: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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;

Page 13: Essential Backbonesamples.leanpub.com/essential-backbonejs-sample.pdf · Essential Backbone.js Ian Chursky . ... Chapter 5: Using Templates in Backbone.js ... This book will give

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.