marionette.modal 1.0.0.6 → 1.0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gruntfile.coffee +1 -1
- data/examples/vendor/backbone.js +189 -169
- data/examples/vendor/marionette.js +287 -161
- data/examples/vendor/underscore.js +210 -123
- data/lib/marionette.modal/version.rb +1 -1
- data/test/spec/backbone.marionette.modals.spec.js +46 -13
- data/test/src/backbone.marionette.modals.spec.coffee +13 -4
- metadata +1 -1
    
        data/examples/vendor/backbone.js
    CHANGED
    
    | @@ -1,19 +1,37 @@ | |
| 1 | 
            -
            //     Backbone.js 1. | 
| 1 | 
            +
            //     Backbone.js 1.1.0
         | 
| 2 2 |  | 
| 3 | 
            -
            //     (c) 2010- | 
| 3 | 
            +
            //     (c) 2010-2011 Jeremy Ashkenas, DocumentCloud Inc.
         | 
| 4 | 
            +
            //     (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
         | 
| 4 5 | 
             
            //     Backbone may be freely distributed under the MIT license.
         | 
| 5 6 | 
             
            //     For all details and documentation:
         | 
| 6 7 | 
             
            //     http://backbonejs.org
         | 
| 7 8 |  | 
| 8 | 
            -
            (function(){
         | 
| 9 | 
            +
            (function(root, factory) {
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              // Set up Backbone appropriately for the environment. Start with AMD.
         | 
| 12 | 
            +
              if (typeof define === 'function' && define.amd) {
         | 
| 13 | 
            +
                define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
         | 
| 14 | 
            +
                  // Export global even in AMD case in case this script is loaded with
         | 
| 15 | 
            +
                  // others that may still expect a global Backbone.
         | 
| 16 | 
            +
                  root.Backbone = factory(root, exports, _, $);
         | 
| 17 | 
            +
                });
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              // Next for Node.js or CommonJS. jQuery may not be needed as a module.
         | 
| 20 | 
            +
              } else if (typeof exports !== 'undefined') {
         | 
| 21 | 
            +
                var _ = require('underscore'), $;
         | 
| 22 | 
            +
                try { $ = require('jquery'); } catch(e) {};
         | 
| 23 | 
            +
                factory(root, exports, _, $);
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              // Finally, as a browser global.
         | 
| 26 | 
            +
              } else {
         | 
| 27 | 
            +
                root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
         | 
| 28 | 
            +
              }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            }(this, function(root, Backbone, _, $) {
         | 
| 9 31 |  | 
| 10 32 | 
             
              // Initial Setup
         | 
| 11 33 | 
             
              // -------------
         | 
| 12 34 |  | 
| 13 | 
            -
              // Save a reference to the global object (`window` in the browser, `exports`
         | 
| 14 | 
            -
              // on the server).
         | 
| 15 | 
            -
              var root = this;
         | 
| 16 | 
            -
             | 
| 17 35 | 
             
              // Save the previous value of the `Backbone` variable, so that it can be
         | 
| 18 36 | 
             
              // restored later on, if `noConflict` is used.
         | 
| 19 37 | 
             
              var previousBackbone = root.Backbone;
         | 
| @@ -24,25 +42,12 @@ | |
| 24 42 | 
             
              var slice = array.slice;
         | 
| 25 43 | 
             
              var splice = array.splice;
         | 
| 26 44 |  | 
| 27 | 
            -
              // The top-level namespace. All public Backbone classes and modules will
         | 
| 28 | 
            -
              // be attached to this. Exported for both the browser and the server.
         | 
| 29 | 
            -
              var Backbone;
         | 
| 30 | 
            -
              if (typeof exports !== 'undefined') {
         | 
| 31 | 
            -
                Backbone = exports;
         | 
| 32 | 
            -
              } else {
         | 
| 33 | 
            -
                Backbone = root.Backbone = {};
         | 
| 34 | 
            -
              }
         | 
| 35 | 
            -
             | 
| 36 45 | 
             
              // Current version of the library. Keep in sync with `package.json`.
         | 
| 37 | 
            -
              Backbone.VERSION = '1. | 
| 38 | 
            -
             | 
| 39 | 
            -
              // Require Underscore, if we're on the server, and it's not already present.
         | 
| 40 | 
            -
              var _ = root._;
         | 
| 41 | 
            -
              if (!_ && (typeof require !== 'undefined')) _ = require('underscore');
         | 
| 46 | 
            +
              Backbone.VERSION = '1.1.0';
         | 
| 42 47 |  | 
| 43 48 | 
             
              // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
         | 
| 44 49 | 
             
              // the `$` variable.
         | 
| 45 | 
            -
              Backbone.$ =  | 
| 50 | 
            +
              Backbone.$ = $;
         | 
| 46 51 |  | 
| 47 52 | 
             
              // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
         | 
| 48 53 | 
             
              // to its previous owner. Returns a reference to this Backbone object.
         | 
| @@ -52,7 +57,7 @@ | |
| 52 57 | 
             
              };
         | 
| 53 58 |  | 
| 54 59 | 
             
              // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
         | 
| 55 | 
            -
              // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and
         | 
| 60 | 
            +
              // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
         | 
| 56 61 | 
             
              // set a `X-Http-Method-Override` header.
         | 
| 57 62 | 
             
              Backbone.emulateHTTP = false;
         | 
| 58 63 |  | 
| @@ -108,10 +113,9 @@ | |
| 108 113 | 
             
                  var retain, ev, events, names, i, l, j, k;
         | 
| 109 114 | 
             
                  if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
         | 
| 110 115 | 
             
                  if (!name && !callback && !context) {
         | 
| 111 | 
            -
                    this._events =  | 
| 116 | 
            +
                    this._events = void 0;
         | 
| 112 117 | 
             
                    return this;
         | 
| 113 118 | 
             
                  }
         | 
| 114 | 
            -
             | 
| 115 119 | 
             
                  names = name ? [name] : _.keys(this._events);
         | 
| 116 120 | 
             
                  for (i = 0, l = names.length; i < l; i++) {
         | 
| 117 121 | 
             
                    name = names[i];
         | 
| @@ -151,14 +155,15 @@ | |
| 151 155 | 
             
                // Tell this object to stop listening to either specific events ... or
         | 
| 152 156 | 
             
                // to every object it's currently listening to.
         | 
| 153 157 | 
             
                stopListening: function(obj, name, callback) {
         | 
| 154 | 
            -
                  var  | 
| 155 | 
            -
                  if (! | 
| 156 | 
            -
                  var  | 
| 157 | 
            -
                  if (typeof name === 'object') callback = this;
         | 
| 158 | 
            -
                  if (obj) ( | 
| 159 | 
            -
                  for (var id in  | 
| 160 | 
            -
                     | 
| 161 | 
            -
                     | 
| 158 | 
            +
                  var listeningTo = this._listeningTo;
         | 
| 159 | 
            +
                  if (!listeningTo) return this;
         | 
| 160 | 
            +
                  var remove = !name && !callback;
         | 
| 161 | 
            +
                  if (!callback && typeof name === 'object') callback = this;
         | 
| 162 | 
            +
                  if (obj) (listeningTo = {})[obj._listenId] = obj;
         | 
| 163 | 
            +
                  for (var id in listeningTo) {
         | 
| 164 | 
            +
                    obj = listeningTo[id];
         | 
| 165 | 
            +
                    obj.off(name, callback, this);
         | 
| 166 | 
            +
                    if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id];
         | 
| 162 167 | 
             
                  }
         | 
| 163 168 | 
             
                  return this;
         | 
| 164 169 | 
             
                }
         | 
| @@ -215,10 +220,10 @@ | |
| 215 220 | 
             
              // listening to.
         | 
| 216 221 | 
             
              _.each(listenMethods, function(implementation, method) {
         | 
| 217 222 | 
             
                Events[method] = function(obj, name, callback) {
         | 
| 218 | 
            -
                  var  | 
| 219 | 
            -
                  var id = obj. | 
| 220 | 
            -
                   | 
| 221 | 
            -
                  if (typeof name === 'object') callback = this;
         | 
| 223 | 
            +
                  var listeningTo = this._listeningTo || (this._listeningTo = {});
         | 
| 224 | 
            +
                  var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
         | 
| 225 | 
            +
                  listeningTo[id] = obj;
         | 
| 226 | 
            +
                  if (!callback && typeof name === 'object') callback = this;
         | 
| 222 227 | 
             
                  obj[implementation](name, callback, this);
         | 
| 223 228 | 
             
                  return this;
         | 
| 224 229 | 
             
                };
         | 
| @@ -243,24 +248,18 @@ | |
| 243 248 | 
             
              // Create a new model with the specified attributes. A client id (`cid`)
         | 
| 244 249 | 
             
              // is automatically generated and assigned for you.
         | 
| 245 250 | 
             
              var Model = Backbone.Model = function(attributes, options) {
         | 
| 246 | 
            -
                var defaults;
         | 
| 247 251 | 
             
                var attrs = attributes || {};
         | 
| 248 252 | 
             
                options || (options = {});
         | 
| 249 253 | 
             
                this.cid = _.uniqueId('c');
         | 
| 250 254 | 
             
                this.attributes = {};
         | 
| 251 | 
            -
                 | 
| 255 | 
            +
                if (options.collection) this.collection = options.collection;
         | 
| 252 256 | 
             
                if (options.parse) attrs = this.parse(attrs, options) || {};
         | 
| 253 | 
            -
                 | 
| 254 | 
            -
                  attrs = _.defaults({}, attrs, defaults);
         | 
| 255 | 
            -
                }
         | 
| 257 | 
            +
                attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
         | 
| 256 258 | 
             
                this.set(attrs, options);
         | 
| 257 259 | 
             
                this.changed = {};
         | 
| 258 260 | 
             
                this.initialize.apply(this, arguments);
         | 
| 259 261 | 
             
              };
         | 
| 260 262 |  | 
| 261 | 
            -
              // A list of options to be attached directly to the model, if provided.
         | 
| 262 | 
            -
              var modelOptions = ['url', 'urlRoot', 'collection'];
         | 
| 263 | 
            -
             | 
| 264 263 | 
             
              // Attach all inheritable methods to the Model prototype.
         | 
| 265 264 | 
             
              _.extend(Model.prototype, Events, {
         | 
| 266 265 |  | 
| @@ -355,7 +354,7 @@ | |
| 355 354 |  | 
| 356 355 | 
             
                  // Trigger all relevant attribute changes.
         | 
| 357 356 | 
             
                  if (!silent) {
         | 
| 358 | 
            -
                    if (changes.length) this._pending =  | 
| 357 | 
            +
                    if (changes.length) this._pending = options;
         | 
| 359 358 | 
             
                    for (var i = 0, l = changes.length; i < l; i++) {
         | 
| 360 359 | 
             
                      this.trigger('change:' + changes[i], this, current[changes[i]], options);
         | 
| 361 360 | 
             
                    }
         | 
| @@ -366,6 +365,7 @@ | |
| 366 365 | 
             
                  if (changing) return this;
         | 
| 367 366 | 
             
                  if (!silent) {
         | 
| 368 367 | 
             
                    while (this._pending) {
         | 
| 368 | 
            +
                      options = this._pending;
         | 
| 369 369 | 
             
                      this._pending = false;
         | 
| 370 370 | 
             
                      this.trigger('change', this, options);
         | 
| 371 371 | 
             
                    }
         | 
| @@ -456,13 +456,16 @@ | |
| 456 456 | 
             
                    (attrs = {})[key] = val;
         | 
| 457 457 | 
             
                  }
         | 
| 458 458 |  | 
| 459 | 
            -
                  // If we're not waiting and attributes exist, save acts as `set(attr).save(null, opts)`.
         | 
| 460 | 
            -
                  if (attrs && (!options || !options.wait) && !this.set(attrs, options)) return false;
         | 
| 461 | 
            -
             | 
| 462 459 | 
             
                  options = _.extend({validate: true}, options);
         | 
| 463 460 |  | 
| 464 | 
            -
                  //  | 
| 465 | 
            -
                   | 
| 461 | 
            +
                  // If we're not waiting and attributes exist, save acts as
         | 
| 462 | 
            +
                  // `set(attr).save(null, opts)` with validation. Otherwise, check if
         | 
| 463 | 
            +
                  // the model will be valid when the attributes, if any, are set.
         | 
| 464 | 
            +
                  if (attrs && !options.wait) {
         | 
| 465 | 
            +
                    if (!this.set(attrs, options)) return false;
         | 
| 466 | 
            +
                  } else {
         | 
| 467 | 
            +
                    if (!this._validate(attrs, options)) return false;
         | 
| 468 | 
            +
                  }
         | 
| 466 469 |  | 
| 467 470 | 
             
                  // Set temporary attributes if `{wait: true}`.
         | 
| 468 471 | 
             
                  if (attrs && options.wait) {
         | 
| @@ -548,7 +551,7 @@ | |
| 548 551 |  | 
| 549 552 | 
             
                // A model is new if it has never been saved to the server, and lacks an id.
         | 
| 550 553 | 
             
                isNew: function() {
         | 
| 551 | 
            -
                  return this. | 
| 554 | 
            +
                  return !this.has(this.idAttribute);
         | 
| 552 555 | 
             
                },
         | 
| 553 556 |  | 
| 554 557 | 
             
                // Check if the model is currently in a valid state.
         | 
| @@ -563,7 +566,7 @@ | |
| 563 566 | 
             
                  attrs = _.extend({}, this.attributes, attrs);
         | 
| 564 567 | 
             
                  var error = this.validationError = this.validate(attrs, options) || null;
         | 
| 565 568 | 
             
                  if (!error) return true;
         | 
| 566 | 
            -
                  this.trigger('invalid', this, error, _.extend(options | 
| 569 | 
            +
                  this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
         | 
| 567 570 | 
             
                  return false;
         | 
| 568 571 | 
             
                }
         | 
| 569 572 |  | 
| @@ -596,7 +599,6 @@ | |
| 596 599 | 
             
              // its models in sort order, as they're added and removed.
         | 
| 597 600 | 
             
              var Collection = Backbone.Collection = function(models, options) {
         | 
| 598 601 | 
             
                options || (options = {});
         | 
| 599 | 
            -
                if (options.url) this.url = options.url;
         | 
| 600 602 | 
             
                if (options.model) this.model = options.model;
         | 
| 601 603 | 
             
                if (options.comparator !== void 0) this.comparator = options.comparator;
         | 
| 602 604 | 
             
                this._reset();
         | 
| @@ -606,7 +608,7 @@ | |
| 606 608 |  | 
| 607 609 | 
             
              // Default options for `Collection#set`.
         | 
| 608 610 | 
             
              var setOptions = {add: true, remove: true, merge: true};
         | 
| 609 | 
            -
              var addOptions = {add: true,  | 
| 611 | 
            +
              var addOptions = {add: true, remove: false};
         | 
| 610 612 |  | 
| 611 613 | 
             
              // Define the Collection's inheritable methods.
         | 
| 612 614 | 
             
              _.extend(Collection.prototype, Events, {
         | 
| @@ -632,19 +634,18 @@ | |
| 632 634 |  | 
| 633 635 | 
             
                // Add a model, or list of models to the set.
         | 
| 634 636 | 
             
                add: function(models, options) {
         | 
| 635 | 
            -
                  return this.set(models, _. | 
| 637 | 
            +
                  return this.set(models, _.extend({merge: false}, options, addOptions));
         | 
| 636 638 | 
             
                },
         | 
| 637 639 |  | 
| 638 640 | 
             
                // Remove a model, or a list of models from the set.
         | 
| 639 641 | 
             
                remove: function(models, options) {
         | 
| 640 | 
            -
                   | 
| 642 | 
            +
                  var singular = !_.isArray(models);
         | 
| 643 | 
            +
                  models = singular ? [models] : _.clone(models);
         | 
| 641 644 | 
             
                  options || (options = {});
         | 
| 642 645 | 
             
                  var i, l, index, model;
         | 
| 643 646 | 
             
                  for (i = 0, l = models.length; i < l; i++) {
         | 
| 644 | 
            -
                    model = this.get(models[i]);
         | 
| 647 | 
            +
                    model = models[i] = this.get(models[i]);
         | 
| 645 648 | 
             
                    if (!model) continue;
         | 
| 646 | 
            -
                    delete this._byId[model.id];
         | 
| 647 | 
            -
                    delete this._byId[model.cid];
         | 
| 648 649 | 
             
                    index = this.indexOf(model);
         | 
| 649 650 | 
             
                    this.models.splice(index, 1);
         | 
| 650 651 | 
             
                    this.length--;
         | 
| @@ -652,9 +653,9 @@ | |
| 652 653 | 
             
                      options.index = index;
         | 
| 653 654 | 
             
                      model.trigger('remove', model, this, options);
         | 
| 654 655 | 
             
                    }
         | 
| 655 | 
            -
                    this._removeReference(model);
         | 
| 656 | 
            +
                    this._removeReference(model, options);
         | 
| 656 657 | 
             
                  }
         | 
| 657 | 
            -
                  return  | 
| 658 | 
            +
                  return singular ? models[0] : models;
         | 
| 658 659 | 
             
                },
         | 
| 659 660 |  | 
| 660 661 | 
             
                // Update a collection by `set`-ing a new list of models, adding new ones,
         | 
| @@ -662,43 +663,53 @@ | |
| 662 663 | 
             
                // already exist in the collection, as necessary. Similar to **Model#set**,
         | 
| 663 664 | 
             
                // the core operation for updating the data contained by the collection.
         | 
| 664 665 | 
             
                set: function(models, options) {
         | 
| 665 | 
            -
                  options = _.defaults( | 
| 666 | 
            +
                  options = _.defaults({}, options, setOptions);
         | 
| 666 667 | 
             
                  if (options.parse) models = this.parse(models, options);
         | 
| 667 | 
            -
                   | 
| 668 | 
            -
                   | 
| 668 | 
            +
                  var singular = !_.isArray(models);
         | 
| 669 | 
            +
                  models = singular ? (models ? [models] : []) : _.clone(models);
         | 
| 670 | 
            +
                  var i, l, id, model, attrs, existing, sort;
         | 
| 669 671 | 
             
                  var at = options.at;
         | 
| 672 | 
            +
                  var targetModel = this.model;
         | 
| 670 673 | 
             
                  var sortable = this.comparator && (at == null) && options.sort !== false;
         | 
| 671 674 | 
             
                  var sortAttr = _.isString(this.comparator) ? this.comparator : null;
         | 
| 672 675 | 
             
                  var toAdd = [], toRemove = [], modelMap = {};
         | 
| 676 | 
            +
                  var add = options.add, merge = options.merge, remove = options.remove;
         | 
| 677 | 
            +
                  var order = !sortable && add && remove ? [] : false;
         | 
| 673 678 |  | 
| 674 679 | 
             
                  // Turn bare objects into model references, and prevent invalid models
         | 
| 675 680 | 
             
                  // from being added.
         | 
| 676 681 | 
             
                  for (i = 0, l = models.length; i < l; i++) {
         | 
| 677 | 
            -
                     | 
| 682 | 
            +
                    attrs = models[i] || {};
         | 
| 683 | 
            +
                    if (attrs instanceof Model) {
         | 
| 684 | 
            +
                      id = model = attrs;
         | 
| 685 | 
            +
                    } else {
         | 
| 686 | 
            +
                      id = attrs[targetModel.prototype.idAttribute || 'id'];
         | 
| 687 | 
            +
                    }
         | 
| 678 688 |  | 
| 679 689 | 
             
                    // If a duplicate is found, prevent it from being added and
         | 
| 680 690 | 
             
                    // optionally merge it into the existing model.
         | 
| 681 | 
            -
                    if (existing = this.get( | 
| 682 | 
            -
                      if ( | 
| 683 | 
            -
                      if ( | 
| 684 | 
            -
                         | 
| 691 | 
            +
                    if (existing = this.get(id)) {
         | 
| 692 | 
            +
                      if (remove) modelMap[existing.cid] = true;
         | 
| 693 | 
            +
                      if (merge) {
         | 
| 694 | 
            +
                        attrs = attrs === model ? model.attributes : attrs;
         | 
| 695 | 
            +
                        if (options.parse) attrs = existing.parse(attrs, options);
         | 
| 696 | 
            +
                        existing.set(attrs, options);
         | 
| 685 697 | 
             
                        if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
         | 
| 686 698 | 
             
                      }
         | 
| 699 | 
            +
                      models[i] = existing;
         | 
| 687 700 |  | 
| 688 | 
            -
                    //  | 
| 689 | 
            -
                    } else if ( | 
| 701 | 
            +
                    // If this is a new, valid model, push it to the `toAdd` list.
         | 
| 702 | 
            +
                    } else if (add) {
         | 
| 703 | 
            +
                      model = models[i] = this._prepareModel(attrs, options);
         | 
| 704 | 
            +
                      if (!model) continue;
         | 
| 690 705 | 
             
                      toAdd.push(model);
         | 
| 691 | 
            -
             | 
| 692 | 
            -
                      // Listen to added models' events, and index models for lookup by
         | 
| 693 | 
            -
                      // `id` and by `cid`.
         | 
| 694 | 
            -
                      model.on('all', this._onModelEvent, this);
         | 
| 695 | 
            -
                      this._byId[model.cid] = model;
         | 
| 696 | 
            -
                      if (model.id != null) this._byId[model.id] = model;
         | 
| 706 | 
            +
                      this._addReference(model, options);
         | 
| 697 707 | 
             
                    }
         | 
| 708 | 
            +
                    if (order) order.push(existing || model);
         | 
| 698 709 | 
             
                  }
         | 
| 699 710 |  | 
| 700 711 | 
             
                  // Remove nonexistent models if appropriate.
         | 
| 701 | 
            -
                  if ( | 
| 712 | 
            +
                  if (remove) {
         | 
| 702 713 | 
             
                    for (i = 0, l = this.length; i < l; ++i) {
         | 
| 703 714 | 
             
                      if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
         | 
| 704 715 | 
             
                    }
         | 
| @@ -706,29 +717,35 @@ | |
| 706 717 | 
             
                  }
         | 
| 707 718 |  | 
| 708 719 | 
             
                  // See if sorting is needed, update `length` and splice in new models.
         | 
| 709 | 
            -
                  if (toAdd.length) {
         | 
| 720 | 
            +
                  if (toAdd.length || (order && order.length)) {
         | 
| 710 721 | 
             
                    if (sortable) sort = true;
         | 
| 711 722 | 
             
                    this.length += toAdd.length;
         | 
| 712 723 | 
             
                    if (at != null) {
         | 
| 713 | 
            -
                       | 
| 724 | 
            +
                      for (i = 0, l = toAdd.length; i < l; i++) {
         | 
| 725 | 
            +
                        this.models.splice(at + i, 0, toAdd[i]);
         | 
| 726 | 
            +
                      }
         | 
| 714 727 | 
             
                    } else {
         | 
| 715 | 
            -
                       | 
| 728 | 
            +
                      if (order) this.models.length = 0;
         | 
| 729 | 
            +
                      var orderedModels = order || toAdd;
         | 
| 730 | 
            +
                      for (i = 0, l = orderedModels.length; i < l; i++) {
         | 
| 731 | 
            +
                        this.models.push(orderedModels[i]);
         | 
| 732 | 
            +
                      }
         | 
| 716 733 | 
             
                    }
         | 
| 717 734 | 
             
                  }
         | 
| 718 735 |  | 
| 719 736 | 
             
                  // Silently sort the collection if appropriate.
         | 
| 720 737 | 
             
                  if (sort) this.sort({silent: true});
         | 
| 721 738 |  | 
| 722 | 
            -
                   | 
| 723 | 
            -
             | 
| 724 | 
            -
             | 
| 725 | 
            -
             | 
| 726 | 
            -
                     | 
| 739 | 
            +
                  // Unless silenced, it's time to fire all appropriate add/sort events.
         | 
| 740 | 
            +
                  if (!options.silent) {
         | 
| 741 | 
            +
                    for (i = 0, l = toAdd.length; i < l; i++) {
         | 
| 742 | 
            +
                      (model = toAdd[i]).trigger('add', model, this, options);
         | 
| 743 | 
            +
                    }
         | 
| 744 | 
            +
                    if (sort || (order && order.length)) this.trigger('sort', this, options);
         | 
| 727 745 | 
             
                  }
         | 
| 728 746 |  | 
| 729 | 
            -
                  //  | 
| 730 | 
            -
                   | 
| 731 | 
            -
                  return this;
         | 
| 747 | 
            +
                  // Return the added (or merged) model (or models).
         | 
| 748 | 
            +
                  return singular ? models[0] : models;
         | 
| 732 749 | 
             
                },
         | 
| 733 750 |  | 
| 734 751 | 
             
                // When you have more items than you want to add or remove individually,
         | 
| @@ -738,20 +755,18 @@ | |
| 738 755 | 
             
                reset: function(models, options) {
         | 
| 739 756 | 
             
                  options || (options = {});
         | 
| 740 757 | 
             
                  for (var i = 0, l = this.models.length; i < l; i++) {
         | 
| 741 | 
            -
                    this._removeReference(this.models[i]);
         | 
| 758 | 
            +
                    this._removeReference(this.models[i], options);
         | 
| 742 759 | 
             
                  }
         | 
| 743 760 | 
             
                  options.previousModels = this.models;
         | 
| 744 761 | 
             
                  this._reset();
         | 
| 745 | 
            -
                  this.add(models, _.extend({silent: true}, options));
         | 
| 762 | 
            +
                  models = this.add(models, _.extend({silent: true}, options));
         | 
| 746 763 | 
             
                  if (!options.silent) this.trigger('reset', this, options);
         | 
| 747 | 
            -
                  return  | 
| 764 | 
            +
                  return models;
         | 
| 748 765 | 
             
                },
         | 
| 749 766 |  | 
| 750 767 | 
             
                // Add a model to the end of the collection.
         | 
| 751 768 | 
             
                push: function(model, options) {
         | 
| 752 | 
            -
                   | 
| 753 | 
            -
                  this.add(model, _.extend({at: this.length}, options));
         | 
| 754 | 
            -
                  return model;
         | 
| 769 | 
            +
                  return this.add(model, _.extend({at: this.length}, options));
         | 
| 755 770 | 
             
                },
         | 
| 756 771 |  | 
| 757 772 | 
             
                // Remove a model from the end of the collection.
         | 
| @@ -763,9 +778,7 @@ | |
| 763 778 |  | 
| 764 779 | 
             
                // Add a model to the beginning of the collection.
         | 
| 765 780 | 
             
                unshift: function(model, options) {
         | 
| 766 | 
            -
                   | 
| 767 | 
            -
                  this.add(model, _.extend({at: 0}, options));
         | 
| 768 | 
            -
                  return model;
         | 
| 781 | 
            +
                  return this.add(model, _.extend({at: 0}, options));
         | 
| 769 782 | 
             
                },
         | 
| 770 783 |  | 
| 771 784 | 
             
                // Remove a model from the beginning of the collection.
         | 
| @@ -776,14 +789,14 @@ | |
| 776 789 | 
             
                },
         | 
| 777 790 |  | 
| 778 791 | 
             
                // Slice out a sub-array of models from the collection.
         | 
| 779 | 
            -
                slice: function( | 
| 780 | 
            -
                  return this.models | 
| 792 | 
            +
                slice: function() {
         | 
| 793 | 
            +
                  return slice.apply(this.models, arguments);
         | 
| 781 794 | 
             
                },
         | 
| 782 795 |  | 
| 783 796 | 
             
                // Get a model from the set by id.
         | 
| 784 797 | 
             
                get: function(obj) {
         | 
| 785 798 | 
             
                  if (obj == null) return void 0;
         | 
| 786 | 
            -
                  return this._byId[obj | 
| 799 | 
            +
                  return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
         | 
| 787 800 | 
             
                },
         | 
| 788 801 |  | 
| 789 802 | 
             
                // Get the model at the given index.
         | 
| @@ -827,16 +840,6 @@ | |
| 827 840 | 
             
                  return this;
         | 
| 828 841 | 
             
                },
         | 
| 829 842 |  | 
| 830 | 
            -
                // Figure out the smallest index at which a model should be inserted so as
         | 
| 831 | 
            -
                // to maintain order.
         | 
| 832 | 
            -
                sortedIndex: function(model, value, context) {
         | 
| 833 | 
            -
                  value || (value = this.comparator);
         | 
| 834 | 
            -
                  var iterator = _.isFunction(value) ? value : function(model) {
         | 
| 835 | 
            -
                    return model.get(value);
         | 
| 836 | 
            -
                  };
         | 
| 837 | 
            -
                  return _.sortedIndex(this.models, model, iterator, context);
         | 
| 838 | 
            -
                },
         | 
| 839 | 
            -
             | 
| 840 843 | 
             
                // Pluck an attribute from each model in the collection.
         | 
| 841 844 | 
             
                pluck: function(attr) {
         | 
| 842 845 | 
             
                  return _.invoke(this.models, 'get', attr);
         | 
| @@ -869,7 +872,7 @@ | |
| 869 872 | 
             
                  if (!options.wait) this.add(model, options);
         | 
| 870 873 | 
             
                  var collection = this;
         | 
| 871 874 | 
             
                  var success = options.success;
         | 
| 872 | 
            -
                  options.success = function(resp) {
         | 
| 875 | 
            +
                  options.success = function(model, resp) {
         | 
| 873 876 | 
             
                    if (options.wait) collection.add(model, options);
         | 
| 874 877 | 
             
                    if (success) success(model, resp, options);
         | 
| 875 878 | 
             
                  };
         | 
| @@ -899,22 +902,27 @@ | |
| 899 902 | 
             
                // Prepare a hash of attributes (or other model) to be added to this
         | 
| 900 903 | 
             
                // collection.
         | 
| 901 904 | 
             
                _prepareModel: function(attrs, options) {
         | 
| 902 | 
            -
                  if (attrs instanceof Model)  | 
| 903 | 
            -
             | 
| 904 | 
            -
                    return attrs;
         | 
| 905 | 
            -
                  }
         | 
| 906 | 
            -
                  options || (options = {});
         | 
| 905 | 
            +
                  if (attrs instanceof Model) return attrs;
         | 
| 906 | 
            +
                  options = options ? _.clone(options) : {};
         | 
| 907 907 | 
             
                  options.collection = this;
         | 
| 908 908 | 
             
                  var model = new this.model(attrs, options);
         | 
| 909 | 
            -
                  if (!model. | 
| 910 | 
            -
             | 
| 911 | 
            -
             | 
| 912 | 
            -
             | 
| 913 | 
            -
             | 
| 909 | 
            +
                  if (!model.validationError) return model;
         | 
| 910 | 
            +
                  this.trigger('invalid', this, model.validationError, options);
         | 
| 911 | 
            +
                  return false;
         | 
| 912 | 
            +
                },
         | 
| 913 | 
            +
             | 
| 914 | 
            +
                // Internal method to create a model's ties to a collection.
         | 
| 915 | 
            +
                _addReference: function(model, options) {
         | 
| 916 | 
            +
                  this._byId[model.cid] = model;
         | 
| 917 | 
            +
                  if (model.id != null) this._byId[model.id] = model;
         | 
| 918 | 
            +
                  if (!model.collection) model.collection = this;
         | 
| 919 | 
            +
                  model.on('all', this._onModelEvent, this);
         | 
| 914 920 | 
             
                },
         | 
| 915 921 |  | 
| 916 922 | 
             
                // Internal method to sever a model's ties to a collection.
         | 
| 917 | 
            -
                _removeReference: function(model) {
         | 
| 923 | 
            +
                _removeReference: function(model, options) {
         | 
| 924 | 
            +
                  delete this._byId[model.id];
         | 
| 925 | 
            +
                  delete this._byId[model.cid];
         | 
| 918 926 | 
             
                  if (this === model.collection) delete model.collection;
         | 
| 919 927 | 
             
                  model.off('all', this._onModelEvent, this);
         | 
| 920 928 | 
             
                },
         | 
| @@ -942,8 +950,8 @@ | |
| 942 950 | 
             
                'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
         | 
| 943 951 | 
             
                'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
         | 
| 944 952 | 
             
                'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
         | 
| 945 | 
            -
                'tail', 'drop', 'last', 'without', ' | 
| 946 | 
            -
                'isEmpty', 'chain'];
         | 
| 953 | 
            +
                'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
         | 
| 954 | 
            +
                'lastIndexOf', 'isEmpty', 'chain', 'sample'];
         | 
| 947 955 |  | 
| 948 956 | 
             
              // Mix in each Underscore method as a proxy to `Collection#models`.
         | 
| 949 957 | 
             
              _.each(methods, function(method) {
         | 
| @@ -955,7 +963,7 @@ | |
| 955 963 | 
             
              });
         | 
| 956 964 |  | 
| 957 965 | 
             
              // Underscore methods that take a property name as an argument.
         | 
| 958 | 
            -
              var attributeMethods = ['groupBy', 'countBy', 'sortBy'];
         | 
| 966 | 
            +
              var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
         | 
| 959 967 |  | 
| 960 968 | 
             
              // Use attributes instead of properties.
         | 
| 961 969 | 
             
              _.each(attributeMethods, function(method) {
         | 
| @@ -982,7 +990,8 @@ | |
| 982 990 | 
             
              // if an existing element is not provided...
         | 
| 983 991 | 
             
              var View = Backbone.View = function(options) {
         | 
| 984 992 | 
             
                this.cid = _.uniqueId('view');
         | 
| 985 | 
            -
                 | 
| 993 | 
            +
                options || (options = {});
         | 
| 994 | 
            +
                _.extend(this, _.pick(options, viewOptions));
         | 
| 986 995 | 
             
                this._ensureElement();
         | 
| 987 996 | 
             
                this.initialize.apply(this, arguments);
         | 
| 988 997 | 
             
                this.delegateEvents();
         | 
| @@ -1001,7 +1010,7 @@ | |
| 1001 1010 | 
             
                tagName: 'div',
         | 
| 1002 1011 |  | 
| 1003 1012 | 
             
                // jQuery delegate for element lookup, scoped to DOM elements within the
         | 
| 1004 | 
            -
                // current view. This should be  | 
| 1013 | 
            +
                // current view. This should be preferred to global lookups where possible.
         | 
| 1005 1014 | 
             
                $: function(selector) {
         | 
| 1006 1015 | 
             
                  return this.$el.find(selector);
         | 
| 1007 1016 | 
             
                },
         | 
| @@ -1041,7 +1050,7 @@ | |
| 1041 1050 | 
             
                //
         | 
| 1042 1051 | 
             
                //     {
         | 
| 1043 1052 | 
             
                //       'mousedown .title':  'edit',
         | 
| 1044 | 
            -
                //       'click .button':     'save'
         | 
| 1053 | 
            +
                //       'click .button':     'save',
         | 
| 1045 1054 | 
             
                //       'click .open':       function(e) { ... }
         | 
| 1046 1055 | 
             
                //     }
         | 
| 1047 1056 | 
             
                //
         | 
| @@ -1079,16 +1088,6 @@ | |
| 1079 1088 | 
             
                  return this;
         | 
| 1080 1089 | 
             
                },
         | 
| 1081 1090 |  | 
| 1082 | 
            -
                // Performs the initial configuration of a View with a set of options.
         | 
| 1083 | 
            -
                // Keys with special meaning *(e.g. model, collection, id, className)* are
         | 
| 1084 | 
            -
                // attached directly to the view.  See `viewOptions` for an exhaustive
         | 
| 1085 | 
            -
                // list.
         | 
| 1086 | 
            -
                _configure: function(options) {
         | 
| 1087 | 
            -
                  if (this.options) options = _.extend({}, _.result(this, 'options'), options);
         | 
| 1088 | 
            -
                  _.extend(this, _.pick(options, viewOptions));
         | 
| 1089 | 
            -
                  this.options = options;
         | 
| 1090 | 
            -
                },
         | 
| 1091 | 
            -
             | 
| 1092 1091 | 
             
                // Ensure that the View has a DOM element to render into.
         | 
| 1093 1092 | 
             
                // If `this.el` is a string, pass it through `$()`, take the first
         | 
| 1094 1093 | 
             
                // matching element, and re-assign it to `el`. Otherwise, create
         | 
| @@ -1174,8 +1173,7 @@ | |
| 1174 1173 | 
             
                // If we're sending a `PATCH` request, and we're in an old Internet Explorer
         | 
| 1175 1174 | 
             
                // that still has ActiveX enabled by default, override jQuery to use that
         | 
| 1176 1175 | 
             
                // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8.
         | 
| 1177 | 
            -
                if (params.type === 'PATCH' &&  | 
| 1178 | 
            -
                      !(window.external && window.external.msActiveXFilteringEnabled)) {
         | 
| 1176 | 
            +
                if (params.type === 'PATCH' && noXhrPatch) {
         | 
| 1179 1177 | 
             
                  params.xhr = function() {
         | 
| 1180 1178 | 
             
                    return new ActiveXObject("Microsoft.XMLHTTP");
         | 
| 1181 1179 | 
             
                  };
         | 
| @@ -1187,6 +1185,10 @@ | |
| 1187 1185 | 
             
                return xhr;
         | 
| 1188 1186 | 
             
              };
         | 
| 1189 1187 |  | 
| 1188 | 
            +
              var noXhrPatch =
         | 
| 1189 | 
            +
                typeof window !== 'undefined' && !!window.ActiveXObject &&
         | 
| 1190 | 
            +
                  !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
         | 
| 1191 | 
            +
             | 
| 1190 1192 | 
             
              // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
         | 
| 1191 1193 | 
             
              var methodMap = {
         | 
| 1192 1194 | 
             
                'create': 'POST',
         | 
| @@ -1275,7 +1277,7 @@ | |
| 1275 1277 | 
             
                _routeToRegExp: function(route) {
         | 
| 1276 1278 | 
             
                  route = route.replace(escapeRegExp, '\\$&')
         | 
| 1277 1279 | 
             
                               .replace(optionalParam, '(?:$1)?')
         | 
| 1278 | 
            -
                               .replace(namedParam, function(match, optional){
         | 
| 1280 | 
            +
                               .replace(namedParam, function(match, optional) {
         | 
| 1279 1281 | 
             
                                 return optional ? match : '([^\/]+)';
         | 
| 1280 1282 | 
             
                               })
         | 
| 1281 1283 | 
             
                               .replace(splatParam, '(.*?)');
         | 
| @@ -1325,6 +1327,9 @@ | |
| 1325 1327 | 
             
              // Cached regex for removing a trailing slash.
         | 
| 1326 1328 | 
             
              var trailingSlash = /\/$/;
         | 
| 1327 1329 |  | 
| 1330 | 
            +
              // Cached regex for stripping urls of hash and query.
         | 
| 1331 | 
            +
              var pathStripper = /[?#].*$/;
         | 
| 1332 | 
            +
             | 
| 1328 1333 | 
             
              // Has the history handling already been started?
         | 
| 1329 1334 | 
             
              History.started = false;
         | 
| 1330 1335 |  | 
| @@ -1349,7 +1354,7 @@ | |
| 1349 1354 | 
             
                    if (this._hasPushState || !this._wantsHashChange || forcePushState) {
         | 
| 1350 1355 | 
             
                      fragment = this.location.pathname;
         | 
| 1351 1356 | 
             
                      var root = this.root.replace(trailingSlash, '');
         | 
| 1352 | 
            -
                      if (!fragment.indexOf(root)) fragment = fragment. | 
| 1357 | 
            +
                      if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
         | 
| 1353 1358 | 
             
                    } else {
         | 
| 1354 1359 | 
             
                      fragment = this.getHash();
         | 
| 1355 1360 | 
             
                    }
         | 
| @@ -1365,7 +1370,7 @@ | |
| 1365 1370 |  | 
| 1366 1371 | 
             
                  // Figure out the initial configuration. Do we need an iframe?
         | 
| 1367 1372 | 
             
                  // Is pushState desired ... is it available?
         | 
| 1368 | 
            -
                  this.options          = _.extend({ | 
| 1373 | 
            +
                  this.options          = _.extend({root: '/'}, this.options, options);
         | 
| 1369 1374 | 
             
                  this.root             = this.options.root;
         | 
| 1370 1375 | 
             
                  this._wantsHashChange = this.options.hashChange !== false;
         | 
| 1371 1376 | 
             
                  this._wantsPushState  = !!this.options.pushState;
         | 
| @@ -1378,7 +1383,8 @@ | |
| 1378 1383 | 
             
                  this.root = ('/' + this.root + '/').replace(rootStripper, '/');
         | 
| 1379 1384 |  | 
| 1380 1385 | 
             
                  if (oldIE && this._wantsHashChange) {
         | 
| 1381 | 
            -
                     | 
| 1386 | 
            +
                    var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');
         | 
| 1387 | 
            +
                    this.iframe = frame.hide().appendTo('body')[0].contentWindow;
         | 
| 1382 1388 | 
             
                    this.navigate(fragment);
         | 
| 1383 1389 | 
             
                  }
         | 
| 1384 1390 |  | 
| @@ -1398,19 +1404,25 @@ | |
| 1398 1404 | 
             
                  var loc = this.location;
         | 
| 1399 1405 | 
             
                  var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root;
         | 
| 1400 1406 |  | 
| 1401 | 
            -
                  //  | 
| 1402 | 
            -
                  //  | 
| 1403 | 
            -
                  if (this._wantsHashChange && this._wantsPushState | 
| 1404 | 
            -
             | 
| 1405 | 
            -
                     | 
| 1406 | 
            -
                    //  | 
| 1407 | 
            -
                     | 
| 1407 | 
            +
                  // Transition from hashChange to pushState or vice versa if both are
         | 
| 1408 | 
            +
                  // requested.
         | 
| 1409 | 
            +
                  if (this._wantsHashChange && this._wantsPushState) {
         | 
| 1410 | 
            +
             | 
| 1411 | 
            +
                    // If we've started off with a route from a `pushState`-enabled
         | 
| 1412 | 
            +
                    // browser, but we're currently in a browser that doesn't support it...
         | 
| 1413 | 
            +
                    if (!this._hasPushState && !atRoot) {
         | 
| 1414 | 
            +
                      this.fragment = this.getFragment(null, true);
         | 
| 1415 | 
            +
                      this.location.replace(this.root + this.location.search + '#' + this.fragment);
         | 
| 1416 | 
            +
                      // Return immediately as browser will do redirect to new url
         | 
| 1417 | 
            +
                      return true;
         | 
| 1418 | 
            +
             | 
| 1419 | 
            +
                    // Or if we've started out with a hash-based route, but we're currently
         | 
| 1420 | 
            +
                    // in a browser where it could be `pushState`-based instead...
         | 
| 1421 | 
            +
                    } else if (this._hasPushState && atRoot && loc.hash) {
         | 
| 1422 | 
            +
                      this.fragment = this.getHash().replace(routeStripper, '');
         | 
| 1423 | 
            +
                      this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
         | 
| 1424 | 
            +
                    }
         | 
| 1408 1425 |  | 
| 1409 | 
            -
                  // Or if we've started out with a hash-based route, but we're currently
         | 
| 1410 | 
            -
                  // in a browser where it could be `pushState`-based instead...
         | 
| 1411 | 
            -
                  } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
         | 
| 1412 | 
            -
                    this.fragment = this.getHash().replace(routeStripper, '');
         | 
| 1413 | 
            -
                    this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
         | 
| 1414 1426 | 
             
                  }
         | 
| 1415 1427 |  | 
| 1416 1428 | 
             
                  if (!this.options.silent) return this.loadUrl();
         | 
| @@ -1439,21 +1451,20 @@ | |
| 1439 1451 | 
             
                  }
         | 
| 1440 1452 | 
             
                  if (current === this.fragment) return false;
         | 
| 1441 1453 | 
             
                  if (this.iframe) this.navigate(current);
         | 
| 1442 | 
            -
                  this.loadUrl() | 
| 1454 | 
            +
                  this.loadUrl();
         | 
| 1443 1455 | 
             
                },
         | 
| 1444 1456 |  | 
| 1445 1457 | 
             
                // Attempt to load the current URL fragment. If a route succeeds with a
         | 
| 1446 1458 | 
             
                // match, returns `true`. If no defined routes matches the fragment,
         | 
| 1447 1459 | 
             
                // returns `false`.
         | 
| 1448 | 
            -
                loadUrl: function( | 
| 1449 | 
            -
                   | 
| 1450 | 
            -
                   | 
| 1460 | 
            +
                loadUrl: function(fragment) {
         | 
| 1461 | 
            +
                  fragment = this.fragment = this.getFragment(fragment);
         | 
| 1462 | 
            +
                  return _.any(this.handlers, function(handler) {
         | 
| 1451 1463 | 
             
                    if (handler.route.test(fragment)) {
         | 
| 1452 1464 | 
             
                      handler.callback(fragment);
         | 
| 1453 1465 | 
             
                      return true;
         | 
| 1454 1466 | 
             
                    }
         | 
| 1455 1467 | 
             
                  });
         | 
| 1456 | 
            -
                  return matched;
         | 
| 1457 1468 | 
             
                },
         | 
| 1458 1469 |  | 
| 1459 1470 | 
             
                // Save a fragment into the hash history, or replace the URL state if the
         | 
| @@ -1465,11 +1476,18 @@ | |
| 1465 1476 | 
             
                // you wish to modify the current URL without adding an entry to the history.
         | 
| 1466 1477 | 
             
                navigate: function(fragment, options) {
         | 
| 1467 1478 | 
             
                  if (!History.started) return false;
         | 
| 1468 | 
            -
                  if (!options || options === true) options = {trigger: options};
         | 
| 1469 | 
            -
             | 
| 1479 | 
            +
                  if (!options || options === true) options = {trigger: !!options};
         | 
| 1480 | 
            +
             | 
| 1481 | 
            +
                  var url = this.root + (fragment = this.getFragment(fragment || ''));
         | 
| 1482 | 
            +
             | 
| 1483 | 
            +
                  // Strip the fragment of the query and hash for matching.
         | 
| 1484 | 
            +
                  fragment = fragment.replace(pathStripper, '');
         | 
| 1485 | 
            +
             | 
| 1470 1486 | 
             
                  if (this.fragment === fragment) return;
         | 
| 1471 1487 | 
             
                  this.fragment = fragment;
         | 
| 1472 | 
            -
             | 
| 1488 | 
            +
             | 
| 1489 | 
            +
                  // Don't include a trailing slash on the root.
         | 
| 1490 | 
            +
                  if (fragment === '' && url !== '/') url = url.slice(0, -1);
         | 
| 1473 1491 |  | 
| 1474 1492 | 
             
                  // If pushState is available, we use it to set the fragment as a real URL.
         | 
| 1475 1493 | 
             
                  if (this._hasPushState) {
         | 
| @@ -1492,7 +1510,7 @@ | |
| 1492 1510 | 
             
                  } else {
         | 
| 1493 1511 | 
             
                    return this.location.assign(url);
         | 
| 1494 1512 | 
             
                  }
         | 
| 1495 | 
            -
                  if (options.trigger) this.loadUrl(fragment);
         | 
| 1513 | 
            +
                  if (options.trigger) return this.loadUrl(fragment);
         | 
| 1496 1514 | 
             
                },
         | 
| 1497 1515 |  | 
| 1498 1516 | 
             
                // Update the hash location, either replacing the current entry, or adding
         | 
| @@ -1560,7 +1578,7 @@ | |
| 1560 1578 | 
             
              };
         | 
| 1561 1579 |  | 
| 1562 1580 | 
             
              // Wrap an optional error callback with a fallback error event.
         | 
| 1563 | 
            -
              var wrapError = function | 
| 1581 | 
            +
              var wrapError = function(model, options) {
         | 
| 1564 1582 | 
             
                var error = options.error;
         | 
| 1565 1583 | 
             
                options.error = function(resp) {
         | 
| 1566 1584 | 
             
                  if (error) error(model, resp, options);
         | 
| @@ -1568,4 +1586,6 @@ | |
| 1568 1586 | 
             
                };
         | 
| 1569 1587 | 
             
              };
         | 
| 1570 1588 |  | 
| 1571 | 
            -
             | 
| 1589 | 
            +
              return Backbone;
         | 
| 1590 | 
            +
             | 
| 1591 | 
            +
            }));
         |