Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote-tracking branch 'upstream/gh-pages' into gh-pages

  • Loading branch information...
commit dd422c814b350c066103af081fa373625d888c3b 2 parents 4391cad + fbed703
@dcmaf dcmaf authored
View
BIN  backbone-fundamentals.epub
Binary file not shown
View
369 backbone-fundamentals.md
@@ -11706,374 +11706,5 @@ From the source for `Backbone.history.start`:
`Backbone.History.stop` similarly uses your DOM manipulation library to unbind these event listeners.
-## Upgrading to Backbone 0.9.10
-
-
-*Developing Backbone.js Applications* is currently based on Backbone 0.9.10. If you are transitioning from 0.9.2 to 0.9.10 or above, the following is a guide of [changes](http://backbonejs.org/#changelog) grouped by classes, where applicable.
-
-**Note:** We aim to update the entirety of this book to Backbone 1.0 once it has been tagged.
-
-### Model
-
-* Model validation is now only enforced by default in `Model#save` and is no longer enforced by default upon construction or in `Model#set`, unless the `{validate:true}` option is passed:
-
-```javascript
-var model = new Backbone.Model({name: "One"});
-model.validate = function(attrs) {
- if (!attrs.name) {
- return "No thanks.";
- }
-};
-model.set({name: "Two"});
-console.log(model.get('name'));
-// 'Two'
-model.unset('name', {validate: true});
-// false
-```
-
-* Passing `{silent:true}` on change will no longer delay individual `"change:attr"` events, instead they are silenced entirely.
-
-```javascript
-var model = new Backbone.Model();
-model.set({x: true}, {silent: true});
-
-console.log(!model.hasChanged(0));
-// true
-console.log(!model.hasChanged(''));
-// true
-```
-
-* The `Model#change` method has been removed, as delayed attribute changes as no longer available.
-
-* Calling `destroy` on a Model will now return `false` if the model `isNew`.
-
-```javascript
-var model = new Backbone.Model();
-console.log(model.destroy());
-// false
-```
-
-* After fetching a model or a collection, all defined parse functions will now be run. So fetching a collection and getting back new models could cause both the collection to parse the list, and then each model to be parsed in turn, if you have both functions defined.
-
-* HTTP PATCH support allows us to send only changed attributes (i.e partial updates) to the server by passing `{patch: true}` i.e `model.save(attrs, {patch: true})`.
-
-```javascript
-// Save partial using PATCH
-model.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4});
-model.save();
-model.save({b: 2, d: 4}, {patch: true});
-console.log(this.syncArgs.method);
-// 'patch'
-```
-
-* When using `add` on a collection, passing `{merge: true}` will now cause duplicate models to have their attributes merged in to the existing models, instead of being ignored.
-
-```javascript
-var items = new Backbone.Collection;
-items.add([{ id : 1, name: "Dog" , age: 3}, { id : 2, name: "cat" , age: 2}]);
-items.add([{ id : 1, name: "Bear" }], {merge: true });
-items.add([{ id : 2, name: "lion" }]); // merge: false
-
-console.log(JSON.stringify(items.toJSON()));
-// [{"id":1,"name":"Bear","age":3},{"id":2,"name":"cat","age":2}]
-
-```
-
-### Collection
-
-
-* While listening to a [reset](http://backbonejs.org/#Collection-reset) event, the list of previous models is now available in `options.previousModels`, for convenience.
-
-```javascript
-var model = new Backbone.Model();
-var collection = new Backbone.Collection([model])
-.on('reset', function(collection, options) {
- console.log(options.previousModels);
- console.log([model]);
- console.log(options.previousModels[0] === model); // true
-});
-collection.reset([]);
-```
-
-* `Collection#sort` now triggers a `sort` event, instead of a `reset` event.
-
-* Removed `getByCid` from Collections. `collection.get` now supports lookup by both id and cid.
-
-* Collections now also proxy Underscore method name aliases (`collect`, `inject`, `foldl`, `foldr`, `head`, `tail`, `take`, and so on...)
-
-* Added `update` (which is also available as an option to fetch) for "smart" updating of sets of models.
-
-The update method attempts to perform smart updating of a collection using a specified list of models. When a model in this list isn't present in the collection, it is added. If it is, its attributes will be merged. Models which are present in the collection but not in the list are removed.
-
-```javascript
-var theBeatles = new Collection(['john', 'paul', 'george', 'ringo']);
-
-theBeatles.update(['john', 'paul', 'george', 'pete']);
-
-// Fires a `remove` event for 'ringo', and an `add` event for 'pete'.
-// Updates any of john, paul and georges's attributes that may have
-// changed over the years.
-```
-
-* `collection.indexOf(model)` can be used to retrieve the index of a model as necessary.
-
-```javascript
-var col = new Backbone.Collection;
-
-col.comparator = function(a, b) {
- return a.get('name') < b.get('name') ? -1 : 1;
-};
-
-var tom = new Backbone.Model({name: 'Tom'});
-var rob = new Backbone.Model({name: 'Rob'});
-var tim = new Backbone.Model({name: 'Tim'});
-
-col.add(tom);
-col.add(rob);
-col.add(tim);
-
-console.log(col.indexOf(rob) === 0); // true
-console.log(col.indexOf(tim) === 1); // true
-console.log(col.indexOf(tom) === 2); // true
-
-```
-
-### View
-* `View#make` has been removed. You'll need to use `$` directly to construct DOM elements now.
-* When declaring a View, `options`, `el`, `tagName`, `id` and `className` may now be defined as functions, if you want their values to be determined at runtime.
-
-### Events
-
-* Backbone events now support jQuery-style event maps `obj.on({click: action})`. This is clearer than needing three separate calls to `.on` and should align better with the events hash used in Views:
-
-```javascript
- model.on({
- ‘change:name’ : this.nameChanged,
- ‘change:age’ : this.ageChanged,
- ‘change:height’ : this.heightChanges
- });
-```
-
-* The Backbone object now extends Events so that you can use it as a global event bus, if you like.
-
-* Backbone events now supports [once](http://backbonejs.org/#Events-once), similar to Node's [once](http://nodejs.org/api/events.html#events_emitter_once_event_listener), or jQuery's [one](http://api.jquery.com/one/). A call to `once()` ensures that the callback only fires once when a notification arrives.
-
-```javascript
-// Use once rather than having to explicitly unbind
-var obj = { counterA: 0, counterB: 0 };
-_.extend(obj, Backbone.Events);
-
-var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
-var incrB = function(){ obj.counterB += 1; };
-
-obj.once('event', incrA);
-obj.once('event', incrB);
-obj.trigger('event');
-
-console.log(obj.counterA === 1); // true
-console.log(obj.counterB === 1); // true
-
-```
-
-`counterA` and `counterB` should only have been incremented once.
-
-* Added [listenTo](http://backbonejs.org/#Events-listenTo) and [stopListening](http://backbonejs.org/#Events-stopListening) to Events. They can be used as inversion-of-control flavors of [on](http://backbonejs.org/#Events-on) and [off](http://backbonejs.org/#Events-off), for convenient unbinding of all events an object is currently listening to. `view.remove()` automatically calls `view.stopListening()`.
-
-If you've had a chance to work on a few Backbone projects by this point, you may know that every `on` called on an object also requires an `off` to be called in order for the garbage collector to do its job.
-
-This can sometimes be overlooked when Views are binding to Models. In 0.9.10, this can now be done the other way around - Views can bind to Model notifications and unbind from all of them with just one call. We achieve this using `view.listenTo(model, 'eventName', func)` and `view.stopListening()`.
-
-The default `remove()` of Views will call `stopListening()` for you, just in case you don't remember to.
-
-```javascript
-var a = _.extend({}, Backbone.Events);
-var b = _.extend({}, Backbone.Events);
-a.listenTo(b, 'all', function(){ console.log(true); });
-b.trigger('anything');
-a.listenTo(b, 'all', function(){ console.log(false); });
-a.stopListening();
-b.trigger('anything');
-```
-
-A more complex example (from [Just JSON](http://justjson.blogspot.co.uk/)) might require our Views to respond to "no connection" and "connection resume" events to re-fetch data on demand in an application.
-
-In 0.9.2, we have to do this to achieve what we need:
-
-```javascript
- // In BaseView definition
-var BaseView = Backbone.View.extend({
- destroy: function() {
- // Allow child views to hook to this event to unsubscribe
- // anything they may have subscribed to to other objects.
- this.trigger('beforedestroy');
- if (this.model) {
- this.model.off(null, null, this);
- }
-
- if (this.collection) {
- this.collection.off(null, null, this);
- }
-
- this.remove();
- this.unbind();
- }
-});
-
-// In MyView definition.
-// We have a global EventBus that allows elements on the app to subscribe to global events.
-// connection/disconnected, connection/resume is two of them.
-
-var MyView = BaseView.extend({
- initialize: function() {
- this.on('beforedestroy', this.onBeforeDestroy, this);
- this.model.on('reset', this.onModelLoaded, this);
- EventBus.on('connection/disconnected', this.onDisconnect, this);
- EventBus.on('connection/resume', this.onConnectionResumed, this);
- },
- onModelLoaded: function() {
- // We only need this to be done once! (Kinda weird...)
- this.model.off('load', this.onModelLoaded, this);
- },
- onDisconnect: function() {
- // Figure out what state we are currently on, display View-specific messaging, etc.
- },
- onConnectionResumed: function() {
- // Re-do previous network request that failed.
- },
- onBeforeDestroy: function() {
- EventBus.off('connection/resume', this.onConnectionResumed, this);
- EventBus.off('connection/disconnected', this.onDisconnect, this);
- }
-});
-```
-
-However, in 0.9.10, what we need to do is quite simple:
-
-```javascript
-
-// In BaseView definition
-var BaseView = Backbone.View.extend({
- destroy: function() {
- this.trigger('beforedestroy');
- this.remove();
- }
-});
-
-// In MyView definition.
-
-var MyView = BaseView.extend({
- initialize: function() {
- this.listenTo(EventBus, 'connection/disconnected', this.onDisconnect);
- this.listenTo(EventBus, 'connection/resume', this.onConnectionResumed);
- this.once(this.model, 'load', this.onModelLoaded);
- },
- onModelLoaded: function() {
- // Don't need to unsubscribe anymore!
- },
- onDisconnect: function() {
- // Figure out the state, display messaging, etc.
- },
- onConnectionResumed: function() {
- // Re-do previous network request that failed.
- }
- // Most importantly, we no longer need onBeforeDestroy() anymore!
-});
-
-```
-
-
-### Routers
-* A "route" event is triggered on the router in addition to being fired on Backbone.history.
-
-```javascript
-Backbone.history.on('route', onRoute);
-
-// Trigger 'route' event on router instance."
-router.on('route', function(name, args) {
- console.log(name === 'routeEvent');
-});
-
-location.replace('http://example.com#route-event/x');
-Backbone.history.checkUrl();
-```
-
-* For semantic and cross browser reasons, routes will now ignore search parameters. Routes like `search?query=…&page=3` should become `search/…/3`.
-* Bugfix for normalizing leading and trailing slashes in the Router definitions. Their presence (or absence) should not affect behavior.
-* Router URLs now support optional parts via parentheses, without having to use a regex.
-
-```javascript
-var Router = Backbone.Router.extend({
- routes: {
- "optional(/:item)": "optionalItem",
- "named/optional/(y:z)": "namedOptionalItem",
- },
- …
-});
-```
-
-### Sync
-* For mixed-mode APIs, `Backbone.sync` now accepts [emulateHTTP](http://backbonejs.org/#Sync-emulateHTTP) and [emulateJSON](http://backbonejs.org/#Sync-emulateJSON) as inline options.
-
-```javascript
-var Library = Backbone.Collection.extend({
- url : function() { return '/library'; }
-});
-
-var attrs = {
- title : "The Tempest",
- author : "Bill Shakespeare",
- length : 123
- };
-
-library = new Library;
-library.create(attrs, {wait: false});
-
-// update with just emulateHTTP
-library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
- emulateHTTP: true
-});
-
-console.log(this.ajaxSettings.url === '/library/2-the-tempest'); // true
-console.log(this.ajaxSettings.type === 'POST'); // true
-console.log(this.ajaxSettings.contentType === 'application/json'); // true
-
-var data = JSON.parse(this.ajaxSettings.data);
-console.log(data.id === '2-the-tempest');
-console.log(data.author === 'Tim Shakespeare');
-console.log(data.length === 123);
-
-// or update with just emulateJSON
-
-library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
- emulateJSON: true
-});
-
-console.log(this.ajaxSettings.url === '/library/2-the-tempest'); // true
-console.log(this.ajaxSettings.type === 'PUT'); // true
-console.log(this.ajaxSettings.contentType ==='application/x-www-form-urlencoded'); // true
-
-var data = JSON.parse(this.ajaxSettings.data.model);
-console.log(data.id === '2-the-tempest');
-console.log(data.author ==='Tim Shakespeare');
-console.log(data.length === 123);
-
-```
-
-* Consolidated `"sync"` and `"error"` events within `Backbone.sync`. They are now triggered regardless of the existence of success or error callbacks.
-
-* Added a `"request"` event to `Backbone.sync`, which triggers whenever a request begins to be made to the server. The natural complement to the `"sync"` event.
-
-
-### Other
-* Bug fix on change where attribute comparison uses `!==` instead of `_.isEqual`.
-* Bug fix where an empty response from the server on save would not call the success function.
-* To improve the performance of add, `options.index` will no longer be set in the `add` event callback.
-* Removed the `Backbone.wrapError` helper method. Overriding sync should work better for those particular use cases.
-* To set what library Backbone uses for DOM manipulation and Ajax calls, use `Backbone.$ =` ... instead of `setDomLibrary`.
-* Added a `Backbone.ajax` hook for more convenient overriding of the default use of `$.ajax`. If AJAX is too passé, set it to your preferred method for server communication.
-* Validation now occurs even during `"silent"` changes. This change means that the `isValid` method has been removed. Failed validations also trigger an error, even if an error callback is specified in the options.
-
-
-
---
Where relevant, copyright Addy Osmani, 2012-2013.
View
309 backbone-fundamentals.rtf
@@ -9103,315 +9103,6 @@ Backbone.sync = function(method, model, options) \{\line
Backbone.$(window).on('hashchange', this.checkUrl);\line
...\par}
{\pard \ql \f0 \sa180 \li0 \fi0 {\f1 Backbone.History.stop} similarly uses your DOM manipulation library to unbind these event listeners.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Upgrading to Backbone 0.9.10\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 {\i Developing Backbone.js Applications} is currently based on Backbone 0.9.10. If you are transitioning from 0.9.2 to 0.9.10 or above, the following is a guide of {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#changelog"}}{\fldrslt{\ul
-changes
-}}}
- grouped by classes, where applicable.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 {\b Note:} We aim to update the entirety of this book to Backbone 1.0 once it has been tagged.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Model\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Model validation is now only enforced by default in {\f1 Model#save} and is no longer enforced by default upon construction or in {\f1 Model#set}, unless the {\f1 \{validate:true\}} option is passed:\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var model = new Backbone.Model(\{name: "One"\});\line
-model.validate = function(attrs) \{\line
- if (!attrs.name) \{\line
- return "No thanks.";\line
- \}\line
-\};\line
-model.set(\{name: "Two"\});\line
-console.log(model.get('name'));\line
-// 'Two'\line
-model.unset('name', \{validate: true\});\line
-// false\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Passing {\f1 \{silent:true\}} on change will no longer delay individual {\f1 "change:attr"} events, instead they are silenced entirely.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var model = new Backbone.Model();\line
-model.set(\{x: true\}, \{silent: true\});\line
-\line
-console.log(!model.hasChanged(0));\line
-// true\line
-console.log(!model.hasChanged(''));\line
-// true\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab The {\f1 Model#change} method has been removed, as delayed attribute changes as no longer available.\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Calling {\f1 destroy} on a Model will now return {\f1 false} if the model {\f1 isNew}.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var model = new Backbone.Model();\line
-console.log(model.destroy());\line
-// false\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab After fetching a model or a collection, all defined parse functions will now be run. So fetching a collection and getting back new models could cause both the collection to parse the list, and then each model to be parsed in turn, if you have both functions defined.\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab HTTP PATCH support allows us to send only changed attributes (i.e partial updates) to the server by passing {\f1 \{patch: true\}} i.e {\f1 model.save(attrs, \{patch: true\})}.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 // Save partial using PATCH\line
-model.clear().set(\{id: 1, a: 1, b: 2, c: 3, d: 4\});\line
-model.save();\line
-model.save(\{b: 2, d: 4\}, \{patch: true\});\line
-console.log(this.syncArgs.method);\line
-// 'patch'\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab When using {\f1 add} on a collection, passing {\f1 \{merge: true\}} will now cause duplicate models to have their attributes merged in to the existing models, instead of being ignored.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var items = new Backbone.Collection;\line
-items.add([\{ id : 1, name: "Dog" , age: 3\}, \{ id : 2, name: "cat" , age: 2\}]);\line
-items.add([\{ id : 1, name: "Bear" \}], \{merge: true \});\line
-items.add([\{ id : 2, name: "lion" \}]); // merge: false\line
- \line
-console.log(JSON.stringify(items.toJSON()));\line
-// [\{"id":1,"name":"Bear","age":3\},\{"id":2,"name":"cat","age":2\}]\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Collection\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab While listening to a {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Collection-reset"}}{\fldrslt{\ul
-reset
-}}}
- event, the list of previous models is now available in {\f1 options.previousModels}, for convenience.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var model = new Backbone.Model();\line
-var collection = new Backbone.Collection([model])\line
-.on('reset', function(collection, options) \{\line
- console.log(options.previousModels);\line
- console.log([model]);\line
- console.log(options.previousModels[0] === model); // true\line
-\});\line
-collection.reset([]);\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab {\f1 Collection#sort} now triggers a {\f1 sort} event, instead of a {\f1 reset} event.\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Removed {\f1 getByCid} from Collections. {\f1 collection.get} now supports lookup by both id and cid.\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Collections now also proxy Underscore method name aliases ({\f1 collect}, {\f1 inject}, {\f1 foldl}, {\f1 foldr}, {\f1 head}, {\f1 tail}, {\f1 take}, and so on\u8230?)\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Added {\f1 update} (which is also available as an option to fetch) for \u8220"smart\u8221" updating of sets of models.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 The update method attempts to perform smart updating of a collection using a specified list of models. When a model in this list isn\u8217't present in the collection, it is added. If it is, its attributes will be merged. Models which are present in the collection but not in the list are removed.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var theBeatles = new Collection(['john', 'paul', 'george', 'ringo']);\line
-\line
-theBeatles.update(['john', 'paul', 'george', 'pete']);\line
-\line
-// Fires a `remove` event for 'ringo', and an `add` event for 'pete'.\line
-// Updates any of john, paul and georges's attributes that may have\line
-// changed over the years.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\f1 collection.indexOf(model)} can be used to retrieve the index of a model as necessary.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var col = new Backbone.Collection;\line
-\line
-col.comparator = function(a, b) \{\line
- return a.get('name') < b.get('name') ? -1 : 1;\line
-\};\line
-\line
-var tom = new Backbone.Model(\{name: 'Tom'\});\line
-var rob = new Backbone.Model(\{name: 'Rob'\});\line
-var tim = new Backbone.Model(\{name: 'Tim'\});\line
-\line
-col.add(tom);\line
-col.add(rob);\line
-col.add(tim);\line
-\line
-console.log(col.indexOf(rob) === 0); // true\line
-console.log(col.indexOf(tim) === 1); // true\line
-console.log(col.indexOf(tom) === 2); // true\line
- \par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 View\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\f1 View#make} has been removed. You\u8217'll need to use {\f1 $} directly to construct DOM elements now.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab When declaring a View, {\f1 options}, {\f1 el}, {\f1 tagName}, {\f1 id} and {\f1 className} may now be defined as functions, if you want their values to be determined at runtime.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Events\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Backbone events now support jQuery-style event maps {\f1 obj.on(\{click: action\})}. This is clearer than needing three separate calls to {\f1 .on} and should align better with the events hash used in Views:\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 model.on(\{\line
- \u8216'change:name\u8217' : this.nameChanged,\line
- \u8216'change:age\u8217' : this.ageChanged,\line
- \u8216'change:height\u8217' : this.heightChanges\line
- \});\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab The Backbone object now extends Events so that you can use it as a global event bus, if you like.\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Backbone events now supports {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Events-once"}}{\fldrslt{\ul
-once
-}}}
-, similar to Node\u8217's {\field{\*\fldinst{HYPERLINK "http://nodejs.org/api/events.html#events_emitter_once_event_listener"}}{\fldrslt{\ul
-once
-}}}
-, or jQuery\u8217's {\field{\*\fldinst{HYPERLINK "http://api.jquery.com/one/"}}{\fldrslt{\ul
-one
-}}}
-. A call to {\f1 once()} ensures that the callback only fires once when a notification arrives.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 // Use once rather than having to explicitly unbind\line
-var obj = \{ counterA: 0, counterB: 0 \};\line
-_.extend(obj, Backbone.Events);\line
-\line
-var incrA = function()\{ obj.counterA += 1; obj.trigger('event'); \};\line
-var incrB = function()\{ obj.counterB += 1; \};\line
-\line
-obj.once('event', incrA);\line
-obj.once('event', incrB);\line
-obj.trigger('event');\line
-\line
-console.log(obj.counterA === 1); // true\line
-console.log(obj.counterB === 1); // true \par}
-{\pard \ql \f0 \sa180 \li0 \fi0 {\f1 counterA} and {\f1 counterB} should only have been incremented once.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Added {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Events-listenTo"}}{\fldrslt{\ul
-listenTo
-}}}
- and {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Events-stopListening"}}{\fldrslt{\ul
-stopListening
-}}}
- to Events. They can be used as inversion-of-control flavors of {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Events-on"}}{\fldrslt{\ul
-on
-}}}
- and {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Events-off"}}{\fldrslt{\ul
-off
-}}}
-, for convenient unbinding of all events an object is currently listening to. {\f1 view.remove()} automatically calls {\f1 view.stopListening()}.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 If you\u8217've had a chance to work on a few Backbone projects by this point, you may know that every {\f1 on} called on an object also requires an {\f1 off} to be called in order for the garbage collector to do its job.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 This can sometimes be overlooked when Views are binding to Models. In 0.9.10, this can now be done the other way around - Views can bind to Model notifications and unbind from all of them with just one call. We achieve this using {\f1 view.listenTo(model, 'eventName', func)} and {\f1 view.stopListening()}.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 The default {\f1 remove()} of Views will call {\f1 stopListening()} for you, just in case you don\u8217't remember to.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var a = _.extend(\{\}, Backbone.Events);\line
-var b = _.extend(\{\}, Backbone.Events);\line
-a.listenTo(b, 'all', function()\{ console.log(true); \});\line
-b.trigger('anything');\line
-a.listenTo(b, 'all', function()\{ console.log(false); \});\line
-a.stopListening();\line
-b.trigger('anything');\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 A more complex example (from {\field{\*\fldinst{HYPERLINK "http://justjson.blogspot.co.uk/"}}{\fldrslt{\ul
-Just JSON
-}}}
-) might require our Views to respond to \u8220"no connection\u8221" and \u8220"connection resume\u8221" events to re-fetch data on demand in an application.\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 In 0.9.2, we have to do this to achieve what we need:\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 // In BaseView definition\line
-var BaseView = Backbone.View.extend(\{\line
- destroy: function() \{\line
- // Allow child views to hook to this event to unsubscribe\line
- // anything they may have subscribed to to other objects.\line
- this.trigger('beforedestroy');\line
- if (this.model) \{\line
- this.model.off(null, null, this);\line
- \}\line
- \line
- if (this.collection) \{\line
- this.collection.off(null, null, this);\line
- \}\line
-\line
- this.remove();\line
- this.unbind();\line
- \}\line
-\});\line
-\line
-// In MyView definition. \line
-// We have a global EventBus that allows elements on the app to subscribe to global events.\line
-// connection/disconnected, connection/resume is two of them.\line
-\line
-var MyView = BaseView.extend(\{\line
- initialize: function() \{\line
- this.on('beforedestroy', this.onBeforeDestroy, this);\line
- this.model.on('reset', this.onModelLoaded, this);\line
- EventBus.on('connection/disconnected', this.onDisconnect, this);\line
- EventBus.on('connection/resume', this.onConnectionResumed, this);\line
- \},\line
- onModelLoaded: function() \{\line
- // We only need this to be done once! (Kinda weird...)\line
- this.model.off('load', this.onModelLoaded, this);\line
- \},\line
- onDisconnect: function() \{\line
- // Figure out what state we are currently on, display View-specific messaging, etc.\line
- \},\line
- onConnectionResumed: function() \{\line
- // Re-do previous network request that failed.\line
- \},\line
- onBeforeDestroy: function() \{\line
- EventBus.off('connection/resume', this.onConnectionResumed, this);\line
- EventBus.off('connection/disconnected', this.onDisconnect, this);\line
- \}\line
-\});\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 However, in 0.9.10, what we need to do is quite simple:\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 \line
-// In BaseView definition\line
-var BaseView = Backbone.View.extend(\{\line
- destroy: function() \{\line
- this.trigger('beforedestroy');\line
- this.remove();\line
- \}\line
-\});\line
-\line
-// In MyView definition. \line
-\line
-var MyView = BaseView.extend(\{\line
- initialize: function() \{\line
- this.listenTo(EventBus, 'connection/disconnected', this.onDisconnect);\line
- this.listenTo(EventBus, 'connection/resume', this.onConnectionResumed);\line
- this.once(this.model, 'load', this.onModelLoaded);\line
- \},\line
- onModelLoaded: function() \{\line
- // Don't need to unsubscribe anymore!\line
- \},\line
- onDisconnect: function() \{\line
- // Figure out the state, display messaging, etc.\line
- \},\line
- onConnectionResumed: function() \{\line
- // Re-do previous network request that failed.\line
- \}\line
- // Most importantly, we no longer need onBeforeDestroy() anymore!\line
-\});\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Routers\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab A \u8220"route\u8221" event is triggered on the router in addition to being fired on Backbone.history.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 Backbone.history.on('route', onRoute);\line
-\line
-// Trigger 'route' event on router instance."\line
-router.on('route', function(name, args) \{\line
- console.log(name === 'routeEvent'); \line
-\});\line
-\line
-location.replace('http://example.com#route-event/x');\line
-Backbone.history.checkUrl();\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab For semantic and cross browser reasons, routes will now ignore search parameters. Routes like {\f1 search?query=\u8230?&page=3} should become {\f1 search/\u8230?/3}.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Bugfix for normalizing leading and trailing slashes in the Router definitions. Their presence (or absence) should not affect behavior.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Router URLs now support optional parts via parentheses, without having to use a regex.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var Router = Backbone.Router.extend(\{\line
- routes: \{\line
- "optional(/:item)": "optionalItem",\line
- "named/optional/(y:z)": "namedOptionalItem",\line
- \},\line
- \u8230?\line
-\});\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Sync\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab For mixed-mode APIs, {\f1 Backbone.sync} now accepts {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Sync-emulateHTTP"}}{\fldrslt{\ul
-emulateHTTP
-}}}
- and {\field{\*\fldinst{HYPERLINK "http://backbonejs.org/#Sync-emulateJSON"}}{\fldrslt{\ul
-emulateJSON
-}}}
- as inline options.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \f1 var Library = Backbone.Collection.extend(\{\line
- url : function() \{ return '/library'; \}\line
-\});\line
-\line
-var attrs = \{\line
- title : "The Tempest",\line
- author : "Bill Shakespeare",\line
- length : 123\line
- \};\line
- \line
-library = new Library;\line
-library.create(attrs, \{wait: false\});\line
- \line
-// update with just emulateHTTP\line
-library.first().save(\{id: '2-the-tempest', author: 'Tim Shakespeare'\}, \{\line
- emulateHTTP: true\line
-\});\line
- \line
-console.log(this.ajaxSettings.url === '/library/2-the-tempest'); // true\line
-console.log(this.ajaxSettings.type === 'POST'); // true\line
-console.log(this.ajaxSettings.contentType === 'application/json'); // true\line
-\line
-var data = JSON.parse(this.ajaxSettings.data);\line
-console.log(data.id === '2-the-tempest');\line
-console.log(data.author === 'Tim Shakespeare');\line
-console.log(data.length === 123);\line
-\line
-// or update with just emulateJSON\line
-\line
-library.first().save(\{id: '2-the-tempest', author: 'Tim Shakespeare'\}, \{\line
- emulateJSON: true\line
-\});\line
-\line
-console.log(this.ajaxSettings.url === '/library/2-the-tempest'); // true\line
-console.log(this.ajaxSettings.type === 'PUT'); // true\line
-console.log(this.ajaxSettings.contentType ==='application/x-www-form-urlencoded'); // true\line
-\line
-var data = JSON.parse(this.ajaxSettings.data.model);\line
-console.log(data.id === '2-the-tempest');\line
-console.log(data.author ==='Tim Shakespeare');\line
-console.log(data.length === 123);\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Consolidated {\f1 "sync"} and {\f1 "error"} events within {\f1 Backbone.sync}. They are now triggered regardless of the existence of success or error callbacks.\par}
-{\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Added a {\f1 "request"} event to {\f1 Backbone.sync}, which triggers whenever a request begins to be made to the server. The natural complement to the {\f1 "sync"} event.\sa180\par}
-{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Other\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Bug fix on change where attribute comparison uses {\f1 !==} instead of {\f1 _.isEqual}.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Bug fix where an empty response from the server on save would not call the success function.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab To improve the performance of add, {\f1 options.index} will no longer be set in the {\f1 add} event callback.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Removed the {\f1 Backbone.wrapError} helper method. Overriding sync should work better for those particular use cases.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab To set what library Backbone uses for DOM manipulation and Ajax calls, use {\f1 Backbone.$ =} \u8230? instead of {\f1 setDomLibrary}.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Added a {\f1 Backbone.ajax} hook for more convenient overriding of the default use of {\f1 $.ajax}. If AJAX is too pass\u233?, set it to your preferred method for server communication.\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Validation now occurs even during {\f1 "silent"} changes. This change means that the {\f1 isValid} method has been removed. Failed validations also trigger an error, even if an error callback is specified in the options.\sa180\par}
{\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par}
{\pard \ql \f0 \sa180 \li0 \fi0 Where relevant, copyright Addy Osmani, 2012-2013.\par}
}
View
369 chapters/16-appendix.md
@@ -620,374 +620,5 @@ From the source for `Backbone.history.start`:
`Backbone.History.stop` similarly uses your DOM manipulation library to unbind these event listeners.
-## Upgrading to Backbone 0.9.10
-
-
-*Developing Backbone.js Applications* is currently based on Backbone 0.9.10. If you are transitioning from 0.9.2 to 0.9.10 or above, the following is a guide of [changes](http://backbonejs.org/#changelog) grouped by classes, where applicable.
-
-**Note:** We aim to update the entirety of this book to Backbone 1.0 once it has been tagged.
-
-### Model
-
-* Model validation is now only enforced by default in `Model#save` and is no longer enforced by default upon construction or in `Model#set`, unless the `{validate:true}` option is passed:
-
-```javascript
-var model = new Backbone.Model({name: "One"});
-model.validate = function(attrs) {
- if (!attrs.name) {
- return "No thanks.";
- }
-};
-model.set({name: "Two"});
-console.log(model.get('name'));
-// 'Two'
-model.unset('name', {validate: true});
-// false
-```
-
-* Passing `{silent:true}` on change will no longer delay individual `"change:attr"` events, instead they are silenced entirely.
-
-```javascript
-var model = new Backbone.Model();
-model.set({x: true}, {silent: true});
-
-console.log(!model.hasChanged(0));
-// true
-console.log(!model.hasChanged(''));
-// true
-```
-
-* The `Model#change` method has been removed, as delayed attribute changes as no longer available.
-
-* Calling `destroy` on a Model will now return `false` if the model `isNew`.
-
-```javascript
-var model = new Backbone.Model();
-console.log(model.destroy());
-// false
-```
-
-* After fetching a model or a collection, all defined parse functions will now be run. So fetching a collection and getting back new models could cause both the collection to parse the list, and then each model to be parsed in turn, if you have both functions defined.
-
-* HTTP PATCH support allows us to send only changed attributes (i.e partial updates) to the server by passing `{patch: true}` i.e `model.save(attrs, {patch: true})`.
-
-```javascript
-// Save partial using PATCH
-model.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4});
-model.save();
-model.save({b: 2, d: 4}, {patch: true});
-console.log(this.syncArgs.method);
-// 'patch'
-```
-
-* When using `add` on a collection, passing `{merge: true}` will now cause duplicate models to have their attributes merged in to the existing models, instead of being ignored.
-
-```javascript
-var items = new Backbone.Collection;
-items.add([{ id : 1, name: "Dog" , age: 3}, { id : 2, name: "cat" , age: 2}]);
-items.add([{ id : 1, name: "Bear" }], {merge: true });
-items.add([{ id : 2, name: "lion" }]); // merge: false
-
-console.log(JSON.stringify(items.toJSON()));
-// [{"id":1,"name":"Bear","age":3},{"id":2,"name":"cat","age":2}]
-
-```
-
-### Collection
-
-
-* While listening to a [reset](http://backbonejs.org/#Collection-reset) event, the list of previous models is now available in `options.previousModels`, for convenience.
-
-```javascript
-var model = new Backbone.Model();
-var collection = new Backbone.Collection([model])
-.on('reset', function(collection, options) {
- console.log(options.previousModels);
- console.log([model]);
- console.log(options.previousModels[0] === model); // true
-});
-collection.reset([]);
-```
-
-* `Collection#sort` now triggers a `sort` event, instead of a `reset` event.
-
-* Removed `getByCid` from Collections. `collection.get` now supports lookup by both id and cid.
-
-* Collections now also proxy Underscore method name aliases (`collect`, `inject`, `foldl`, `foldr`, `head`, `tail`, `take`, and so on...)
-
-* Added `update` (which is also available as an option to fetch) for "smart" updating of sets of models.
-
-The update method attempts to perform smart updating of a collection using a specified list of models. When a model in this list isn't present in the collection, it is added. If it is, its attributes will be merged. Models which are present in the collection but not in the list are removed.
-
-```javascript
-var theBeatles = new Collection(['john', 'paul', 'george', 'ringo']);
-
-theBeatles.update(['john', 'paul', 'george', 'pete']);
-
-// Fires a `remove` event for 'ringo', and an `add` event for 'pete'.
-// Updates any of john, paul and georges's attributes that may have
-// changed over the years.
-```
-
-* `collection.indexOf(model)` can be used to retrieve the index of a model as necessary.
-
-```javascript
-var col = new Backbone.Collection;
-
-col.comparator = function(a, b) {
- return a.get('name') < b.get('name') ? -1 : 1;
-};
-
-var tom = new Backbone.Model({name: 'Tom'});
-var rob = new Backbone.Model({name: 'Rob'});
-var tim = new Backbone.Model({name: 'Tim'});
-
-col.add(tom);
-col.add(rob);
-col.add(tim);
-
-console.log(col.indexOf(rob) === 0); // true
-console.log(col.indexOf(tim) === 1); // true
-console.log(col.indexOf(tom) === 2); // true
-
-```
-
-### View
-* `View#make` has been removed. You'll need to use `$` directly to construct DOM elements now.
-* When declaring a View, `options`, `el`, `tagName`, `id` and `className` may now be defined as functions, if you want their values to be determined at runtime.
-
-### Events
-
-* Backbone events now support jQuery-style event maps `obj.on({click: action})`. This is clearer than needing three separate calls to `.on` and should align better with the events hash used in Views:
-
-```javascript
- model.on({
- ‘change:name’ : this.nameChanged,
- ‘change:age’ : this.ageChanged,
- ‘change:height’ : this.heightChanges
- });
-```
-
-* The Backbone object now extends Events so that you can use it as a global event bus, if you like.
-
-* Backbone events now supports [once](http://backbonejs.org/#Events-once), similar to Node's [once](http://nodejs.org/api/events.html#events_emitter_once_event_listener), or jQuery's [one](http://api.jquery.com/one/). A call to `once()` ensures that the callback only fires once when a notification arrives.
-
-```javascript
-// Use once rather than having to explicitly unbind
-var obj = { counterA: 0, counterB: 0 };
-_.extend(obj, Backbone.Events);
-
-var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
-var incrB = function(){ obj.counterB += 1; };
-
-obj.once('event', incrA);
-obj.once('event', incrB);
-obj.trigger('event');
-
-console.log(obj.counterA === 1); // true
-console.log(obj.counterB === 1); // true
-
-```
-
-`counterA` and `counterB` should only have been incremented once.
-
-* Added [listenTo](http://backbonejs.org/#Events-listenTo) and [stopListening](http://backbonejs.org/#Events-stopListening) to Events. They can be used as inversion-of-control flavors of [on](http://backbonejs.org/#Events-on) and [off](http://backbonejs.org/#Events-off), for convenient unbinding of all events an object is currently listening to. `view.remove()` automatically calls `view.stopListening()`.
-
-If you've had a chance to work on a few Backbone projects by this point, you may know that every `on` called on an object also requires an `off` to be called in order for the garbage collector to do its job.
-
-This can sometimes be overlooked when Views are binding to Models. In 0.9.10, this can now be done the other way around - Views can bind to Model notifications and unbind from all of them with just one call. We achieve this using `view.listenTo(model, 'eventName', func)` and `view.stopListening()`.
-
-The default `remove()` of Views will call `stopListening()` for you, just in case you don't remember to.
-
-```javascript
-var a = _.extend({}, Backbone.Events);
-var b = _.extend({}, Backbone.Events);
-a.listenTo(b, 'all', function(){ console.log(true); });
-b.trigger('anything');
-a.listenTo(b, 'all', function(){ console.log(false); });
-a.stopListening();
-b.trigger('anything');
-```
-
-A more complex example (from [Just JSON](http://justjson.blogspot.co.uk/)) might require our Views to respond to "no connection" and "connection resume" events to re-fetch data on demand in an application.
-
-In 0.9.2, we have to do this to achieve what we need:
-
-```javascript
- // In BaseView definition
-var BaseView = Backbone.View.extend({
- destroy: function() {
- // Allow child views to hook to this event to unsubscribe
- // anything they may have subscribed to to other objects.
- this.trigger('beforedestroy');
- if (this.model) {
- this.model.off(null, null, this);
- }
-
- if (this.collection) {
- this.collection.off(null, null, this);
- }
-
- this.remove();
- this.unbind();
- }
-});
-
-// In MyView definition.
-// We have a global EventBus that allows elements on the app to subscribe to global events.
-// connection/disconnected, connection/resume is two of them.
-
-var MyView = BaseView.extend({
- initialize: function() {
- this.on('beforedestroy', this.onBeforeDestroy, this);
- this.model.on('reset', this.onModelLoaded, this);
- EventBus.on('connection/disconnected', this.onDisconnect, this);
- EventBus.on('connection/resume', this.onConnectionResumed, this);
- },
- onModelLoaded: function() {
- // We only need this to be done once! (Kinda weird...)
- this.model.off('load', this.onModelLoaded, this);
- },
- onDisconnect: function() {
- // Figure out what state we are currently on, display View-specific messaging, etc.
- },
- onConnectionResumed: function() {
- // Re-do previous network request that failed.
- },
- onBeforeDestroy: function() {
- EventBus.off('connection/resume', this.onConnectionResumed, this);
- EventBus.off('connection/disconnected', this.onDisconnect, this);
- }
-});
-```
-
-However, in 0.9.10, what we need to do is quite simple:
-
-```javascript
-
-// In BaseView definition
-var BaseView = Backbone.View.extend({
- destroy: function() {
- this.trigger('beforedestroy');
- this.remove();
- }
-});
-
-// In MyView definition.
-
-var MyView = BaseView.extend({
- initialize: function() {
- this.listenTo(EventBus, 'connection/disconnected', this.onDisconnect);
- this.listenTo(EventBus, 'connection/resume', this.onConnectionResumed);
- this.once(this.model, 'load', this.onModelLoaded);
- },
- onModelLoaded: function() {
- // Don't need to unsubscribe anymore!
- },
- onDisconnect: function() {
- // Figure out the state, display messaging, etc.
- },
- onConnectionResumed: function() {
- // Re-do previous network request that failed.
- }
- // Most importantly, we no longer need onBeforeDestroy() anymore!
-});
-
-```
-
-
-### Routers
-* A "route" event is triggered on the router in addition to being fired on Backbone.history.
-
-```javascript
-Backbone.history.on('route', onRoute);
-
-// Trigger 'route' event on router instance."
-router.on('route', function(name, args) {
- console.log(name === 'routeEvent');
-});
-
-location.replace('http://example.com#route-event/x');
-Backbone.history.checkUrl();
-```
-
-* For semantic and cross browser reasons, routes will now ignore search parameters. Routes like `search?query=…&page=3` should become `search/…/3`.
-* Bugfix for normalizing leading and trailing slashes in the Router definitions. Their presence (or absence) should not affect behavior.
-* Router URLs now support optional parts via parentheses, without having to use a regex.
-
-```javascript
-var Router = Backbone.Router.extend({
- routes: {
- "optional(/:item)": "optionalItem",
- "named/optional/(y:z)": "namedOptionalItem",
- },
-
-});
-```
-
-### Sync
-* For mixed-mode APIs, `Backbone.sync` now accepts [emulateHTTP](http://backbonejs.org/#Sync-emulateHTTP) and [emulateJSON](http://backbonejs.org/#Sync-emulateJSON) as inline options.
-
-```javascript
-var Library = Backbone.Collection.extend({
- url : function() { return '/library'; }
-});
-
-var attrs = {
- title : "The Tempest",
- author : "Bill Shakespeare",
- length : 123
- };
-
-library = new Library;
-library.create(attrs, {wait: false});
-
-// update with just emulateHTTP
-library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
- emulateHTTP: true
-});
-
-console.log(this.ajaxSettings.url === '/library/2-the-tempest'); // true
-console.log(this.ajaxSettings.type === 'POST'); // true
-console.log(this.ajaxSettings.contentType === 'application/json'); // true
-
-var data = JSON.parse(this.ajaxSettings.data);
-console.log(data.id === '2-the-tempest');
-console.log(data.author === 'Tim Shakespeare');
-console.log(data.length === 123);
-
-// or update with just emulateJSON
-
-library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
- emulateJSON: true
-});
-
-console.log(this.ajaxSettings.url === '/library/2-the-tempest'); // true
-console.log(this.ajaxSettings.type === 'PUT'); // true
-console.log(this.ajaxSettings.contentType ==='application/x-www-form-urlencoded'); // true
-
-var data = JSON.parse(this.ajaxSettings.data.model);
-console.log(data.id === '2-the-tempest');
-console.log(data.author ==='Tim Shakespeare');
-console.log(data.length === 123);
-
-```
-
-* Consolidated `"sync"` and `"error"` events within `Backbone.sync`. They are now triggered regardless of the existence of success or error callbacks.
-
-* Added a `"request"` event to `Backbone.sync`, which triggers whenever a request begins to be made to the server. The natural complement to the `"sync"` event.
-
-
-### Other
-* Bug fix on change where attribute comparison uses `!==` instead of `_.isEqual`.
-* Bug fix where an empty response from the server on save would not call the success function.
-* To improve the performance of add, `options.index` will no longer be set in the `add` event callback.
-* Removed the `Backbone.wrapError` helper method. Overriding sync should work better for those particular use cases.
-* To set what library Backbone uses for DOM manipulation and Ajax calls, use `Backbone.$ =` ... instead of `setDomLibrary`.
-* Added a `Backbone.ajax` hook for more convenient overriding of the default use of `$.ajax`. If AJAX is too passé, set it to your preferred method for server communication.
-* Validation now occurs even during `"silent"` changes. This change means that the `isValid` method has been removed. Failed validations also trigger an error, even if an error callback is specified in the options.
-
-
-
---
Where relevant, copyright Addy Osmani, 2012-2013.
View
316 index.html
@@ -397,15 +397,6 @@
<li><a href="#restful-persistence-1">RESTful persistence</a></li>
<li><a href="#routing">Routing</a></li>
</ul></li>
-<li><a href="#upgrading-to-backbone-0.9.10">Upgrading to Backbone 0.9.10</a><ul>
-<li><a href="#model">Model</a></li>
-<li><a href="#collection">Collection</a></li>
-<li><a href="#view">View</a></li>
-<li><a href="#events-2">Events</a></li>
-<li><a href="#routers-1">Routers</a></li>
-<li><a href="#sync">Sync</a></li>
-<li><a href="#other">Other</a></li>
-</ul></li>
</ul></li>
</ul>
</nav>
@@ -9058,313 +9049,6 @@ <h3 id="routing"><a href="#TOC">Routing</a></h3>
Backbone.$(window).on(&#39;hashchange&#39;, this.checkUrl);
...</code></pre>
<p><code>Backbone.History.stop</code> similarly uses your DOM manipulation library to unbind these event listeners.</p>
-<h2 id="upgrading-to-backbone-0.9.10"><a href="#TOC">Upgrading to Backbone 0.9.10</a></h2>
-<p><em>Developing Backbone.js Applications</em> is currently based on Backbone 0.9.10. If you are transitioning from 0.9.2 to 0.9.10 or above, the following is a guide of <a href="http://backbonejs.org/#changelog">changes</a> grouped by classes, where applicable.</p>
-<p><strong>Note:</strong> We aim to update the entirety of this book to Backbone 1.0 once it has been tagged.</p>
-<h3 id="model"><a href="#TOC">Model</a></h3>
-<ul>
-<li>Model validation is now only enforced by default in <code>Model#save</code> and is no longer enforced by default upon construction or in <code>Model#set</code>, unless the <code>{validate:true}</code> option is passed:</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> model = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Model</span>({<span class="dt">name</span>: <span class="st">&quot;One&quot;</span>});
-<span class="kw">model</span>.<span class="fu">validate</span> = <span class="kw">function</span>(attrs) {
- <span class="kw">if</span> (!<span class="kw">attrs</span>.<span class="fu">name</span>) {
- <span class="kw">return</span> <span class="st">&quot;No thanks.&quot;</span>;
- }
-};
-<span class="kw">model</span>.<span class="fu">set</span>({<span class="dt">name</span>: <span class="st">&quot;Two&quot;</span>});
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">model</span>.<span class="fu">get</span>(<span class="ch">&#39;name&#39;</span>));
-<span class="co">// &#39;Two&#39;</span>
-<span class="kw">model</span>.<span class="fu">unset</span>(<span class="ch">&#39;name&#39;</span>, {<span class="dt">validate</span>: <span class="kw">true</span>});
-<span class="co">// false</span></code></pre>
-<ul>
-<li>Passing <code>{silent:true}</code> on change will no longer delay individual <code>&quot;change:attr&quot;</code> events, instead they are silenced entirely.</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> model = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Model</span>();
-<span class="kw">model</span>.<span class="fu">set</span>({<span class="dt">x</span>: <span class="kw">true</span>}, {<span class="dt">silent</span>: <span class="kw">true</span>});
-
-<span class="kw">console</span>.<span class="fu">log</span>(!<span class="kw">model</span>.<span class="fu">hasChanged</span>(<span class="dv">0</span>));
-<span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(!<span class="kw">model</span>.<span class="fu">hasChanged</span>(<span class="ch">&#39;&#39;</span>));
-<span class="co">// true</span></code></pre>
-<ul>
-<li><p>The <code>Model#change</code> method has been removed, as delayed attribute changes as no longer available.</p></li>
-<li><p>Calling <code>destroy</code> on a Model will now return <code>false</code> if the model <code>isNew</code>.</p></li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> model = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Model</span>();
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">model</span>.<span class="fu">destroy</span>());
-<span class="co">// false</span></code></pre>
-<ul>
-<li><p>After fetching a model or a collection, all defined parse functions will now be run. So fetching a collection and getting back new models could cause both the collection to parse the list, and then each model to be parsed in turn, if you have both functions defined.</p></li>
-<li><p>HTTP PATCH support allows us to send only changed attributes (i.e partial updates) to the server by passing <code>{patch: true}</code> i.e <code>model.save(attrs, {patch: true})</code>.</p></li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="co">// Save partial using PATCH</span>
-<span class="kw">model</span>.<span class="fu">clear</span>().<span class="fu">set</span>({<span class="dt">id</span>: <span class="dv">1</span>, <span class="dt">a</span>: <span class="dv">1</span>, <span class="dt">b</span>: <span class="dv">2</span>, <span class="dt">c</span>: <span class="dv">3</span>, <span class="dt">d</span>: <span class="dv">4</span>});
-<span class="kw">model</span>.<span class="fu">save</span>();
-<span class="kw">model</span>.<span class="fu">save</span>({<span class="dt">b</span>: <span class="dv">2</span>, <span class="dt">d</span>: <span class="dv">4</span>}, {<span class="dt">patch</span>: <span class="kw">true</span>});
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">this</span>.<span class="fu">syncArgs</span>.<span class="fu">method</span>);
-<span class="co">// &#39;patch&#39;</span></code></pre>
-<ul>
-<li>When using <code>add</code> on a collection, passing <code>{merge: true}</code> will now cause duplicate models to have their attributes merged in to the existing models, instead of being ignored.</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> items = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Collection</span>;
-<span class="kw">items</span>.<span class="fu">add</span>([{ <span class="dt">id </span>: <span class="dv">1</span>, <span class="dt">name</span>: <span class="st">&quot;Dog&quot;</span> , <span class="dt">age</span>: <span class="dv">3</span>}, { <span class="dt">id </span>: <span class="dv">2</span>, <span class="dt">name</span>: <span class="st">&quot;cat&quot;</span> , <span class="dt">age</span>: <span class="dv">2</span>}]);
-<span class="kw">items</span>.<span class="fu">add</span>([{ <span class="dt">id </span>: <span class="dv">1</span>, <span class="dt">name</span>: <span class="st">&quot;Bear&quot;</span> }], {<span class="dt">merge</span>: <span class="kw">true</span> });
-<span class="kw">items</span>.<span class="fu">add</span>([{ <span class="dt">id </span>: <span class="dv">2</span>, <span class="dt">name</span>: <span class="st">&quot;lion&quot;</span> }]); <span class="co">// merge: false</span>
-
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">JSON</span>.<span class="fu">stringify</span>(<span class="kw">items</span>.<span class="fu">toJSON</span>()));
-<span class="co">// [{&quot;id&quot;:1,&quot;name&quot;:&quot;Bear&quot;,&quot;age&quot;:3},{&quot;id&quot;:2,&quot;name&quot;:&quot;cat&quot;,&quot;age&quot;:2}]</span></code></pre>
-<h3 id="collection"><a href="#TOC">Collection</a></h3>
-<ul>
-<li>While listening to a <a href="http://backbonejs.org/#Collection-reset">reset</a> event, the list of previous models is now available in <code>options.previousModels</code>, for convenience.</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> model = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Model</span>();
-<span class="kw">var</span> collection = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Collection</span>([model])
-.<span class="fu">on</span>(<span class="ch">&#39;reset&#39;</span>, <span class="kw">function</span>(collection, options) {
- <span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">options</span>.<span class="fu">previousModels</span>);
- <span class="kw">console</span>.<span class="fu">log</span>([model]);
- <span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">options</span>.<span class="fu">previousModels</span>[<span class="dv">0</span>] === model); <span class="co">// true</span>
-});
-<span class="kw">collection</span>.<span class="fu">reset</span>([]);</code></pre>
-<ul>
-<li><p><code>Collection#sort</code> now triggers a <code>sort</code> event, instead of a <code>reset</code> event.</p></li>
-<li><p>Removed <code>getByCid</code> from Collections. <code>collection.get</code> now supports lookup by both id and cid.</p></li>
-<li><p>Collections now also proxy Underscore method name aliases (<code>collect</code>, <code>inject</code>, <code>foldl</code>, <code>foldr</code>, <code>head</code>, <code>tail</code>, <code>take</code>, and so on…)</p></li>
-<li><p>Added <code>update</code> (which is also available as an option to fetch) for <q>smart</q> updating of sets of models.</p></li>
-</ul>
-<p>The update method attempts to perform smart updating of a collection using a specified list of models. When a model in this list isn’t present in the collection, it is added. If it is, its attributes will be merged. Models which are present in the collection but not in the list are removed.</p>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> theBeatles = <span class="kw">new</span> Collection([<span class="ch">&#39;john&#39;</span>, <span class="ch">&#39;paul&#39;</span>, <span class="ch">&#39;george&#39;</span>, <span class="ch">&#39;ringo&#39;</span>]);
-
-<span class="kw">theBeatles</span>.<span class="fu">update</span>([<span class="ch">&#39;john&#39;</span>, <span class="ch">&#39;paul&#39;</span>, <span class="ch">&#39;george&#39;</span>, <span class="ch">&#39;pete&#39;</span>]);
-
-<span class="co">// Fires a `remove` event for &#39;ringo&#39;, and an `add` event for &#39;pete&#39;.</span>
-<span class="co">// Updates any of john, paul and georges&#39;s attributes that may have</span>
-<span class="co">// changed over the years.</span></code></pre>
-<ul>
-<li><code>collection.indexOf(model)</code> can be used to retrieve the index of a model as necessary.</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> col = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Collection</span>;
-
-<span class="kw">col</span>.<span class="fu">comparator</span> = <span class="kw">function</span>(a, b) {
- <span class="kw">return</span> <span class="kw">a</span>.<span class="fu">get</span>(<span class="ch">&#39;name&#39;</span>) &lt; <span class="kw">b</span>.<span class="fu">get</span>(<span class="ch">&#39;name&#39;</span>) ? -<span class="dv">1</span> : <span class="dv">1</span>;
-};
-
-<span class="kw">var</span> tom = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Model</span>({<span class="dt">name</span>: <span class="ch">&#39;Tom&#39;</span>});
-<span class="kw">var</span> rob = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Model</span>({<span class="dt">name</span>: <span class="ch">&#39;Rob&#39;</span>});
-<span class="kw">var</span> tim = <span class="kw">new</span> <span class="kw">Backbone</span>.<span class="fu">Model</span>({<span class="dt">name</span>: <span class="ch">&#39;Tim&#39;</span>});
-
-<span class="kw">col</span>.<span class="fu">add</span>(tom);
-<span class="kw">col</span>.<span class="fu">add</span>(rob);
-<span class="kw">col</span>.<span class="fu">add</span>(tim);
-
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">col</span>.<span class="fu">indexOf</span>(rob) === <span class="dv">0</span>); <span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">col</span>.<span class="fu">indexOf</span>(tim) === <span class="dv">1</span>); <span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">col</span>.<span class="fu">indexOf</span>(tom) === <span class="dv">2</span>); <span class="co">// true</span>
- </code></pre>
-<h3 id="view"><a href="#TOC">View</a></h3>
-<ul>
-<li><code>View#make</code> has been removed. You’ll need to use <code>$</code> directly to construct DOM elements now.</li>
-<li>When declaring a View, <code>options</code>, <code>el</code>, <code>tagName</code>, <code>id</code> and <code>className</code> may now be defined as functions, if you want their values to be determined at runtime.</li>
-</ul>
-<h3 id="events-2"><a href="#TOC">Events</a></h3>
-<ul>
-<li>Backbone events now support jQuery-style event maps <code>obj.on({click: action})</code>. This is clearer than needing three separate calls to <code>.on</code> and should align better with the events hash used in Views:</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"> <span class="kw">model</span>.<span class="fu">on</span>({
- ‘change:name’ : <span class="kw">this</span>.<span class="fu">nameChanged</span>,
- ‘change:age’ : <span class="kw">this</span>.<span class="fu">ageChanged</span>,
- ‘change:height’ : <span class="kw">this</span>.<span class="fu">heightChanges</span>
- });</code></pre>
-<ul>
-<li><p>The Backbone object now extends Events so that you can use it as a global event bus, if you like.</p></li>
-<li><p>Backbone events now supports <a href="http://backbonejs.org/#Events-once">once</a>, similar to Node’s <a href="http://nodejs.org/api/events.html#events_emitter_once_event_listener">once</a>, or jQuery’s <a href="http://api.jquery.com/one/">one</a>. A call to <code>once()</code> ensures that the callback only fires once when a notification arrives.</p></li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="co">// Use once rather than having to explicitly unbind</span>
-<span class="kw">var</span> obj = { <span class="dt">counterA</span>: <span class="dv">0</span>, <span class="dt">counterB</span>: <span class="dv">0</span> };
-<span class="kw">_</span>.<span class="fu">extend</span>(obj, <span class="kw">Backbone</span>.<span class="fu">Events</span>);
-
-<span class="kw">var</span> incrA = <span class="kw">function</span>(){ <span class="kw">obj</span>.<span class="fu">counterA</span> += <span class="dv">1</span>; <span class="kw">obj</span>.<span class="fu">trigger</span>(<span class="ch">&#39;event&#39;</span>); };
-<span class="kw">var</span> incrB = <span class="kw">function</span>(){ <span class="kw">obj</span>.<span class="fu">counterB</span> += <span class="dv">1</span>; };
-
-<span class="kw">obj</span>.<span class="fu">once</span>(<span class="ch">&#39;event&#39;</span>, incrA);
-<span class="kw">obj</span>.<span class="fu">once</span>(<span class="ch">&#39;event&#39;</span>, incrB);
-<span class="kw">obj</span>.<span class="fu">trigger</span>(<span class="ch">&#39;event&#39;</span>);
-
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">obj</span>.<span class="fu">counterA</span> === <span class="dv">1</span>); <span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">obj</span>.<span class="fu">counterB</span> === <span class="dv">1</span>); <span class="co">// true </span></code></pre>
-<p><code>counterA</code> and <code>counterB</code> should only have been incremented once.</p>
-<ul>
-<li>Added <a href="http://backbonejs.org/#Events-listenTo">listenTo</a> and <a href="http://backbonejs.org/#Events-stopListening">stopListening</a> to Events. They can be used as inversion-of-control flavors of <a href="http://backbonejs.org/#Events-on">on</a> and <a href="http://backbonejs.org/#Events-off">off</a>, for convenient unbinding of all events an object is currently listening to. <code>view.remove()</code> automatically calls <code>view.stopListening()</code>.</li>
-</ul>
-<p>If you’ve had a chance to work on a few Backbone projects by this point, you may know that every <code>on</code> called on an object also requires an <code>off</code> to be called in order for the garbage collector to do its job.</p>
-<p>This can sometimes be overlooked when Views are binding to Models. In 0.9.10, this can now be done the other way around - Views can bind to Model notifications and unbind from all of them with just one call. We achieve this using <code>view.listenTo(model, 'eventName', func)</code> and <code>view.stopListening()</code>.</p>
-<p>The default <code>remove()</code> of Views will call <code>stopListening()</code> for you, just in case you don’t remember to.</p>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> a = <span class="kw">_</span>.<span class="fu">extend</span>({}, <span class="kw">Backbone</span>.<span class="fu">Events</span>);
-<span class="kw">var</span> b = <span class="kw">_</span>.<span class="fu">extend</span>({}, <span class="kw">Backbone</span>.<span class="fu">Events</span>);
-<span class="kw">a</span>.<span class="fu">listenTo</span>(b, <span class="ch">&#39;all&#39;</span>, <span class="kw">function</span>(){ <span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">true</span>); });
-<span class="kw">b</span>.<span class="fu">trigger</span>(<span class="ch">&#39;anything&#39;</span>);
-<span class="kw">a</span>.<span class="fu">listenTo</span>(b, <span class="ch">&#39;all&#39;</span>, <span class="kw">function</span>(){ <span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">false</span>); });
-<span class="kw">a</span>.<span class="fu">stopListening</span>();
-<span class="kw">b</span>.<span class="fu">trigger</span>(<span class="ch">&#39;anything&#39;</span>);</code></pre>
-<p>A more complex example (from <a href="http://justjson.blogspot.co.uk/">Just JSON</a>) might require our Views to respond to <q>no connection</q> and <q>connection resume</q> events to re-fetch data on demand in an application.</p>
-<p>In 0.9.2, we have to do this to achieve what we need:</p>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"> <span class="co">// In BaseView definition</span>
-<span class="kw">var</span> BaseView = <span class="kw">Backbone.View</span>.<span class="fu">extend</span>({
- <span class="dt">destroy</span>: <span class="kw">function</span>() {
- <span class="co">// Allow child views to hook to this event to unsubscribe</span>
- <span class="co">// anything they may have subscribed to to other objects.</span>
- <span class="kw">this</span>.<span class="fu">trigger</span>(<span class="ch">&#39;beforedestroy&#39;</span>);
- <span class="kw">if</span> (<span class="kw">this</span>.<span class="fu">model</span>) {
- <span class="kw">this</span>.<span class="fu">model</span>.<span class="fu">off</span>(null, null, <span class="kw">this</span>);
- }
-
- <span class="kw">if</span> (<span class="kw">this</span>.<span class="fu">collection</span>) {
- <span class="kw">this</span>.<span class="fu">collection</span>.<span class="fu">off</span>(null, null, <span class="kw">this</span>);
- }
-
- <span class="kw">this</span>.<span class="fu">remove</span>();
- <span class="kw">this</span>.<span class="fu">unbind</span>();
- }
-});
-
-<span class="co">// In MyView definition. </span>
-<span class="co">// We have a global EventBus that allows elements on the app to subscribe to global events.</span>
-<span class="co">// connection/disconnected, connection/resume is two of them.</span>
-
-<span class="kw">var</span> MyView = <span class="kw">BaseView</span>.<span class="fu">extend</span>({
- <span class="dt">initialize</span>: <span class="kw">function</span>() {
- <span class="kw">this</span>.<span class="fu">on</span>(<span class="ch">&#39;beforedestroy&#39;</span>, <span class="kw">this</span>.<span class="fu">onBeforeDestroy</span>, <span class="kw">this</span>);
- <span class="kw">this</span>.<span class="fu">model</span>.<span class="fu">on</span>(<span class="ch">&#39;reset&#39;</span>, <span class="kw">this</span>.<span class="fu">onModelLoaded</span>, <span class="kw">this</span>);
- <span class="kw">EventBus</span>.<span class="fu">on</span>(<span class="ch">&#39;connection/disconnected&#39;</span>, <span class="kw">this</span>.<span class="fu">onDisconnect</span>, <span class="kw">this</span>);
- <span class="kw">EventBus</span>.<span class="fu">on</span>(<span class="ch">&#39;connection/resume&#39;</span>, <span class="kw">this</span>.<span class="fu">onConnectionResumed</span>, <span class="kw">this</span>);
- },
- <span class="dt">onModelLoaded</span>: <span class="kw">function</span>() {
- <span class="co">// We only need this to be done once! (Kinda weird...)</span>
- <span class="kw">this</span>.<span class="fu">model</span>.<span class="fu">off</span>(<span class="ch">&#39;load&#39;</span>, <span class="kw">this</span>.<span class="fu">onModelLoaded</span>, <span class="kw">this</span>);
- },
- <span class="dt">onDisconnect</span>: <span class="kw">function</span>() {
- <span class="co">// Figure out what state we are currently on, display View-specific messaging, etc.</span>
- },
- <span class="dt">onConnectionResumed</span>: <span class="kw">function</span>() {
- <span class="co">// Re-do previous network request that failed.</span>
- },
- <span class="dt">onBeforeDestroy</span>: <span class="kw">function</span>() {
- <span class="kw">EventBus</span>.<span class="fu">off</span>(<span class="ch">&#39;connection/resume&#39;</span>, <span class="kw">this</span>.<span class="fu">onConnectionResumed</span>, <span class="kw">this</span>);
- <span class="kw">EventBus</span>.<span class="fu">off</span>(<span class="ch">&#39;connection/disconnected&#39;</span>, <span class="kw">this</span>.<span class="fu">onDisconnect</span>, <span class="kw">this</span>);
- }
-});</code></pre>
-<p>However, in 0.9.10, what we need to do is quite simple:</p>
-<pre class="sourceCode javascript"><code class="sourceCode javascript">
-<span class="co">// In BaseView definition</span>
-<span class="kw">var</span> BaseView = <span class="kw">Backbone.View</span>.<span class="fu">extend</span>({
- <span class="dt">destroy</span>: <span class="kw">function</span>() {
- <span class="kw">this</span>.<span class="fu">trigger</span>(<span class="ch">&#39;beforedestroy&#39;</span>);
- <span class="kw">this</span>.<span class="fu">remove</span>();
- }
-});
-
-<span class="co">// In MyView definition. </span>
-
-<span class="kw">var</span> MyView = <span class="kw">BaseView</span>.<span class="fu">extend</span>({
- <span class="dt">initialize</span>: <span class="kw">function</span>() {
- <span class="kw">this</span>.<span class="fu">listenTo</span>(EventBus, <span class="ch">&#39;connection/disconnected&#39;</span>, <span class="kw">this</span>.<span class="fu">onDisconnect</span>);
- <span class="kw">this</span>.<span class="fu">listenTo</span>(EventBus, <span class="ch">&#39;connection/resume&#39;</span>, <span class="kw">this</span>.<span class="fu">onConnectionResumed</span>);
- <span class="kw">this</span>.<span class="fu">once</span>(<span class="kw">this</span>.<span class="fu">model</span>, <span class="ch">&#39;load&#39;</span>, <span class="kw">this</span>.<span class="fu">onModelLoaded</span>);
- },
- <span class="dt">onModelLoaded</span>: <span class="kw">function</span>() {
- <span class="co">// Don&#39;t need to unsubscribe anymore!</span>
- },
- <span class="dt">onDisconnect</span>: <span class="kw">function</span>() {
- <span class="co">// Figure out the state, display messaging, etc.</span>
- },
- <span class="dt">onConnectionResumed</span>: <span class="kw">function</span>() {
- <span class="co">// Re-do previous network request that failed.</span>
- }
- <span class="co">// Most importantly, we no longer need onBeforeDestroy() anymore!</span>
-});</code></pre>
-<h3 id="routers-1"><a href="#TOC">Routers</a></h3>
-<ul>
-<li>A <q>route</q> event is triggered on the router in addition to being fired on Backbone.history.</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">Backbone.history</span>.<span class="fu">on</span>(<span class="ch">&#39;route&#39;</span>, onRoute);
-
-<span class="co">// Trigger &#39;route&#39; event on router instance.&quot;</span>
-<span class="kw">router</span>.<span class="fu">on</span>(<span class="ch">&#39;route&#39;</span>, <span class="kw">function</span>(name, args) {
- <span class="kw">console</span>.<span class="fu">log</span>(name === <span class="ch">&#39;routeEvent&#39;</span>);
-});
-
-<span class="kw">location</span>.<span class="fu">replace</span>(<span class="ch">&#39;http://example.com#route-event/x&#39;</span>);
-<span class="kw">Backbone.history</span>.<span class="fu">checkUrl</span>();</code></pre>
-<ul>
-<li>For semantic and cross browser reasons, routes will now ignore search parameters. Routes like <code>search?query=…&amp;page=3</code> should become <code>search/…/3</code>.</li>
-<li>Bugfix for normalizing leading and trailing slashes in the Router definitions. Their presence (or absence) should not affect behavior.</li>
-<li>Router URLs now support optional parts via parentheses, without having to use a regex.</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> Router = <span class="kw">Backbone.Router</span>.<span class="fu">extend</span>({
- <span class="dt">routes</span>: {
- <span class="st">&quot;optional(/:item)&quot;</span>: <span class="st">&quot;optionalItem&quot;</span>,
- <span class="st">&quot;named/optional/(y:z)&quot;</span>: <span class="st">&quot;namedOptionalItem&quot;</span>,
- },
- …
-});</code></pre>
-<h3 id="sync"><a href="#TOC">Sync</a></h3>
-<ul>
-<li>For mixed-mode APIs, <code>Backbone.sync</code> now accepts <a href="http://backbonejs.org/#Sync-emulateHTTP">emulateHTTP</a> and <a href="http://backbonejs.org/#Sync-emulateJSON">emulateJSON</a> as inline options.</li>
-</ul>
-<pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> Library = <span class="kw">Backbone.Collection</span>.<span class="fu">extend</span>({
- <span class="dt">url </span>: <span class="kw">function</span>() { <span class="kw">return</span> <span class="ch">&#39;/library&#39;</span>; }
-});
-
-<span class="kw">var</span> attrs = {
- <span class="dt">title </span>: <span class="st">&quot;The Tempest&quot;</span>,
- <span class="dt">author </span>: <span class="st">&quot;Bill Shakespeare&quot;</span>,
- <span class="dt">length </span>: <span class="dv">123</span>
- };
-
-library = <span class="kw">new</span> Library;
-<span class="kw">library</span>.<span class="fu">create</span>(attrs, {<span class="dt">wait</span>: <span class="kw">false</span>});
-
-<span class="co">// update with just emulateHTTP</span>
-<span class="kw">library</span>.<span class="fu">first</span>().<span class="fu">save</span>({<span class="dt">id</span>: <span class="ch">&#39;2-the-tempest&#39;</span>, <span class="dt">author</span>: <span class="ch">&#39;Tim Shakespeare&#39;</span>}, {
- <span class="dt">emulateHTTP</span>: <span class="kw">true</span>
-});
-
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">url</span> === <span class="ch">&#39;/library/2-the-tempest&#39;</span>); <span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">type</span> === <span class="ch">&#39;POST&#39;</span>); <span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">contentType</span> === <span class="ch">&#39;application/json&#39;</span>); <span class="co">// true</span>
-
-<span class="kw">var</span> data = <span class="kw">JSON</span>.<span class="fu">parse</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">data</span>);
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">data</span>.<span class="fu">id</span> === <span class="ch">&#39;2-the-tempest&#39;</span>);
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">data</span>.<span class="fu">author</span> === <span class="ch">&#39;Tim Shakespeare&#39;</span>);
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">data</span>.<span class="fu">length</span> === <span class="dv">123</span>);
-
-<span class="co">// or update with just emulateJSON</span>
-
-<span class="kw">library</span>.<span class="fu">first</span>().<span class="fu">save</span>({<span class="dt">id</span>: <span class="ch">&#39;2-the-tempest&#39;</span>, <span class="dt">author</span>: <span class="ch">&#39;Tim Shakespeare&#39;</span>}, {
- <span class="dt">emulateJSON</span>: <span class="kw">true</span>
-});
-
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">url</span> === <span class="ch">&#39;/library/2-the-tempest&#39;</span>); <span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">type</span> === <span class="ch">&#39;PUT&#39;</span>); <span class="co">// true</span>
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">contentType</span> ===<span class="ch">&#39;application/x-www-form-urlencoded&#39;</span>); <span class="co">// true</span>
-
-<span class="kw">var</span> data = <span class="kw">JSON</span>.<span class="fu">parse</span>(<span class="kw">this</span>.<span class="fu">ajaxSettings</span>.<span class="fu">data</span>.<span class="fu">model</span>);
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">data</span>.<span class="fu">id</span> === <span class="ch">&#39;2-the-tempest&#39;</span>);
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">data</span>.<span class="fu">author</span> ===<span class="ch">&#39;Tim Shakespeare&#39;</span>);
-<span class="kw">console</span>.<span class="fu">log</span>(<span class="kw">data</span>.<span class="fu">length</span> === <span class="dv">123</span>);</code></pre>
-<ul>
-<li><p>Consolidated <code>&quot;sync&quot;</code> and <code>&quot;error&quot;</code> events within <code>Backbone.sync</code>. They are now triggered regardless of the existence of success or error callbacks.</p></li>
-<li><p>Added a <code>&quot;request&quot;</code> event to <code>Backbone.sync</code>, which triggers whenever a request begins to be made to the server. The natural complement to the <code>&quot;sync&quot;</code> event.</p></li>
-</ul>
-<h3 id="other"><a href="#TOC">Other</a></h3>
-<ul>
-<li>Bug fix on change where attribute comparison uses <code>!==</code> instead of <code>_.isEqual</code>.</li>
-<li>Bug fix where an empty response from the server on save would not call the success function.</li>
-<li>To improve the performance of add, <code>options.index</code> will no longer be set in the <code>add</code> event callback.</li>
-<li>Removed the <code>Backbone.wrapError</code> helper method. Overriding sync should work better for those particular use cases.</li>
-<li>To set what library Backbone uses for DOM manipulation and Ajax calls, use <code>Backbone.$ =</code> … instead of <code>setDomLibrary</code>.</li>
-<li>Added a <code>Backbone.ajax</code> hook for more convenient overriding of the default use of <code>$.ajax</code>. If AJAX is too passé, set it to your preferred method for server communication.</li>
-<li>Validation now occurs even during <code>&quot;silent&quot;</code> changes. This change means that the <code>isValid</code> method has been removed. Failed validations also trigger an error, even if an error callback is specified in the options.</li>
-</ul>
<hr>
<p>Where relevant, copyright Addy Osmani, 2012-2013.</p>
<script type="text/javascript">

0 comments on commit dd422c8

Please sign in to comment.
Something went wrong with that request. Please try again.