taming that client side mess with backbone.js

34
Taming that client side mess with…

Upload: jarod-ferguson

Post on 10-May-2015

4.491 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Taming that client side mess with Backbone.js

Taming that client side mess with…

Page 2: Taming that client side mess with Backbone.js

About me

[email protected] @jarodf

Page 3: Taming that client side mess with Backbone.js

Backbone.js

Oct 2010, DocumentCloud (Underscore.js, CoffeeScript)

Page 4: Taming that client side mess with Backbone.js

What does it do?

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

Page 5: Taming that client side mess with Backbone.js

Who uses backbone?

Page 6: Taming that client side mess with Backbone.js

But wait, this is way less code?

$(function () { var count = 0; $('#thebutton').click(function () { count++; $("#secondview").html(count); }); });

Page 7: Taming that client side mess with Backbone.js

var count = 0; $('#thebutton').click(function () { count++; if (count > 1) { $.ajax({ url: '/foo/dizzle/', type: "POST", dataType: 'json', data: someObjects.toJSON(), success: function (result) { if (result.status == 'Success') {

var html = ''; for (d in result.data) { if (d.whatever === ‘yola') { html += "<li class='yep'>" + d.name + "</li>"; } else { html += "<li class='nope'>" + d.name + "</li>"; } }

$("#secondview").html(html); toggleHistItems(result.tabId);

} else { alert(result.status); }

}, error: function (err) { uhOh(err); }

}); } else { yipKiYay(); } });

Page 8: Taming that client side mess with Backbone.js

var count = 0; $('#thebutton').click(function () { count++; if (count > 1) { $.ajax({ url: '/foo/dizzle/', type: "POST", dataType: 'json', data: someObjects.toJSON(), success: function (result) { if (result.status == 'Success') {

var html = ''; for (d in result.data) { if (d.whatever === ‘yola') { html += "<li class='yep'>" + d.name + "</li>"; } else { html += "<li class='nope'>" + d.name + "</li>"; } }

$("#secondview").html(html); toggleHistItems(result.tabId);

} else { alert(result.status); }

}, error: function (err) { uhOh(err); }

}); } else { yipKiYay(); } });

Page 9: Taming that client side mess with Backbone.js

The jQuery DivideRebecca Murphy – JSConf.eu

Page 10: Taming that client side mess with Backbone.js
Page 11: Taming that client side mess with Backbone.js

http://www.flickr.com/photos/ppix/2305078608/

Page 12: Taming that client side mess with Backbone.js
Page 13: Taming that client side mess with Backbone.js
Page 14: Taming that client side mess with Backbone.js
Page 15: Taming that client side mess with Backbone.js

Problem Not Unique

• Avoid callback soup• Patterns > Spaghetti• Logic in expected place, not tied to DOM

Page 16: Taming that client side mess with Backbone.js

Model

• Thing• Business Logic• Persistence

Page 17: Taming that client side mess with Backbone.js

var Todo = Backbone.Model.extend({ defaults: { content: "empty todo...", done: false }, initialize: function() { if (!this.get("content")) { this.set({"content": this.defaults.content}); } }, toggle: function() { this.save({done: !this.get("done")}); },

clear: function() { this.destroy(); } });

Page 18: Taming that client side mess with Backbone.js

Common Model Functions/Properties

• defaults, initialize• get/set/unset• id/cid• custom functions• validate/isValid• save/fetch/destroy• url/urlRoot

Page 19: Taming that client side mess with Backbone.js

Views

• Convention tied to a box on the page• Handles presentation logic (Presenter?)• Tied to a Model or Collections• Listens for Model changes• Listens for DOM events (click, hover, etc)

Page 20: Taming that client side mess with Backbone.js

var TodoView = Backbone.View.extend({ tagName: "li", template: _.template($('#item-template').html()),

events: { "click .check": "toggleDone", "dblclick label.todo-content": "edit", "click span.todo-destroy": "clear", "keypress .todo-input": "updateOnEnter", "blur .todo-input": "close" },

initialize: function () { this.model.bind('change', this.render, this);

this.model.bind('destroy', this.remove, this); },

render: function () { $el.html(this.template(this.model.toJSON())); this.input = this.$('.todo-input'); return this; },

edit: function () { $el.addClass("editing"); this.input.focus(); }, … snipped .. });

Page 21: Taming that client side mess with Backbone.js

Templates

• The ‘Markup’• Decouples UI Definition from data logic• Promotes reuse• Increased maintainability• Backbone doesn’t care which one you use– Underscore, Mustache, jsRender, jQuery etc

Page 22: Taming that client side mess with Backbone.js

$.each(messages.reverse(), function(index, message) {    $('#messageList').append(        '<li><span class="list-title">' +        message.userName + '</span>' +        '<abbr class="list-timestamp" title="' +        message.datePosted + '"></abbr>' +        '<p class="list-text">' + message.messageText + '</p></li>');    }});

Page 23: Taming that client side mess with Backbone.js

<script id="categoryTemplate" type="text/x-jquery-tmpl"> <button class="back-btn pointer" title="Back"></button> <div class="title"> ${name} </div> <ul> {{each(i, item) items}} <li class="hover" iid=${item.id}> <div class="title">${item.name}</div> <div class="desc">${item.description}</div> </li> {{/each}} </ul></script>

var fragment = $('#categoryTemplate').tmpl(category); $(this.el).html(fragment);

Page 24: Taming that client side mess with Backbone.js

Collections

• Set of Models• add, remove, refresh• get, at, length• fetch• sorting• _

Page 25: Taming that client side mess with Backbone.js

TV Timeout for Underscore.js

• Collections– each, any, all, find– filter/select, map, reduce

• Arrays– first, last– union, intersect

• Functions– bind, bindAll– memoize, defer

• Objects– keys, values– extend, clone

findCategory: function(id) { return _(this.categories()).find(function(cat){ return cat.id == id; }); },

Page 26: Taming that client side mess with Backbone.js

var TodoList = Backbone.Collection.extend({ model: Todo, localStorage: new Store("todos-backbone"),

done: function () { return this.filter(function (todo) {

return todo.get('done'); });

},

remaining: function () { return this.without.apply(this, this.done()); },

nextOrder: function () { if (!this.length) return 1; return this.last().get('order') + 1; },

comparator: function (todo) { return todo.get('order'); } });

Page 27: Taming that client side mess with Backbone.js

var accounts = new Backbone.Collection;accounts.url = '/accounts';

accounts.fetch();

Page 28: Taming that client side mess with Backbone.js

Routers

• Page Routing• Control Flow• Stateful, Bookmarkable

Page 29: Taming that client side mess with Backbone.js

TestRouter = Backbone.Router.extend({ routes: { "": "home", "foo": "foo", "bar/:name": "somefunction" },

home: function () {

},

foo: function () { alert('hi from foo'); },

somefunction: function (name) { alert(name); } });

Page 30: Taming that client side mess with Backbone.js

Events

var object = {};

_.extend(object, Backbone.Events);

object.on("alert", function(msg) { alert("Triggered " + msg);});

object.trigger("alert", "an event");

Page 31: Taming that client side mess with Backbone.js

Other

• History– a global router (per frame) to

handle hashchange events or pushState– matchs the appropriate route, and trigger callbacks

• Backbone.sync– method: the CRUD method– model: the model to be saved (or collection to be

read)– options: success and error callbacks, and all other

jQuery request options

Page 32: Taming that client side mess with Backbone.js

Catalog of Events• "add" (model, collection) — when a model is added to a collection.• "remove" (model, collection) — when a model is removed from a collection.• "reset" (collection) — when the collection's entire contents have been replaced.• "change" (model, options) — when a model's attributes have changed.• "change:[attribute]" (model, value, options) — when a specific attribute has

been updated.• "destroy" (model, collection) — when a model is destroyed.• "sync" (model, collection) — triggers whenever a model has been successfully

synced to the server.• "error" (model, collection) — when a model's validation fails, or a save call fails

on the server.• "route:[name]" (router) — when one of a router's routes has matched.• "all" — this special event fires for any triggered event, passing the event name

as the first argument.

Page 33: Taming that client side mess with Backbone.js

Advanced

• CoffeeScript• AMD/Require.js

Page 34: Taming that client side mess with Backbone.js

Get Started

Github sitehttp://documentcloud.github.com/backbone/

Backbone Fundamentalshttps://github.com/addyosmani/backbone-fundamentals

TodoMVChttp://addyosmani.github.com/todomvc/