~openerp-dev/openerp-web/trunk-jquery1.9-ppa

« back to all changes in this revision

Viewing changes to addons/web/static/lib/backbone/backbone.js

  • Committer: Prashant Panchal(OpenERP)
  • Date: 2014-04-16 09:24:51 UTC
  • Revision ID: ppa@tinyerp.com-20140416092451-outv36dahgip1860
[IMP] add jquery-migrate-1.1.1.j & jquery-1.9.1.js & change in web

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1603
    };
1579
1604
  };
1580
1605
 
1581
 
}).call(this);
 
1606
  return Backbone;
 
1607
 
 
1608
}));