Changeset 36546
- Timestamp:
- 02/17/2016 03:21:09 PM (9 years ago)
- Location:
- trunk/src
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/js/customize-widgets.js
r36522 r36546 664 664 _setupReorderUI: function() { 665 665 var self = this, selectSidebarItem, $moveWidgetArea, 666 $reorderNav, updateAvailableSidebars ;666 $reorderNav, updateAvailableSidebars, template; 667 667 668 668 /** … … 682 682 */ 683 683 this.container.find( '.widget-title-action' ).after( $( api.Widgets.data.tpl.widgetReorderNav ) ); 684 $moveWidgetArea = $( 685 _.template( api.Widgets.data.tpl.moveWidgetArea, { 684 685 686 template = _.template( api.Widgets.data.tpl.moveWidgetArea ); 687 $moveWidgetArea = $( template( { 686 688 sidebars: _( api.Widgets.registeredSidebars.toArray() ).pluck( 'attributes' ) 687 689 } ) -
trunk/src/wp-includes/js/backbone.js
r31471 r36546 1 // Backbone.js 1. 1.22 3 // (c) 2010-201 4Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors1 // Backbone.js 1.2.3 2 3 // (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 4 // Backbone may be freely distributed under the MIT license. 5 5 // For all details and documentation: 6 6 // http://backbonejs.org 7 7 8 (function(root, factory) { 8 (function(factory) { 9 10 // Establish the root object, `window` (`self`) in the browser, or `global` on the server. 11 // We use `self` instead of `window` for `WebWorker` support. 12 var root = (typeof self == 'object' && self.self == self && self) || 13 (typeof global == 'object' && global.global == global && global); 9 14 10 15 // Set up Backbone appropriately for the environment. Start with AMD. … … 18 23 // Next for Node.js or CommonJS. jQuery may not be needed as a module. 19 24 } else if (typeof exports !== 'undefined') { 20 var _ = require('underscore'); 21 factory(root, exports, _); 25 var _ = require('underscore'), $; 26 try { $ = require('jquery'); } catch(e) {} 27 factory(root, exports, _, $); 22 28 23 29 // Finally, as a browser global. … … 26 32 } 27 33 28 }( this,function(root, Backbone, _, $) {34 }(function(root, Backbone, _, $) { 29 35 30 36 // Initial Setup … … 35 41 var previousBackbone = root.Backbone; 36 42 37 // Create local references to array methods we'll want to use later. 38 var array = []; 39 var push = array.push; 40 var slice = array.slice; 41 var splice = array.splice; 43 // Create a local reference to a common array method we'll want to use later. 44 var slice = Array.prototype.slice; 42 45 43 46 // Current version of the library. Keep in sync with `package.json`. 44 Backbone.VERSION = '1. 1.2';47 Backbone.VERSION = '1.2.3'; 45 48 46 49 // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns … … 61 64 62 65 // Turn on `emulateJSON` to support legacy servers that can't deal with direct 63 // `application/json` requests ... will encode the body as66 // `application/json` requests ... this will encode the body as 64 67 // `application/x-www-form-urlencoded` instead and will send the model in a 65 68 // form param named `model`. 66 69 Backbone.emulateJSON = false; 67 70 71 // Proxy Backbone class methods to Underscore functions, wrapping the model's 72 // `attributes` object or collection's `models` array behind the scenes. 73 // 74 // collection.filter(function(model) { return model.get('age') > 10 }); 75 // collection.each(this.addView); 76 // 77 // `Function#apply` can be slow so we use the method's arg count, if we know it. 78 var addMethod = function(length, method, attribute) { 79 switch (length) { 80 case 1: return function() { 81 return _[method](this[attribute]); 82 }; 83 case 2: return function(value) { 84 return _[method](this[attribute], value); 85 }; 86 case 3: return function(iteratee, context) { 87 return _[method](this[attribute], cb(iteratee, this), context); 88 }; 89 case 4: return function(iteratee, defaultVal, context) { 90 return _[method](this[attribute], cb(iteratee, this), defaultVal, context); 91 }; 92 default: return function() { 93 var args = slice.call(arguments); 94 args.unshift(this[attribute]); 95 return _[method].apply(_, args); 96 }; 97 } 98 }; 99 var addUnderscoreMethods = function(Class, methods, attribute) { 100 _.each(methods, function(length, method) { 101 if (_[method]) Class.prototype[method] = addMethod(length, method, attribute); 102 }); 103 }; 104 105 // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`. 106 var cb = function(iteratee, instance) { 107 if (_.isFunction(iteratee)) return iteratee; 108 if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee); 109 if (_.isString(iteratee)) return function(model) { return model.get(iteratee); }; 110 return iteratee; 111 }; 112 var modelMatcher = function(attrs) { 113 var matcher = _.matches(attrs); 114 return function(model) { 115 return matcher(model.attributes); 116 }; 117 }; 118 68 119 // Backbone.Events 69 120 // --------------- 70 121 71 122 // A module that can be mixed in to *any object* in order to provide it with 72 // custom events. You may bind with `on` or remove with `off` callback73 // functions to an event; `trigger`-ing an event fires all callbacks in123 // a custom event channel. You may bind a callback to an event with `on` or 124 // remove with `off`; `trigger`-ing an event fires all callbacks in 74 125 // succession. 75 126 // … … 79 130 // object.trigger('expand'); 80 131 // 81 var Events = Backbone.Events = { 82 83 // Bind an event to a `callback` function. Passing `"all"` will bind 84 // the callback to all events fired. 85 on: function(name, callback, context) { 86 if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; 87 this._events || (this._events = {}); 88 var events = this._events[name] || (this._events[name] = []); 89 events.push({callback: callback, context: context, ctx: context || this}); 90 return this; 91 }, 92 93 // Bind an event to only be triggered a single time. After the first time 94 // the callback is invoked, it will be removed. 95 once: function(name, callback, context) { 96 if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; 97 var self = this; 98 var once = _.once(function() { 99 self.off(name, once); 132 var Events = Backbone.Events = {}; 133 134 // Regular expression used to split event strings. 135 var eventSplitter = /\s+/; 136 137 // Iterates over the standard `event, callback` (as well as the fancy multiple 138 // space-separated events `"change blur", callback` and jQuery-style event 139 // maps `{event: callback}`). 140 var eventsApi = function(iteratee, events, name, callback, opts) { 141 var i = 0, names; 142 if (name && typeof name === 'object') { 143 // Handle event maps. 144 if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback; 145 for (names = _.keys(name); i < names.length ; i++) { 146 events = eventsApi(iteratee, events, names[i], name[names[i]], opts); 147 } 148 } else if (name && eventSplitter.test(name)) { 149 // Handle space separated event names by delegating them individually. 150 for (names = name.split(eventSplitter); i < names.length; i++) { 151 events = iteratee(events, names[i], callback, opts); 152 } 153 } else { 154 // Finally, standard events. 155 events = iteratee(events, name, callback, opts); 156 } 157 return events; 158 }; 159 160 // Bind an event to a `callback` function. Passing `"all"` will bind 161 // the callback to all events fired. 162 Events.on = function(name, callback, context) { 163 return internalOn(this, name, callback, context); 164 }; 165 166 // Guard the `listening` argument from the public API. 167 var internalOn = function(obj, name, callback, context, listening) { 168 obj._events = eventsApi(onApi, obj._events || {}, name, callback, { 169 context: context, 170 ctx: obj, 171 listening: listening 172 }); 173 174 if (listening) { 175 var listeners = obj._listeners || (obj._listeners = {}); 176 listeners[listening.id] = listening; 177 } 178 179 return obj; 180 }; 181 182 // Inversion-of-control versions of `on`. Tell *this* object to listen to 183 // an event in another object... keeping track of what it's listening to 184 // for easier unbinding later. 185 Events.listenTo = function(obj, name, callback) { 186 if (!obj) return this; 187 var id = obj._listenId || (obj._listenId = _.uniqueId('l')); 188 var listeningTo = this._listeningTo || (this._listeningTo = {}); 189 var listening = listeningTo[id]; 190 191 // This object is not listening to any other events on `obj` yet. 192 // Setup the necessary references to track the listening callbacks. 193 if (!listening) { 194 var thisId = this._listenId || (this._listenId = _.uniqueId('l')); 195 listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0}; 196 } 197 198 // Bind callbacks on obj, and keep track of them on listening. 199 internalOn(obj, name, callback, this, listening); 200 return this; 201 }; 202 203 // The reducing API that adds a callback to the `events` object. 204 var onApi = function(events, name, callback, options) { 205 if (callback) { 206 var handlers = events[name] || (events[name] = []); 207 var context = options.context, ctx = options.ctx, listening = options.listening; 208 if (listening) listening.count++; 209 210 handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening }); 211 } 212 return events; 213 }; 214 215 // Remove one or many callbacks. If `context` is null, removes all 216 // callbacks with that function. If `callback` is null, removes all 217 // callbacks for the event. If `name` is null, removes all bound 218 // callbacks for all events. 219 Events.off = function(name, callback, context) { 220 if (!this._events) return this; 221 this._events = eventsApi(offApi, this._events, name, callback, { 222 context: context, 223 listeners: this._listeners 224 }); 225 return this; 226 }; 227 228 // Tell this object to stop listening to either specific events ... or 229 // to every object it's currently listening to. 230 Events.stopListening = function(obj, name, callback) { 231 var listeningTo = this._listeningTo; 232 if (!listeningTo) return this; 233 234 var ids = obj ? [obj._listenId] : _.keys(listeningTo); 235 236 for (var i = 0; i < ids.length; i++) { 237 var listening = listeningTo[ids[i]]; 238 239 // If listening doesn't exist, this object is not currently 240 // listening to obj. Break out early. 241 if (!listening) break; 242 243 listening.obj.off(name, callback, this); 244 } 245 if (_.isEmpty(listeningTo)) this._listeningTo = void 0; 246 247 return this; 248 }; 249 250 // The reducing API that removes a callback from the `events` object. 251 var offApi = function(events, name, callback, options) { 252 if (!events) return; 253 254 var i = 0, listening; 255 var context = options.context, listeners = options.listeners; 256 257 // Delete all events listeners and "drop" events. 258 if (!name && !callback && !context) { 259 var ids = _.keys(listeners); 260 for (; i < ids.length; i++) { 261 listening = listeners[ids[i]]; 262 delete listeners[listening.id]; 263 delete listening.listeningTo[listening.objId]; 264 } 265 return; 266 } 267 268 var names = name ? [name] : _.keys(events); 269 for (; i < names.length; i++) { 270 name = names[i]; 271 var handlers = events[name]; 272 273 // Bail out if there are no events stored. 274 if (!handlers) break; 275 276 // Replace events if there are any remaining. Otherwise, clean up. 277 var remaining = []; 278 for (var j = 0; j < handlers.length; j++) { 279 var handler = handlers[j]; 280 if ( 281 callback && callback !== handler.callback && 282 callback !== handler.callback._callback || 283 context && context !== handler.context 284 ) { 285 remaining.push(handler); 286 } else { 287 listening = handler.listening; 288 if (listening && --listening.count === 0) { 289 delete listeners[listening.id]; 290 delete listening.listeningTo[listening.objId]; 291 } 292 } 293 } 294 295 // Update tail event if the list has any events. Otherwise, clean up. 296 if (remaining.length) { 297 events[name] = remaining; 298 } else { 299 delete events[name]; 300 } 301 } 302 if (_.size(events)) return events; 303 }; 304 305 // Bind an event to only be triggered a single time. After the first time 306 // the callback is invoked, its listener will be removed. If multiple events 307 // are passed in using the space-separated syntax, the handler will fire 308 // once for each event, not once for a combination of all events. 309 Events.once = function(name, callback, context) { 310 // Map the event into a `{event: once}` object. 311 var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this)); 312 return this.on(events, void 0, context); 313 }; 314 315 // Inversion-of-control versions of `once`. 316 Events.listenToOnce = function(obj, name, callback) { 317 // Map the event into a `{event: once}` object. 318 var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj)); 319 return this.listenTo(obj, events); 320 }; 321 322 // Reduces the event callbacks into a map of `{event: onceWrapper}`. 323 // `offer` unbinds the `onceWrapper` after it has been called. 324 var onceMap = function(map, name, callback, offer) { 325 if (callback) { 326 var once = map[name] = _.once(function() { 327 offer(name, once); 100 328 callback.apply(this, arguments); 101 329 }); 102 330 once._callback = callback; 103 return this.on(name, once, context); 104 }, 105 106 // Remove one or many callbacks. If `context` is null, removes all 107 // callbacks with that function. If `callback` is null, removes all 108 // callbacks for the event. If `name` is null, removes all bound 109 // callbacks for all events. 110 off: function(name, callback, context) { 111 var retain, ev, events, names, i, l, j, k; 112 if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; 113 if (!name && !callback && !context) { 114 this._events = void 0; 115 return this; 116 } 117 names = name ? [name] : _.keys(this._events); 118 for (i = 0, l = names.length; i < l; i++) { 119 name = names[i]; 120 if (events = this._events[name]) { 121 this._events[name] = retain = []; 122 if (callback || context) { 123 for (j = 0, k = events.length; j < k; j++) { 124 ev = events[j]; 125 if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || 126 (context && context !== ev.context)) { 127 retain.push(ev); 128 } 129 } 130 } 131 if (!retain.length) delete this._events[name]; 132 } 133 } 134 135 return this; 136 }, 137 138 // Trigger one or many events, firing all bound callbacks. Callbacks are 139 // passed the same arguments as `trigger` is, apart from the event name 140 // (unless you're listening on `"all"`, which will cause your callback to 141 // receive the true name of the event as the first argument). 142 trigger: function(name) { 143 if (!this._events) return this; 144 var args = slice.call(arguments, 1); 145 if (!eventsApi(this, 'trigger', name, args)) return this; 146 var events = this._events[name]; 147 var allEvents = this._events.all; 331 } 332 return map; 333 }; 334 335 // Trigger one or many events, firing all bound callbacks. Callbacks are 336 // passed the same arguments as `trigger` is, apart from the event name 337 // (unless you're listening on `"all"`, which will cause your callback to 338 // receive the true name of the event as the first argument). 339 Events.trigger = function(name) { 340 if (!this._events) return this; 341 342 var length = Math.max(0, arguments.length - 1); 343 var args = Array(length); 344 for (var i = 0; i < length; i++) args[i] = arguments[i + 1]; 345 346 eventsApi(triggerApi, this._events, name, void 0, args); 347 return this; 348 }; 349 350 // Handles triggering the appropriate event callbacks. 351 var triggerApi = function(objEvents, name, cb, args) { 352 if (objEvents) { 353 var events = objEvents[name]; 354 var allEvents = objEvents.all; 355 if (events && allEvents) allEvents = allEvents.slice(); 148 356 if (events) triggerEvents(events, args); 149 if (allEvents) triggerEvents(allEvents, arguments); 150 return this; 151 }, 152 153 // Tell this object to stop listening to either specific events ... or 154 // to every object it's currently listening to. 155 stopListening: function(obj, name, callback) { 156 var listeningTo = this._listeningTo; 157 if (!listeningTo) return this; 158 var remove = !name && !callback; 159 if (!callback && typeof name === 'object') callback = this; 160 if (obj) (listeningTo = {})[obj._listenId] = obj; 161 for (var id in listeningTo) { 162 obj = listeningTo[id]; 163 obj.off(name, callback, this); 164 if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id]; 165 } 166 return this; 167 } 168 169 }; 170 171 // Regular expression used to split event strings. 172 var eventSplitter = /\s+/; 173 174 // Implement fancy features of the Events API such as multiple event 175 // names `"change blur"` and jQuery-style event maps `{change: action}` 176 // in terms of the existing API. 177 var eventsApi = function(obj, action, name, rest) { 178 if (!name) return true; 179 180 // Handle event maps. 181 if (typeof name === 'object') { 182 for (var key in name) { 183 obj[action].apply(obj, [key, name[key]].concat(rest)); 184 } 185 return false; 186 } 187 188 // Handle space separated event names. 189 if (eventSplitter.test(name)) { 190 var names = name.split(eventSplitter); 191 for (var i = 0, l = names.length; i < l; i++) { 192 obj[action].apply(obj, [names[i]].concat(rest)); 193 } 194 return false; 195 } 196 197 return true; 357 if (allEvents) triggerEvents(allEvents, [name].concat(args)); 358 } 359 return objEvents; 198 360 }; 199 361 … … 212 374 }; 213 375 214 var listenMethods = {listenTo: 'on', listenToOnce: 'once'};215 216 // Inversion-of-control versions of `on` and `once`. Tell *this* object to217 // listen to an event in another object ... keeping track of what it's218 // listening to.219 _.each(listenMethods, function(implementation, method) {220 Events[method] = function(obj, name, callback) {221 var listeningTo = this._listeningTo || (this._listeningTo = {});222 var id = obj._listenId || (obj._listenId = _.uniqueId('l'));223 listeningTo[id] = obj;224 if (!callback && typeof name === 'object') callback = this;225 obj[implementation](name, callback, this);226 return this;227 };228 });229 230 376 // Aliases for backwards compatibility. 231 377 Events.bind = Events.on; … … 249 395 var attrs = attributes || {}; 250 396 options || (options = {}); 251 this.cid = _.uniqueId( 'c');397 this.cid = _.uniqueId(this.cidPrefix); 252 398 this.attributes = {}; 253 399 if (options.collection) this.collection = options.collection; … … 272 418 idAttribute: 'id', 273 419 420 // The prefix is used to create the client id which is used to identify models locally. 421 // You may want to override this if you're experiencing name clashes with model ids. 422 cidPrefix: 'c', 423 274 424 // Initialize is an empty function by default. Override it with your own 275 425 // initialization logic. … … 303 453 }, 304 454 455 // Special-cased proxy to underscore's `_.matches` method. 456 matches: function(attrs) { 457 return !!_.iteratee(attrs, this)(this.attributes); 458 }, 459 305 460 // Set a hash of model attributes on the object, firing `"change"`. This is 306 461 // the core primitive operation of a model, updating the data and notifying 307 462 // anyone who needs to know about the change in state. The heart of the beast. 308 463 set: function(key, val, options) { 309 var attr, attrs, unset, changes, silent, changing, prev, current;310 464 if (key == null) return this; 311 465 312 466 // Handle both `"key", value` and `{key: value}` -style arguments. 467 var attrs; 313 468 if (typeof key === 'object') { 314 469 attrs = key; … … 324 479 325 480 // Extract attributes and options. 326 unset= options.unset;327 silent= options.silent;328 changes= [];329 changing= this._changing;330 this._changing 481 var unset = options.unset; 482 var silent = options.silent; 483 var changes = []; 484 var changing = this._changing; 485 this._changing = true; 331 486 332 487 if (!changing) { … … 334 489 this.changed = {}; 335 490 } 336 current = this.attributes, prev = this._previousAttributes; 337 338 // Check for changes of `id`.339 if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];491 492 var current = this.attributes; 493 var changed = this.changed; 494 var prev = this._previousAttributes; 340 495 341 496 // For each `set` attribute, update or delete the current value. 342 for ( attr in attrs) {497 for (var attr in attrs) { 343 498 val = attrs[attr]; 344 499 if (!_.isEqual(current[attr], val)) changes.push(attr); 345 500 if (!_.isEqual(prev[attr], val)) { 346 this.changed[attr] = val;501 changed[attr] = val; 347 502 } else { 348 delete this.changed[attr];503 delete changed[attr]; 349 504 } 350 505 unset ? delete current[attr] : current[attr] = val; 351 506 } 507 508 // Update the `id`. 509 this.id = this.get(this.idAttribute); 352 510 353 511 // Trigger all relevant attribute changes. 354 512 if (!silent) { 355 513 if (changes.length) this._pending = options; 356 for (var i = 0 , l = changes.length; i < l; i++) {514 for (var i = 0; i < changes.length; i++) { 357 515 this.trigger('change:' + changes[i], this, current[changes[i]], options); 358 516 } … … 402 560 changedAttributes: function(diff) { 403 561 if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; 404 var val, changed = false;405 562 var old = this._changing ? this._previousAttributes : this.attributes; 563 var changed = {}; 406 564 for (var attr in diff) { 407 if (_.isEqual(old[attr], (val = diff[attr]))) continue; 408 (changed || (changed = {}))[attr] = val; 409 } 410 return changed; 565 var val = diff[attr]; 566 if (_.isEqual(old[attr], val)) continue; 567 changed[attr] = val; 568 } 569 return _.size(changed) ? changed : false; 411 570 }, 412 571 … … 424 583 }, 425 584 426 // Fetch the model from the server. If the server's representation of the 427 // model differs from its current attributes, they will be overridden, 428 // triggering a `"change"` event. 585 // Fetch the model from the server, merging the response with the model's 586 // local attributes. Any changed attributes will trigger a "change" event. 429 587 fetch: function(options) { 430 options = options ? _.clone(options) : {}; 431 if (options.parse === void 0) options.parse = true; 588 options = _.extend({parse: true}, options); 432 589 var model = this; 433 590 var success = options.success; 434 591 options.success = function(resp) { 435 if (!model.set(model.parse(resp, options), options)) return false; 436 if (success) success(model, resp, options); 592 var serverAttrs = options.parse ? model.parse(resp, options) : resp; 593 if (!model.set(serverAttrs, options)) return false; 594 if (success) success.call(options.context, model, resp, options); 437 595 model.trigger('sync', model, resp, options); 438 596 }; … … 445 603 // state will be `set` again. 446 604 save: function(key, val, options) { 447 var attrs, method, xhr, attributes = this.attributes;448 449 605 // Handle both `"key", value` and `{key: value}` -style arguments. 606 var attrs; 450 607 if (key == null || typeof key === 'object') { 451 608 attrs = key; … … 455 612 } 456 613 457 options = _.extend({validate: true}, options); 614 options = _.extend({validate: true, parse: true}, options); 615 var wait = options.wait; 458 616 459 617 // If we're not waiting and attributes exist, save acts as 460 618 // `set(attr).save(null, opts)` with validation. Otherwise, check if 461 619 // the model will be valid when the attributes, if any, are set. 462 if (attrs && ! options.wait) {620 if (attrs && !wait) { 463 621 if (!this.set(attrs, options)) return false; 464 622 } else { … … 466 624 } 467 625 468 // Set temporary attributes if `{wait: true}`.469 if (attrs && options.wait) {470 this.attributes = _.extend({}, attributes, attrs);471 }472 473 626 // After a successful server-side save, the client is (optionally) 474 627 // updated with the server-side state. 475 if (options.parse === void 0) options.parse = true;476 628 var model = this; 477 629 var success = options.success; 630 var attributes = this.attributes; 478 631 options.success = function(resp) { 479 632 // Ensure attributes are restored during synchronous saves. 480 633 model.attributes = attributes; 481 var serverAttrs = model.parse(resp, options); 482 if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs); 483 if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { 484 return false; 485 } 486 if (success) success(model, resp, options); 634 var serverAttrs = options.parse ? model.parse(resp, options) : resp; 635 if (wait) serverAttrs = _.extend({}, attrs, serverAttrs); 636 if (serverAttrs && !model.set(serverAttrs, options)) return false; 637 if (success) success.call(options.context, model, resp, options); 487 638 model.trigger('sync', model, resp, options); 488 639 }; 489 640 wrapError(this, options); 490 641 491 method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); 492 if (method === 'patch') options.attrs = attrs; 493 xhr = this.sync(method, this, options); 642 // Set temporary attributes if `{wait: true}` to properly find new ids. 643 if (attrs && wait) this.attributes = _.extend({}, attributes, attrs); 644 645 var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); 646 if (method === 'patch' && !options.attrs) options.attrs = attrs; 647 var xhr = this.sync(method, this, options); 494 648 495 649 // Restore attributes. 496 if (attrs && options.wait)this.attributes = attributes;650 this.attributes = attributes; 497 651 498 652 return xhr; … … 506 660 var model = this; 507 661 var success = options.success; 662 var wait = options.wait; 508 663 509 664 var destroy = function() { 665 model.stopListening(); 510 666 model.trigger('destroy', model, model.collection, options); 511 667 }; 512 668 513 669 options.success = function(resp) { 514 if ( options.wait || model.isNew()) destroy();515 if (success) success (model, resp, options);670 if (wait) destroy(); 671 if (success) success.call(options.context, model, resp, options); 516 672 if (!model.isNew()) model.trigger('sync', model, resp, options); 517 673 }; 518 674 675 var xhr = false; 519 676 if (this.isNew()) { 520 options.success(); 521 return false; 522 } 523 wrapError(this, options); 524 525 var xhr = this.sync('delete', this, options); 526 if (!options.wait) destroy(); 677 _.defer(options.success); 678 } else { 679 wrapError(this, options); 680 xhr = this.sync('delete', this, options); 681 } 682 if (!wait) destroy(); 527 683 return xhr; 528 684 }, … … 537 693 urlError(); 538 694 if (this.isNew()) return base; 539 return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id); 695 var id = this.get(this.idAttribute); 696 return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id); 540 697 }, 541 698 … … 558 715 // Check if the model is currently in a valid state. 559 716 isValid: function(options) { 560 return this._validate({}, _. extend(options || {}, { validate: true }));717 return this._validate({}, _.defaults({validate: true}, options)); 561 718 }, 562 719 … … 574 731 }); 575 732 576 // Underscore methods that we want to implement on the Model. 577 var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit']; 733 // Underscore methods that we want to implement on the Model, mapped to the 734 // number of arguments they take. 735 var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0, 736 omit: 0, chain: 1, isEmpty: 1 }; 578 737 579 738 // Mix in each Underscore method as a proxy to `Model#attributes`. 580 _.each(modelMethods, function(method) { 581 Model.prototype[method] = function() { 582 var args = slice.call(arguments); 583 args.unshift(this.attributes); 584 return _[method].apply(_, args); 585 }; 586 }); 739 addUnderscoreMethods(Model, modelMethods, 'attributes'); 587 740 588 741 // Backbone.Collection … … 590 743 591 744 // If models tend to represent a single row of data, a Backbone Collection is 592 // more anal agous to a table full of data ... or a small slice or page of that745 // more analogous to a table full of data ... or a small slice or page of that 593 746 // table, or a collection of rows that belong together for a particular reason 594 747 // -- all of the messages in this particular folder, all of the documents … … 612 765 var addOptions = {add: true, remove: false}; 613 766 767 // Splices `insert` into `array` at index `at`. 768 var splice = function(array, insert, at) { 769 at = Math.min(Math.max(at, 0), array.length); 770 var tail = Array(array.length - at); 771 var length = insert.length; 772 for (var i = 0; i < tail.length; i++) tail[i] = array[i + at]; 773 for (i = 0; i < length; i++) array[i + at] = insert[i]; 774 for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i]; 775 }; 776 614 777 // Define the Collection's inheritable methods. 615 778 _.extend(Collection.prototype, Events, { … … 626 789 // models' attributes. 627 790 toJSON: function(options) { 628 return this.map(function(model) { return model.toJSON(options); });791 return this.map(function(model) { return model.toJSON(options); }); 629 792 }, 630 793 … … 634 797 }, 635 798 636 // Add a model, or list of models to the set. 799 // Add a model, or list of models to the set. `models` may be Backbone 800 // Models or raw JavaScript objects to be converted to Models, or any 801 // combination of the two. 637 802 add: function(models, options) { 638 803 return this.set(models, _.extend({merge: false}, options, addOptions)); … … 641 806 // Remove a model, or a list of models from the set. 642 807 remove: function(models, options) { 808 options = _.extend({}, options); 643 809 var singular = !_.isArray(models); 644 810 models = singular ? [models] : _.clone(models); 645 options || (options = {}); 646 var i, l, index, model; 647 for (i = 0, l = models.length; i < l; i++) { 648 model = models[i] = this.get(models[i]); 649 if (!model) continue; 650 delete this._byId[model.id]; 651 delete this._byId[model.cid]; 652 index = this.indexOf(model); 653 this.models.splice(index, 1); 654 this.length--; 655 if (!options.silent) { 656 options.index = index; 657 model.trigger('remove', model, this, options); 658 } 659 this._removeReference(model, options); 660 } 661 return singular ? models[0] : models; 811 var removed = this._removeModels(models, options); 812 if (!options.silent && removed) this.trigger('update', this, options); 813 return singular ? removed[0] : removed; 662 814 }, 663 815 … … 667 819 // the core operation for updating the data contained by the collection. 668 820 set: function(models, options) { 821 if (models == null) return; 822 669 823 options = _.defaults({}, options, setOptions); 670 if (options.parse) models = this.parse(models, options); 824 if (options.parse && !this._isModel(models)) models = this.parse(models, options); 825 671 826 var singular = !_.isArray(models); 672 models = singular ? (models ? [models] : []) : _.clone(models);673 var i, l, id, model, attrs, existing, sort; 827 models = singular ? [models] : models.slice(); 828 674 829 var at = options.at; 675 var targetModel = this.model; 830 if (at != null) at = +at; 831 if (at < 0) at += this.length + 1; 832 833 var set = []; 834 var toAdd = []; 835 var toRemove = []; 836 var modelMap = {}; 837 838 var add = options.add; 839 var merge = options.merge; 840 var remove = options.remove; 841 842 var sort = false; 676 843 var sortable = this.comparator && (at == null) && options.sort !== false; 677 844 var sortAttr = _.isString(this.comparator) ? this.comparator : null; 678 var toAdd = [], toRemove = [], modelMap = {};679 var add = options.add, merge = options.merge, remove = options.remove;680 var order = !sortable && add && remove ? [] : false;681 845 682 846 // Turn bare objects into model references, and prevent invalid models 683 847 // from being added. 684 for (i = 0, l = models.length; i < l; i++) { 685 attrs = models[i] || {}; 686 if (attrs instanceof Model) { 687 id = model = attrs; 688 } else { 689 id = attrs[targetModel.prototype.idAttribute || 'id']; 690 } 848 var model; 849 for (var i = 0; i < models.length; i++) { 850 model = models[i]; 691 851 692 852 // If a duplicate is found, prevent it from being added and 693 853 // optionally merge it into the existing model. 694 if (existing = this.get(id)) {695 if (remove) modelMap[existing.cid] = true;696 if (merge ) {697 attrs = attrs === model ? model.attributes : attrs;854 var existing = this.get(model); 855 if (existing) { 856 if (merge && model !== existing) { 857 var attrs = this._isModel(model) ? model.attributes : model; 698 858 if (options.parse) attrs = existing.parse(attrs, options); 699 859 existing.set(attrs, options); 700 if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true; 860 if (sortable && !sort) sort = existing.hasChanged(sortAttr); 861 } 862 if (!modelMap[existing.cid]) { 863 modelMap[existing.cid] = true; 864 set.push(existing); 701 865 } 702 866 models[i] = existing; … … 704 868 // If this is a new, valid model, push it to the `toAdd` list. 705 869 } else if (add) { 706 model = models[i] = this._prepareModel(attrs, options); 707 if (!model) continue; 708 toAdd.push(model); 709 this._addReference(model, options); 710 } 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; 716 } 717 718 // Remove nonexistent models if appropriate. 719 if (remove) { 720 for (i = 0, l = this.length; i < l; ++i) { 721 if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model); 722 } 723 if (toRemove.length) this.remove(toRemove, options); 724 } 725 726 // See if sorting is needed, update `length` and splice in new models. 727 if (toAdd.length || (order && order.length)) { 728 if (sortable) sort = true; 729 this.length += toAdd.length; 730 if (at != null) { 731 for (i = 0, l = toAdd.length; i < l; i++) { 732 this.models.splice(at + i, 0, toAdd[i]); 733 } 734 } else { 735 if (order) this.models.length = 0; 736 var orderedModels = order || toAdd; 737 for (i = 0, l = orderedModels.length; i < l; i++) { 738 this.models.push(orderedModels[i]); 870 model = models[i] = this._prepareModel(model, options); 871 if (model) { 872 toAdd.push(model); 873 this._addReference(model, options); 874 modelMap[model.cid] = true; 875 set.push(model); 739 876 } 740 877 } 741 878 } 742 879 880 // Remove stale models. 881 if (remove) { 882 for (i = 0; i < this.length; i++) { 883 model = this.models[i]; 884 if (!modelMap[model.cid]) toRemove.push(model); 885 } 886 if (toRemove.length) this._removeModels(toRemove, options); 887 } 888 889 // See if sorting is needed, update `length` and splice in new models. 890 var orderChanged = false; 891 var replace = !sortable && add && remove; 892 if (set.length && replace) { 893 orderChanged = this.length != set.length || _.some(this.models, function(model, index) { 894 return model !== set[index]; 895 }); 896 this.models.length = 0; 897 splice(this.models, set, 0); 898 this.length = this.models.length; 899 } else if (toAdd.length) { 900 if (sortable) sort = true; 901 splice(this.models, toAdd, at == null ? this.length : at); 902 this.length = this.models.length; 903 } 904 743 905 // Silently sort the collection if appropriate. 744 906 if (sort) this.sort({silent: true}); … … 746 908 // Unless silenced, it's time to fire all appropriate add/sort events. 747 909 if (!options.silent) { 748 for (i = 0, l = toAdd.length; i < l; i++) { 749 (model = toAdd[i]).trigger('add', model, this, options); 910 for (i = 0; i < toAdd.length; i++) { 911 if (at != null) options.index = at + i; 912 model = toAdd[i]; 913 model.trigger('add', model, this, options); 750 914 } 751 if (sort || (order && order.length)) this.trigger('sort', this, options); 915 if (sort || orderChanged) this.trigger('sort', this, options); 916 if (toAdd.length || toRemove.length) this.trigger('update', this, options); 752 917 } 753 918 … … 761 926 // Useful for bulk operations and optimizations. 762 927 reset: function(models, options) { 763 options || (options = {});764 for (var i = 0 , l = this.models.length; i < l; i++) {928 options = options ? _.clone(options) : {}; 929 for (var i = 0; i < this.models.length; i++) { 765 930 this._removeReference(this.models[i], options); 766 931 } … … 780 945 pop: function(options) { 781 946 var model = this.at(this.length - 1); 782 this.remove(model, options); 783 return model; 947 return this.remove(model, options); 784 948 }, 785 949 … … 792 956 shift: function(options) { 793 957 var model = this.at(0); 794 this.remove(model, options); 795 return model; 958 return this.remove(model, options); 796 959 }, 797 960 … … 804 967 get: function(obj) { 805 968 if (obj == null) return void 0; 806 return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid]; 969 var id = this.modelId(this._isModel(obj) ? obj.attributes : obj); 970 return this._byId[obj] || this._byId[id] || this._byId[obj.cid]; 807 971 }, 808 972 809 973 // Get the model at the given index. 810 974 at: function(index) { 975 if (index < 0) index += this.length; 811 976 return this.models[index]; 812 977 }, … … 815 980 // `filter`. 816 981 where: function(attrs, first) { 817 if (_.isEmpty(attrs)) return first ? void 0 : []; 818 return this[first ? 'find' : 'filter'](function(model) { 819 for (var key in attrs) { 820 if (attrs[key] !== model.get(key)) return false; 821 } 822 return true; 823 }); 982 return this[first ? 'find' : 'filter'](attrs); 824 983 }, 825 984 … … 834 993 // is added. 835 994 sort: function(options) { 836 if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); 995 var comparator = this.comparator; 996 if (!comparator) throw new Error('Cannot sort a set without a comparator'); 837 997 options || (options = {}); 838 998 999 var length = comparator.length; 1000 if (_.isFunction(comparator)) comparator = _.bind(comparator, this); 1001 839 1002 // Run sort based on type of `comparator`. 840 if ( _.isString(this.comparator) || this.comparator.length === 1) {841 this.models = this.sortBy( this.comparator, this);1003 if (length === 1 || _.isString(comparator)) { 1004 this.models = this.sortBy(comparator); 842 1005 } else { 843 this.models.sort(_.bind(this.comparator, this)); 844 } 845 1006 this.models.sort(comparator); 1007 } 846 1008 if (!options.silent) this.trigger('sort', this, options); 847 1009 return this; … … 857 1019 // data will be passed through the `reset` method instead of `set`. 858 1020 fetch: function(options) { 859 options = options ? _.clone(options) : {}; 860 if (options.parse === void 0) options.parse = true; 1021 options = _.extend({parse: true}, options); 861 1022 var success = options.success; 862 1023 var collection = this; … … 864 1025 var method = options.reset ? 'reset' : 'set'; 865 1026 collection[method](resp, options); 866 if (success) success (collection, resp, options);1027 if (success) success.call(options.context, collection, resp, options); 867 1028 collection.trigger('sync', collection, resp, options); 868 1029 }; … … 876 1037 create: function(model, options) { 877 1038 options = options ? _.clone(options) : {}; 878 if (!(model = this._prepareModel(model, options))) return false; 879 if (!options.wait) this.add(model, options); 1039 var wait = options.wait; 1040 model = this._prepareModel(model, options); 1041 if (!model) return false; 1042 if (!wait) this.add(model, options); 880 1043 var collection = this; 881 1044 var success = options.success; 882 options.success = function(model, resp ) {883 if ( options.wait) collection.add(model, options);884 if (success) success (model, resp, options);1045 options.success = function(model, resp, callbackOpts) { 1046 if (wait) collection.add(model, callbackOpts); 1047 if (success) success.call(callbackOpts.context, model, resp, callbackOpts); 885 1048 }; 886 1049 model.save(null, options); … … 896 1059 // Create a new collection with an identical list of models as this one. 897 1060 clone: function() { 898 return new this.constructor(this.models); 1061 return new this.constructor(this.models, { 1062 model: this.model, 1063 comparator: this.comparator 1064 }); 1065 }, 1066 1067 // Define how to uniquely identify models in the collection. 1068 modelId: function (attrs) { 1069 return attrs[this.model.prototype.idAttribute || 'id']; 899 1070 }, 900 1071 … … 910 1081 // collection. 911 1082 _prepareModel: function(attrs, options) { 912 if (attrs instanceof Model) return attrs; 1083 if (this._isModel(attrs)) { 1084 if (!attrs.collection) attrs.collection = this; 1085 return attrs; 1086 } 913 1087 options = options ? _.clone(options) : {}; 914 1088 options.collection = this; … … 919 1093 }, 920 1094 1095 // Internal method called by both remove and set. 1096 _removeModels: function(models, options) { 1097 var removed = []; 1098 for (var i = 0; i < models.length; i++) { 1099 var model = this.get(models[i]); 1100 if (!model) continue; 1101 1102 var index = this.indexOf(model); 1103 this.models.splice(index, 1); 1104 this.length--; 1105 1106 if (!options.silent) { 1107 options.index = index; 1108 model.trigger('remove', model, this, options); 1109 } 1110 1111 removed.push(model); 1112 this._removeReference(model, options); 1113 } 1114 return removed.length ? removed : false; 1115 }, 1116 1117 // Method for checking whether an object should be considered a model for 1118 // the purposes of adding to the collection. 1119 _isModel: function (model) { 1120 return model instanceof Model; 1121 }, 1122 921 1123 // Internal method to create a model's ties to a collection. 922 1124 _addReference: function(model, options) { 923 1125 this._byId[model.cid] = model; 924 if (model.id != null) this._byId[model.id] = model;925 if ( !model.collection) model.collection = this;1126 var id = this.modelId(model.attributes); 1127 if (id != null) this._byId[id] = model; 926 1128 model.on('all', this._onModelEvent, this); 927 1129 }, … … 929 1131 // Internal method to sever a model's ties to a collection. 930 1132 _removeReference: function(model, options) { 1133 delete this._byId[model.cid]; 1134 var id = this.modelId(model.attributes); 1135 if (id != null) delete this._byId[id]; 931 1136 if (this === model.collection) delete model.collection; 932 1137 model.off('all', this._onModelEvent, this); … … 940 1145 if ((event === 'add' || event === 'remove') && collection !== this) return; 941 1146 if (event === 'destroy') this.remove(model, options); 942 if (model && event === 'change:' + model.idAttribute) { 943 delete this._byId[model.previous(model.idAttribute)]; 944 if (model.id != null) this._byId[model.id] = model; 1147 if (event === 'change') { 1148 var prevId = this.modelId(model.previousAttributes()); 1149 var id = this.modelId(model.attributes); 1150 if (prevId !== id) { 1151 if (prevId != null) delete this._byId[prevId]; 1152 if (id != null) this._byId[id] = model; 1153 } 945 1154 } 946 1155 this.trigger.apply(this, arguments); … … 952 1161 // 90% of the core usefulness of Backbone Collections is actually implemented 953 1162 // right here: 954 var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl', 955 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select', 956 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', 957 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest', 958 'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle', 959 'lastIndexOf', 'isEmpty', 'chain', 'sample']; 1163 var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4, 1164 foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3, 1165 select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3, 1166 contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, 1167 head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3, 1168 without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3, 1169 isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3, 1170 sortBy: 3, indexBy: 3}; 960 1171 961 1172 // Mix in each Underscore method as a proxy to `Collection#models`. 962 _.each(methods, function(method) { 963 Collection.prototype[method] = function() { 964 var args = slice.call(arguments); 965 args.unshift(this.models); 966 return _[method].apply(_, args); 967 }; 968 }); 969 970 // Underscore methods that take a property name as an argument. 971 var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy']; 972 973 // Use attributes instead of properties. 974 _.each(attributeMethods, function(method) { 975 Collection.prototype[method] = function(value, context) { 976 var iterator = _.isFunction(value) ? value : function(model) { 977 return model.get(value); 978 }; 979 return _[method](this.models, iterator, context); 980 }; 981 }); 1173 addUnderscoreMethods(Collection, collectionMethods, 'models'); 982 1174 983 1175 // Backbone.View … … 996 1188 var View = Backbone.View = function(options) { 997 1189 this.cid = _.uniqueId('view'); 998 options || (options = {});999 1190 _.extend(this, _.pick(options, viewOptions)); 1000 1191 this._ensureElement(); 1001 1192 this.initialize.apply(this, arguments); 1002 this.delegateEvents();1003 1193 }; 1004 1194 … … 1006 1196 var delegateEventSplitter = /^(\S+)\s*(.*)$/; 1007 1197 1008 // List of view options to be mergedas properties.1198 // List of view options to be set as properties. 1009 1199 var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; 1010 1200 … … 1035 1225 // applicable Backbone.Events listeners. 1036 1226 remove: function() { 1037 this. $el.remove();1227 this._removeElement(); 1038 1228 this.stopListening(); 1039 1229 return this; 1040 1230 }, 1041 1231 1042 // Change the view's element (`this.el` property), including event 1043 // re-delegation. 1044 setElement: function(element, delegate) { 1045 if (this.$el) this.undelegateEvents(); 1046 this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); 1232 // Remove this view's element from the document and all event listeners 1233 // attached to it. Exposed for subclasses using an alternative DOM 1234 // manipulation API. 1235 _removeElement: function() { 1236 this.$el.remove(); 1237 }, 1238 1239 // Change the view's element (`this.el` property) and re-delegate the 1240 // view's events on the new element. 1241 setElement: function(element) { 1242 this.undelegateEvents(); 1243 this._setElement(element); 1244 this.delegateEvents(); 1245 return this; 1246 }, 1247 1248 // Creates the `this.el` and `this.$el` references for this view using the 1249 // given `el`. `el` can be a CSS selector or an HTML string, a jQuery 1250 // context or an element. Subclasses can override this to utilize an 1251 // alternative DOM manipulation API and are only required to set the 1252 // `this.el` property. 1253 _setElement: function(el) { 1254 this.$el = el instanceof Backbone.$ ? el : Backbone.$(el); 1047 1255 this.el = this.$el[0]; 1048 if (delegate !== false) this.delegateEvents();1049 return this;1050 1256 }, 1051 1257 … … 1063 1269 // Uses event delegation for efficiency. 1064 1270 // Omitting the selector binds the event to `this.el`. 1065 // This only works for delegate-able events: not `focus`, `blur`, and1066 // not `change`, `submit`, and `reset` in Internet Explorer.1067 1271 delegateEvents: function(events) { 1068 if (!(events || (events = _.result(this, 'events')))) return this; 1272 events || (events = _.result(this, 'events')); 1273 if (!events) return this; 1069 1274 this.undelegateEvents(); 1070 1275 for (var key in events) { 1071 1276 var method = events[key]; 1072 if (!_.isFunction(method)) method = this[ events[key]];1277 if (!_.isFunction(method)) method = this[method]; 1073 1278 if (!method) continue; 1074 1075 1279 var match = key.match(delegateEventSplitter); 1076 var eventName = match[1], selector = match[2]; 1077 method = _.bind(method, this); 1078 eventName += '.delegateEvents' + this.cid; 1079 if (selector === '') { 1080 this.$el.on(eventName, method); 1081 } else { 1082 this.$el.on(eventName, selector, method); 1083 } 1280 this.delegate(match[1], match[2], _.bind(method, this)); 1084 1281 } 1085 1282 return this; 1086 1283 }, 1087 1284 1088 // Clears all callbacks previously bound to the view with `delegateEvents`. 1285 // Add a single event listener to the view's element (or a child element 1286 // using `selector`). This only works for delegate-able events: not `focus`, 1287 // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer. 1288 delegate: function(eventName, selector, listener) { 1289 this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener); 1290 return this; 1291 }, 1292 1293 // Clears all callbacks previously bound to the view by `delegateEvents`. 1089 1294 // You usually don't need to use this, but may wish to if you have multiple 1090 1295 // Backbone views attached to the same DOM element. 1091 1296 undelegateEvents: function() { 1092 this.$el.off('.delegateEvents' + this.cid);1297 if (this.$el) this.$el.off('.delegateEvents' + this.cid); 1093 1298 return this; 1299 }, 1300 1301 // A finer-grained `undelegateEvents` for removing a single delegated event. 1302 // `selector` and `listener` are both optional. 1303 undelegate: function(eventName, selector, listener) { 1304 this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener); 1305 return this; 1306 }, 1307 1308 // Produces a DOM element to be assigned to your view. Exposed for 1309 // subclasses using an alternative DOM manipulation API. 1310 _createElement: function(tagName) { 1311 return document.createElement(tagName); 1094 1312 }, 1095 1313 … … 1103 1321 if (this.id) attrs.id = _.result(this, 'id'); 1104 1322 if (this.className) attrs['class'] = _.result(this, 'className'); 1105 var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs);1106 this. setElement($el, false);1323 this.setElement(this._createElement(_.result(this, 'tagName'))); 1324 this._setAttributes(attrs); 1107 1325 } else { 1108 this.setElement(_.result(this, 'el'), false); 1109 } 1326 this.setElement(_.result(this, 'el')); 1327 } 1328 }, 1329 1330 // Set attributes from a hash on this view's element. Exposed for 1331 // subclasses using an alternative DOM manipulation API. 1332 _setAttributes: function(attributes) { 1333 this.$el.attr(attributes); 1110 1334 } 1111 1335 … … 1176 1400 } 1177 1401 1178 // If we're sending a `PATCH` request, and we're in an old Internet Explorer 1179 // that still has ActiveX enabled by default, override jQuery to use that 1180 // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8. 1181 if (params.type === 'PATCH' && noXhrPatch) { 1182 params.xhr = function() { 1183 return new ActiveXObject("Microsoft.XMLHTTP"); 1184 }; 1185 } 1402 // Pass along `textStatus` and `errorThrown` from jQuery. 1403 var error = options.error; 1404 options.error = function(xhr, textStatus, errorThrown) { 1405 options.textStatus = textStatus; 1406 options.errorThrown = errorThrown; 1407 if (error) error.call(options.context, xhr, textStatus, errorThrown); 1408 }; 1186 1409 1187 1410 // Make the request, allowing the user to override any Ajax options. … … 1190 1413 return xhr; 1191 1414 }; 1192 1193 var noXhrPatch =1194 typeof window !== 'undefined' && !!window.ActiveXObject &&1195 !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);1196 1415 1197 1416 // Map from CRUD to HTTP for our default `Backbone.sync` implementation. … … 1252 1471 Backbone.history.route(route, function(fragment) { 1253 1472 var args = router._extractParameters(route, fragment); 1254 router.execute(callback, args); 1255 router.trigger.apply(router, ['route:' + name].concat(args)); 1256 router.trigger('route', name, args); 1257 Backbone.history.trigger('route', router, name, args); 1473 if (router.execute(callback, args, name) !== false) { 1474 router.trigger.apply(router, ['route:' + name].concat(args)); 1475 router.trigger('route', name, args); 1476 Backbone.history.trigger('route', router, name, args); 1477 } 1258 1478 }); 1259 1479 return this; … … 1262 1482 // Execute a route handler with the provided parameters. This is an 1263 1483 // excellent place to do pre-route setup or post-route cleanup. 1264 execute: function(callback, args ) {1484 execute: function(callback, args, name) { 1265 1485 if (callback) callback.apply(this, args); 1266 1486 }, … … 1320 1540 var History = Backbone.History = function() { 1321 1541 this.handlers = []; 1322 _.bindAll(this, 'checkUrl');1542 this.checkUrl = _.bind(this.checkUrl, this); 1323 1543 1324 1544 // Ensure that `History` can be used outside of the browser. … … 1335 1555 var rootStripper = /^\/+|\/+$/g; 1336 1556 1337 // Cached regex for detecting MSIE.1338 var isExplorer = /msie [\w.]+/;1339 1340 // Cached regex for removing a trailing slash.1341 var trailingSlash = /\/$/;1342 1343 1557 // Cached regex for stripping urls of hash. 1344 1558 var pathStripper = /#.*$/; … … 1356 1570 // Are we at the app root? 1357 1571 atRoot: function() { 1358 return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root; 1572 var path = this.location.pathname.replace(/[^\/]$/, '$&/'); 1573 return path === this.root && !this.getSearch(); 1574 }, 1575 1576 // Does the pathname match the root? 1577 matchRoot: function() { 1578 var path = this.decodeFragment(this.location.pathname); 1579 var root = path.slice(0, this.root.length - 1) + '/'; 1580 return root === this.root; 1581 }, 1582 1583 // Unicode characters in `location.pathname` are percent encoded so they're 1584 // decoded for comparison. `%25` should not be decoded since it may be part 1585 // of an encoded parameter. 1586 decodeFragment: function(fragment) { 1587 return decodeURI(fragment.replace(/%25/g, '%2525')); 1588 }, 1589 1590 // In IE6, the hash fragment and search params are incorrect if the 1591 // fragment contains `?`. 1592 getSearch: function() { 1593 var match = this.location.href.replace(/#.*/, '').match(/\?.+/); 1594 return match ? match[0] : ''; 1359 1595 }, 1360 1596 … … 1366 1602 }, 1367 1603 1368 // Get the cross-browser normalized URL fragment, either from the URL, 1369 // the hash, or the override. 1370 getFragment: function(fragment, forcePushState) { 1604 // Get the pathname and search params, without the root. 1605 getPath: function() { 1606 var path = this.decodeFragment( 1607 this.location.pathname + this.getSearch() 1608 ).slice(this.root.length - 1); 1609 return path.charAt(0) === '/' ? path.slice(1) : path; 1610 }, 1611 1612 // Get the cross-browser normalized URL fragment from the path or hash. 1613 getFragment: function(fragment) { 1371 1614 if (fragment == null) { 1372 if (this._hasPushState || !this._wantsHashChange || forcePushState) { 1373 fragment = decodeURI(this.location.pathname + this.location.search); 1374 var root = this.root.replace(trailingSlash, ''); 1375 if (!fragment.indexOf(root)) fragment = fragment.slice(root.length); 1615 if (this._usePushState || !this._wantsHashChange) { 1616 fragment = this.getPath(); 1376 1617 } else { 1377 1618 fragment = this.getHash(); … … 1384 1625 // an existing route, and `false` otherwise. 1385 1626 start: function(options) { 1386 if (History.started) throw new Error( "Backbone.history has already been started");1627 if (History.started) throw new Error('Backbone.history has already been started'); 1387 1628 History.started = true; 1388 1629 … … 1392 1633 this.root = this.options.root; 1393 1634 this._wantsHashChange = this.options.hashChange !== false; 1635 this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7); 1636 this._useHashChange = this._wantsHashChange && this._hasHashChange; 1394 1637 this._wantsPushState = !!this.options.pushState; 1395 this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); 1396 var fragment = this.getFragment(); 1397 var docMode = document.documentMode; 1398 var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); 1638 this._hasPushState = !!(this.history && this.history.pushState); 1639 this._usePushState = this._wantsPushState && this._hasPushState; 1640 this.fragment = this.getFragment(); 1399 1641 1400 1642 // Normalize root to always include a leading and trailing slash. 1401 1643 this.root = ('/' + this.root + '/').replace(rootStripper, '/'); 1402 1403 if (oldIE && this._wantsHashChange) {1404 var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');1405 this.iframe = frame.hide().appendTo('body')[0].contentWindow;1406 this.navigate(fragment);1407 }1408 1409 // Depending on whether we're using pushState or hashes, and whether1410 // 'onhashchange' is supported, determine how we check the URL state.1411 if (this._hasPushState) {1412 Backbone.$(window).on('popstate', this.checkUrl);1413 } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {1414 Backbone.$(window).on('hashchange', this.checkUrl);1415 } else if (this._wantsHashChange) {1416 this._checkUrlInterval = setInterval(this.checkUrl, this.interval);1417 }1418 1419 // Determine if we need to change the base url, for a pushState link1420 // opened by a non-pushState browser.1421 this.fragment = fragment;1422 var loc = this.location;1423 1644 1424 1645 // Transition from hashChange to pushState or vice versa if both are … … 1429 1650 // browser, but we're currently in a browser that doesn't support it... 1430 1651 if (!this._hasPushState && !this.atRoot()) { 1431 this.fragment = this.getFragment(null, true);1432 this.location.replace( this.root + '#' + this.fragment);1652 var root = this.root.slice(0, -1) || '/'; 1653 this.location.replace(root + '#' + this.getPath()); 1433 1654 // Return immediately as browser will do redirect to new url 1434 1655 return true; … … 1436 1657 // Or if we've started out with a hash-based route, but we're currently 1437 1658 // in a browser where it could be `pushState`-based instead... 1438 } else if (this._hasPushState && this.atRoot() && loc.hash) { 1439 this.fragment = this.getHash().replace(routeStripper, ''); 1440 this.history.replaceState({}, document.title, this.root + this.fragment); 1659 } else if (this._hasPushState && this.atRoot()) { 1660 this.navigate(this.getHash(), {replace: true}); 1441 1661 } 1442 1662 1663 } 1664 1665 // Proxy an iframe to handle location events if the browser doesn't 1666 // support the `hashchange` event, HTML5 history, or the user wants 1667 // `hashChange` but not `pushState`. 1668 if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) { 1669 this.iframe = document.createElement('iframe'); 1670 this.iframe.src = 'javascript:0'; 1671 this.iframe.style.display = 'none'; 1672 this.iframe.tabIndex = -1; 1673 var body = document.body; 1674 // Using `appendChild` will throw on IE < 9 if the document is not ready. 1675 var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow; 1676 iWindow.document.open(); 1677 iWindow.document.close(); 1678 iWindow.location.hash = '#' + this.fragment; 1679 } 1680 1681 // Add a cross-platform `addEventListener` shim for older browsers. 1682 var addEventListener = window.addEventListener || function (eventName, listener) { 1683 return attachEvent('on' + eventName, listener); 1684 }; 1685 1686 // Depending on whether we're using pushState or hashes, and whether 1687 // 'onhashchange' is supported, determine how we check the URL state. 1688 if (this._usePushState) { 1689 addEventListener('popstate', this.checkUrl, false); 1690 } else if (this._useHashChange && !this.iframe) { 1691 addEventListener('hashchange', this.checkUrl, false); 1692 } else if (this._wantsHashChange) { 1693 this._checkUrlInterval = setInterval(this.checkUrl, this.interval); 1443 1694 } 1444 1695 … … 1449 1700 // but possibly useful for unit testing Routers. 1450 1701 stop: function() { 1451 Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl); 1702 // Add a cross-platform `removeEventListener` shim for older browsers. 1703 var removeEventListener = window.removeEventListener || function (eventName, listener) { 1704 return detachEvent('on' + eventName, listener); 1705 }; 1706 1707 // Remove window listeners. 1708 if (this._usePushState) { 1709 removeEventListener('popstate', this.checkUrl, false); 1710 } else if (this._useHashChange && !this.iframe) { 1711 removeEventListener('hashchange', this.checkUrl, false); 1712 } 1713 1714 // Clean up the iframe if necessary. 1715 if (this.iframe) { 1716 document.body.removeChild(this.iframe); 1717 this.iframe = null; 1718 } 1719 1720 // Some environments will throw when clearing an undefined interval. 1452 1721 if (this._checkUrlInterval) clearInterval(this._checkUrlInterval); 1453 1722 History.started = false; … … 1464 1733 checkUrl: function(e) { 1465 1734 var current = this.getFragment(); 1735 1736 // If the user pressed the back button, the iframe's hash will have 1737 // changed and we should use that for comparison. 1466 1738 if (current === this.fragment && this.iframe) { 1467 current = this.getFragment(this.getHash(this.iframe)); 1468 } 1739 current = this.getHash(this.iframe.contentWindow); 1740 } 1741 1469 1742 if (current === this.fragment) return false; 1470 1743 if (this.iframe) this.navigate(current); … … 1476 1749 // returns `false`. 1477 1750 loadUrl: function(fragment) { 1751 // If the root doesn't match, no routes can match either. 1752 if (!this.matchRoot()) return false; 1478 1753 fragment = this.fragment = this.getFragment(fragment); 1479 return _. any(this.handlers, function(handler) {1754 return _.some(this.handlers, function(handler) { 1480 1755 if (handler.route.test(fragment)) { 1481 1756 handler.callback(fragment); … … 1496 1771 if (!options || options === true) options = {trigger: !!options}; 1497 1772 1498 var url = this.root + (fragment = this.getFragment(fragment || '')); 1499 1500 // Strip the hash for matching. 1501 fragment = fragment.replace(pathStripper, ''); 1773 // Normalize the fragment. 1774 fragment = this.getFragment(fragment || ''); 1775 1776 // Don't include a trailing slash on the root. 1777 var root = this.root; 1778 if (fragment === '' || fragment.charAt(0) === '?') { 1779 root = root.slice(0, -1) || '/'; 1780 } 1781 var url = root + fragment; 1782 1783 // Strip the hash and decode for matching. 1784 fragment = this.decodeFragment(fragment.replace(pathStripper, '')); 1502 1785 1503 1786 if (this.fragment === fragment) return; 1504 1787 this.fragment = fragment; 1505 1788 1506 // Don't include a trailing slash on the root.1507 if (fragment === '' && url !== '/') url = url.slice(0, -1);1508 1509 1789 // If pushState is available, we use it to set the fragment as a real URL. 1510 if (this._ hasPushState) {1790 if (this._usePushState) { 1511 1791 this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url); 1512 1792 … … 1515 1795 } else if (this._wantsHashChange) { 1516 1796 this._updateHash(this.location, fragment, options.replace); 1517 if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) { 1797 if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) { 1798 var iWindow = this.iframe.contentWindow; 1799 1518 1800 // Opening and closing the iframe tricks IE7 and earlier to push a 1519 1801 // history entry on hash-tag change. When replace is true, we don't 1520 1802 // want this. 1521 if(!options.replace) this.iframe.document.open().close(); 1522 this._updateHash(this.iframe.location, fragment, options.replace); 1803 if (!options.replace) { 1804 iWindow.document.open(); 1805 iWindow.document.close(); 1806 } 1807 1808 this._updateHash(iWindow.location, fragment, options.replace); 1523 1809 } 1524 1810 … … 1551 1837 // ------- 1552 1838 1553 // Helper function to correctly set up the prototype chain ,for subclasses.1839 // Helper function to correctly set up the prototype chain for subclasses. 1554 1840 // Similar to `goog.inherits`, but uses a hash of prototype properties and 1555 1841 // class properties to be extended. … … 1560 1846 // The constructor function for the new subclass is either defined by you 1561 1847 // (the "constructor" property in your `extend` definition), or defaulted 1562 // by us to simply call the parent 'sconstructor.1848 // by us to simply call the parent constructor. 1563 1849 if (protoProps && _.has(protoProps, 'constructor')) { 1564 1850 child = protoProps.constructor; … … 1571 1857 1572 1858 // Set the prototype chain to inherit from `parent`, without calling 1573 // `parent` 'sconstructor function.1859 // `parent` constructor function. 1574 1860 var Surrogate = function(){ this.constructor = child; }; 1575 1861 Surrogate.prototype = parent.prototype; … … 1599 1885 var error = options.error; 1600 1886 options.error = function(resp) { 1601 if (error) error (model, resp, options);1887 if (error) error.call(options.context, model, resp, options); 1602 1888 model.trigger('error', model, resp, options); 1603 1889 }; -
trunk/src/wp-includes/js/backbone.min.js
r27233 r36546 1 (function(t ,e){if(typeof define==="function"&&define.amd){define(["underscore","jquery","exports"],function(i,r,s){t.Backbone=e(t,s,i,r)})}else if(typeof exports!=="undefined"){var i=require("underscore");e(t,exports,i)}else{t.Backbone=e(t,{},t._,t.jQuery||t.Zepto||t.ender||t.$)}})(this,function(t,e,i,r){var s=t.Backbone;var n=[];var a=n.push;var o=n.slice;var h=n.splice;e.VERSION="1.1.2";e.$=r;e.noConflict=function(){t.Backbone=s;return this};e.emulateHTTP=false;e.emulateJSON=false;var u=e.Events={on:function(t,e,i){if(!c(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,r){if(!c(this,"once",t,[e,r])||!e)return this;var s=this;var n=i.once(function(){s.off(t,n);e.apply(this,arguments)});n._callback=e;return this.on(t,n,r)},off:function(t,e,r){var s,n,a,o,h,u,l,f;if(!this._events||!c(this,"off",t,[e,r]))return this;if(!t&&!e&&!r){this._events=void 0;return this}o=t?[t]:i.keys(this._events);for(h=0,u=o.length;h<u;h++){t=o[h];if(a=this._events[t]){this._events[t]=s=[];if(e||r){for(l=0,f=a.length;l<f;l++){n=a[l];if(e&&e!==n.callback&&e!==n.callback._callback||r&&r!==n.context){s.push(n)}}}if(!s.length)delete this._events[t]}}return this},trigger:function(t){if(!this._events)return this;var e=o.call(arguments,1);if(!c(this,"trigger",t,e))return this;var i=this._events[t];var r=this._events.all;if(i)f(i,e);if(r)f(r,arguments);return this},stopListening:function(t,e,r){var s=this._listeningTo;if(!s)return this;var n=!e&&!r;if(!r&&typeof e==="object")r=this;if(t)(s={})[t._listenId]=t;for(var a in s){t=s[a];t.off(e,r,this);if(n||i.isEmpty(t._events))delete this._listeningTo[a]}return this}};var l=/\s+/;var c=function(t,e,i,r){if(!i)return true;if(typeof i==="object"){for(var s in i){t[e].apply(t,[s,i[s]].concat(r))}return false}if(l.test(i)){var n=i.split(l);for(var a=0,o=n.length;a<o;a++){t[e].apply(t,[n[a]].concat(r))}return false}return true};var f=function(t,e){var i,r=-1,s=t.length,n=e[0],a=e[1],o=e[2];switch(e.length){case 0:while(++r<s)(i=t[r]).callback.call(i.ctx);return;case 1:while(++r<s)(i=t[r]).callback.call(i.ctx,n);return;case 2:while(++r<s)(i=t[r]).callback.call(i.ctx,n,a);return;case 3:while(++r<s)(i=t[r]).callback.call(i.ctx,n,a,o);return;default:while(++r<s)(i=t[r]).callback.apply(i.ctx,e);return}};var d={listenTo:"on",listenToOnce:"once"};i.each(d,function(t,e){u[e]=function(e,r,s){var n=this._listeningTo||(this._listeningTo={});var a=e._listenId||(e._listenId=i.uniqueId("l"));n[a]=e;if(!s&&typeof r==="object")s=this;e[t](r,s,this);return this}});u.bind=u.on;u.unbind=u.off;i.extend(e,u);var p=e.Model=function(t,e){var r=t||{};e||(e={});this.cid=i.uniqueId("c");this.attributes={};if(e.collection)this.collection=e.collection;if(e.parse)r=this.parse(r,e)||{};r=i.defaults({},r,i.result(this,"defaults"));this.set(r,e);this.changed={};this.initialize.apply(this,arguments)};i.extend(p.prototype,u,{changed:null,validationError:null,idAttribute:"id",initialize:function(){},toJSON:function(t){return i.clone(this.attributes)},sync:function(){return e.sync.apply(this,arguments)},get:function(t){return this.attributes[t]},escape:function(t){return i.escape(this.get(t))},has:function(t){return this.get(t)!=null},set:function(t,e,r){var s,n,a,o,h,u,l,c;if(t==null)return this;if(typeof t==="object"){n=t;r=e}else{(n={})[t]=e}r||(r={});if(!this._validate(n,r))return false;a=r.unset;h=r.silent;o=[];u=this._changing;this._changing=true;if(!u){this._previousAttributes=i.clone(this.attributes);this.changed={}}c=this.attributes,l=this._previousAttributes;if(this.idAttribute in n)this.id=n[this.idAttribute];for(s in n){e=n[s];if(!i.isEqual(c[s],e))o.push(s);if(!i.isEqual(l[s],e)){this.changed[s]=e}else{delete this.changed[s]}a?delete c[s]:c[s]=e}if(!h){if(o.length)this._pending=r;for(var f=0,d=o.length;f<d;f++){this.trigger("change:"+o[f],this,c[o[f]],r)}}if(u)return this;if(!h){while(this._pending){r=this._pending;this._pending=false;this.trigger("change",this,r)}}this._pending=false;this._changing=false;return this},unset:function(t,e){return this.set(t,void 0,i.extend({},e,{unset:true}))},clear:function(t){var e={};for(var r in this.attributes)e[r]=void 0;return this.set(e,i.extend({},t,{unset:true}))},hasChanged:function(t){if(t==null)return!i.isEmpty(this.changed);return i.has(this.changed,t)},changedAttributes:function(t){if(!t)return this.hasChanged()?i.clone(this.changed):false;var e,r=false;var s=this._changing?this._previousAttributes:this.attributes;for(var n in t){if(i.isEqual(s[n],e=t[n]))continue;(r||(r={}))[n]=e}return r},previous:function(t){if(t==null||!this._previousAttributes)return null;return this._previousAttributes[t]},previousAttributes:function(){return i.clone(this._previousAttributes)},fetch:function(t){t=t?i.clone(t):{};if(t.parse===void 0)t.parse=true;var e=this;var r=t.success;t.success=function(i){if(!e.set(e.parse(i,t),t))return false;if(r)r(e,i,t);e.trigger("sync",e,i,t)};q(this,t);return this.sync("read",this,t)},save:function(t,e,r){var s,n,a,o=this.attributes;if(t==null||typeof t==="object"){s=t;r=e}else{(s={})[t]=e}r=i.extend({validate:true},r);if(s&&!r.wait){if(!this.set(s,r))return false}else{if(!this._validate(s,r))return false}if(s&&r.wait){this.attributes=i.extend({},o,s)}if(r.parse===void 0)r.parse=true;var h=this;var u=r.success;r.success=function(t){h.attributes=o;var e=h.parse(t,r);if(r.wait)e=i.extend(s||{},e);if(i.isObject(e)&&!h.set(e,r)){return false}if(u)u(h,t,r);h.trigger("sync",h,t,r)};q(this,r);n=this.isNew()?"create":r.patch?"patch":"update";if(n==="patch")r.attrs=s;a=this.sync(n,this,r);if(s&&r.wait)this.attributes=o;return a},destroy:function(t){t=t?i.clone(t):{};var e=this;var r=t.success;var s=function(){e.trigger("destroy",e,e.collection,t)};t.success=function(i){if(t.wait||e.isNew())s();if(r)r(e,i,t);if(!e.isNew())e.trigger("sync",e,i,t)};if(this.isNew()){t.success();return false}q(this,t);var n=this.sync("delete",this,t);if(!t.wait)s();return n},url:function(){var t=i.result(this,"urlRoot")||i.result(this.collection,"url")||M();if(this.isNew())return t;return t.replace(/([^\/])$/,"$1/")+encodeURIComponent(this.id)},parse:function(t,e){return t},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return!this.has(this.idAttribute)},isValid:function(t){return this._validate({},i.extend(t||{},{validate:true}))},_validate:function(t,e){if(!e.validate||!this.validate)return true;t=i.extend({},this.attributes,t);var r=this.validationError=this.validate(t,e)||null;if(!r)return true;this.trigger("invalid",this,r,i.extend(e,{validationError:r}));return false}});var v=["keys","values","pairs","invert","pick","omit"];i.each(v,function(t){p.prototype[t]=function(){var e=o.call(arguments);e.unshift(this.attributes);return i[t].apply(i,e)}});var g=e.Collection=function(t,e){e||(e={});if(e.model)this.model=e.model;if(e.comparator!==void 0)this.comparator=e.comparator;this._reset();this.initialize.apply(this,arguments);if(t)this.reset(t,i.extend({silent:true},e))};var m={add:true,remove:true,merge:true};var y={add:true,remove:false};i.extend(g.prototype,u,{model:p,initialize:function(){},toJSON:function(t){return this.map(function(e){return e.toJSON(t)})},sync:function(){return e.sync.apply(this,arguments)},add:function(t,e){return this.set(t,i.extend({merge:false},e,y))},remove:function(t,e){var r=!i.isArray(t);t=r?[t]:i.clone(t);e||(e={});var s,n,a,o;for(s=0,n=t.length;s<n;s++){o=t[s]=this.get(t[s]);if(!o)continue;delete this._byId[o.id];delete this._byId[o.cid];a=this.indexOf(o);this.models.splice(a,1);this.length--;if(!e.silent){e.index=a;o.trigger("remove",o,this,e)}this._removeReference(o,e)}return r?t[0]:t},set:function(t,e){e=i.defaults({},e,m);if(e.parse)t=this.parse(t,e);var r=!i.isArray(t);t=r?t?[t]:[]:i.clone(t);var s,n,a,o,h,u,l;var c=e.at;var f=this.model;var d=this.comparator&&c==null&&e.sort!==false;var v=i.isString(this.comparator)?this.comparator:null;var g=[],y=[],_={};var b=e.add,w=e.merge,x=e.remove;var E=!d&&b&&x?[]:false;for(s=0,n=t.length;s<n;s++){h=t[s]||{};if(h instanceof p){a=o=h}else{a=h[f.prototype.idAttribute||"id"]}if(u=this.get(a)){if(x)_[u.cid]=true;if(w){h=h===o?o.attributes:h;if(e.parse)h=u.parse(h,e);u.set(h,e);if(d&&!l&&u.hasChanged(v))l=true}t[s]=u}else if(b){o=t[s]=this._prepareModel(h,e);if(!o)continue;g.push(o);this._addReference(o,e)}o=u||o;if(E&&(o.isNew()||!_[o.id]))E.push(o);_[o.id]=true}if(x){for(s=0,n=this.length;s<n;++s){if(!_[(o=this.models[s]).cid])y.push(o)}if(y.length)this.remove(y,e)}if(g.length||E&&E.length){if(d)l=true;this.length+=g.length;if(c!=null){for(s=0,n=g.length;s<n;s++){this.models.splice(c+s,0,g[s])}}else{if(E)this.models.length=0;var k=E||g;for(s=0,n=k.length;s<n;s++){this.models.push(k[s])}}}if(l)this.sort({silent:true});if(!e.silent){for(s=0,n=g.length;s<n;s++){(o=g[s]).trigger("add",o,this,e)}if(l||E&&E.length)this.trigger("sort",this,e)}return r?t[0]:t},reset:function(t,e){e||(e={});for(var r=0,s=this.models.length;r<s;r++){this._removeReference(this.models[r],e)}e.previousModels=this.models;this._reset();t=this.add(t,i.extend({silent:true},e));if(!e.silent)this.trigger("reset",this,e);return t},push:function(t,e){return this.add(t,i.extend({at:this.length},e))},pop:function(t){var e=this.at(this.length-1);this.remove(e,t);return e},unshift:function(t,e){return this.add(t,i.extend({at:0},e))},shift:function(t){var e=this.at(0);this.remove(e,t);return e},slice:function(){return o.apply(this.models,arguments)},get:function(t){if(t==null)return void 0;return this._byId[t]||this._byId[t.id]||this._byId[t.cid]},at:function(t){return this.models[t]},where:function(t,e){if(i.isEmpty(t))return e?void 0:[];return this[e?"find":"filter"](function(e){for(var i in t){if(t[i]!==e.get(i))return false}return true})},findWhere:function(t){return this.where(t,true)},sort:function(t){if(!this.comparator)throw new Error("Cannot sort a set without a comparator");t||(t={});if(i.isString(this.comparator)||this.comparator.length===1){this.models=this.sortBy(this.comparator,this)}else{this.models.sort(i.bind(this.comparator,this))}if(!t.silent)this.trigger("sort",this,t);return this},pluck:function(t){return i.invoke(this.models,"get",t)},fetch:function(t){t=t?i.clone(t):{};if(t.parse===void 0)t.parse=true;var e=t.success;var r=this;t.success=function(i){var s=t.reset?"reset":"set";r[s](i,t);if(e)e(r,i,t);r.trigger("sync",r,i,t)};q(this,t);return this.sync("read",this,t)},create:function(t,e){e=e?i.clone(e):{};if(!(t=this._prepareModel(t,e)))return false;if(!e.wait)this.add(t,e);var r=this;var s=e.success;e.success=function(t,i){if(e.wait)r.add(t,e);if(s)s(t,i,e)};t.save(null,e);return t},parse:function(t,e){return t},clone:function(){return new this.constructor(this.models)},_reset:function(){this.length=0;this.models=[];this._byId={}},_prepareModel:function(t,e){if(t instanceof p)return t;e=e?i.clone(e):{};e.collection=this;var r=new this.model(t,e);if(!r.validationError)return r;this.trigger("invalid",this,r.validationError,e);return false},_addReference:function(t,e){this._byId[t.cid]=t;if(t.id!=null)this._byId[t.id]=t;if(!t.collection)t.collection=this;t.on("all",this._onModelEvent,this)},_removeReference:function(t,e){if(this===t.collection)delete t.collection;t.off("all",this._onModelEvent,this)},_onModelEvent:function(t,e,i,r){if((t==="add"||t==="remove")&&i!==this)return;if(t==="destroy")this.remove(e,r);if(e&&t==="change:"+e.idAttribute){delete this._byId[e.previous(e.idAttribute)];if(e.id!=null)this._byId[e.id]=e}this.trigger.apply(this,arguments)}});var _=["forEach","each","map","collect","reduce","foldl","inject","reduceRight","foldr","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","max","min","toArray","size","first","head","take","initial","rest","tail","drop","last","without","difference","indexOf","shuffle","lastIndexOf","isEmpty","chain","sample"];i.each(_,function(t){g.prototype[t]=function(){var e=o.call(arguments);e.unshift(this.models);return i[t].apply(i,e)}});var b=["groupBy","countBy","sortBy","indexBy"];i.each(b,function(t){g.prototype[t]=function(e,r){var s=i.isFunction(e)?e:function(t){return t.get(e)};return i[t](this.models,s,r)}});var w=e.View=function(t){this.cid=i.uniqueId("view");t||(t={});i.extend(this,i.pick(t,E));this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()};var x=/^(\S+)\s*(.*)$/;var E=["model","collection","el","id","attributes","className","tagName","events"];i.extend(w.prototype,u,{tagName:"div",$:function(t){return this.$el.find(t)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();this.stopListening();return this},setElement:function(t,i){if(this.$el)this.undelegateEvents();this.$el=t instanceof e.$?t:e.$(t);this.el=this.$el[0];if(i!==false)this.delegateEvents();return this},delegateEvents:function(t){if(!(t||(t=i.result(this,"events"))))return this;this.undelegateEvents();for(var e in t){var r=t[e];if(!i.isFunction(r))r=this[t[e]];if(!r)continue;var s=e.match(x);var n=s[1],a=s[2];r=i.bind(r,this);n+=".delegateEvents"+this.cid;if(a===""){this.$el.on(n,r)}else{this.$el.on(n,a,r)}}return this},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid);return this},_ensureElement:function(){if(!this.el){var t=i.extend({},i.result(this,"attributes"));if(this.id)t.id=i.result(this,"id");if(this.className)t["class"]=i.result(this,"className");var r=e.$("<"+i.result(this,"tagName")+">").attr(t);this.setElement(r,false)}else{this.setElement(i.result(this,"el"),false)}}});e.sync=function(t,r,s){var n=T[t];i.defaults(s||(s={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:n,dataType:"json"};if(!s.url){a.url=i.result(r,"url")||M()}if(s.data==null&&r&&(t==="create"||t==="update"||t==="patch")){a.contentType="application/json";a.data=JSON.stringify(s.attrs||r.toJSON(s))}if(s.emulateJSON){a.contentType="application/x-www-form-urlencoded";a.data=a.data?{model:a.data}:{}}if(s.emulateHTTP&&(n==="PUT"||n==="DELETE"||n==="PATCH")){a.type="POST";if(s.emulateJSON)a.data._method=n;var o=s.beforeSend;s.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",n);if(o)return o.apply(this,arguments)}}if(a.type!=="GET"&&!s.emulateJSON){a.processData=false}if(a.type==="PATCH"&&k){a.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var h=s.xhr=e.ajax(i.extend(a,s));r.trigger("request",r,h,s);return h};var k=typeof window!=="undefined"&&!!window.ActiveXObject&&!(window.XMLHttpRequest&&(new XMLHttpRequest).dispatchEvent);var T={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var $=e.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var S=/\((.*?)\)/g;var H=/(\(\?)?:\w+/g;var A=/\*\w+/g;var I=/[\-{}\[\]+?.,\\\^$|#\s]/g;i.extend($.prototype,u,{initialize:function(){},route:function(t,r,s){if(!i.isRegExp(t))t=this._routeToRegExp(t);if(i.isFunction(r)){s=r;r=""}if(!s)s=this[r];var n=this;e.history.route(t,function(i){var a=n._extractParameters(t,i);n.execute(s,a);n.trigger.apply(n,["route:"+r].concat(a));n.trigger("route",r,a);e.history.trigger("route",n,r,a)});return this},execute:function(t,e){if(t)t.apply(this,e)},navigate:function(t,i){e.history.navigate(t,i);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=i.result(this,"routes");var t,e=i.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(I,"\\$&").replace(S,"(?:$1)?").replace(H,function(t,e){return e?t:"([^/?]+)"}).replace(A,"([^?]*?)");return new RegExp("^"+t+"(?:\\?([\\s\\S]*))?$")},_extractParameters:function(t,e){var r=t.exec(e).slice(1);return i.map(r,function(t,e){if(e===r.length-1)return t||null;return t?decodeURIComponent(t):null})}});var N=e.History=function(){this.handlers=[];i.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var R=/^[#\/]|\s+$/g;var O=/^\/+|\/+$/g;var P=/msie [\w.]+/;var C=/\/$/;var j=/#.*$/;N.started=false;i.extend(N.prototype,u,{interval:50,atRoot:function(){return this.location.pathname.replace(/[^\/]$/,"$&/")===this.root},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=decodeURI(this.location.pathname+this.location.search);var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.slice(i.length)}else{t=this.getHash()}}return t.replace(R,"")},start:function(t){if(N.started)throw new Error("Backbone.history has already been started");N.started=true;this.options=i.extend({root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var r=this.getFragment();var s=document.documentMode;var n=P.exec(navigator.userAgent.toLowerCase())&&(!s||s<=7);this.root=("/"+this.root+"/").replace(O,"/");if(n&&this._wantsHashChange){var a=e.$('<iframe src="javascript:0" tabindex="-1">');this.iframe=a.hide().appendTo("body")[0].contentWindow;this.navigate(r)}if(this._hasPushState){e.$(window).on("popstate",this.checkUrl)}else if(this._wantsHashChange&&"onhashchange"in window&&!n){e.$(window).on("hashchange",this.checkUrl)}else if(this._wantsHashChange){this._checkUrlInterval=setInterval(this.checkUrl,this.interval)}this.fragment=r;var o=this.location;if(this._wantsHashChange&&this._wantsPushState){if(!this._hasPushState&&!this.atRoot()){this.fragment=this.getFragment(null,true);this.location.replace(this.root+"#"+this.fragment);return true}else if(this._hasPushState&&this.atRoot()&&o.hash){this.fragment=this.getHash().replace(R,"");this.history.replaceState({},document.title,this.root+this.fragment)}}if(!this.options.silent)return this.loadUrl()},stop:function(){e.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl);if(this._checkUrlInterval)clearInterval(this._checkUrlInterval);N.started=false},route:function(t,e){this.handlers.unshift({route:t,callback:e})},checkUrl:function(t){var e=this.getFragment();if(e===this.fragment&&this.iframe){e=this.getFragment(this.getHash(this.iframe))}if(e===this.fragment)return false;if(this.iframe)this.navigate(e);this.loadUrl()},loadUrl:function(t){t=this.fragment=this.getFragment(t);return i.any(this.handlers,function(e){if(e.route.test(t)){e.callback(t);return true}})},navigate:function(t,e){if(!N.started)return false;if(!e||e===true)e={trigger:!!e};var i=this.root+(t=this.getFragment(t||""));t=t.replace(j,"");if(this.fragment===t)return;this.fragment=t;if(t===""&&i!=="/")i=i.slice(0,-1);if(this._hasPushState){this.history[e.replace?"replaceState":"pushState"]({},document.title,i)}else if(this._wantsHashChange){this._updateHash(this.location,t,e.replace);if(this.iframe&&t!==this.getFragment(this.getHash(this.iframe))){if(!e.replace)this.iframe.document.open().close();this._updateHash(this.iframe.location,t,e.replace)}}else{return this.location.assign(i)}if(e.trigger)return this.loadUrl(t)},_updateHash:function(t,e,i){if(i){var r=t.href.replace(/(javascript:|#).*$/,"");t.replace(r+"#"+e)}else{t.hash="#"+e}}});e.history=new N;var U=function(t,e){var r=this;var s;if(t&&i.has(t,"constructor")){s=t.constructor}else{s=function(){return r.apply(this,arguments)}}i.extend(s,r,e);var n=function(){this.constructor=s};n.prototype=r.prototype;s.prototype=new n;if(t)i.extend(s.prototype,t);s.__super__=r.prototype;return s};p.extend=g.extend=$.extend=w.extend=N.extend=U;var M=function(){throw new Error('A "url" property or function must be specified')};var q=function(t,e){var i=e.error;e.error=function(r){if(i)i(t,r,e);t.trigger("error",t,r,e)}};return e});1 (function(t){var e=typeof self=="object"&&self.self==self&&self||typeof global=="object"&&global.global==global&&global;if(typeof define==="function"&&define.amd){define(["underscore","jquery","exports"],function(i,r,n){e.Backbone=t(e,n,i,r)})}else if(typeof exports!=="undefined"){var i=require("underscore"),r;try{r=require("jquery")}catch(n){}t(e,exports,i,r)}else{e.Backbone=t(e,{},e._,e.jQuery||e.Zepto||e.ender||e.$)}})(function(t,e,i,r){var n=t.Backbone;var s=Array.prototype.slice;e.VERSION="1.2.3";e.$=r;e.noConflict=function(){t.Backbone=n;return this};e.emulateHTTP=false;e.emulateJSON=false;var a=function(t,e,r){switch(t){case 1:return function(){return i[e](this[r])};case 2:return function(t){return i[e](this[r],t)};case 3:return function(t,n){return i[e](this[r],h(t,this),n)};case 4:return function(t,n,s){return i[e](this[r],h(t,this),n,s)};default:return function(){var t=s.call(arguments);t.unshift(this[r]);return i[e].apply(i,t)}}};var o=function(t,e,r){i.each(e,function(e,n){if(i[n])t.prototype[n]=a(e,n,r)})};var h=function(t,e){if(i.isFunction(t))return t;if(i.isObject(t)&&!e._isModel(t))return u(t);if(i.isString(t))return function(e){return e.get(t)};return t};var u=function(t){var e=i.matches(t);return function(t){return e(t.attributes)}};var l=e.Events={};var c=/\s+/;var f=function(t,e,r,n,s){var a=0,o;if(r&&typeof r==="object"){if(n!==void 0&&"context"in s&&s.context===void 0)s.context=n;for(o=i.keys(r);a<o.length;a++){e=f(t,e,o[a],r[o[a]],s)}}else if(r&&c.test(r)){for(o=r.split(c);a<o.length;a++){e=t(e,o[a],n,s)}}else{e=t(e,r,n,s)}return e};l.on=function(t,e,i){return d(this,t,e,i)};var d=function(t,e,i,r,n){t._events=f(v,t._events||{},e,i,{context:r,ctx:t,listening:n});if(n){var s=t._listeners||(t._listeners={});s[n.id]=n}return t};l.listenTo=function(t,e,r){if(!t)return this;var n=t._listenId||(t._listenId=i.uniqueId("l"));var s=this._listeningTo||(this._listeningTo={});var a=s[n];if(!a){var o=this._listenId||(this._listenId=i.uniqueId("l"));a=s[n]={obj:t,objId:n,id:o,listeningTo:s,count:0}}d(t,e,r,this,a);return this};var v=function(t,e,i,r){if(i){var n=t[e]||(t[e]=[]);var s=r.context,a=r.ctx,o=r.listening;if(o)o.count++;n.push({callback:i,context:s,ctx:s||a,listening:o})}return t};l.off=function(t,e,i){if(!this._events)return this;this._events=f(g,this._events,t,e,{context:i,listeners:this._listeners});return this};l.stopListening=function(t,e,r){var n=this._listeningTo;if(!n)return this;var s=t?[t._listenId]:i.keys(n);for(var a=0;a<s.length;a++){var o=n[s[a]];if(!o)break;o.obj.off(e,r,this)}if(i.isEmpty(n))this._listeningTo=void 0;return this};var g=function(t,e,r,n){if(!t)return;var s=0,a;var o=n.context,h=n.listeners;if(!e&&!r&&!o){var u=i.keys(h);for(;s<u.length;s++){a=h[u[s]];delete h[a.id];delete a.listeningTo[a.objId]}return}var l=e?[e]:i.keys(t);for(;s<l.length;s++){e=l[s];var c=t[e];if(!c)break;var f=[];for(var d=0;d<c.length;d++){var v=c[d];if(r&&r!==v.callback&&r!==v.callback._callback||o&&o!==v.context){f.push(v)}else{a=v.listening;if(a&&--a.count===0){delete h[a.id];delete a.listeningTo[a.objId]}}}if(f.length){t[e]=f}else{delete t[e]}}if(i.size(t))return t};l.once=function(t,e,r){var n=f(p,{},t,e,i.bind(this.off,this));return this.on(n,void 0,r)};l.listenToOnce=function(t,e,r){var n=f(p,{},e,r,i.bind(this.stopListening,this,t));return this.listenTo(t,n)};var p=function(t,e,r,n){if(r){var s=t[e]=i.once(function(){n(e,s);r.apply(this,arguments)});s._callback=r}return t};l.trigger=function(t){if(!this._events)return this;var e=Math.max(0,arguments.length-1);var i=Array(e);for(var r=0;r<e;r++)i[r]=arguments[r+1];f(m,this._events,t,void 0,i);return this};var m=function(t,e,i,r){if(t){var n=t[e];var s=t.all;if(n&&s)s=s.slice();if(n)_(n,r);if(s)_(s,[e].concat(r))}return t};var _=function(t,e){var i,r=-1,n=t.length,s=e[0],a=e[1],o=e[2];switch(e.length){case 0:while(++r<n)(i=t[r]).callback.call(i.ctx);return;case 1:while(++r<n)(i=t[r]).callback.call(i.ctx,s);return;case 2:while(++r<n)(i=t[r]).callback.call(i.ctx,s,a);return;case 3:while(++r<n)(i=t[r]).callback.call(i.ctx,s,a,o);return;default:while(++r<n)(i=t[r]).callback.apply(i.ctx,e);return}};l.bind=l.on;l.unbind=l.off;i.extend(e,l);var y=e.Model=function(t,e){var r=t||{};e||(e={});this.cid=i.uniqueId(this.cidPrefix);this.attributes={};if(e.collection)this.collection=e.collection;if(e.parse)r=this.parse(r,e)||{};r=i.defaults({},r,i.result(this,"defaults"));this.set(r,e);this.changed={};this.initialize.apply(this,arguments)};i.extend(y.prototype,l,{changed:null,validationError:null,idAttribute:"id",cidPrefix:"c",initialize:function(){},toJSON:function(t){return i.clone(this.attributes)},sync:function(){return e.sync.apply(this,arguments)},get:function(t){return this.attributes[t]},escape:function(t){return i.escape(this.get(t))},has:function(t){return this.get(t)!=null},matches:function(t){return!!i.iteratee(t,this)(this.attributes)},set:function(t,e,r){if(t==null)return this;var n;if(typeof t==="object"){n=t;r=e}else{(n={})[t]=e}r||(r={});if(!this._validate(n,r))return false;var s=r.unset;var a=r.silent;var o=[];var h=this._changing;this._changing=true;if(!h){this._previousAttributes=i.clone(this.attributes);this.changed={}}var u=this.attributes;var l=this.changed;var c=this._previousAttributes;for(var f in n){e=n[f];if(!i.isEqual(u[f],e))o.push(f);if(!i.isEqual(c[f],e)){l[f]=e}else{delete l[f]}s?delete u[f]:u[f]=e}this.id=this.get(this.idAttribute);if(!a){if(o.length)this._pending=r;for(var d=0;d<o.length;d++){this.trigger("change:"+o[d],this,u[o[d]],r)}}if(h)return this;if(!a){while(this._pending){r=this._pending;this._pending=false;this.trigger("change",this,r)}}this._pending=false;this._changing=false;return this},unset:function(t,e){return this.set(t,void 0,i.extend({},e,{unset:true}))},clear:function(t){var e={};for(var r in this.attributes)e[r]=void 0;return this.set(e,i.extend({},t,{unset:true}))},hasChanged:function(t){if(t==null)return!i.isEmpty(this.changed);return i.has(this.changed,t)},changedAttributes:function(t){if(!t)return this.hasChanged()?i.clone(this.changed):false;var e=this._changing?this._previousAttributes:this.attributes;var r={};for(var n in t){var s=t[n];if(i.isEqual(e[n],s))continue;r[n]=s}return i.size(r)?r:false},previous:function(t){if(t==null||!this._previousAttributes)return null;return this._previousAttributes[t]},previousAttributes:function(){return i.clone(this._previousAttributes)},fetch:function(t){t=i.extend({parse:true},t);var e=this;var r=t.success;t.success=function(i){var n=t.parse?e.parse(i,t):i;if(!e.set(n,t))return false;if(r)r.call(t.context,e,i,t);e.trigger("sync",e,i,t)};z(this,t);return this.sync("read",this,t)},save:function(t,e,r){var n;if(t==null||typeof t==="object"){n=t;r=e}else{(n={})[t]=e}r=i.extend({validate:true,parse:true},r);var s=r.wait;if(n&&!s){if(!this.set(n,r))return false}else{if(!this._validate(n,r))return false}var a=this;var o=r.success;var h=this.attributes;r.success=function(t){a.attributes=h;var e=r.parse?a.parse(t,r):t;if(s)e=i.extend({},n,e);if(e&&!a.set(e,r))return false;if(o)o.call(r.context,a,t,r);a.trigger("sync",a,t,r)};z(this,r);if(n&&s)this.attributes=i.extend({},h,n);var u=this.isNew()?"create":r.patch?"patch":"update";if(u==="patch"&&!r.attrs)r.attrs=n;var l=this.sync(u,this,r);this.attributes=h;return l},destroy:function(t){t=t?i.clone(t):{};var e=this;var r=t.success;var n=t.wait;var s=function(){e.stopListening();e.trigger("destroy",e,e.collection,t)};t.success=function(i){if(n)s();if(r)r.call(t.context,e,i,t);if(!e.isNew())e.trigger("sync",e,i,t)};var a=false;if(this.isNew()){i.defer(t.success)}else{z(this,t);a=this.sync("delete",this,t)}if(!n)s();return a},url:function(){var t=i.result(this,"urlRoot")||i.result(this.collection,"url")||F();if(this.isNew())return t;var e=this.get(this.idAttribute);return t.replace(/[^\/]$/,"$&/")+encodeURIComponent(e)},parse:function(t,e){return t},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return!this.has(this.idAttribute)},isValid:function(t){return this._validate({},i.defaults({validate:true},t))},_validate:function(t,e){if(!e.validate||!this.validate)return true;t=i.extend({},this.attributes,t);var r=this.validationError=this.validate(t,e)||null;if(!r)return true;this.trigger("invalid",this,r,i.extend(e,{validationError:r}));return false}});var b={keys:1,values:1,pairs:1,invert:1,pick:0,omit:0,chain:1,isEmpty:1};o(y,b,"attributes");var x=e.Collection=function(t,e){e||(e={});if(e.model)this.model=e.model;if(e.comparator!==void 0)this.comparator=e.comparator;this._reset();this.initialize.apply(this,arguments);if(t)this.reset(t,i.extend({silent:true},e))};var w={add:true,remove:true,merge:true};var E={add:true,remove:false};var k=function(t,e,i){i=Math.min(Math.max(i,0),t.length);var r=Array(t.length-i);var n=e.length;for(var s=0;s<r.length;s++)r[s]=t[s+i];for(s=0;s<n;s++)t[s+i]=e[s];for(s=0;s<r.length;s++)t[s+n+i]=r[s]};i.extend(x.prototype,l,{model:y,initialize:function(){},toJSON:function(t){return this.map(function(e){return e.toJSON(t)})},sync:function(){return e.sync.apply(this,arguments)},add:function(t,e){return this.set(t,i.extend({merge:false},e,E))},remove:function(t,e){e=i.extend({},e);var r=!i.isArray(t);t=r?[t]:i.clone(t);var n=this._removeModels(t,e);if(!e.silent&&n)this.trigger("update",this,e);return r?n[0]:n},set:function(t,e){if(t==null)return;e=i.defaults({},e,w);if(e.parse&&!this._isModel(t))t=this.parse(t,e);var r=!i.isArray(t);t=r?[t]:t.slice();var n=e.at;if(n!=null)n=+n;if(n<0)n+=this.length+1;var s=[];var a=[];var o=[];var h={};var u=e.add;var l=e.merge;var c=e.remove;var f=false;var d=this.comparator&&n==null&&e.sort!==false;var v=i.isString(this.comparator)?this.comparator:null;var g;for(var p=0;p<t.length;p++){g=t[p];var m=this.get(g);if(m){if(l&&g!==m){var _=this._isModel(g)?g.attributes:g;if(e.parse)_=m.parse(_,e);m.set(_,e);if(d&&!f)f=m.hasChanged(v)}if(!h[m.cid]){h[m.cid]=true;s.push(m)}t[p]=m}else if(u){g=t[p]=this._prepareModel(g,e);if(g){a.push(g);this._addReference(g,e);h[g.cid]=true;s.push(g)}}}if(c){for(p=0;p<this.length;p++){g=this.models[p];if(!h[g.cid])o.push(g)}if(o.length)this._removeModels(o,e)}var y=false;var b=!d&&u&&c;if(s.length&&b){y=this.length!=s.length||i.some(this.models,function(t,e){return t!==s[e]});this.models.length=0;k(this.models,s,0);this.length=this.models.length}else if(a.length){if(d)f=true;k(this.models,a,n==null?this.length:n);this.length=this.models.length}if(f)this.sort({silent:true});if(!e.silent){for(p=0;p<a.length;p++){if(n!=null)e.index=n+p;g=a[p];g.trigger("add",g,this,e)}if(f||y)this.trigger("sort",this,e);if(a.length||o.length)this.trigger("update",this,e)}return r?t[0]:t},reset:function(t,e){e=e?i.clone(e):{};for(var r=0;r<this.models.length;r++){this._removeReference(this.models[r],e)}e.previousModels=this.models;this._reset();t=this.add(t,i.extend({silent:true},e));if(!e.silent)this.trigger("reset",this,e);return t},push:function(t,e){return this.add(t,i.extend({at:this.length},e))},pop:function(t){var e=this.at(this.length-1);return this.remove(e,t)},unshift:function(t,e){return this.add(t,i.extend({at:0},e))},shift:function(t){var e=this.at(0);return this.remove(e,t)},slice:function(){return s.apply(this.models,arguments)},get:function(t){if(t==null)return void 0;var e=this.modelId(this._isModel(t)?t.attributes:t);return this._byId[t]||this._byId[e]||this._byId[t.cid]},at:function(t){if(t<0)t+=this.length;return this.models[t]},where:function(t,e){return this[e?"find":"filter"](t)},findWhere:function(t){return this.where(t,true)},sort:function(t){var e=this.comparator;if(!e)throw new Error("Cannot sort a set without a comparator");t||(t={});var r=e.length;if(i.isFunction(e))e=i.bind(e,this);if(r===1||i.isString(e)){this.models=this.sortBy(e)}else{this.models.sort(e)}if(!t.silent)this.trigger("sort",this,t);return this},pluck:function(t){return i.invoke(this.models,"get",t)},fetch:function(t){t=i.extend({parse:true},t);var e=t.success;var r=this;t.success=function(i){var n=t.reset?"reset":"set";r[n](i,t);if(e)e.call(t.context,r,i,t);r.trigger("sync",r,i,t)};z(this,t);return this.sync("read",this,t)},create:function(t,e){e=e?i.clone(e):{};var r=e.wait;t=this._prepareModel(t,e);if(!t)return false;if(!r)this.add(t,e);var n=this;var s=e.success;e.success=function(t,e,i){if(r)n.add(t,i);if(s)s.call(i.context,t,e,i)};t.save(null,e);return t},parse:function(t,e){return t},clone:function(){return new this.constructor(this.models,{model:this.model,comparator:this.comparator})},modelId:function(t){return t[this.model.prototype.idAttribute||"id"]},_reset:function(){this.length=0;this.models=[];this._byId={}},_prepareModel:function(t,e){if(this._isModel(t)){if(!t.collection)t.collection=this;return t}e=e?i.clone(e):{};e.collection=this;var r=new this.model(t,e);if(!r.validationError)return r;this.trigger("invalid",this,r.validationError,e);return false},_removeModels:function(t,e){var i=[];for(var r=0;r<t.length;r++){var n=this.get(t[r]);if(!n)continue;var s=this.indexOf(n);this.models.splice(s,1);this.length--;if(!e.silent){e.index=s;n.trigger("remove",n,this,e)}i.push(n);this._removeReference(n,e)}return i.length?i:false},_isModel:function(t){return t instanceof y},_addReference:function(t,e){this._byId[t.cid]=t;var i=this.modelId(t.attributes);if(i!=null)this._byId[i]=t;t.on("all",this._onModelEvent,this)},_removeReference:function(t,e){delete this._byId[t.cid];var i=this.modelId(t.attributes);if(i!=null)delete this._byId[i];if(this===t.collection)delete t.collection;t.off("all",this._onModelEvent,this)},_onModelEvent:function(t,e,i,r){if((t==="add"||t==="remove")&&i!==this)return;if(t==="destroy")this.remove(e,r);if(t==="change"){var n=this.modelId(e.previousAttributes());var s=this.modelId(e.attributes);if(n!==s){if(n!=null)delete this._byId[n];if(s!=null)this._byId[s]=e}}this.trigger.apply(this,arguments)}});var S={forEach:3,each:3,map:3,collect:3,reduce:4,foldl:4,inject:4,reduceRight:4,foldr:4,find:3,detect:3,filter:3,select:3,reject:3,every:3,all:3,some:3,any:3,include:3,includes:3,contains:3,invoke:0,max:3,min:3,toArray:1,size:1,first:3,head:3,take:3,initial:3,rest:3,tail:3,drop:3,last:3,without:0,difference:0,indexOf:3,shuffle:1,lastIndexOf:3,isEmpty:1,chain:1,sample:3,partition:3,groupBy:3,countBy:3,sortBy:3,indexBy:3};o(x,S,"models");var I=e.View=function(t){this.cid=i.uniqueId("view");i.extend(this,i.pick(t,P));this._ensureElement();this.initialize.apply(this,arguments)};var T=/^(\S+)\s*(.*)$/;var P=["model","collection","el","id","attributes","className","tagName","events"];i.extend(I.prototype,l,{tagName:"div",$:function(t){return this.$el.find(t)},initialize:function(){},render:function(){return this},remove:function(){this._removeElement();this.stopListening();return this},_removeElement:function(){this.$el.remove()},setElement:function(t){this.undelegateEvents();this._setElement(t);this.delegateEvents();return this},_setElement:function(t){this.$el=t instanceof e.$?t:e.$(t);this.el=this.$el[0]},delegateEvents:function(t){t||(t=i.result(this,"events"));if(!t)return this;this.undelegateEvents();for(var e in t){var r=t[e];if(!i.isFunction(r))r=this[r];if(!r)continue;var n=e.match(T);this.delegate(n[1],n[2],i.bind(r,this))}return this},delegate:function(t,e,i){this.$el.on(t+".delegateEvents"+this.cid,e,i);return this},undelegateEvents:function(){if(this.$el)this.$el.off(".delegateEvents"+this.cid);return this},undelegate:function(t,e,i){this.$el.off(t+".delegateEvents"+this.cid,e,i);return this},_createElement:function(t){return document.createElement(t)},_ensureElement:function(){if(!this.el){var t=i.extend({},i.result(this,"attributes"));if(this.id)t.id=i.result(this,"id");if(this.className)t["class"]=i.result(this,"className");this.setElement(this._createElement(i.result(this,"tagName")));this._setAttributes(t)}else{this.setElement(i.result(this,"el"))}},_setAttributes:function(t){this.$el.attr(t)}});e.sync=function(t,r,n){var s=H[t];i.defaults(n||(n={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:s,dataType:"json"};if(!n.url){a.url=i.result(r,"url")||F()}if(n.data==null&&r&&(t==="create"||t==="update"||t==="patch")){a.contentType="application/json";a.data=JSON.stringify(n.attrs||r.toJSON(n))}if(n.emulateJSON){a.contentType="application/x-www-form-urlencoded";a.data=a.data?{model:a.data}:{}}if(n.emulateHTTP&&(s==="PUT"||s==="DELETE"||s==="PATCH")){a.type="POST";if(n.emulateJSON)a.data._method=s;var o=n.beforeSend;n.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",s);if(o)return o.apply(this,arguments)}}if(a.type!=="GET"&&!n.emulateJSON){a.processData=false}var h=n.error;n.error=function(t,e,i){n.textStatus=e;n.errorThrown=i;if(h)h.call(n.context,t,e,i)};var u=n.xhr=e.ajax(i.extend(a,n));r.trigger("request",r,u,n);return u};var H={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var $=e.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var A=/\((.*?)\)/g;var C=/(\(\?)?:\w+/g;var R=/\*\w+/g;var j=/[\-{}\[\]+?.,\\\^$|#\s]/g;i.extend($.prototype,l,{initialize:function(){},route:function(t,r,n){if(!i.isRegExp(t))t=this._routeToRegExp(t);if(i.isFunction(r)){n=r;r=""}if(!n)n=this[r];var s=this;e.history.route(t,function(i){var a=s._extractParameters(t,i);if(s.execute(n,a,r)!==false){s.trigger.apply(s,["route:"+r].concat(a));s.trigger("route",r,a);e.history.trigger("route",s,r,a)}});return this},execute:function(t,e,i){if(t)t.apply(this,e)},navigate:function(t,i){e.history.navigate(t,i);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=i.result(this,"routes");var t,e=i.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(j,"\\$&").replace(A,"(?:$1)?").replace(C,function(t,e){return e?t:"([^/?]+)"}).replace(R,"([^?]*?)");return new RegExp("^"+t+"(?:\\?([\\s\\S]*))?$")},_extractParameters:function(t,e){var r=t.exec(e).slice(1);return i.map(r,function(t,e){if(e===r.length-1)return t||null;return t?decodeURIComponent(t):null})}});var M=e.History=function(){this.handlers=[];this.checkUrl=i.bind(this.checkUrl,this);if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var N=/^[#\/]|\s+$/g;var O=/^\/+|\/+$/g;var U=/#.*$/;M.started=false;i.extend(M.prototype,l,{interval:50,atRoot:function(){var t=this.location.pathname.replace(/[^\/]$/,"$&/");return t===this.root&&!this.getSearch()},matchRoot:function(){var t=this.decodeFragment(this.location.pathname);var e=t.slice(0,this.root.length-1)+"/";return e===this.root},decodeFragment:function(t){return decodeURI(t.replace(/%25/g,"%2525"))},getSearch:function(){var t=this.location.href.replace(/#.*/,"").match(/\?.+/);return t?t[0]:""},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getPath:function(){var t=this.decodeFragment(this.location.pathname+this.getSearch()).slice(this.root.length-1);return t.charAt(0)==="/"?t.slice(1):t},getFragment:function(t){if(t==null){if(this._usePushState||!this._wantsHashChange){t=this.getPath()}else{t=this.getHash()}}return t.replace(N,"")},start:function(t){if(M.started)throw new Error("Backbone.history has already been started");M.started=true;this.options=i.extend({root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._hasHashChange="onhashchange"in window&&(document.documentMode===void 0||document.documentMode>7);this._useHashChange=this._wantsHashChange&&this._hasHashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.history&&this.history.pushState);this._usePushState=this._wantsPushState&&this._hasPushState;this.fragment=this.getFragment();this.root=("/"+this.root+"/").replace(O,"/");if(this._wantsHashChange&&this._wantsPushState){if(!this._hasPushState&&!this.atRoot()){var e=this.root.slice(0,-1)||"/";this.location.replace(e+"#"+this.getPath());return true}else if(this._hasPushState&&this.atRoot()){this.navigate(this.getHash(),{replace:true})}}if(!this._hasHashChange&&this._wantsHashChange&&!this._usePushState){this.iframe=document.createElement("iframe");this.iframe.src="javascript:0";this.iframe.style.display="none";this.iframe.tabIndex=-1;var r=document.body;var n=r.insertBefore(this.iframe,r.firstChild).contentWindow;n.document.open();n.document.close();n.location.hash="#"+this.fragment}var s=window.addEventListener||function(t,e){return attachEvent("on"+t,e)};if(this._usePushState){s("popstate",this.checkUrl,false)}else if(this._useHashChange&&!this.iframe){s("hashchange",this.checkUrl,false)}else if(this._wantsHashChange){this._checkUrlInterval=setInterval(this.checkUrl,this.interval)}if(!this.options.silent)return this.loadUrl()},stop:function(){var t=window.removeEventListener||function(t,e){return detachEvent("on"+t,e)};if(this._usePushState){t("popstate",this.checkUrl,false)}else if(this._useHashChange&&!this.iframe){t("hashchange",this.checkUrl,false)}if(this.iframe){document.body.removeChild(this.iframe);this.iframe=null}if(this._checkUrlInterval)clearInterval(this._checkUrlInterval);M.started=false},route:function(t,e){this.handlers.unshift({route:t,callback:e})},checkUrl:function(t){var e=this.getFragment();if(e===this.fragment&&this.iframe){e=this.getHash(this.iframe.contentWindow)}if(e===this.fragment)return false;if(this.iframe)this.navigate(e);this.loadUrl()},loadUrl:function(t){if(!this.matchRoot())return false;t=this.fragment=this.getFragment(t);return i.some(this.handlers,function(e){if(e.route.test(t)){e.callback(t);return true}})},navigate:function(t,e){if(!M.started)return false;if(!e||e===true)e={trigger:!!e};t=this.getFragment(t||"");var i=this.root;if(t===""||t.charAt(0)==="?"){i=i.slice(0,-1)||"/"}var r=i+t;t=this.decodeFragment(t.replace(U,""));if(this.fragment===t)return;this.fragment=t;if(this._usePushState){this.history[e.replace?"replaceState":"pushState"]({},document.title,r)}else if(this._wantsHashChange){this._updateHash(this.location,t,e.replace);if(this.iframe&&t!==this.getHash(this.iframe.contentWindow)){var n=this.iframe.contentWindow;if(!e.replace){n.document.open();n.document.close()}this._updateHash(n.location,t,e.replace)}}else{return this.location.assign(r)}if(e.trigger)return this.loadUrl(t)},_updateHash:function(t,e,i){if(i){var r=t.href.replace(/(javascript:|#).*$/,"");t.replace(r+"#"+e)}else{t.hash="#"+e}}});e.history=new M;var q=function(t,e){var r=this;var n;if(t&&i.has(t,"constructor")){n=t.constructor}else{n=function(){return r.apply(this,arguments)}}i.extend(n,r,e);var s=function(){this.constructor=n};s.prototype=r.prototype;n.prototype=new s;if(t)i.extend(n.prototype,t);n.__super__=r.prototype;return n};y.extend=x.extend=$.extend=I.extend=M.extend=q;var F=function(){throw new Error('A "url" property or function must be specified')};var z=function(t,e){var i=e.error;e.error=function(r){if(i)i.call(e.context,t,r,e);t.trigger("error",t,r,e)}};return e}); -
trunk/src/wp-includes/js/media-audiovideo.js
r36233 r36546 729 729 this.on( 'media:setting:remove', this.render ); 730 730 this.on( 'media:setting:remove', this.setPlayer ); 731 this.events = _.extend( this.events, { 731 732 AttachmentDisplay.prototype.initialize.apply( this, arguments ); 733 }, 734 735 events: function(){ 736 return _.extend( { 732 737 'click .remove-setting' : 'removeSetting', 733 738 'change .content-track' : 'setTracks', 734 739 'click .remove-track' : 'setTracks', 735 740 'click .add-media-source' : 'addSource' 736 } ); 737 738 AttachmentDisplay.prototype.initialize.apply( this, arguments ); 741 }, AttachmentDisplay.prototype.events ); 739 742 }, 740 743 -
trunk/src/wp-includes/js/media/views/media-details.js
r36233 r36546 24 24 this.on( 'media:setting:remove', this.render ); 25 25 this.on( 'media:setting:remove', this.setPlayer ); 26 this.events = _.extend( this.events, { 26 27 AttachmentDisplay.prototype.initialize.apply( this, arguments ); 28 }, 29 30 events: function(){ 31 return _.extend( { 27 32 'click .remove-setting' : 'removeSetting', 28 33 'change .content-track' : 'setTracks', 29 34 'click .remove-track' : 'setTracks', 30 35 'click .add-media-source' : 'addSource' 31 } ); 32 33 AttachmentDisplay.prototype.initialize.apply( this, arguments ); 36 }, AttachmentDisplay.prototype.events ); 34 37 }, 35 38 -
trunk/src/wp-includes/js/underscore.js
r31471 r36546 1 // Underscore.js 1. 6.01 // Underscore.js 1.8.3 2 2 // http://underscorejs.org 3 // (c) 2009-201 4Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors3 // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 4 // Underscore may be freely distributed under the MIT license. 5 5 … … 14 14 // Save the previous value of the `_` variable. 15 15 var previousUnderscore = root._; 16 17 // Establish the object that gets returned to break out of a loop iteration.18 var breaker = {};19 16 20 17 // Save bytes in the minified (but not gzipped) version: … … 25 22 push = ArrayProto.push, 26 23 slice = ArrayProto.slice, 27 concat = ArrayProto.concat,28 24 toString = ObjProto.toString, 29 25 hasOwnProperty = ObjProto.hasOwnProperty; … … 32 28 // are declared here. 33 29 var 34 nativeForEach = ArrayProto.forEach,35 nativeMap = ArrayProto.map,36 nativeReduce = ArrayProto.reduce,37 nativeReduceRight = ArrayProto.reduceRight,38 nativeFilter = ArrayProto.filter,39 nativeEvery = ArrayProto.every,40 nativeSome = ArrayProto.some,41 nativeIndexOf = ArrayProto.indexOf,42 nativeLastIndexOf = ArrayProto.lastIndexOf,43 30 nativeIsArray = Array.isArray, 44 31 nativeKeys = Object.keys, 45 nativeBind = FuncProto.bind; 32 nativeBind = FuncProto.bind, 33 nativeCreate = Object.create; 34 35 // Naked function reference for surrogate-prototype-swapping. 36 var Ctor = function(){}; 46 37 47 38 // Create a safe reference to the Underscore object for use below. … … 54 45 // Export the Underscore object for **Node.js**, with 55 46 // backwards-compatibility for the old `require()` API. If we're in 56 // the browser, add `_` as a global object via a string identifier, 57 // for Closure Compiler "advanced" mode. 47 // the browser, add `_` as a global object. 58 48 if (typeof exports !== 'undefined') { 59 49 if (typeof module !== 'undefined' && module.exports) { … … 66 56 67 57 // Current version. 68 _.VERSION = '1.6.0'; 58 _.VERSION = '1.8.3'; 59 60 // Internal function that returns an efficient (for current engines) version 61 // of the passed-in callback, to be repeatedly applied in other Underscore 62 // functions. 63 var optimizeCb = function(func, context, argCount) { 64 if (context === void 0) return func; 65 switch (argCount == null ? 3 : argCount) { 66 case 1: return function(value) { 67 return func.call(context, value); 68 }; 69 case 2: return function(value, other) { 70 return func.call(context, value, other); 71 }; 72 case 3: return function(value, index, collection) { 73 return func.call(context, value, index, collection); 74 }; 75 case 4: return function(accumulator, value, index, collection) { 76 return func.call(context, accumulator, value, index, collection); 77 }; 78 } 79 return function() { 80 return func.apply(context, arguments); 81 }; 82 }; 83 84 // A mostly-internal function to generate callbacks that can be applied 85 // to each element in a collection, returning the desired result — either 86 // identity, an arbitrary callback, a property matcher, or a property accessor. 87 var cb = function(value, context, argCount) { 88 if (value == null) return _.identity; 89 if (_.isFunction(value)) return optimizeCb(value, context, argCount); 90 if (_.isObject(value)) return _.matcher(value); 91 return _.property(value); 92 }; 93 _.iteratee = function(value, context) { 94 return cb(value, context, Infinity); 95 }; 96 97 // An internal function for creating assigner functions. 98 var createAssigner = function(keysFunc, undefinedOnly) { 99 return function(obj) { 100 var length = arguments.length; 101 if (length < 2 || obj == null) return obj; 102 for (var index = 1; index < length; index++) { 103 var source = arguments[index], 104 keys = keysFunc(source), 105 l = keys.length; 106 for (var i = 0; i < l; i++) { 107 var key = keys[i]; 108 if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; 109 } 110 } 111 return obj; 112 }; 113 }; 114 115 // An internal function for creating a new object that inherits from another. 116 var baseCreate = function(prototype) { 117 if (!_.isObject(prototype)) return {}; 118 if (nativeCreate) return nativeCreate(prototype); 119 Ctor.prototype = prototype; 120 var result = new Ctor; 121 Ctor.prototype = null; 122 return result; 123 }; 124 125 var property = function(key) { 126 return function(obj) { 127 return obj == null ? void 0 : obj[key]; 128 }; 129 }; 130 131 // Helper for collection methods to determine whether a collection 132 // should be iterated as an array or as an object 133 // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength 134 // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 135 var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; 136 var getLength = property('length'); 137 var isArrayLike = function(collection) { 138 var length = getLength(collection); 139 return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; 140 }; 69 141 70 142 // Collection Functions … … 72 144 73 145 // The cornerstone, an `each` implementation, aka `forEach`. 74 // Handles objects with the built-in `forEach`, arrays, and raw objects. 75 // Delegates to **ECMAScript 5**'s native `forEach` if available. 76 var each = _.each = _.forEach = function(obj, iterator, context) { 77 if (obj == null) return obj; 78 if (nativeForEach && obj.forEach === nativeForEach) { 79 obj.forEach(iterator, context); 80 } else if (obj.length === +obj.length) { 81 for (var i = 0, length = obj.length; i < length; i++) { 82 if (iterator.call(context, obj[i], i, obj) === breaker) return; 146 // Handles raw objects in addition to array-likes. Treats all 147 // sparse array-likes as if they were dense. 148 _.each = _.forEach = function(obj, iteratee, context) { 149 iteratee = optimizeCb(iteratee, context); 150 var i, length; 151 if (isArrayLike(obj)) { 152 for (i = 0, length = obj.length; i < length; i++) { 153 iteratee(obj[i], i, obj); 83 154 } 84 155 } else { 85 156 var keys = _.keys(obj); 86 for ( vari = 0, length = keys.length; i < length; i++) {87 i f (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;157 for (i = 0, length = keys.length; i < length; i++) { 158 iteratee(obj[keys[i]], keys[i], obj); 88 159 } 89 160 } … … 91 162 }; 92 163 93 // Return the results of applying the iterator to each element. 94 // Delegates to **ECMAScript 5**'s native `map` if available. 95 _.map = _.collect = function(obj, iterator, context) { 96 var results = []; 97 if (obj == null) return results; 98 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); 99 each(obj, function(value, index, list) { 100 results.push(iterator.call(context, value, index, list)); 101 }); 164 // Return the results of applying the iteratee to each element. 165 _.map = _.collect = function(obj, iteratee, context) { 166 iteratee = cb(iteratee, context); 167 var keys = !isArrayLike(obj) && _.keys(obj), 168 length = (keys || obj).length, 169 results = Array(length); 170 for (var index = 0; index < length; index++) { 171 var currentKey = keys ? keys[index] : index; 172 results[index] = iteratee(obj[currentKey], currentKey, obj); 173 } 102 174 return results; 103 175 }; 104 176 105 var reduceError = 'Reduce of empty array with no initial value'; 177 // Create a reducing function iterating left or right. 178 function createReduce(dir) { 179 // Optimized iterator function as using arguments.length 180 // in the main function will deoptimize the, see #1991. 181 function iterator(obj, iteratee, memo, keys, index, length) { 182 for (; index >= 0 && index < length; index += dir) { 183 var currentKey = keys ? keys[index] : index; 184 memo = iteratee(memo, obj[currentKey], currentKey, obj); 185 } 186 return memo; 187 } 188 189 return function(obj, iteratee, memo, context) { 190 iteratee = optimizeCb(iteratee, context, 4); 191 var keys = !isArrayLike(obj) && _.keys(obj), 192 length = (keys || obj).length, 193 index = dir > 0 ? 0 : length - 1; 194 // Determine the initial value if none is provided. 195 if (arguments.length < 3) { 196 memo = obj[keys ? keys[index] : index]; 197 index += dir; 198 } 199 return iterator(obj, iteratee, memo, keys, index, length); 200 }; 201 } 106 202 107 203 // **Reduce** builds up a single result from a list of values, aka `inject`, 108 // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. 109 _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { 110 var initial = arguments.length > 2; 111 if (obj == null) obj = []; 112 if (nativeReduce && obj.reduce === nativeReduce) { 113 if (context) iterator = _.bind(iterator, context); 114 return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); 115 } 116 each(obj, function(value, index, list) { 117 if (!initial) { 118 memo = value; 119 initial = true; 120 } else { 121 memo = iterator.call(context, memo, value, index, list); 122 } 123 }); 124 if (!initial) throw new TypeError(reduceError); 125 return memo; 126 }; 204 // or `foldl`. 205 _.reduce = _.foldl = _.inject = createReduce(1); 127 206 128 207 // The right-associative version of reduce, also known as `foldr`. 129 // Delegates to **ECMAScript 5**'s native `reduceRight` if available. 130 _.reduceRight = _.foldr = function(obj, iterator, memo, context) { 131 var initial = arguments.length > 2; 132 if (obj == null) obj = []; 133 if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { 134 if (context) iterator = _.bind(iterator, context); 135 return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); 136 } 137 var length = obj.length; 138 if (length !== +length) { 139 var keys = _.keys(obj); 140 length = keys.length; 141 } 142 each(obj, function(value, index, list) { 143 index = keys ? keys[--length] : --length; 144 if (!initial) { 145 memo = obj[index]; 146 initial = true; 147 } else { 148 memo = iterator.call(context, memo, obj[index], index, list); 149 } 150 }); 151 if (!initial) throw new TypeError(reduceError); 152 return memo; 153 }; 208 _.reduceRight = _.foldr = createReduce(-1); 154 209 155 210 // Return the first value which passes a truth test. Aliased as `detect`. 156 211 _.find = _.detect = function(obj, predicate, context) { 157 var result; 158 any(obj, function(value, index, list) { 159 if (predicate.call(context, value, index, list)) { 160 result = value; 161 return true; 162 } 163 }); 164 return result; 212 var key; 213 if (isArrayLike(obj)) { 214 key = _.findIndex(obj, predicate, context); 215 } else { 216 key = _.findKey(obj, predicate, context); 217 } 218 if (key !== void 0 && key !== -1) return obj[key]; 165 219 }; 166 220 167 221 // Return all the elements that pass a truth test. 168 // Delegates to **ECMAScript 5**'s native `filter` if available.169 222 // Aliased as `select`. 170 223 _.filter = _.select = function(obj, predicate, context) { 171 224 var results = []; 172 if (obj == null) return results; 173 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); 174 each(obj, function(value, index, list) { 175 if (predicate.call(context, value, index, list)) results.push(value); 225 predicate = cb(predicate, context); 226 _.each(obj, function(value, index, list) { 227 if (predicate(value, index, list)) results.push(value); 176 228 }); 177 229 return results; … … 180 232 // Return all the elements for which a truth test fails. 181 233 _.reject = function(obj, predicate, context) { 182 return _.filter(obj, function(value, index, list) { 183 return !predicate.call(context, value, index, list); 184 }, context); 234 return _.filter(obj, _.negate(cb(predicate)), context); 185 235 }; 186 236 187 237 // Determine whether all of the elements match a truth test. 188 // Delegates to **ECMAScript 5**'s native `every` if available.189 238 // Aliased as `all`. 190 239 _.every = _.all = function(obj, predicate, context) { 191 predicate || (predicate = _.identity);192 var result = true;193 if (obj == null) return result;194 if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);195 each(obj, function(value, index, list) {196 if (! (result = result && predicate.call(context, value, index, list))) return breaker;197 } );198 return !!result;240 predicate = cb(predicate, context); 241 var keys = !isArrayLike(obj) && _.keys(obj), 242 length = (keys || obj).length; 243 for (var index = 0; index < length; index++) { 244 var currentKey = keys ? keys[index] : index; 245 if (!predicate(obj[currentKey], currentKey, obj)) return false; 246 } 247 return true; 199 248 }; 200 249 201 250 // Determine if at least one element in the object matches a truth test. 202 // Delegates to **ECMAScript 5**'s native `some` if available.203 251 // Aliased as `any`. 204 var any = _.some = _.any = function(obj, predicate, context) { 205 predicate || (predicate = _.identity); 206 var result = false; 207 if (obj == null) return result; 208 if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); 209 each(obj, function(value, index, list) { 210 if (result || (result = predicate.call(context, value, index, list))) return breaker; 211 }); 212 return !!result; 213 }; 214 215 // Determine if the array or object contains a given value (using `===`). 216 // Aliased as `include`. 217 _.contains = _.include = function(obj, target) { 218 if (obj == null) return false; 219 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; 220 return any(obj, function(value) { 221 return value === target; 222 }); 252 _.some = _.any = function(obj, predicate, context) { 253 predicate = cb(predicate, context); 254 var keys = !isArrayLike(obj) && _.keys(obj), 255 length = (keys || obj).length; 256 for (var index = 0; index < length; index++) { 257 var currentKey = keys ? keys[index] : index; 258 if (predicate(obj[currentKey], currentKey, obj)) return true; 259 } 260 return false; 261 }; 262 263 // Determine if the array or object contains a given item (using `===`). 264 // Aliased as `includes` and `include`. 265 _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { 266 if (!isArrayLike(obj)) obj = _.values(obj); 267 if (typeof fromIndex != 'number' || guard) fromIndex = 0; 268 return _.indexOf(obj, item, fromIndex) >= 0; 223 269 }; 224 270 … … 228 274 var isFunc = _.isFunction(method); 229 275 return _.map(obj, function(value) { 230 return (isFunc ? method : value[method]).apply(value, args); 276 var func = isFunc ? method : value[method]; 277 return func == null ? func : func.apply(value, args); 231 278 }); 232 279 }; … … 240 287 // containing specific `key:value` pairs. 241 288 _.where = function(obj, attrs) { 242 return _.filter(obj, _.matche s(attrs));289 return _.filter(obj, _.matcher(attrs)); 243 290 }; 244 291 … … 246 293 // containing specific `key:value` pairs. 247 294 _.findWhere = function(obj, attrs) { 248 return _.find(obj, _.matches(attrs)); 249 }; 250 251 // Return the maximum element or (element-based computation). 252 // Can't optimize arrays of integers longer than 65,535 elements. 253 // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) 254 _.max = function(obj, iterator, context) { 255 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { 256 return Math.max.apply(Math, obj); 257 } 258 var result = -Infinity, lastComputed = -Infinity; 259 each(obj, function(value, index, list) { 260 var computed = iterator ? iterator.call(context, value, index, list) : value; 261 if (computed > lastComputed) { 262 result = value; 263 lastComputed = computed; 264 } 265 }); 295 return _.find(obj, _.matcher(attrs)); 296 }; 297 298 // Return the maximum element (or element-based computation). 299 _.max = function(obj, iteratee, context) { 300 var result = -Infinity, lastComputed = -Infinity, 301 value, computed; 302 if (iteratee == null && obj != null) { 303 obj = isArrayLike(obj) ? obj : _.values(obj); 304 for (var i = 0, length = obj.length; i < length; i++) { 305 value = obj[i]; 306 if (value > result) { 307 result = value; 308 } 309 } 310 } else { 311 iteratee = cb(iteratee, context); 312 _.each(obj, function(value, index, list) { 313 computed = iteratee(value, index, list); 314 if (computed > lastComputed || computed === -Infinity && result === -Infinity) { 315 result = value; 316 lastComputed = computed; 317 } 318 }); 319 } 266 320 return result; 267 321 }; 268 322 269 323 // Return the minimum element (or element-based computation). 270 _.min = function(obj, iterator, context) { 271 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { 272 return Math.min.apply(Math, obj); 273 } 274 var result = Infinity, lastComputed = Infinity; 275 each(obj, function(value, index, list) { 276 var computed = iterator ? iterator.call(context, value, index, list) : value; 277 if (computed < lastComputed) { 278 result = value; 279 lastComputed = computed; 280 } 281 }); 324 _.min = function(obj, iteratee, context) { 325 var result = Infinity, lastComputed = Infinity, 326 value, computed; 327 if (iteratee == null && obj != null) { 328 obj = isArrayLike(obj) ? obj : _.values(obj); 329 for (var i = 0, length = obj.length; i < length; i++) { 330 value = obj[i]; 331 if (value < result) { 332 result = value; 333 } 334 } 335 } else { 336 iteratee = cb(iteratee, context); 337 _.each(obj, function(value, index, list) { 338 computed = iteratee(value, index, list); 339 if (computed < lastComputed || computed === Infinity && result === Infinity) { 340 result = value; 341 lastComputed = computed; 342 } 343 }); 344 } 282 345 return result; 283 346 }; 284 347 285 // Shuffle a n array, using the modern version of the348 // Shuffle a collection, using the modern version of the 286 349 // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). 287 350 _.shuffle = function(obj) { 288 var rand;289 var index = 0;290 var shuffled = [];291 each(obj, function(value) {292 rand = _.random( index++);293 shuffled[index - 1] = shuffled[rand];294 shuffled[rand] = value;295 } );351 var set = isArrayLike(obj) ? obj : _.values(obj); 352 var length = set.length; 353 var shuffled = Array(length); 354 for (var index = 0, rand; index < length; index++) { 355 rand = _.random(0, index); 356 if (rand !== index) shuffled[index] = shuffled[rand]; 357 shuffled[rand] = set[index]; 358 } 296 359 return shuffled; 297 360 }; … … 302 365 _.sample = function(obj, n, guard) { 303 366 if (n == null || guard) { 304 if ( obj.length !== +obj.length) obj = _.values(obj);367 if (!isArrayLike(obj)) obj = _.values(obj); 305 368 return obj[_.random(obj.length - 1)]; 306 369 } … … 308 371 }; 309 372 310 // An internal function to generate lookup iterators. 311 var lookupIterator = function(value) { 312 if (value == null) return _.identity; 313 if (_.isFunction(value)) return value; 314 return _.property(value); 315 }; 316 317 // Sort the object's values by a criterion produced by an iterator. 318 _.sortBy = function(obj, iterator, context) { 319 iterator = lookupIterator(iterator); 373 // Sort the object's values by a criterion produced by an iteratee. 374 _.sortBy = function(obj, iteratee, context) { 375 iteratee = cb(iteratee, context); 320 376 return _.pluck(_.map(obj, function(value, index, list) { 321 377 return { 322 378 value: value, 323 379 index: index, 324 criteria: iterat or.call(context,value, index, list)380 criteria: iteratee(value, index, list) 325 381 }; 326 382 }).sort(function(left, right) { … … 337 393 // An internal function used for aggregate "group by" operations. 338 394 var group = function(behavior) { 339 return function(obj, iterat or, context) {395 return function(obj, iteratee, context) { 340 396 var result = {}; 341 iterat or = lookupIterator(iterator);342 each(obj, function(value, index) {343 var key = iterat or.call(context,value, index, obj);344 behavior(result, key, value);397 iteratee = cb(iteratee, context); 398 _.each(obj, function(value, index) { 399 var key = iteratee(value, index, obj); 400 behavior(result, value, key); 345 401 }); 346 402 return result; … … 350 406 // Groups the object's values by a criterion. Pass either a string attribute 351 407 // to group by, or a function that returns the criterion. 352 _.groupBy = group(function(result, key, value) {353 _.has(result, key) ? result[key].push(value) :result[key] = [value];408 _.groupBy = group(function(result, value, key) { 409 if (_.has(result, key)) result[key].push(value); else result[key] = [value]; 354 410 }); 355 411 356 412 // Indexes the object's values by a criterion, similar to `groupBy`, but for 357 413 // when you know that your index values will be unique. 358 _.indexBy = group(function(result, key, value) {414 _.indexBy = group(function(result, value, key) { 359 415 result[key] = value; 360 416 }); … … 363 419 // either a string attribute to count by, or a function that returns the 364 420 // criterion. 365 _.countBy = group(function(result, key) {366 _.has(result, key) ? result[key]++ :result[key] = 1;421 _.countBy = group(function(result, value, key) { 422 if (_.has(result, key)) result[key]++; else result[key] = 1; 367 423 }); 368 369 // Use a comparator function to figure out the smallest index at which370 // an object should be inserted so as to maintain order. Uses binary search.371 _.sortedIndex = function(array, obj, iterator, context) {372 iterator = lookupIterator(iterator);373 var value = iterator.call(context, obj);374 var low = 0, high = array.length;375 while (low < high) {376 var mid = (low + high) >>> 1;377 iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;378 }379 return low;380 };381 424 382 425 // Safely create a real, live array from anything iterable. … … 384 427 if (!obj) return []; 385 428 if (_.isArray(obj)) return slice.call(obj); 386 if ( obj.length === +obj.length) return _.map(obj, _.identity);429 if (isArrayLike(obj)) return _.map(obj, _.identity); 387 430 return _.values(obj); 388 431 }; … … 391 434 _.size = function(obj) { 392 435 if (obj == null) return 0; 393 return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; 436 return isArrayLike(obj) ? obj.length : _.keys(obj).length; 437 }; 438 439 // Split a collection into two arrays: one whose elements all satisfy the given 440 // predicate, and one whose elements all do not satisfy the predicate. 441 _.partition = function(obj, predicate, context) { 442 predicate = cb(predicate, context); 443 var pass = [], fail = []; 444 _.each(obj, function(value, key, obj) { 445 (predicate(value, key, obj) ? pass : fail).push(value); 446 }); 447 return [pass, fail]; 394 448 }; 395 449 … … 402 456 _.first = _.head = _.take = function(array, n, guard) { 403 457 if (array == null) return void 0; 404 if ((n == null) || guard) return array[0]; 405 if (n < 0) return []; 406 return slice.call(array, 0, n); 458 if (n == null || guard) return array[0]; 459 return _.initial(array, array.length - n); 407 460 }; 408 461 409 462 // Returns everything but the last entry of the array. Especially useful on 410 463 // the arguments object. Passing **n** will return all the values in 411 // the array, excluding the last N. The **guard** check allows it to work with 412 // `_.map`. 464 // the array, excluding the last N. 413 465 _.initial = function(array, n, guard) { 414 return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));466 return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); 415 467 }; 416 468 417 469 // Get the last element of an array. Passing **n** will return the last N 418 // values in the array. The **guard** check allows it to work with `_.map`.470 // values in the array. 419 471 _.last = function(array, n, guard) { 420 472 if (array == null) return void 0; 421 if ( (n == null)|| guard) return array[array.length - 1];422 return slice.call(array, Math.max(array.length - n, 0));473 if (n == null || guard) return array[array.length - 1]; 474 return _.rest(array, Math.max(0, array.length - n)); 423 475 }; 424 476 425 477 // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. 426 478 // Especially useful on the arguments object. Passing an **n** will return 427 // the rest N values in the array. The **guard** 428 // check allows it to work with `_.map`. 479 // the rest N values in the array. 429 480 _.rest = _.tail = _.drop = function(array, n, guard) { 430 return slice.call(array, (n == null)|| guard ? 1 : n);481 return slice.call(array, n == null || guard ? 1 : n); 431 482 }; 432 483 … … 437 488 438 489 // Internal implementation of a recursive `flatten` function. 439 var flatten = function(input, shallow, output) { 440 if (shallow && _.every(input, _.isArray)) { 441 return concat.apply(output, input); 442 } 443 each(input, function(value) { 444 if (_.isArray(value) || _.isArguments(value)) { 445 shallow ? push.apply(output, value) : flatten(value, shallow, output); 446 } else { 447 output.push(value); 448 } 449 }); 490 var flatten = function(input, shallow, strict, startIndex) { 491 var output = [], idx = 0; 492 for (var i = startIndex || 0, length = getLength(input); i < length; i++) { 493 var value = input[i]; 494 if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { 495 //flatten current level of array or arguments object 496 if (!shallow) value = flatten(value, shallow, strict); 497 var j = 0, len = value.length; 498 output.length += len; 499 while (j < len) { 500 output[idx++] = value[j++]; 501 } 502 } else if (!strict) { 503 output[idx++] = value; 504 } 505 } 450 506 return output; 451 507 }; … … 453 509 // Flatten out an array, either recursively (by default), or just one level. 454 510 _.flatten = function(array, shallow) { 455 return flatten(array, shallow, []);511 return flatten(array, shallow, false); 456 512 }; 457 513 … … 461 517 }; 462 518 463 // Split an array into two arrays: one whose elements all satisfy the given464 // predicate, and one whose elements all do not satisfy the predicate.465 _.partition = function(array, predicate) {466 var pass = [], fail = [];467 each(array, function(elem) {468 (predicate(elem) ? pass : fail).push(elem);469 });470 return [pass, fail];471 };472 473 519 // Produce a duplicate-free version of the array. If the array has already 474 520 // been sorted, you have the option of using a faster algorithm. 475 521 // Aliased as `unique`. 476 _.uniq = _.unique = function(array, isSorted, iterat or, context) {477 if ( _.isFunction(isSorted)) {478 context = iterat or;479 iterat or= isSorted;522 _.uniq = _.unique = function(array, isSorted, iteratee, context) { 523 if (!_.isBoolean(isSorted)) { 524 context = iteratee; 525 iteratee = isSorted; 480 526 isSorted = false; 481 527 } 482 var initial = iterator ? _.map(array, iterator, context) : array;483 var result s= [];528 if (iteratee != null) iteratee = cb(iteratee, context); 529 var result = []; 484 530 var seen = []; 485 each(initial, function(value, index) { 486 if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { 487 seen.push(value); 488 results.push(array[index]); 489 } 490 }); 491 return results; 531 for (var i = 0, length = getLength(array); i < length; i++) { 532 var value = array[i], 533 computed = iteratee ? iteratee(value, i, array) : value; 534 if (isSorted) { 535 if (!i || seen !== computed) result.push(value); 536 seen = computed; 537 } else if (iteratee) { 538 if (!_.contains(seen, computed)) { 539 seen.push(computed); 540 result.push(value); 541 } 542 } else if (!_.contains(result, value)) { 543 result.push(value); 544 } 545 } 546 return result; 492 547 }; 493 548 … … 495 550 // the passed-in arrays. 496 551 _.union = function() { 497 return _.uniq( _.flatten(arguments, true));552 return _.uniq(flatten(arguments, true, true)); 498 553 }; 499 554 … … 501 556 // passed-in arrays. 502 557 _.intersection = function(array) { 503 var rest = slice.call(arguments, 1); 504 return _.filter(_.uniq(array), function(item) { 505 return _.every(rest, function(other) { 506 return _.contains(other, item); 507 }); 508 }); 558 var result = []; 559 var argsLength = arguments.length; 560 for (var i = 0, length = getLength(array); i < length; i++) { 561 var item = array[i]; 562 if (_.contains(result, item)) continue; 563 for (var j = 1; j < argsLength; j++) { 564 if (!_.contains(arguments[j], item)) break; 565 } 566 if (j === argsLength) result.push(item); 567 } 568 return result; 509 569 }; 510 570 … … 512 572 // Only the elements present in just the first array will remain. 513 573 _.difference = function(array) { 514 var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); 515 return _.filter(array, function(value){ return !_.contains(rest, value); }); 574 var rest = flatten(arguments, true, true, 1); 575 return _.filter(array, function(value){ 576 return !_.contains(rest, value); 577 }); 516 578 }; 517 579 … … 519 581 // an index go together. 520 582 _.zip = function() { 521 var length = _.max(_.pluck(arguments, 'length').concat(0)); 522 var results = new Array(length); 523 for (var i = 0; i < length; i++) { 524 results[i] = _.pluck(arguments, '' + i); 525 } 526 return results; 583 return _.unzip(arguments); 584 }; 585 586 // Complement of _.zip. Unzip accepts an array of arrays and groups 587 // each array's elements on shared indices 588 _.unzip = function(array) { 589 var length = array && _.max(array, getLength).length || 0; 590 var result = Array(length); 591 592 for (var index = 0; index < length; index++) { 593 result[index] = _.pluck(array, index); 594 } 595 return result; 527 596 }; 528 597 … … 531 600 // the corresponding values. 532 601 _.object = function(list, values) { 533 if (list == null) return {};534 602 var result = {}; 535 for (var i = 0, length = list.length; i < length; i++) {603 for (var i = 0, length = getLength(list); i < length; i++) { 536 604 if (values) { 537 605 result[list[i]] = values[i]; … … 543 611 }; 544 612 545 // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), 546 // we need this function. Return the position of the first occurrence of an 547 // item in an array, or -1 if the item is not included in the array. 548 // Delegates to **ECMAScript 5**'s native `indexOf` if available. 613 // Generator function to create the findIndex and findLastIndex functions 614 function createPredicateIndexFinder(dir) { 615 return function(array, predicate, context) { 616 predicate = cb(predicate, context); 617 var length = getLength(array); 618 var index = dir > 0 ? 0 : length - 1; 619 for (; index >= 0 && index < length; index += dir) { 620 if (predicate(array[index], index, array)) return index; 621 } 622 return -1; 623 }; 624 } 625 626 // Returns the first index on an array-like that passes a predicate test 627 _.findIndex = createPredicateIndexFinder(1); 628 _.findLastIndex = createPredicateIndexFinder(-1); 629 630 // Use a comparator function to figure out the smallest index at which 631 // an object should be inserted so as to maintain order. Uses binary search. 632 _.sortedIndex = function(array, obj, iteratee, context) { 633 iteratee = cb(iteratee, context, 1); 634 var value = iteratee(obj); 635 var low = 0, high = getLength(array); 636 while (low < high) { 637 var mid = Math.floor((low + high) / 2); 638 if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; 639 } 640 return low; 641 }; 642 643 // Generator function to create the indexOf and lastIndexOf functions 644 function createIndexFinder(dir, predicateFind, sortedIndex) { 645 return function(array, item, idx) { 646 var i = 0, length = getLength(array); 647 if (typeof idx == 'number') { 648 if (dir > 0) { 649 i = idx >= 0 ? idx : Math.max(idx + length, i); 650 } else { 651 length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; 652 } 653 } else if (sortedIndex && idx && length) { 654 idx = sortedIndex(array, item); 655 return array[idx] === item ? idx : -1; 656 } 657 if (item !== item) { 658 idx = predicateFind(slice.call(array, i, length), _.isNaN); 659 return idx >= 0 ? idx + i : -1; 660 } 661 for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { 662 if (array[idx] === item) return idx; 663 } 664 return -1; 665 }; 666 } 667 668 // Return the position of the first occurrence of an item in an array, 669 // or -1 if the item is not included in the array. 549 670 // If the array is large and already in sort order, pass `true` 550 671 // for **isSorted** to use binary search. 551 _.indexOf = function(array, item, isSorted) { 552 if (array == null) return -1; 553 var i = 0, length = array.length; 554 if (isSorted) { 555 if (typeof isSorted == 'number') { 556 i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); 557 } else { 558 i = _.sortedIndex(array, item); 559 return array[i] === item ? i : -1; 560 } 561 } 562 if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); 563 for (; i < length; i++) if (array[i] === item) return i; 564 return -1; 565 }; 566 567 // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. 568 _.lastIndexOf = function(array, item, from) { 569 if (array == null) return -1; 570 var hasIndex = from != null; 571 if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { 572 return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); 573 } 574 var i = (hasIndex ? from : array.length); 575 while (i--) if (array[i] === item) return i; 576 return -1; 577 }; 672 _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); 673 _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); 578 674 579 675 // Generate an integer Array containing an arithmetic progression. A port of … … 581 677 // [the Python documentation](http://docs.python.org/library/functions.html#range). 582 678 _.range = function(start, stop, step) { 583 if ( arguments.length <= 1) {679 if (stop == null) { 584 680 stop = start || 0; 585 681 start = 0; 586 682 } 587 step = arguments[2]|| 1;683 step = step || 1; 588 684 589 685 var length = Math.max(Math.ceil((stop - start) / step), 0); 590 var idx = 0; 591 var range = new Array(length); 592 593 while(idx < length) { 594 range[idx++] = start; 595 start += step; 686 var range = Array(length); 687 688 for (var idx = 0; idx < length; idx++, start += step) { 689 range[idx] = start; 596 690 } 597 691 … … 602 696 // ------------------ 603 697 604 // Reusable constructor function for prototype setting. 605 var ctor = function(){}; 698 // Determines whether to execute a function as a constructor 699 // or a normal function with the provided arguments 700 var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { 701 if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); 702 var self = baseCreate(sourceFunc.prototype); 703 var result = sourceFunc.apply(self, args); 704 if (_.isObject(result)) return result; 705 return self; 706 }; 606 707 607 708 // Create a function bound to a given object (assigning `this`, and arguments, … … 609 710 // available. 610 711 _.bind = function(func, context) { 611 var args, bound;612 712 if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); 613 if (!_.isFunction(func)) throw new TypeError; 614 args = slice.call(arguments, 2); 615 return bound = function() { 616 if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); 617 ctor.prototype = func.prototype; 618 var self = new ctor; 619 ctor.prototype = null; 620 var result = func.apply(self, args.concat(slice.call(arguments))); 621 if (Object(result) === result) return result; 622 return self; 623 }; 713 if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); 714 var args = slice.call(arguments, 2); 715 var bound = function() { 716 return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); 717 }; 718 return bound; 624 719 }; 625 720 … … 629 724 _.partial = function(func) { 630 725 var boundArgs = slice.call(arguments, 1); 631 returnfunction() {632 var position = 0 ;633 var args = boundArgs.slice();634 for (var i = 0 , length = args.length; i < length; i++) {635 if (args[i] === _) args[i] = arguments[position++];726 var bound = function() { 727 var position = 0, length = boundArgs.length; 728 var args = Array(length); 729 for (var i = 0; i < length; i++) { 730 args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; 636 731 } 637 732 while (position < arguments.length) args.push(arguments[position++]); 638 return func.apply(this, args); 639 }; 733 return executeBound(func, bound, this, this, args); 734 }; 735 return bound; 640 736 }; 641 737 … … 644 740 // defined on an object belong to it. 645 741 _.bindAll = function(obj) { 646 var funcs = slice.call(arguments, 1); 647 if (funcs.length === 0) throw new Error('bindAll must be passed function names'); 648 each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); 742 var i, length = arguments.length, key; 743 if (length <= 1) throw new Error('bindAll must be passed function names'); 744 for (i = 1; i < length; i++) { 745 key = arguments[i]; 746 obj[key] = _.bind(obj[key], obj); 747 } 649 748 return obj; 650 749 }; … … 652 751 // Memoize an expensive function by storing its results. 653 752 _.memoize = function(func, hasher) { 654 var memo = {}; 655 hasher || (hasher = _.identity); 656 return function() { 657 var key = hasher.apply(this, arguments); 658 return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); 659 }; 753 var memoize = function(key) { 754 var cache = memoize.cache; 755 var address = '' + (hasher ? hasher.apply(this, arguments) : key); 756 if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); 757 return cache[address]; 758 }; 759 memoize.cache = {}; 760 return memoize; 660 761 }; 661 762 … … 664 765 _.delay = function(func, wait) { 665 766 var args = slice.call(arguments, 2); 666 return setTimeout(function(){ return func.apply(null, args); }, wait); 767 return setTimeout(function(){ 768 return func.apply(null, args); 769 }, wait); 667 770 }; 668 771 669 772 // Defers a function, scheduling it to run after the current call stack has 670 773 // cleared. 671 _.defer = function(func) { 672 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); 673 }; 774 _.defer = _.partial(_.delay, _, 1); 674 775 675 776 // Returns a function, that, when invoked, will only be triggered at most once … … 682 783 var timeout = null; 683 784 var previous = 0; 684 options || (options = {});785 if (!options) options = {}; 685 786 var later = function() { 686 787 previous = options.leading === false ? 0 : _.now(); 687 788 timeout = null; 688 789 result = func.apply(context, args); 689 context = args = null;790 if (!timeout) context = args = null; 690 791 }; 691 792 return function() { … … 695 796 context = this; 696 797 args = arguments; 697 if (remaining <= 0) { 698 clearTimeout(timeout); 699 timeout = null; 798 if (remaining <= 0 || remaining > wait) { 799 if (timeout) { 800 clearTimeout(timeout); 801 timeout = null; 802 } 700 803 previous = now; 701 804 result = func.apply(context, args); 702 context = args = null;805 if (!timeout) context = args = null; 703 806 } else if (!timeout && options.trailing !== false) { 704 807 timeout = setTimeout(later, remaining); … … 717 820 var later = function() { 718 821 var last = _.now() - timestamp; 719 if (last < wait) { 822 823 if (last < wait && last >= 0) { 720 824 timeout = setTimeout(later, wait - last); 721 825 } else { … … 723 827 if (!immediate) { 724 828 result = func.apply(context, args); 725 context = args = null;829 if (!timeout) context = args = null; 726 830 } 727 831 } … … 733 837 timestamp = _.now(); 734 838 var callNow = immediate && !timeout; 735 if (!timeout) { 736 timeout = setTimeout(later, wait); 737 } 839 if (!timeout) timeout = setTimeout(later, wait); 738 840 if (callNow) { 739 841 result = func.apply(context, args); … … 742 844 743 845 return result; 744 };745 };746 747 // Returns a function that will be executed at most one time, no matter how748 // often you call it. Useful for lazy initialization.749 _.once = function(func) {750 var ran = false, memo;751 return function() {752 if (ran) return memo;753 ran = true;754 memo = func.apply(this, arguments);755 func = null;756 return memo;757 846 }; 758 847 }; … … 765 854 }; 766 855 856 // Returns a negated version of the passed-in predicate. 857 _.negate = function(predicate) { 858 return function() { 859 return !predicate.apply(this, arguments); 860 }; 861 }; 862 767 863 // Returns a function that is the composition of a list of functions, each 768 864 // consuming the return value of the function that follows. 769 865 _.compose = function() { 770 var funcs = arguments; 866 var args = arguments; 867 var start = args.length - 1; 771 868 return function() { 772 var args = arguments; 773 for (var i = funcs.length - 1; i >= 0; i--) { 774 args = [funcs[i].apply(this, args)]; 775 } 776 return args[0]; 777 }; 778 }; 779 780 // Returns a function that will only be executed after being called N times. 869 var i = start; 870 var result = args[start].apply(this, arguments); 871 while (i--) result = args[i].call(this, result); 872 return result; 873 }; 874 }; 875 876 // Returns a function that will only be executed on and after the Nth call. 781 877 _.after = function(times, func) { 782 878 return function() { … … 787 883 }; 788 884 885 // Returns a function that will only be executed up to (but not including) the Nth call. 886 _.before = function(times, func) { 887 var memo; 888 return function() { 889 if (--times > 0) { 890 memo = func.apply(this, arguments); 891 } 892 if (times <= 1) func = null; 893 return memo; 894 }; 895 }; 896 897 // Returns a function that will be executed at most one time, no matter how 898 // often you call it. Useful for lazy initialization. 899 _.once = _.partial(_.before, 2); 900 789 901 // Object Functions 790 902 // ---------------- 791 903 792 // Retrieve the names of an object's properties. 904 // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. 905 var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); 906 var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', 907 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; 908 909 function collectNonEnumProps(obj, keys) { 910 var nonEnumIdx = nonEnumerableProps.length; 911 var constructor = obj.constructor; 912 var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; 913 914 // Constructor is a special case. 915 var prop = 'constructor'; 916 if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); 917 918 while (nonEnumIdx--) { 919 prop = nonEnumerableProps[nonEnumIdx]; 920 if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { 921 keys.push(prop); 922 } 923 } 924 } 925 926 // Retrieve the names of an object's own properties. 793 927 // Delegates to **ECMAScript 5**'s native `Object.keys` 794 928 _.keys = function(obj) { … … 797 931 var keys = []; 798 932 for (var key in obj) if (_.has(obj, key)) keys.push(key); 933 // Ahem, IE < 9. 934 if (hasEnumBug) collectNonEnumProps(obj, keys); 935 return keys; 936 }; 937 938 // Retrieve all the property names of an object. 939 _.allKeys = function(obj) { 940 if (!_.isObject(obj)) return []; 941 var keys = []; 942 for (var key in obj) keys.push(key); 943 // Ahem, IE < 9. 944 if (hasEnumBug) collectNonEnumProps(obj, keys); 799 945 return keys; 800 946 }; … … 804 950 var keys = _.keys(obj); 805 951 var length = keys.length; 806 var values = newArray(length);952 var values = Array(length); 807 953 for (var i = 0; i < length; i++) { 808 954 values[i] = obj[keys[i]]; 809 955 } 810 956 return values; 957 }; 958 959 // Returns the results of applying the iteratee to each element of the object 960 // In contrast to _.map it returns an object 961 _.mapObject = function(obj, iteratee, context) { 962 iteratee = cb(iteratee, context); 963 var keys = _.keys(obj), 964 length = keys.length, 965 results = {}, 966 currentKey; 967 for (var index = 0; index < length; index++) { 968 currentKey = keys[index]; 969 results[currentKey] = iteratee(obj[currentKey], currentKey, obj); 970 } 971 return results; 811 972 }; 812 973 … … 815 976 var keys = _.keys(obj); 816 977 var length = keys.length; 817 var pairs = newArray(length);978 var pairs = Array(length); 818 979 for (var i = 0; i < length; i++) { 819 980 pairs[i] = [keys[i], obj[keys[i]]]; … … 843 1004 844 1005 // Extend a given object with all the properties in passed-in object(s). 845 _.extend = function(obj) { 846 each(slice.call(arguments, 1), function(source) { 847 if (source) { 848 for (var prop in source) { 849 obj[prop] = source[prop]; 850 } 851 } 852 }); 853 return obj; 1006 _.extend = createAssigner(_.allKeys); 1007 1008 // Assigns a given object with all the own properties in the passed-in object(s) 1009 // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) 1010 _.extendOwn = _.assign = createAssigner(_.keys); 1011 1012 // Returns the first key on an object that passes a predicate test 1013 _.findKey = function(obj, predicate, context) { 1014 predicate = cb(predicate, context); 1015 var keys = _.keys(obj), key; 1016 for (var i = 0, length = keys.length; i < length; i++) { 1017 key = keys[i]; 1018 if (predicate(obj[key], key, obj)) return key; 1019 } 854 1020 }; 855 1021 856 1022 // Return a copy of the object only containing the whitelisted properties. 857 _.pick = function(obj) { 858 var copy = {}; 859 var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); 860 each(keys, function(key) { 861 if (key in obj) copy[key] = obj[key]; 862 }); 863 return copy; 1023 _.pick = function(object, oiteratee, context) { 1024 var result = {}, obj = object, iteratee, keys; 1025 if (obj == null) return result; 1026 if (_.isFunction(oiteratee)) { 1027 keys = _.allKeys(obj); 1028 iteratee = optimizeCb(oiteratee, context); 1029 } else { 1030 keys = flatten(arguments, false, false, 1); 1031 iteratee = function(value, key, obj) { return key in obj; }; 1032 obj = Object(obj); 1033 } 1034 for (var i = 0, length = keys.length; i < length; i++) { 1035 var key = keys[i]; 1036 var value = obj[key]; 1037 if (iteratee(value, key, obj)) result[key] = value; 1038 } 1039 return result; 864 1040 }; 865 1041 866 1042 // Return a copy of the object without the blacklisted properties. 867 _.omit = function(obj) { 868 var copy = {}; 869 var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); 870 for (var key in obj) { 871 if (!_.contains(keys, key)) copy[key] = obj[key]; 872 } 873 return copy; 1043 _.omit = function(obj, iteratee, context) { 1044 if (_.isFunction(iteratee)) { 1045 iteratee = _.negate(iteratee); 1046 } else { 1047 var keys = _.map(flatten(arguments, false, false, 1), String); 1048 iteratee = function(value, key) { 1049 return !_.contains(keys, key); 1050 }; 1051 } 1052 return _.pick(obj, iteratee, context); 874 1053 }; 875 1054 876 1055 // Fill in a given object with default properties. 877 _.defaults = function(obj) {878 each(slice.call(arguments, 1), function(source) { 879 if (source) {880 for (var prop in source) {881 if (obj[prop] === void 0) obj[prop] = source[prop];882 }883 }884 });885 return obj;1056 _.defaults = createAssigner(_.allKeys, true); 1057 1058 // Creates an object that inherits from the given prototype object. 1059 // If additional properties are provided then they will be added to the 1060 // created object. 1061 _.create = function(prototype, props) { 1062 var result = baseCreate(prototype); 1063 if (props) _.extendOwn(result, props); 1064 return result; 886 1065 }; 887 1066 … … 900 1079 }; 901 1080 1081 // Returns whether an object has a given set of `key:value` pairs. 1082 _.isMatch = function(object, attrs) { 1083 var keys = _.keys(attrs), length = keys.length; 1084 if (object == null) return !length; 1085 var obj = Object(object); 1086 for (var i = 0; i < length; i++) { 1087 var key = keys[i]; 1088 if (attrs[key] !== obj[key] || !(key in obj)) return false; 1089 } 1090 return true; 1091 }; 1092 1093 902 1094 // Internal recursive comparison function for `isEqual`. 903 1095 var eq = function(a, b, aStack, bStack) { 904 1096 // Identical objects are equal. `0 === -0`, but they aren't identical. 905 1097 // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). 906 if (a === b) return a !== 0 || 1 / a == 1 / b;1098 if (a === b) return a !== 0 || 1 / a === 1 / b; 907 1099 // A strict comparison is necessary because `null == undefined`. 908 1100 if (a == null || b == null) return a === b; … … 912 1104 // Compare `[[Class]]` names. 913 1105 var className = toString.call(a); 914 if (className != toString.call(b)) return false;1106 if (className !== toString.call(b)) return false; 915 1107 switch (className) { 916 // Strings, numbers, dates, and booleans are compared by value. 1108 // Strings, numbers, regular expressions, dates, and booleans are compared by value. 1109 case '[object RegExp]': 1110 // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') 917 1111 case '[object String]': 918 1112 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is 919 1113 // equivalent to `new String("5")`. 920 return a == String(b);1114 return '' + a === '' + b; 921 1115 case '[object Number]': 922 // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for 923 // other numeric values. 924 return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); 1116 // `NaN`s are equivalent, but non-reflexive. 1117 // Object(NaN) is equivalent to NaN 1118 if (+a !== +a) return +b !== +b; 1119 // An `egal` comparison is performed for other numeric values. 1120 return +a === 0 ? 1 / +a === 1 / b : +a === +b; 925 1121 case '[object Date]': 926 1122 case '[object Boolean]': … … 928 1124 // millisecond representations. Note that invalid dates with millisecond representations 929 1125 // of `NaN` are not equivalent. 930 return +a == +b; 931 // RegExps are compared by their source patterns and flags. 932 case '[object RegExp]': 933 return a.source == b.source && 934 a.global == b.global && 935 a.multiline == b.multiline && 936 a.ignoreCase == b.ignoreCase; 937 } 938 if (typeof a != 'object' || typeof b != 'object') return false; 1126 return +a === +b; 1127 } 1128 1129 var areArrays = className === '[object Array]'; 1130 if (!areArrays) { 1131 if (typeof a != 'object' || typeof b != 'object') return false; 1132 1133 // Objects with different constructors are not equivalent, but `Object`s or `Array`s 1134 // from different frames are. 1135 var aCtor = a.constructor, bCtor = b.constructor; 1136 if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && 1137 _.isFunction(bCtor) && bCtor instanceof bCtor) 1138 && ('constructor' in a && 'constructor' in b)) { 1139 return false; 1140 } 1141 } 939 1142 // Assume equality for cyclic structures. The algorithm for detecting cyclic 940 1143 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. 1144 1145 // Initializing stack of traversed objects. 1146 // It's done here since we only need them for objects and arrays comparison. 1147 aStack = aStack || []; 1148 bStack = bStack || []; 941 1149 var length = aStack.length; 942 1150 while (length--) { 943 1151 // Linear search. Performance is inversely proportional to the number of 944 1152 // unique nested structures. 945 if (aStack[length] == a) return bStack[length] == b; 946 } 947 // Objects with different constructors are not equivalent, but `Object`s 948 // from different frames are. 949 var aCtor = a.constructor, bCtor = b.constructor; 950 if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && 951 _.isFunction(bCtor) && (bCtor instanceof bCtor)) 952 && ('constructor' in a && 'constructor' in b)) { 953 return false; 954 } 1153 if (aStack[length] === a) return bStack[length] === b; 1154 } 1155 955 1156 // Add the first object to the stack of traversed objects. 956 1157 aStack.push(a); 957 1158 bStack.push(b); 958 var size = 0, result = true; 1159 959 1160 // Recursively compare objects and arrays. 960 if ( className == '[object Array]') {1161 if (areArrays) { 961 1162 // Compare array lengths to determine if a deep comparison is necessary. 962 size = a.length; 963 result = size == b.length; 964 if (result) { 965 // Deep compare the contents, ignoring non-numeric properties. 966 while (size--) { 967 if (!(result = eq(a[size], b[size], aStack, bStack))) break; 968 } 1163 length = a.length; 1164 if (length !== b.length) return false; 1165 // Deep compare the contents, ignoring non-numeric properties. 1166 while (length--) { 1167 if (!eq(a[length], b[length], aStack, bStack)) return false; 969 1168 } 970 1169 } else { 971 1170 // Deep compare objects. 972 for (var key in a) { 973 if (_.has(a, key)) { 974 // Count the expected number of properties. 975 size++; 976 // Deep compare each member. 977 if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; 978 } 979 } 980 // Ensure that both objects contain the same number of properties. 981 if (result) { 982 for (key in b) { 983 if (_.has(b, key) && !(size--)) break; 984 } 985 result = !size; 1171 var keys = _.keys(a), key; 1172 length = keys.length; 1173 // Ensure that both objects contain the same number of properties before comparing deep equality. 1174 if (_.keys(b).length !== length) return false; 1175 while (length--) { 1176 // Deep compare each member 1177 key = keys[length]; 1178 if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; 986 1179 } 987 1180 } … … 989 1182 aStack.pop(); 990 1183 bStack.pop(); 991 return result;1184 return true; 992 1185 }; 993 1186 994 1187 // Perform a deep comparison to check if two objects are equal. 995 1188 _.isEqual = function(a, b) { 996 return eq(a, b , [], []);1189 return eq(a, b); 997 1190 }; 998 1191 … … 1001 1194 _.isEmpty = function(obj) { 1002 1195 if (obj == null) return true; 1003 if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; 1004 for (var key in obj) if (_.has(obj, key)) return false; 1005 return true; 1196 if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; 1197 return _.keys(obj).length === 0; 1006 1198 }; 1007 1199 … … 1014 1206 // Delegates to ECMA5's native Array.isArray 1015 1207 _.isArray = nativeIsArray || function(obj) { 1016 return toString.call(obj) == '[object Array]';1208 return toString.call(obj) === '[object Array]'; 1017 1209 }; 1018 1210 1019 1211 // Is a given variable an object? 1020 1212 _.isObject = function(obj) { 1021 return obj === Object(obj); 1022 }; 1023 1024 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. 1025 each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { 1213 var type = typeof obj; 1214 return type === 'function' || type === 'object' && !!obj; 1215 }; 1216 1217 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. 1218 _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { 1026 1219 _['is' + name] = function(obj) { 1027 return toString.call(obj) == '[object ' + name + ']';1220 return toString.call(obj) === '[object ' + name + ']'; 1028 1221 }; 1029 1222 }); 1030 1223 1031 // Define a fallback version of the method in browsers (ahem, IE ), where1224 // Define a fallback version of the method in browsers (ahem, IE < 9), where 1032 1225 // there isn't any inspectable "Arguments" type. 1033 1226 if (!_.isArguments(arguments)) { 1034 1227 _.isArguments = function(obj) { 1035 return !!(obj && _.has(obj, 'callee'));1228 return _.has(obj, 'callee'); 1036 1229 }; 1037 1230 } 1038 1231 1039 // Optimize `isFunction` if appropriate. 1040 if (typeof (/./) !== 'function') { 1232 // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, 1233 // IE 11 (#1621), and in Safari 8 (#1929). 1234 if (typeof /./ != 'function' && typeof Int8Array != 'object') { 1041 1235 _.isFunction = function(obj) { 1042 return typeof obj == = 'function';1236 return typeof obj == 'function' || false; 1043 1237 }; 1044 1238 } … … 1051 1245 // Is the given value `NaN`? (NaN is the only number which does not equal itself). 1052 1246 _.isNaN = function(obj) { 1053 return _.isNumber(obj) && obj != +obj;1247 return _.isNumber(obj) && obj !== +obj; 1054 1248 }; 1055 1249 1056 1250 // Is a given value a boolean? 1057 1251 _.isBoolean = function(obj) { 1058 return obj === true || obj === false || toString.call(obj) == '[object Boolean]';1252 return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; 1059 1253 }; 1060 1254 … … 1072 1266 // on itself (in other words, not on a prototype). 1073 1267 _.has = function(obj, key) { 1074 return hasOwnProperty.call(obj, key);1268 return obj != null && hasOwnProperty.call(obj, key); 1075 1269 }; 1076 1270 … … 1085 1279 }; 1086 1280 1087 // Keep the identity function around for default iterat ors.1281 // Keep the identity function around for default iteratees. 1088 1282 _.identity = function(value) { 1089 1283 return value; 1090 1284 }; 1091 1285 1286 // Predicate-generating functions. Often useful outside of Underscore. 1092 1287 _.constant = function(value) { 1093 return function 1288 return function() { 1094 1289 return value; 1095 1290 }; 1096 1291 }; 1097 1292 1098 _.property = function(key) { 1293 _.noop = function(){}; 1294 1295 _.property = property; 1296 1297 // Generates a function for a given object that returns a given property. 1298 _.propertyOf = function(obj) { 1299 return obj == null ? function(){} : function(key) { 1300 return obj[key]; 1301 }; 1302 }; 1303 1304 // Returns a predicate for checking whether an object has a given set of 1305 // `key:value` pairs. 1306 _.matcher = _.matches = function(attrs) { 1307 attrs = _.extendOwn({}, attrs); 1099 1308 return function(obj) { 1100 return obj[key]; 1101 }; 1102 }; 1103 1104 // Returns a predicate for checking whether an object has a given set of `key:value` pairs. 1105 _.matches = function(attrs) { 1106 return function(obj) { 1107 if (obj === attrs) return true; //avoid comparing an object to itself. 1108 for (var key in attrs) { 1109 if (attrs[key] !== obj[key]) 1110 return false; 1111 } 1112 return true; 1113 } 1309 return _.isMatch(obj, attrs); 1310 }; 1114 1311 }; 1115 1312 1116 1313 // Run a function **n** times. 1117 _.times = function(n, iterat or, context) {1314 _.times = function(n, iteratee, context) { 1118 1315 var accum = Array(Math.max(0, n)); 1119 for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); 1316 iteratee = optimizeCb(iteratee, context, 1); 1317 for (var i = 0; i < n; i++) accum[i] = iteratee(i); 1120 1318 return accum; 1121 1319 }; … … 1131 1329 1132 1330 // A (possibly faster) way to get the current timestamp as an integer. 1133 _.now = Date.now || function() { return new Date().getTime(); }; 1134 1135 // List of HTML entities for escaping. 1136 var entityMap = { 1137 escape: { 1138 '&': '&', 1139 '<': '<', 1140 '>': '>', 1141 '"': '"', 1142 "'": ''' 1143 } 1144 }; 1145 entityMap.unescape = _.invert(entityMap.escape); 1146 1147 // Regexes containing the keys and values listed immediately above. 1148 var entityRegexes = { 1149 escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), 1150 unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') 1151 }; 1331 _.now = Date.now || function() { 1332 return new Date().getTime(); 1333 }; 1334 1335 // List of HTML entities for escaping. 1336 var escapeMap = { 1337 '&': '&', 1338 '<': '<', 1339 '>': '>', 1340 '"': '"', 1341 "'": ''', 1342 '`': '`' 1343 }; 1344 var unescapeMap = _.invert(escapeMap); 1152 1345 1153 1346 // Functions for escaping and unescaping strings to/from HTML interpolation. 1154 _.each(['escape', 'unescape'], function(method) { 1155 _[method] = function(string) { 1156 if (string == null) return ''; 1157 return ('' + string).replace(entityRegexes[method], function(match) { 1158 return entityMap[method][match]; 1159 }); 1160 }; 1161 }); 1347 var createEscaper = function(map) { 1348 var escaper = function(match) { 1349 return map[match]; 1350 }; 1351 // Regexes for identifying a key that needs to be escaped 1352 var source = '(?:' + _.keys(map).join('|') + ')'; 1353 var testRegexp = RegExp(source); 1354 var replaceRegexp = RegExp(source, 'g'); 1355 return function(string) { 1356 string = string == null ? '' : '' + string; 1357 return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; 1358 }; 1359 }; 1360 _.escape = createEscaper(escapeMap); 1361 _.unescape = createEscaper(unescapeMap); 1162 1362 1163 1363 // If the value of the named `property` is a function then invoke it with the 1164 1364 // `object` as context; otherwise, return it. 1165 _.result = function(object, property) { 1166 if (object == null) return void 0; 1167 var value = object[property]; 1365 _.result = function(object, property, fallback) { 1366 var value = object == null ? void 0 : object[property]; 1367 if (value === void 0) { 1368 value = fallback; 1369 } 1168 1370 return _.isFunction(value) ? value.call(object) : value; 1169 };1170 1171 // Add your own custom functions to the Underscore object.1172 _.mixin = function(obj) {1173 each(_.functions(obj), function(name) {1174 var func = _[name] = obj[name];1175 _.prototype[name] = function() {1176 var args = [this._wrapped];1177 push.apply(args, arguments);1178 return result.call(this, func.apply(_, args));1179 };1180 });1181 1371 }; 1182 1372 … … 1209 1399 '\r': 'r', 1210 1400 '\n': 'n', 1211 '\t': 't',1212 1401 '\u2028': 'u2028', 1213 1402 '\u2029': 'u2029' 1214 1403 }; 1215 1404 1216 var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; 1405 var escaper = /\\|'|\r|\n|\u2028|\u2029/g; 1406 1407 var escapeChar = function(match) { 1408 return '\\' + escapes[match]; 1409 }; 1217 1410 1218 1411 // JavaScript micro-templating, similar to John Resig's implementation. 1219 1412 // Underscore templating handles arbitrary delimiters, preserves whitespace, 1220 1413 // and correctly escapes quotes within interpolated code. 1221 _.template = function(text, data, settings) { 1222 var render; 1414 // NB: `oldSettings` only exists for backwards compatibility. 1415 _.template = function(text, settings, oldSettings) { 1416 if (!settings && oldSettings) settings = oldSettings; 1223 1417 settings = _.defaults({}, settings, _.templateSettings); 1224 1418 1225 1419 // Combine delimiters into one regular expression via alternation. 1226 var matcher = newRegExp([1420 var matcher = RegExp([ 1227 1421 (settings.escape || noMatch).source, 1228 1422 (settings.interpolate || noMatch).source, … … 1234 1428 var source = "__p+='"; 1235 1429 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { 1236 source += text.slice(index, offset) 1237 .replace(escaper, function(match) { return '\\' + escapes[match]; });1430 source += text.slice(index, offset).replace(escaper, escapeChar); 1431 index = offset + match.length; 1238 1432 1239 1433 if (escape) { 1240 1434 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; 1241 } 1242 if (interpolate) { 1435 } else if (interpolate) { 1243 1436 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; 1244 } 1245 if (evaluate) { 1437 } else if (evaluate) { 1246 1438 source += "';\n" + evaluate + "\n__p+='"; 1247 1439 } 1248 index = offset + match.length; 1440 1441 // Adobe VMs need the match returned to produce the correct offest. 1249 1442 return match; 1250 1443 }); … … 1256 1449 source = "var __t,__p='',__j=Array.prototype.join," + 1257 1450 "print=function(){__p+=__j.call(arguments,'');};\n" + 1258 source + "return __p;\n";1451 source + 'return __p;\n'; 1259 1452 1260 1453 try { 1261 render = new Function(settings.variable || 'obj', '_', source);1454 var render = new Function(settings.variable || 'obj', '_', source); 1262 1455 } catch (e) { 1263 1456 e.source = source; … … 1265 1458 } 1266 1459 1267 if (data) return render(data, _);1268 1460 var template = function(data) { 1269 1461 return render.call(this, data, _); 1270 1462 }; 1271 1463 1272 // Provide the compiled function source as a convenience for precompilation. 1273 template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; 1464 // Provide the compiled source as a convenience for precompilation. 1465 var argument = settings.variable || 'obj'; 1466 template.source = 'function(' + argument + '){\n' + source + '}'; 1274 1467 1275 1468 return template; 1276 1469 }; 1277 1470 1278 // Add a "chain" function , which will delegate to the wrapper.1471 // Add a "chain" function. Start chaining a wrapped Underscore object. 1279 1472 _.chain = function(obj) { 1280 return _(obj).chain(); 1473 var instance = _(obj); 1474 instance._chain = true; 1475 return instance; 1281 1476 }; 1282 1477 … … 1288 1483 1289 1484 // Helper function to continue chaining intermediate results. 1290 var result = function(obj) { 1291 return this._chain ? _(obj).chain() : obj; 1485 var result = function(instance, obj) { 1486 return instance._chain ? _(obj).chain() : obj; 1487 }; 1488 1489 // Add your own custom functions to the Underscore object. 1490 _.mixin = function(obj) { 1491 _.each(_.functions(obj), function(name) { 1492 var func = _[name] = obj[name]; 1493 _.prototype[name] = function() { 1494 var args = [this._wrapped]; 1495 push.apply(args, arguments); 1496 return result(this, func.apply(_, args)); 1497 }; 1498 }); 1292 1499 }; 1293 1500 … … 1296 1503 1297 1504 // Add all mutator Array functions to the wrapper. 1298 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {1505 _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { 1299 1506 var method = ArrayProto[name]; 1300 1507 _.prototype[name] = function() { 1301 1508 var obj = this._wrapped; 1302 1509 method.apply(obj, arguments); 1303 if ((name == 'shift' || name== 'splice') && obj.length === 0) delete obj[0];1304 return result .call(this, obj);1510 if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; 1511 return result(this, obj); 1305 1512 }; 1306 1513 }); 1307 1514 1308 1515 // Add all accessor Array functions to the wrapper. 1309 each(['concat', 'join', 'slice'], function(name) {1516 _.each(['concat', 'join', 'slice'], function(name) { 1310 1517 var method = ArrayProto[name]; 1311 1518 _.prototype[name] = function() { 1312 return result .call(this, method.apply(this._wrapped, arguments));1519 return result(this, method.apply(this._wrapped, arguments)); 1313 1520 }; 1314 1521 }); 1315 1522 1316 _.extend(_.prototype, { 1317 1318 // Start chaining a wrapped Underscore object. 1319 chain: function() { 1320 this._chain = true; 1321 return this; 1322 }, 1323 1324 // Extracts the result from a wrapped and chained object. 1325 value: function() { 1326 return this._wrapped; 1327 } 1328 1329 }); 1523 // Extracts the result from a wrapped and chained object. 1524 _.prototype.value = function() { 1525 return this._wrapped; 1526 }; 1527 1528 // Provide unwrapping proxy for some methods used in engine operations 1529 // such as arithmetic and JSON stringification. 1530 _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; 1531 1532 _.prototype.toString = function() { 1533 return '' + this._wrapped; 1534 }; 1330 1535 1331 1536 // AMD registration happens at the end for compatibility with AMD loaders … … 1341 1546 }); 1342 1547 } 1343 } ).call(this);1548 }.call(this)); -
trunk/src/wp-includes/js/underscore.min.js
r32065 r36546 1 // Underscore.js 1. 6.01 // Underscore.js 1.8.3 2 2 // http://underscorejs.org 3 // (c) 2009-201 4Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors3 // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 4 // Underscore may be freely distributed under the MIT license. 5 (function(){ var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?void(this._wrapped=n):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.6.0";var A=j.each=j.forEach=function(n,t,e){if(null==n)return n;if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return;return n};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var O="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},j.find=j.detect=function(n,t,r){var e;return k(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var k=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:k(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,j.property(t))},j.where=function(n,t){return j.filter(n,j.matches(t))},j.findWhere=function(n,t){return j.find(n,j.matches(t))},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);var e=-1/0,u=-1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;o>u&&(e=n,u=o)}),e},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);var e=1/0,u=1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;u>o&&(e=n,u=o)}),e},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return null==t||r?(n.length!==+n.length&&(n=j.values(n)),n[j.random(n.length-1)]):j.shuffle(n).slice(0,Math.max(0,t))};var E=function(n){return null==n?j.identity:j.isFunction(n)?n:j.property(n)};j.sortBy=function(n,t,r){return t=E(t),j.pluck(j.map(n,function(n,e,u){return{value:n,index:e,criteria:t.call(r,n,e,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=E(r),A(t,function(i,a){var o=r.call(e,i,a,t);n(u,o,i)}),u}};j.groupBy=F(function(n,t,r){j.has(n,t)?n[t].push(r):n[t]=[r]}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=E(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])<u?i=o+1:a=o}return i},j.toArray=function(n){return n?j.isArray(n)?o.call(n):n.length===+n.length?j.map(n,j.identity):j.values(n):[]},j.size=function(n){return null==n?0:n.length===+n.length?n.length:j.keys(n).length},j.first=j.head=j.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:0>t?[]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.partition=function(n,t){var r=[],e=[];return A(n,function(n){(t(n)?r:e).push(n)}),[r,e]},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.contains(t,n)})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){for(var r=0,e=t.slice(),u=0,i=e.length;i>u;u++)e[u]===j&&(e[u]=arguments[r++]);for(;r<arguments.length;)e.push(arguments[r++]);return n.apply(this,e)}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:j.now(),a=null,i=n.apply(e,u),e=u=null};return function(){var l=j.now();o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u),e=u=null):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o,c=function(){var l=j.now()-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u),i=u=null))};return function(){i=this,u=arguments,a=j.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u),i=u=null),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return j.partial(t,n)},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=function(n){if(!j.isObject(n))return[];if(w)return w(n);var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o)&&"constructor"in n&&"constructor"in t)return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.constant=function(n){return function(){return n}},j.property=function(n){return function(t){return t[n]}},j.matches=function(n){return function(t){if(t===n)return!0;for(var r in n)if(n[r]!==t[r])return!1;return!0}},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},j.now=Date.now||function(){return(new Date).getTime()};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};T.unescape=j.invert(T.escape);var I={escape:new RegExp("["+j.keys(T.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(T.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(I[n],function(t){return T[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),"function"==typeof define&&define.amd&&define("underscore",[],function(){return j})}).call(this);5 (function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this); -
trunk/src/wp-includes/script-loader.php
r36510 r36546 315 315 did_action( 'init' ) && $scripts->add_data( 'json2', 'conditional', 'lt IE 8' ); 316 316 317 $scripts->add( 'underscore', "/wp-includes/js/underscore$dev_suffix.js", array(), '1. 6.0', 1 );318 $scripts->add( 'backbone', "/wp-includes/js/backbone$dev_suffix.js", array( 'underscore','jquery' ), '1. 1.2', 1 );317 $scripts->add( 'underscore', "/wp-includes/js/underscore$dev_suffix.js", array(), '1.8.3', 1 ); 318 $scripts->add( 'backbone', "/wp-includes/js/backbone$dev_suffix.js", array( 'underscore','jquery' ), '1.2.3', 1 ); 319 319 320 320 $scripts->add( 'wp-util', "/wp-includes/js/wp-util$suffix.js", array('underscore', 'jquery'), false, 1 );
Note: See TracChangeset
for help on using the changeset viewer.