backbone_extensions 0.0.25 → 0.0.26

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59d7036f3b251e916af7c8d9227a294fce060026
4
- data.tar.gz: a9332784311a470d1ced7ca2a09d7d932c413ed4
3
+ metadata.gz: 41065848bcb6d0904170efdcf9d0ab594e139a5b
4
+ data.tar.gz: c57e5fbe5d6dd6483fe8e9505058f0cf9359dd0d
5
5
  SHA512:
6
- metadata.gz: f77b11283eb53eaa567711fc58f1be9b60130f1e2b758ceec7af718cd353bfee61aaca940d9d5c4156bfffd17fb5eb3a647542e3186d3762276b9b6255efef35
7
- data.tar.gz: e251d0ec44dca77ddcdb463cd9889b1e8a0331457335010acad5a47cadeaac3d4bd7d29b8461c5c31c3d87653f9473016f200be60691b0d516f40a0213db0d98
6
+ metadata.gz: b58476dad803260f8f93c4cd335d07f4ba61057a02fb61dfab32981e97569ed55bf49b861acfe28b101edbc8df461867594762a1a463a2839be9a8057b748865
7
+ data.tar.gz: fce7ee30b61fbb97601ff7b6e30f2f2479c8da2bd08a7334ee09be1bb811f0dea105969049b6bdb56f7f8a20ca228b52b702885c05eddcebbd7d8988780181fd
@@ -1,20 +1,35 @@
1
- // Backbone.js 1.1.0
1
+ // Backbone.js 1.1.2
2
2
 
3
- // (c) 2010-2011 Jeremy Ashkenas, DocumentCloud Inc.
4
- // (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
3
+ // (c) 2010-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
5
4
  // Backbone may be freely distributed under the MIT license.
6
5
  // For all details and documentation:
7
6
  // http://backbonejs.org
8
7
 
9
- (function(){
8
+ (function(root, factory) {
9
+
10
+ // Set up Backbone appropriately for the environment. Start with AMD.
11
+ if (typeof define === 'function' && define.amd) {
12
+ define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
13
+ // Export global even in AMD case in case this script is loaded with
14
+ // others that may still expect a global Backbone.
15
+ root.Backbone = factory(root, exports, _, $);
16
+ });
17
+
18
+ // Next for Node.js or CommonJS. jQuery may not be needed as a module.
19
+ } else if (typeof exports !== 'undefined') {
20
+ var _ = require('underscore');
21
+ factory(root, exports, _);
22
+
23
+ // Finally, as a browser global.
24
+ } else {
25
+ root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
26
+ }
27
+
28
+ }(this, function(root, Backbone, _, $) {
10
29
 
11
30
  // Initial Setup
12
31
  // -------------
13
32
 
14
- // Save a reference to the global object (`window` in the browser, `exports`
15
- // on the server).
16
- var root = this;
17
-
18
33
  // Save the previous value of the `Backbone` variable, so that it can be
19
34
  // restored later on, if `noConflict` is used.
20
35
  var previousBackbone = root.Backbone;
@@ -25,25 +40,12 @@
25
40
  var slice = array.slice;
26
41
  var splice = array.splice;
27
42
 
28
- // The top-level namespace. All public Backbone classes and modules will
29
- // be attached to this. Exported for both the browser and the server.
30
- var Backbone;
31
- if (typeof exports !== 'undefined') {
32
- Backbone = exports;
33
- } else {
34
- Backbone = root.Backbone = {};
35
- }
36
-
37
43
  // Current version of the library. Keep in sync with `package.json`.
38
- Backbone.VERSION = '1.1.0';
39
-
40
- // Require Underscore, if we're on the server, and it's not already present.
41
- var _ = root._;
42
- if (!_ && (typeof require !== 'undefined')) _ = require('underscore');
44
+ Backbone.VERSION = '1.1.2';
43
45
 
44
46
  // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
45
47
  // the `$` variable.
46
- Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$;
48
+ Backbone.$ = $;
47
49
 
48
50
  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
49
51
  // to its previous owner. Returns a reference to this Backbone object.
@@ -109,7 +111,7 @@
109
111
  var retain, ev, events, names, i, l, j, k;
110
112
  if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
111
113
  if (!name && !callback && !context) {
112
- this._events = {};
114
+ this._events = void 0;
113
115
  return this;
114
116
  }
115
117
  names = name ? [name] : _.keys(this._events);
@@ -205,7 +207,7 @@
205
207
  case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
206
208
  case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
207
209
  case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
208
- default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
210
+ default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
209
211
  }
210
212
  };
211
213
 
@@ -350,7 +352,7 @@
350
352
 
351
353
  // Trigger all relevant attribute changes.
352
354
  if (!silent) {
353
- if (changes.length) this._pending = true;
355
+ if (changes.length) this._pending = options;
354
356
  for (var i = 0, l = changes.length; i < l; i++) {
355
357
  this.trigger('change:' + changes[i], this, current[changes[i]], options);
356
358
  }
@@ -361,6 +363,7 @@
361
363
  if (changing) return this;
362
364
  if (!silent) {
363
365
  while (this._pending) {
366
+ options = this._pending;
364
367
  this._pending = false;
365
368
  this.trigger('change', this, options);
366
369
  }
@@ -528,9 +531,12 @@
528
531
  // using Backbone's restful methods, override this to change the endpoint
529
532
  // that will be called.
530
533
  url: function() {
531
- var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError();
534
+ var base =
535
+ _.result(this, 'urlRoot') ||
536
+ _.result(this.collection, 'url') ||
537
+ urlError();
532
538
  if (this.isNew()) return base;
533
- return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id);
539
+ return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
534
540
  },
535
541
 
536
542
  // **parse** converts a response into the hash of attributes to be `set` on
@@ -546,7 +552,7 @@
546
552
 
547
553
  // A model is new if it has never been saved to the server, and lacks an id.
548
554
  isNew: function() {
549
- return this.id == null;
555
+ return !this.has(this.idAttribute);
550
556
  },
551
557
 
552
558
  // Check if the model is currently in a valid state.
@@ -650,7 +656,7 @@
650
656
  options.index = index;
651
657
  model.trigger('remove', model, this, options);
652
658
  }
653
- this._removeReference(model);
659
+ this._removeReference(model, options);
654
660
  }
655
661
  return singular ? models[0] : models;
656
662
  },
@@ -676,11 +682,11 @@
676
682
  // Turn bare objects into model references, and prevent invalid models
677
683
  // from being added.
678
684
  for (i = 0, l = models.length; i < l; i++) {
679
- attrs = models[i];
685
+ attrs = models[i] || {};
680
686
  if (attrs instanceof Model) {
681
687
  id = model = attrs;
682
688
  } else {
683
- id = attrs[targetModel.prototype.idAttribute];
689
+ id = attrs[targetModel.prototype.idAttribute || 'id'];
684
690
  }
685
691
 
686
692
  // If a duplicate is found, prevent it from being added and
@@ -700,14 +706,13 @@
700
706
  model = models[i] = this._prepareModel(attrs, options);
701
707
  if (!model) continue;
702
708
  toAdd.push(model);
703
-
704
- // Listen to added models' events, and index models for lookup by
705
- // `id` and by `cid`.
706
- model.on('all', this._onModelEvent, this);
707
- this._byId[model.cid] = model;
708
- if (model.id != null) this._byId[model.id] = model;
709
+ this._addReference(model, options);
709
710
  }
710
- if (order) order.push(existing || model);
711
+
712
+ // Do not add multiple models with the same `id`.
713
+ model = existing || model;
714
+ if (order && (model.isNew() || !modelMap[model.id])) order.push(model);
715
+ modelMap[model.id] = true;
711
716
  }
712
717
 
713
718
  // Remove nonexistent models if appropriate.
@@ -745,7 +750,7 @@
745
750
  }
746
751
  if (sort || (order && order.length)) this.trigger('sort', this, options);
747
752
  }
748
-
753
+
749
754
  // Return the added (or merged) model (or models).
750
755
  return singular ? models[0] : models;
751
756
  },
@@ -757,7 +762,7 @@
757
762
  reset: function(models, options) {
758
763
  options || (options = {});
759
764
  for (var i = 0, l = this.models.length; i < l; i++) {
760
- this._removeReference(this.models[i]);
765
+ this._removeReference(this.models[i], options);
761
766
  }
762
767
  options.previousModels = this.models;
763
768
  this._reset();
@@ -798,7 +803,7 @@
798
803
  // Get a model from the set by id.
799
804
  get: function(obj) {
800
805
  if (obj == null) return void 0;
801
- return this._byId[obj.id] || this._byId[obj.cid] || this._byId[obj];
806
+ return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
802
807
  },
803
808
 
804
809
  // Get the model at the given index.
@@ -874,7 +879,7 @@
874
879
  if (!options.wait) this.add(model, options);
875
880
  var collection = this;
876
881
  var success = options.success;
877
- options.success = function(model, resp, options) {
882
+ options.success = function(model, resp) {
878
883
  if (options.wait) collection.add(model, options);
879
884
  if (success) success(model, resp, options);
880
885
  };
@@ -904,10 +909,7 @@
904
909
  // Prepare a hash of attributes (or other model) to be added to this
905
910
  // collection.
906
911
  _prepareModel: function(attrs, options) {
907
- if (attrs instanceof Model) {
908
- if (!attrs.collection) attrs.collection = this;
909
- return attrs;
910
- }
912
+ if (attrs instanceof Model) return attrs;
911
913
  options = options ? _.clone(options) : {};
912
914
  options.collection = this;
913
915
  var model = new this.model(attrs, options);
@@ -916,8 +918,16 @@
916
918
  return false;
917
919
  },
918
920
 
921
+ // Internal method to create a model's ties to a collection.
922
+ _addReference: function(model, options) {
923
+ this._byId[model.cid] = model;
924
+ if (model.id != null) this._byId[model.id] = model;
925
+ if (!model.collection) model.collection = this;
926
+ model.on('all', this._onModelEvent, this);
927
+ },
928
+
919
929
  // Internal method to sever a model's ties to a collection.
920
- _removeReference: function(model) {
930
+ _removeReference: function(model, options) {
921
931
  if (this === model.collection) delete model.collection;
922
932
  model.off('all', this._onModelEvent, this);
923
933
  },
@@ -946,7 +956,7 @@
946
956
  'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
947
957
  'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
948
958
  'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
949
- 'lastIndexOf', 'isEmpty', 'chain'];
959
+ 'lastIndexOf', 'isEmpty', 'chain', 'sample'];
950
960
 
951
961
  // Mix in each Underscore method as a proxy to `Collection#models`.
952
962
  _.each(methods, function(method) {
@@ -958,7 +968,7 @@
958
968
  });
959
969
 
960
970
  // Underscore methods that take a property name as an argument.
961
- var attributeMethods = ['groupBy', 'countBy', 'sortBy'];
971
+ var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
962
972
 
963
973
  // Use attributes instead of properties.
964
974
  _.each(attributeMethods, function(method) {
@@ -1180,7 +1190,9 @@
1180
1190
  return xhr;
1181
1191
  };
1182
1192
 
1183
- var noXhrPatch = typeof window !== 'undefined' && !!window.ActiveXObject && !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
1193
+ var noXhrPatch =
1194
+ typeof window !== 'undefined' && !!window.ActiveXObject &&
1195
+ !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
1184
1196
 
1185
1197
  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
1186
1198
  var methodMap = {
@@ -1239,7 +1251,7 @@
1239
1251
  var router = this;
1240
1252
  Backbone.history.route(route, function(fragment) {
1241
1253
  var args = router._extractParameters(route, fragment);
1242
- callback && callback.apply(router, args);
1254
+ router.execute(callback, args);
1243
1255
  router.trigger.apply(router, ['route:' + name].concat(args));
1244
1256
  router.trigger('route', name, args);
1245
1257
  Backbone.history.trigger('route', router, name, args);
@@ -1247,6 +1259,12 @@
1247
1259
  return this;
1248
1260
  },
1249
1261
 
1262
+ // Execute a route handler with the provided parameters. This is an
1263
+ // excellent place to do pre-route setup or post-route cleanup.
1264
+ execute: function(callback, args) {
1265
+ if (callback) callback.apply(this, args);
1266
+ },
1267
+
1250
1268
  // Simple proxy to `Backbone.history` to save a fragment into the history.
1251
1269
  navigate: function(fragment, options) {
1252
1270
  Backbone.history.navigate(fragment, options);
@@ -1271,10 +1289,10 @@
1271
1289
  route = route.replace(escapeRegExp, '\\$&')
1272
1290
  .replace(optionalParam, '(?:$1)?')
1273
1291
  .replace(namedParam, function(match, optional) {
1274
- return optional ? match : '([^\/]+)';
1292
+ return optional ? match : '([^/?]+)';
1275
1293
  })
1276
- .replace(splatParam, '(.*?)');
1277
- return new RegExp('^' + route + '$');
1294
+ .replace(splatParam, '([^?]*?)');
1295
+ return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
1278
1296
  },
1279
1297
 
1280
1298
  // Given a route, and a URL fragment that it matches, return the array of
@@ -1282,7 +1300,9 @@
1282
1300
  // treated as `null` to normalize cross-browser behavior.
1283
1301
  _extractParameters: function(route, fragment) {
1284
1302
  var params = route.exec(fragment).slice(1);
1285
- return _.map(params, function(param) {
1303
+ return _.map(params, function(param, i) {
1304
+ // Don't decode the search params.
1305
+ if (i === params.length - 1) return param || null;
1286
1306
  return param ? decodeURIComponent(param) : null;
1287
1307
  });
1288
1308
  }
@@ -1320,8 +1340,8 @@
1320
1340
  // Cached regex for removing a trailing slash.
1321
1341
  var trailingSlash = /\/$/;
1322
1342
 
1323
- // Cached regex for stripping urls of hash and query.
1324
- var pathStripper = /[?#].*$/;
1343
+ // Cached regex for stripping urls of hash.
1344
+ var pathStripper = /#.*$/;
1325
1345
 
1326
1346
  // Has the history handling already been started?
1327
1347
  History.started = false;
@@ -1333,6 +1353,11 @@
1333
1353
  // twenty times a second.
1334
1354
  interval: 50,
1335
1355
 
1356
+ // Are we at the app root?
1357
+ atRoot: function() {
1358
+ return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root;
1359
+ },
1360
+
1336
1361
  // Gets the true hash value. Cannot use location.hash directly due to bug
1337
1362
  // in Firefox where location.hash will always be decoded.
1338
1363
  getHash: function(window) {
@@ -1345,7 +1370,7 @@
1345
1370
  getFragment: function(fragment, forcePushState) {
1346
1371
  if (fragment == null) {
1347
1372
  if (this._hasPushState || !this._wantsHashChange || forcePushState) {
1348
- fragment = this.location.pathname;
1373
+ fragment = decodeURI(this.location.pathname + this.location.search);
1349
1374
  var root = this.root.replace(trailingSlash, '');
1350
1375
  if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
1351
1376
  } else {
@@ -1376,7 +1401,8 @@
1376
1401
  this.root = ('/' + this.root + '/').replace(rootStripper, '/');
1377
1402
 
1378
1403
  if (oldIE && this._wantsHashChange) {
1379
- this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
1404
+ var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');
1405
+ this.iframe = frame.hide().appendTo('body')[0].contentWindow;
1380
1406
  this.navigate(fragment);
1381
1407
  }
1382
1408
 
@@ -1394,7 +1420,6 @@
1394
1420
  // opened by a non-pushState browser.
1395
1421
  this.fragment = fragment;
1396
1422
  var loc = this.location;
1397
- var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root;
1398
1423
 
1399
1424
  // Transition from hashChange to pushState or vice versa if both are
1400
1425
  // requested.
@@ -1402,17 +1427,17 @@
1402
1427
 
1403
1428
  // If we've started off with a route from a `pushState`-enabled
1404
1429
  // browser, but we're currently in a browser that doesn't support it...
1405
- if (!this._hasPushState && !atRoot) {
1430
+ if (!this._hasPushState && !this.atRoot()) {
1406
1431
  this.fragment = this.getFragment(null, true);
1407
- this.location.replace(this.root + this.location.search + '#' + this.fragment);
1432
+ this.location.replace(this.root + '#' + this.fragment);
1408
1433
  // Return immediately as browser will do redirect to new url
1409
1434
  return true;
1410
1435
 
1411
1436
  // Or if we've started out with a hash-based route, but we're currently
1412
1437
  // in a browser where it could be `pushState`-based instead...
1413
- } else if (this._hasPushState && atRoot && loc.hash) {
1438
+ } else if (this._hasPushState && this.atRoot() && loc.hash) {
1414
1439
  this.fragment = this.getHash().replace(routeStripper, '');
1415
- this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
1440
+ this.history.replaceState({}, document.title, this.root + this.fragment);
1416
1441
  }
1417
1442
 
1418
1443
  }
@@ -1424,7 +1449,7 @@
1424
1449
  // but possibly useful for unit testing Routers.
1425
1450
  stop: function() {
1426
1451
  Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl);
1427
- clearInterval(this._checkUrlInterval);
1452
+ if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
1428
1453
  History.started = false;
1429
1454
  },
1430
1455
 
@@ -1472,7 +1497,7 @@
1472
1497
 
1473
1498
  var url = this.root + (fragment = this.getFragment(fragment || ''));
1474
1499
 
1475
- // Strip the fragment of the query and hash for matching.
1500
+ // Strip the hash for matching.
1476
1501
  fragment = fragment.replace(pathStripper, '');
1477
1502
 
1478
1503
  if (this.fragment === fragment) return;
@@ -1578,4 +1603,6 @@
1578
1603
  };
1579
1604
  };
1580
1605
 
1581
- }).call(this);
1606
+ return Backbone;
1607
+
1608
+ }));
@@ -1,3 +1,3 @@
1
1
  module BackboneExtensions
2
- VERSION = '0.0.25'
2
+ VERSION = '0.0.26'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backbone_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.25
4
+ version: 0.0.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Dy
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-26 00:00:00.000000000 Z
12
+ date: 2014-02-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fuubar