<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[37723] trunk: External Libraries: Update Backbone to version 1.3.3.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/37723">37723</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/37723","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>ocean90</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-06-16 09:26:06 +0000 (Thu, 16 Jun 2016)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>External Libraries: Update Backbone to version 1.3.3.

Changelog: https://cdn.rawgit.com/jashkenas/backbone/1.3.3/index.html#changelog
Diff: https://github.com/jashkenas/backbone/compare/1.2.3...1.3.3

Includes a unit test to ensure that the minified version doesn't include `sourceMappingURL`.

Props adamsilverstein.
Fixes <a href="https://core.trac.wordpress.org/ticket/37099">#37099</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesjsbackbonejs">trunk/src/wp-includes/js/backbone.js</a></li>
<li><a href="#trunksrcwpincludesjsbackboneminjs">trunk/src/wp-includes/js/backbone.min.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsdependenciesbackbonejsphp">trunk/tests/phpunit/tests/dependencies/backbonejs.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesjsbackbonejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/backbone.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/backbone.js      2016-06-16 04:53:42 UTC (rev 37722)
+++ trunk/src/wp-includes/js/backbone.js        2016-06-16 09:26:06 UTC (rev 37723)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,6 +1,6 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//     Backbone.js 1.2.3
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//     Backbone.js 1.3.3
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//     (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//     (c) 2010-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
</ins><span class="cx" style="display: block; padding: 0 10px"> //     Backbone may be freely distributed under the MIT license.
</span><span class="cx" style="display: block; padding: 0 10px"> //     For all details and documentation:
</span><span class="cx" style="display: block; padding: 0 10px"> //     http://backbonejs.org
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -9,8 +9,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
</span><span class="cx" style="display: block; padding: 0 10px">   // We use `self` instead of `window` for `WebWorker` support.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  var root = (typeof self == 'object' && self.self == self && self) ||
-            (typeof global == 'object' && global.global == global && global);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  var root = (typeof self == 'object' && self.self === self && self) ||
+            (typeof global == 'object' && global.global === global && global);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Set up Backbone appropriately for the environment. Start with AMD.
</span><span class="cx" style="display: block; padding: 0 10px">   if (typeof define === 'function' && define.amd) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23,7 +23,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">   // Next for Node.js or CommonJS. jQuery may not be needed as a module.
</span><span class="cx" style="display: block; padding: 0 10px">   } else if (typeof exports !== 'undefined') {
</span><span class="cx" style="display: block; padding: 0 10px">     var _ = require('underscore'), $;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    try { $ = require('jquery'); } catch(e) {}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    try { $ = require('jquery'); } catch (e) {}
</ins><span class="cx" style="display: block; padding: 0 10px">     factory(root, exports, _, $);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Finally, as a browser global.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31,7 +31,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">     root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
</span><span class="cx" style="display: block; padding: 0 10px">   }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-}(function(root, Backbone, _, $) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+})(function(root, Backbone, _, $) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Initial Setup
</span><span class="cx" style="display: block; padding: 0 10px">   // -------------
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44,7 +44,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">   var slice = Array.prototype.slice;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Current version of the library. Keep in sync with `package.json`.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  Backbone.VERSION = '1.2.3';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  Backbone.VERSION = '1.3.3';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
</span><span class="cx" style="display: block; padding: 0 10px">   // the `$` variable.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -146,7 +146,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
</span><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="cx" style="display: block; padding: 0 10px">     } else if (name && eventSplitter.test(name)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      // Handle space separated event names by delegating them individually.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      // Handle space-separated event names by delegating them individually.
</ins><span class="cx" style="display: block; padding: 0 10px">       for (names = name.split(eventSplitter); i < names.length; i++) {
</span><span class="cx" style="display: block; padding: 0 10px">         events = iteratee(events, names[i], callback, opts);
</span><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -166,9 +166,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">   // Guard the `listening` argument from the public API.
</span><span class="cx" style="display: block; padding: 0 10px">   var internalOn = function(obj, name, callback, context, listening) {
</span><span class="cx" style="display: block; padding: 0 10px">     obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        context: context,
-        ctx: obj,
-        listening: listening
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      context: context,
+      ctx: obj,
+      listening: listening
</ins><span class="cx" style="display: block; padding: 0 10px">     });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     if (listening) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -182,7 +182,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">   // Inversion-of-control versions of `on`. Tell *this* object to listen to
</span><span class="cx" style="display: block; padding: 0 10px">   // an event in another object... keeping track of what it's listening to
</span><span class="cx" style="display: block; padding: 0 10px">   // for easier unbinding later.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  Events.listenTo =  function(obj, name, callback) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  Events.listenTo = function(obj, name, callback) {
</ins><span class="cx" style="display: block; padding: 0 10px">     if (!obj) return this;
</span><span class="cx" style="display: block; padding: 0 10px">     var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
</span><span class="cx" style="display: block; padding: 0 10px">     var listeningTo = this._listeningTo || (this._listeningTo = {});
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -207,7 +207,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">       var context = options.context, ctx = options.ctx, listening = options.listening;
</span><span class="cx" style="display: block; padding: 0 10px">       if (listening) listening.count++;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening});
</ins><span class="cx" style="display: block; padding: 0 10px">     }
</span><span class="cx" style="display: block; padding: 0 10px">     return events;
</span><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -216,18 +216,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">   // callbacks with that function. If `callback` is null, removes all
</span><span class="cx" style="display: block; padding: 0 10px">   // callbacks for the event. If `name` is null, removes all bound
</span><span class="cx" style="display: block; padding: 0 10px">   // callbacks for all events.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  Events.off =  function(name, callback, context) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  Events.off = function(name, callback, context) {
</ins><span class="cx" style="display: block; padding: 0 10px">     if (!this._events) return this;
</span><span class="cx" style="display: block; padding: 0 10px">     this._events = eventsApi(offApi, this._events, name, callback, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        context: context,
-        listeners: this._listeners
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      context: context,
+      listeners: this._listeners
</ins><span class="cx" style="display: block; padding: 0 10px">     });
</span><span class="cx" style="display: block; padding: 0 10px">     return this;
</span><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Tell this object to stop listening to either specific events ... or
</span><span class="cx" style="display: block; padding: 0 10px">   // to every object it's currently listening to.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  Events.stopListening =  function(obj, name, callback) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  Events.stopListening = function(obj, name, callback) {
</ins><span class="cx" style="display: block; padding: 0 10px">     var listeningTo = this._listeningTo;
</span><span class="cx" style="display: block; padding: 0 10px">     if (!listeningTo) return this;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -242,7 +242,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       listening.obj.off(name, callback, this);
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     return this;
</span><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -299,21 +298,22 @@
</span><span class="cx" style="display: block; padding: 0 10px">         delete events[name];
</span><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    if (_.size(events)) return events;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    return events;
</ins><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Bind an event to only be triggered a single time. After the first time
</span><span class="cx" style="display: block; padding: 0 10px">   // the callback is invoked, its listener will be removed. If multiple events
</span><span class="cx" style="display: block; padding: 0 10px">   // are passed in using the space-separated syntax, the handler will fire
</span><span class="cx" style="display: block; padding: 0 10px">   // once for each event, not once for a combination of all events.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  Events.once =  function(name, callback, context) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  Events.once = function(name, callback, context) {
</ins><span class="cx" style="display: block; padding: 0 10px">     // Map the event into a `{event: once}` object.
</span><span class="cx" style="display: block; padding: 0 10px">     var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    return this.on(events, void 0, context);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    if (typeof name === 'string' && context == null) callback = void 0;
+    return this.on(events, callback, context);
</ins><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Inversion-of-control versions of `once`.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  Events.listenToOnce =  function(obj, name, callback) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  Events.listenToOnce = function(obj, name, callback) {
</ins><span class="cx" style="display: block; padding: 0 10px">     // Map the event into a `{event: once}` object.
</span><span class="cx" style="display: block; padding: 0 10px">     var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
</span><span class="cx" style="display: block; padding: 0 10px">     return this.listenTo(obj, events);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -336,7 +336,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">   // passed the same arguments as `trigger` is, apart from the event name
</span><span class="cx" style="display: block; padding: 0 10px">   // (unless you're listening on `"all"`, which will cause your callback to
</span><span class="cx" style="display: block; padding: 0 10px">   // receive the true name of the event as the first argument).
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  Events.trigger =  function(name) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  Events.trigger = function(name) {
</ins><span class="cx" style="display: block; padding: 0 10px">     if (!this._events) return this;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     var length = Math.max(0, arguments.length - 1);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -348,7 +348,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Handles triggering the appropriate event callbacks.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  var triggerApi = function(objEvents, name, cb, args) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  var triggerApi = function(objEvents, name, callback, args) {
</ins><span class="cx" style="display: block; padding: 0 10px">     if (objEvents) {
</span><span class="cx" style="display: block; padding: 0 10px">       var events = objEvents[name];
</span><span class="cx" style="display: block; padding: 0 10px">       var allEvents = objEvents.all;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -398,7 +398,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     this.attributes = {};
</span><span class="cx" style="display: block; padding: 0 10px">     if (options.collection) this.collection = options.collection;
</span><span class="cx" style="display: block; padding: 0 10px">     if (options.parse) attrs = this.parse(attrs, options) || {};
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    var defaults = _.result(this, 'defaults');
+    attrs = _.defaults(_.extend({}, defaults, attrs), defaults);
</ins><span class="cx" style="display: block; padding: 0 10px">     this.set(attrs, options);
</span><span class="cx" style="display: block; padding: 0 10px">     this.changed = {};
</span><span class="cx" style="display: block; padding: 0 10px">     this.initialize.apply(this, arguments);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -506,7 +507,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // Update the `id`.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      this.id = this.get(this.idAttribute);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      if (this.idAttribute in attrs) this.id = this.get(this.idAttribute);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // Trigger all relevant attribute changes.
</span><span class="cx" style="display: block; padding: 0 10px">       if (!silent) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -619,8 +620,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">       // the model will be valid when the attributes, if any, are set.
</span><span class="cx" style="display: block; padding: 0 10px">       if (attrs && !wait) {
</span><span class="cx" style="display: block; padding: 0 10px">         if (!this.set(attrs, options)) return false;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      } else {
-        if (!this._validate(attrs, options)) return false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      } else if (!this._validate(attrs, options)) {
+        return false;
</ins><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // After a successful server-side save, the client is (optionally)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -714,7 +715,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Check if the model is currently in a valid state.
</span><span class="cx" style="display: block; padding: 0 10px">     isValid: function(options) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      return this._validate({}, _.defaults({validate: true}, options));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      return this._validate({}, _.extend({}, options, {validate: true}));
</ins><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Run validation against the next complete set of model attributes,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -732,8 +733,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Underscore methods that we want to implement on the Model, mapped to the
</span><span class="cx" style="display: block; padding: 0 10px">   // number of arguments they take.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
-      omit: 0, chain: 1, isEmpty: 1 };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
+      omit: 0, chain: 1, isEmpty: 1};
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Mix in each Underscore method as a proxy to `Model#attributes`.
</span><span class="cx" style="display: block; padding: 0 10px">   addUnderscoreMethods(Model, modelMethods, 'attributes');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -769,7 +770,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     at = Math.min(Math.max(at, 0), array.length);
</span><span class="cx" style="display: block; padding: 0 10px">     var tail = Array(array.length - at);
</span><span class="cx" style="display: block; padding: 0 10px">     var length = insert.length;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    for (var i = 0; i < tail.length; i++) tail[i] = array[i + at];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    var i;
+    for (i = 0; i < tail.length; i++) tail[i] = array[i + at];
</ins><span class="cx" style="display: block; padding: 0 10px">     for (i = 0; i < length; i++) array[i + at] = insert[i];
</span><span class="cx" style="display: block; padding: 0 10px">     for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];
</span><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -807,9 +809,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">     remove: function(models, options) {
</span><span class="cx" style="display: block; padding: 0 10px">       options = _.extend({}, options);
</span><span class="cx" style="display: block; padding: 0 10px">       var singular = !_.isArray(models);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      models = singular ? [models] : _.clone(models);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      models = singular ? [models] : models.slice();
</ins><span class="cx" style="display: block; padding: 0 10px">       var removed = this._removeModels(models, options);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      if (!options.silent && removed) this.trigger('update', this, options);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      if (!options.silent && removed.length) {
+        options.changes = {added: [], merged: [], removed: removed};
+        this.trigger('update', this, options);
+      }
</ins><span class="cx" style="display: block; padding: 0 10px">       return singular ? removed[0] : removed;
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -820,18 +825,22 @@
</span><span class="cx" style="display: block; padding: 0 10px">     set: function(models, options) {
</span><span class="cx" style="display: block; padding: 0 10px">       if (models == null) return;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      options = _.defaults({}, options, setOptions);
-      if (options.parse && !this._isModel(models)) models = this.parse(models, options);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      options = _.extend({}, setOptions, options);
+      if (options.parse && !this._isModel(models)) {
+        models = this.parse(models, options) || [];
+      }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       var singular = !_.isArray(models);
</span><span class="cx" style="display: block; padding: 0 10px">       models = singular ? [models] : models.slice();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       var at = options.at;
</span><span class="cx" style="display: block; padding: 0 10px">       if (at != null) at = +at;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      if (at > this.length) at = this.length;
</ins><span class="cx" style="display: block; padding: 0 10px">       if (at < 0) at += this.length + 1;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       var set = [];
</span><span class="cx" style="display: block; padding: 0 10px">       var toAdd = [];
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var toMerge = [];
</ins><span class="cx" style="display: block; padding: 0 10px">       var toRemove = [];
</span><span class="cx" style="display: block; padding: 0 10px">       var modelMap = {};
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -840,13 +849,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">       var remove = options.remove;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       var sort = false;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var sortable = this.comparator && (at == null) && options.sort !== false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var sortable = this.comparator && at == null && options.sort !== false;
</ins><span class="cx" style="display: block; padding: 0 10px">       var sortAttr = _.isString(this.comparator) ? this.comparator : null;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // Turn bare objects into model references, and prevent invalid models
</span><span class="cx" style="display: block; padding: 0 10px">       // from being added.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var model;
-      for (var i = 0; i < models.length; i++) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var model, i;
+      for (i = 0; i < models.length; i++) {
</ins><span class="cx" style="display: block; padding: 0 10px">         model = models[i];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">         // If a duplicate is found, prevent it from being added and
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -857,6 +866,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">             var attrs = this._isModel(model) ? model.attributes : model;
</span><span class="cx" style="display: block; padding: 0 10px">             if (options.parse) attrs = existing.parse(attrs, options);
</span><span class="cx" style="display: block; padding: 0 10px">             existing.set(attrs, options);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+            toMerge.push(existing);
</ins><span class="cx" style="display: block; padding: 0 10px">             if (sortable && !sort) sort = existing.hasChanged(sortAttr);
</span><span class="cx" style="display: block; padding: 0 10px">           }
</span><span class="cx" style="display: block; padding: 0 10px">           if (!modelMap[existing.cid]) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -890,8 +900,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">       var orderChanged = false;
</span><span class="cx" style="display: block; padding: 0 10px">       var replace = !sortable && add && remove;
</span><span class="cx" style="display: block; padding: 0 10px">       if (set.length && replace) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        orderChanged = this.length != set.length || _.some(this.models, function(model, index) {
-          return model !== set[index];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        orderChanged = this.length !== set.length || _.some(this.models, function(m, index) {
+          return m !== set[index];
</ins><span class="cx" style="display: block; padding: 0 10px">         });
</span><span class="cx" style="display: block; padding: 0 10px">         this.models.length = 0;
</span><span class="cx" style="display: block; padding: 0 10px">         splice(this.models, set, 0);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -905,7 +915,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">       // Silently sort the collection if appropriate.
</span><span class="cx" style="display: block; padding: 0 10px">       if (sort) this.sort({silent: true});
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      // Unless silenced, it's time to fire all appropriate add/sort events.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      // Unless silenced, it's time to fire all appropriate add/sort/update events.
</ins><span class="cx" style="display: block; padding: 0 10px">       if (!options.silent) {
</span><span class="cx" style="display: block; padding: 0 10px">         for (i = 0; i < toAdd.length; i++) {
</span><span class="cx" style="display: block; padding: 0 10px">           if (at != null) options.index = at + i;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -913,7 +923,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">           model.trigger('add', model, this, options);
</span><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px">         if (sort || orderChanged) this.trigger('sort', this, options);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if (toAdd.length || toRemove.length) this.trigger('update', this, options);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if (toAdd.length || toRemove.length || toMerge.length) {
+          options.changes = {
+            added: toAdd,
+            removed: toRemove,
+            merged: toMerge
+          };
+          this.trigger('update', this, options);
+        }
</ins><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // Return the added (or merged) model (or models).
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -963,13 +980,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">       return slice.apply(this.models, arguments);
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    // Get a model from the set by id.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    // Get a model from the set by id, cid, model object with id or cid
+    // properties, or an attributes object that is transformed through modelId.
</ins><span class="cx" style="display: block; padding: 0 10px">     get: function(obj) {
</span><span class="cx" style="display: block; padding: 0 10px">       if (obj == null) return void 0;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var id = this.modelId(this._isModel(obj) ? obj.attributes : obj);
-      return this._byId[obj] || this._byId[id] || this._byId[obj.cid];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      return this._byId[obj] ||
+        this._byId[this.modelId(obj.attributes || obj)] ||
+        obj.cid && this._byId[obj.cid];
</ins><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    // Returns `true` if the model is in the collection.
+    has: function(obj) {
+      return this.get(obj) != null;
+    },
+
</ins><span class="cx" style="display: block; padding: 0 10px">     // Get the model at the given index.
</span><span class="cx" style="display: block; padding: 0 10px">     at: function(index) {
</span><span class="cx" style="display: block; padding: 0 10px">       if (index < 0) index += this.length;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1011,7 +1035,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Pluck an attribute from each model in the collection.
</span><span class="cx" style="display: block; padding: 0 10px">     pluck: function(attr) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      return _.invoke(this.models, 'get', attr);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      return this.map(attr + '');
</ins><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Fetch the default set of models for this collection, resetting the
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1042,9 +1066,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">       if (!wait) this.add(model, options);
</span><span class="cx" style="display: block; padding: 0 10px">       var collection = this;
</span><span class="cx" style="display: block; padding: 0 10px">       var success = options.success;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      options.success = function(model, resp, callbackOpts) {
-        if (wait) collection.add(model, callbackOpts);
-        if (success) success.call(callbackOpts.context, model, resp, callbackOpts);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      options.success = function(m, resp, callbackOpts) {
+        if (wait) collection.add(m, callbackOpts);
+        if (success) success.call(callbackOpts.context, m, resp, callbackOpts);
</ins><span class="cx" style="display: block; padding: 0 10px">       };
</span><span class="cx" style="display: block; padding: 0 10px">       model.save(null, options);
</span><span class="cx" style="display: block; padding: 0 10px">       return model;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1065,7 +1089,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Define how to uniquely identify models in the collection.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    modelId: function (attrs) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    modelId: function(attrs) {
</ins><span class="cx" style="display: block; padding: 0 10px">       return attrs[this.model.prototype.idAttribute || 'id'];
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1103,6 +1127,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">         this.models.splice(index, 1);
</span><span class="cx" style="display: block; padding: 0 10px">         this.length--;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // Remove references before triggering 'remove' event to prevent an
+        // infinite loop. #3693
+        delete this._byId[model.cid];
+        var id = this.modelId(model.attributes);
+        if (id != null) delete this._byId[id];
+
</ins><span class="cx" style="display: block; padding: 0 10px">         if (!options.silent) {
</span><span class="cx" style="display: block; padding: 0 10px">           options.index = index;
</span><span class="cx" style="display: block; padding: 0 10px">           model.trigger('remove', model, this, options);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1111,12 +1141,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">         removed.push(model);
</span><span class="cx" style="display: block; padding: 0 10px">         this._removeReference(model, options);
</span><span class="cx" style="display: block; padding: 0 10px">       }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      return removed.length ? removed : false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      return removed;
</ins><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Method for checking whether an object should be considered a model for
</span><span class="cx" style="display: block; padding: 0 10px">     // the purposes of adding to the collection.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    _isModel: function (model) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    _isModel: function(model) {
</ins><span class="cx" style="display: block; padding: 0 10px">       return model instanceof Model;
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1142,14 +1172,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">     // events simply proxy through. "add" and "remove" events that originate
</span><span class="cx" style="display: block; padding: 0 10px">     // in other collections are ignored.
</span><span class="cx" style="display: block; padding: 0 10px">     _onModelEvent: function(event, model, collection, options) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      if ((event === 'add' || event === 'remove') && collection !== this) return;
-      if (event === 'destroy') this.remove(model, options);
-      if (event === 'change') {
-        var prevId = this.modelId(model.previousAttributes());
-        var id = this.modelId(model.attributes);
-        if (prevId !== id) {
-          if (prevId != null) delete this._byId[prevId];
-          if (id != null) this._byId[id] = model;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      if (model) {
+        if ((event === 'add' || event === 'remove') && collection !== this) return;
+        if (event === 'destroy') this.remove(model, options);
+        if (event === 'change') {
+          var prevId = this.modelId(model.previousAttributes());
+          var id = this.modelId(model.attributes);
+          if (prevId !== id) {
+            if (prevId != null) delete this._byId[prevId];
+            if (id != null) this._byId[id] = model;
+          }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="cx" style="display: block; padding: 0 10px">       this.trigger.apply(this, arguments);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1160,14 +1192,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">   // Underscore methods that we want to implement on the Collection.
</span><span class="cx" style="display: block; padding: 0 10px">   // 90% of the core usefulness of Backbone Collections is actually implemented
</span><span class="cx" style="display: block; padding: 0 10px">   // right here:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4,
-      foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  var collectionMethods = {forEach: 3, each: 3, map: 3, collect: 3, reduce: 0,
+      foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3,
</ins><span class="cx" style="display: block; padding: 0 10px">       select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3,
</span><span class="cx" style="display: block; padding: 0 10px">       contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
</span><span class="cx" style="display: block; padding: 0 10px">       head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
</span><span class="cx" style="display: block; padding: 0 10px">       without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3,
</span><span class="cx" style="display: block; padding: 0 10px">       isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      sortBy: 3, indexBy: 3};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      sortBy: 3, indexBy: 3, findIndex: 3, findLastIndex: 3};
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Mix in each Underscore method as a proxy to `Collection#models`.
</span><span class="cx" style="display: block; padding: 0 10px">   addUnderscoreMethods(Collection, collectionMethods, 'models');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1417,9 +1449,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">   var methodMap = {
</span><span class="cx" style="display: block; padding: 0 10px">     'create': 'POST',
</span><span class="cx" style="display: block; padding: 0 10px">     'update': 'PUT',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    'patch':  'PATCH',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    'patch': 'PATCH',
</ins><span class="cx" style="display: block; padding: 0 10px">     'delete': 'DELETE',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    'read':   'GET'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    'read': 'GET'
</ins><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1576,8 +1608,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     // Does the pathname match the root?
</span><span class="cx" style="display: block; padding: 0 10px">     matchRoot: function() {
</span><span class="cx" style="display: block; padding: 0 10px">       var path = this.decodeFragment(this.location.pathname);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var root = path.slice(0, this.root.length - 1) + '/';
-      return root === this.root;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var rootPath = path.slice(0, this.root.length - 1) + '/';
+      return rootPath === this.root;
</ins><span class="cx" style="display: block; padding: 0 10px">     },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Unicode characters in `location.pathname` are percent encoded so they're
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1649,8 +1681,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">         // If we've started off with a route from a `pushState`-enabled
</span><span class="cx" style="display: block; padding: 0 10px">         // browser, but we're currently in a browser that doesn't support it...
</span><span class="cx" style="display: block; padding: 0 10px">         if (!this._hasPushState && !this.atRoot()) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-          var root = this.root.slice(0, -1) || '/';
-          this.location.replace(root + '#' + this.getPath());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          var rootPath = this.root.slice(0, -1) || '/';
+          this.location.replace(rootPath + '#' + this.getPath());
</ins><span class="cx" style="display: block; padding: 0 10px">           // Return immediately as browser will do redirect to new url
</span><span class="cx" style="display: block; padding: 0 10px">           return true;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1679,7 +1711,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">       }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // Add a cross-platform `addEventListener` shim for older browsers.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var addEventListener = window.addEventListener || function (eventName, listener) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var addEventListener = window.addEventListener || function(eventName, listener) {
</ins><span class="cx" style="display: block; padding: 0 10px">         return attachEvent('on' + eventName, listener);
</span><span class="cx" style="display: block; padding: 0 10px">       };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1700,7 +1732,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">     // but possibly useful for unit testing Routers.
</span><span class="cx" style="display: block; padding: 0 10px">     stop: function() {
</span><span class="cx" style="display: block; padding: 0 10px">       // Add a cross-platform `removeEventListener` shim for older browsers.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var removeEventListener = window.removeEventListener || function (eventName, listener) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var removeEventListener = window.removeEventListener || function(eventName, listener) {
</ins><span class="cx" style="display: block; padding: 0 10px">         return detachEvent('on' + eventName, listener);
</span><span class="cx" style="display: block; padding: 0 10px">       };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1774,11 +1806,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">       fragment = this.getFragment(fragment || '');
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // Don't include a trailing slash on the root.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var root = this.root;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var rootPath = this.root;
</ins><span class="cx" style="display: block; padding: 0 10px">       if (fragment === '' || fragment.charAt(0) === '?') {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        root = root.slice(0, -1) || '/';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        rootPath = rootPath.slice(0, -1) || '/';
</ins><span class="cx" style="display: block; padding: 0 10px">       }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      var url = root + fragment;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      var url = rootPath + fragment;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">       // Strip the hash and decode for matching.
</span><span class="cx" style="display: block; padding: 0 10px">       fragment = this.decodeFragment(fragment.replace(pathStripper, ''));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1794,7 +1826,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">       // fragment to store history.
</span><span class="cx" style="display: block; padding: 0 10px">       } else if (this._wantsHashChange) {
</span><span class="cx" style="display: block; padding: 0 10px">         this._updateHash(this.location, fragment, options.replace);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if (this.iframe && fragment !== this.getHash(this.iframe.contentWindow)) {
</ins><span class="cx" style="display: block; padding: 0 10px">           var iWindow = this.iframe.contentWindow;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">           // Opening and closing the iframe tricks IE7 and earlier to push a
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1856,15 +1888,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">     _.extend(child, parent, staticProps);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     // Set the prototype chain to inherit from `parent`, without calling
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    // `parent` constructor function.
-    var Surrogate = function(){ this.constructor = child; };
-    Surrogate.prototype = parent.prototype;
-    child.prototype = new Surrogate;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    // `parent`'s constructor function and add the prototype properties.
+    child.prototype = _.create(parent.prototype, protoProps);
+    child.prototype.constructor = child;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    // Add prototype properties (instance properties) to the subclass,
-    // if supplied.
-    if (protoProps) _.extend(child.prototype, protoProps);
-
</del><span class="cx" style="display: block; padding: 0 10px">     // Set a convenience property in case the parent's prototype is needed
</span><span class="cx" style="display: block; padding: 0 10px">     // later.
</span><span class="cx" style="display: block; padding: 0 10px">     child.__super__ = parent.prototype;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1890,5 +1917,4 @@
</span><span class="cx" style="display: block; padding: 0 10px">   };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">   return Backbone;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-}));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+});
</ins></span></pre></div>
<a id="trunksrcwpincludesjsbackboneminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/backbone.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/backbone.min.js  2016-06-16 04:53:42 UTC (rev 37722)
+++ trunk/src/wp-includes/js/backbone.min.js    2016-06-16 09:26:06 UTC (rev 37723)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-(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,{contex
 t: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&quo
 t;,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],t
 his,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=func
 tion(){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&am
 p;&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:func
 tion(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("r
 oute",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 Err
 or("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(),{repl
 ace: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});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(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.3.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],o(t,this),n)};case 4:return function(t,n,s){return i[e](this[r],o(t,this),n,s)};default:return function(){var t=s.call(arguments);t.unshift(this[r]);return i[e].apply(i,t)}}};var h=function(t,e,r){i.each(e,function(e,n){if(i[n])t.prototype[n]=a(e,n,r)})};var o=function(t,e){if(i.isFunction(t))return t;if(i.isObject(t)&&!e._isModel(t))return l(t);if(i.isString(t))return function(e){return e.get(t)};return t};var l=function(t){var e=i.matches(t);return function(t){return e(t.attributes)}};var u=e.Events={};var c=/\s+/;var f=function(t,e,r,n,s){var a=0,h;if(r&&typeof r==="object"){if(n!==void 0&&"context"in s&&s.context===void 0)s.context=n;for(h=i.keys(r);a<h.length;a++){e=f(t,e,h[a],r[h[a]],s)}}else if(r&&c.test(r)){for(h=r.split(c);a<h.length;a++){e=t(e,h[a],n,s)}}else{e=t(e,r,n,s)}return e};u.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,{conte
 xt:r,ctx:t,listening:n});if(n){var s=t._listeners||(t._listeners={});s[n.id]=n}return t};u.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 h=this._listenId||(this._listenId=i.uniqueId("l"));a=s[n]={obj:t,objId:n,id:h,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,h=r.listening;if(h)h.count++;n.push({callback:i,context:s,ctx:s||a,listening:h})}return t};u.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};u.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 h=n[s[a]];if(!h)break;h.obj.off(e,r,this)}return this};var g=function(t,e,r,n){if(!t)return;var s=0,a;var h=n.context,o=n.listeners;if(!e&&!r
 &&!h){var l=i.keys(o);for(;s<l.length;s++){a=o[l[s]];delete o[a.id];delete a.listeningTo[a.objId]}return}var u=e?[e]:i.keys(t);for(;s<u.length;s++){e=u[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||h&&h!==v.context){f.push(v)}else{a=v.listening;if(a&&--a.count===0){delete o[a.id];delete a.listeningTo[a.objId]}}}if(f.length){t[e]=f}else{delete t[e]}}return t};u.once=function(t,e,r){var n=f(p,{},t,e,i.bind(this.off,this));if(typeof t==="string"&&r==null)e=void 0;return this.on(n,e,r)};u.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};u.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],h=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,h);return;default:while(++r<n)(i=t[r]).callback.apply(i.ctx,e);return}};u.bind=u.on;u.unbind=u.off;i.extend(e,u);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)||{};var n=i.result(this,"defaults");r=i.defaults(i.extend({},n,r),n);this.set(r,e);this.changed={};this.initialize.apply(this,arguments)};i.extend(y.prototype,u,{changed:null,validationError:null,idA
 ttribute:"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 h=[];var o=this._changing;this._changing=true;if(!o){this._previousAttributes=i.clone(this.attributes);this.changed={}}var l=this.attributes;var u=this.changed;var c=this._previousAttributes;for(var f in n){e=n[f];if(!i.isEqual(l[f],e))h.push(f);if(!i.isEqual(c[f],e)){u[f]=e}else{delete u[f]}s?delete l[f]:l[f]=e}if(this.idAttribute in n)this.id=this.get(this.idAttribute);if(!a){if(h.length)this._pending=r;for(var d=0;d<h.lengt
 h;d++){this.trigger("change:"+h[d],this,l[h[d]],r)}}if(o)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)};B(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 h=r.success;var o=this.attributes;r.success=function(t){a.attributes=o;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(h)h.call(r.context,a,t,r);a.trigger("sync",a,t,r)};B(this,r);if(n&&s)this.attributes=i.extend({},o,n);var l=this.isNew()?"create":r.patch?"patch":"update";if(l==="patch"&&!r.attrs)r.attrs=n;var u=this.sync(l,this,r);this.attributes=o;return u},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{B(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.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("i
 nvalid",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};h(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 I=function(t,e,i){i=Math.min(Math.max(i,0),t.length);var r=Array(t.length-i);var n=e.length;var s;for(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,u,{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]:t.slice(
 );var n=this._removeModels(t,e);if(!e.silent&&n.length){e.changes={added:[],merged:[],removed:n};this.trigger("update",this,e)}return r?n[0]:n},set:function(t,e){if(t==null)return;e=i.extend({},w,e);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>this.length)n=this.length;if(n<0)n+=this.length+1;var s=[];var a=[];var h=[];var o=[];var l={};var u=e.add;var c=e.merge;var f=e.remove;var d=false;var v=this.comparator&&n==null&&e.sort!==false;var g=i.isString(this.comparator)?this.comparator:null;var p,m;for(m=0;m<t.length;m++){p=t[m];var _=this.get(p);if(_){if(c&&p!==_){var y=this._isModel(p)?p.attributes:p;if(e.parse)y=_.parse(y,e);_.set(y,e);h.push(_);if(v&&!d)d=_.hasChanged(g)}if(!l[_.cid]){l[_.cid]=true;s.push(_)}t[m]=_}else if(u){p=t[m]=this._prepareModel(p,e);if(p){a.push(p);this._addReference(p,e);l[p.cid]=true;s.push(p)}}}if(f){for(m=0;m&l
 t;this.length;m++){p=this.models[m];if(!l[p.cid])o.push(p)}if(o.length)this._removeModels(o,e)}var b=false;var x=!v&&u&&f;if(s.length&&x){b=this.length!==s.length||i.some(this.models,function(t,e){return t!==s[e]});this.models.length=0;I(this.models,s,0);this.length=this.models.length}else if(a.length){if(v)d=true;I(this.models,a,n==null?this.length:n);this.length=this.models.length}if(d)this.sort({silent:true});if(!e.silent){for(m=0;m<a.length;m++){if(n!=null)e.index=n+m;p=a[m];p.trigger("add",p,this,e)}if(d||b)this.trigger("sort",this,e);if(a.length||o.length||h.length){e.changes={added:a,removed:o,merged:h};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:funct
 ion(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;return this._byId[t]||this._byId[this.modelId(t.attributes||t)]||t.cid&&this._byId[t.cid]},has:function(t){return this.get(t)!=null},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:fu
 nction(t){return this.map(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)};B(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.valida
 tionError)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--;delete this._byId[n.cid];var a=this.modelId(n.attributes);if(a!=null)delete this._byId[a];if(!e.silent){e.index=s;n.trigger("remove",n,this,e)}i.push(n);this._removeReference(n,e)}return i},_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(e){if((t==="add"||t==="remove")&&i!==this)return;if(t==="destr
 oy")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:0,foldl:0,inject:0,reduceRight:0,foldr:0,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,findIndex:3,findLastIndex:3};h(x,S,"models");var k=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(k.prototype,u,{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&quo
 t;;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 h=n.beforeSend;n.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",s);if(h)return h.apply(this,arguments)}}if(a.type!=="GET"&&!n.emulateJSON){a.processData=false}var o=n.error;n.error=function(t,e,i){n.textStatus=e;n.errorThrown=i;if(o)o.call(n.context,t,e,i)};var l=n.xhr=e.ajax(i.extend(a,n));r.trigger("request",r,l,n);return l};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.exten
 d($.prototype,u,{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 N=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 M=/^[#\/]|\s+$/g;var O=/^\/+|\/+$/g;var U=/#.*$/;N.started=false;i.extend(N.prototype,u,{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(M,"")},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._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,f
 alse)}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);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.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(!N.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 N;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);n.prototype=i.create(r.prototype,t);n.prototype.constructor=n;n.__super__=r.prototype;return n};y.extend=x.extend=$.extend=k.extend=N.extend=q;var F=function(){throw new Error('A "url" property or function must be specified')};var B=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});
</ins></span></pre></div>
<a id="trunktestsphpunittestsdependenciesbackbonejsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/dependencies/backbonejs.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/dependencies/backbonejs.php                             (rev 0)
+++ trunk/tests/phpunit/tests/dependencies/backbonejs.php       2016-06-16 09:26:06 UTC (rev 37723)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,15 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * @group dependencies
+ * @group scripts
+ */
+class Tests_Dependencies_Backbonejs extends WP_UnitTestCase {
+
+       function test_exclusion_of_sourcemaps() {
+               $file = ABSPATH . WPINC . '/js/backbone.min.js';
+               $this->assertTrue( file_exists( $file ) );
+               $contents = trim( file_get_contents( $file ) );
+               $this->assertFalse( strpos( $contents, 'sourceMappingURL' ), 'Presence of sourceMappingURL' );
+       }
+}
</ins></span></pre>
</div>
</div>

</body>
</html>