소스 검색

Update to Backbone 1.4.0 and use fork of Backbone.NativeView

with `_setElement` fix.

See https://github.com/akre54/Backbone.NativeView/pull/29
JC Brand 6 년 전
부모
커밋
b15ebdde40
5개의 변경된 파일664개의 추가작업 그리고 460개의 파일을 삭제
  1. 2 0
      CHANGES.md
  2. 343 141
      dist/converse.js
  3. 316 316
      package-lock.json
  4. 2 2
      package.json
  5. 1 1
      src/headless/package.json

+ 2 - 0
CHANGES.md

@@ -2,6 +2,8 @@
 
 
 ## 4.1.3 (Unreleased)
 ## 4.1.3 (Unreleased)
 
 
+- Upgrade to Backbone 1.4.0
+- Fix "flashing" of roster filter when you have less than 5 roster contacts.
 - Allow setting of debug mode via URL with `/#converse?debug=true`
 - Allow setting of debug mode via URL with `/#converse?debug=true`
 - New config setting [locked_muc_domain](https://conversejs.org/docs/html/configuration.html#locked-muc-domain)
 - New config setting [locked_muc_domain](https://conversejs.org/docs/html/configuration.html#locked-muc-domain)
 - New config setting [show_client_info](https://conversejs.org/docs/html/configuration.html#show-client-info)
 - New config setting [show_client_info](https://conversejs.org/docs/html/configuration.html#show-client-info)

+ 343 - 141
dist/converse.js

@@ -893,12 +893,12 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 //     https://github.com/akre54/Backbone.NativeView
 //     https://github.com/akre54/Backbone.NativeView
 
 
 (function (factory) {
 (function (factory) {
-  if (true) { !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! backbone */ "./node_modules/backbone/backbone.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
+  if (true) { !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! underscore */ "./src/underscore-shim.js"), __webpack_require__(/*! backbone */ "./node_modules/backbone/backbone.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
 				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
 				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
 				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
 				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
 				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
   } else {}
   } else {}
-}(function (Backbone) {
+}(function (_, Backbone) {
   // Cached regex to match an opening '<' of an HTML tag, possibly left-padded
   // Cached regex to match an opening '<' of an HTML tag, possibly left-padded
   // with whitespace.
   // with whitespace.
   var paddedLt = /^\s*</;
   var paddedLt = /^\s*</;
@@ -907,10 +907,15 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
   var ElementProto = (typeof Element !== 'undefined' && Element.prototype) || {};
   var ElementProto = (typeof Element !== 'undefined' && Element.prototype) || {};
 
 
   // Cross-browser event listener shims
   // Cross-browser event listener shims
-  var elementAddEventListener = ElementProto.addEventListener || function(eventName, listener) {
+  var elementAddEventListener = ElementProto.addEventListener ? function(eventName, listener) {
+    return this.addEventListener(eventName, listener, false);
+  } : function(eventName, listener) {
     return this.attachEvent('on' + eventName, listener);
     return this.attachEvent('on' + eventName, listener);
   }
   }
-  var elementRemoveEventListener = ElementProto.removeEventListener || function(eventName, listener) {
+
+  var elementRemoveEventListener = ElementProto.removeEventListener ? function(eventName, listener) {
+    return this.removeEventListener(eventName, listener, false);
+  } : function(eventName, listener) {
     return this.detachEvent('on' + eventName, listener);
     return this.detachEvent('on' + eventName, listener);
   }
   }
 
 
@@ -959,7 +964,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
     },
     },
 
 
     // Apply the `element` to the view. `element` can be a CSS selector,
     // Apply the `element` to the view. `element` can be a CSS selector,
-    // a string of HTML, or an Element node.
+    // a string of HTML, or an Element node. If passed a NodeList or CSS
+    // selector, uses just the first match.
     _setElement: function(element) {
     _setElement: function(element) {
       if (typeof element == 'string') {
       if (typeof element == 'string') {
         if (paddedLt.test(element)) {
         if (paddedLt.test(element)) {
@@ -969,6 +975,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
         } else {
         } else {
           this.el = document.querySelector(element);
           this.el = document.querySelector(element);
         }
         }
+      } else if (element && !_.isElement(element) && element.length) {
+        this.el = element[0];
       } else {
       } else {
         this.el = element;
         this.el = element;
       }
       }
@@ -991,12 +999,28 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
     // result of calling bound `listener` with the parameters given to the
     // result of calling bound `listener` with the parameters given to the
     // handler.
     // handler.
     delegate: function(eventName, selector, listener) {
     delegate: function(eventName, selector, listener) {
+      var root = this.el;
+
+      if (!root) {
+        return;
+      }
+
       if (typeof selector === 'function') {
       if (typeof selector === 'function') {
         listener = selector;
         listener = selector;
         selector = null;
         selector = null;
       }
       }
 
 
-      var root = this.el;
+      // Given that `focus` and `blur` events do not bubble, do not delegate these events
+      if (['focus', 'blur'].indexOf(eventName) !== -1) {
+        var els = this.el.querySelectorAll(selector);
+        for (var i = 0, len = els.length; i < len; i++) {
+          var item = els[i];
+          elementAddEventListener.call(item, eventName, listener, false);
+          this._domEvents.push({el: item, eventName: eventName, handler: listener});
+        }
+        return listener;
+      }
+
       var handler = selector ? function (e) {
       var handler = selector ? function (e) {
         var node = e.target || e.srcElement;
         var node = e.target || e.srcElement;
         for (; node && node != root; node = node.parentNode) {
         for (; node && node != root; node = node.parentNode) {
@@ -1008,7 +1032,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
       } : listener;
       } : listener;
 
 
       elementAddEventListener.call(this.el, eventName, handler, false);
       elementAddEventListener.call(this.el, eventName, handler, false);
-      this._domEvents.push({eventName: eventName, handler: handler, listener: listener, selector: selector});
+      this._domEvents.push({el: this.el, eventName: eventName, handler: handler, listener: listener, selector: selector});
       return handler;
       return handler;
     },
     },
 
 
@@ -1022,7 +1046,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
 
       if (this.el) {
       if (this.el) {
         var handlers = this._domEvents.slice();
         var handlers = this._domEvents.slice();
-        for (var i = 0, len = handlers.length; i < len; i++) {
+        var i = handlers.length;
+        while (i--) {
           var item = handlers[i];
           var item = handlers[i];
 
 
           var match = item.eventName === eventName &&
           var match = item.eventName === eventName &&
@@ -1031,8 +1056,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
 
           if (!match) continue;
           if (!match) continue;
 
 
-          elementRemoveEventListener.call(this.el, item.eventName, item.handler, false);
-          this._domEvents.splice(indexOf(handlers, item), 1);
+          elementRemoveEventListener.call(item.el, item.eventName, item.handler, false);
+          this._domEvents.splice(i, 1);
         }
         }
       }
       }
       return this;
       return this;
@@ -1043,7 +1068,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
       if (this.el) {
       if (this.el) {
         for (var i = 0, len = this._domEvents.length; i < len; i++) {
         for (var i = 0, len = this._domEvents.length; i < len; i++) {
           var item = this._domEvents[i];
           var item = this._domEvents[i];
-          elementRemoveEventListener.call(this.el, item.eventName, item.handler, false);
+          elementRemoveEventListener.call(item.el, item.eventName, item.handler, false);
         };
         };
         this._domEvents.length = 0;
         this._domEvents.length = 0;
       }
       }
@@ -1057,6 +1082,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 }));
 }));
 
 
 
 
+
 /***/ }),
 /***/ }),
 
 
 /***/ "./node_modules/backbone.overview/backbone.orderedlistview.js":
 /***/ "./node_modules/backbone.overview/backbone.orderedlistview.js":
@@ -1478,9 +1504,9 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
 /*! no static exports found */
 /*! no static exports found */
 /***/ (function(module, exports, __webpack_require__) {
 /***/ (function(module, exports, __webpack_require__) {
 
 
-/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;//     Backbone.js 1.3.3
+/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;//     Backbone.js 1.4.0
 
 
-//     (c) 2010-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+//     (c) 2010-2019 Jeremy Ashkenas and DocumentCloud
 //     Backbone may be freely distributed under the MIT license.
 //     Backbone may be freely distributed under the MIT license.
 //     For all details and documentation:
 //     For all details and documentation:
 //     http://backbonejs.org
 //     http://backbonejs.org
@@ -1489,8 +1515,8 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
 
 
   // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
   // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
   // We use `self` instead of `window` for `WebWorker` support.
   // We use `self` instead of `window` for `WebWorker` support.
-  var root = (typeof self == 'object' && self.self === self && self) ||
-            (typeof global == 'object' && global.global === global && global);
+  var root = typeof self == 'object' && self.self === self && self ||
+            typeof global == 'object' && global.global === global && global;
 
 
   // Set up Backbone appropriately for the environment. Start with AMD.
   // Set up Backbone appropriately for the environment. Start with AMD.
   if (true) {
   if (true) {
@@ -1517,7 +1543,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   var slice = Array.prototype.slice;
   var slice = Array.prototype.slice;
 
 
   // Current version of the library. Keep in sync with `package.json`.
   // Current version of the library. Keep in sync with `package.json`.
-  Backbone.VERSION = '1.3.3';
+  Backbone.VERSION = '1.4.0';
 
 
   // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
   // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
   // the `$` variable.
   // the `$` variable.
@@ -1541,54 +1567,6 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // form param named `model`.
   // form param named `model`.
   Backbone.emulateJSON = false;
   Backbone.emulateJSON = false;
 
 
-  // Proxy Backbone class methods to Underscore functions, wrapping the model's
-  // `attributes` object or collection's `models` array behind the scenes.
-  //
-  // collection.filter(function(model) { return model.get('age') > 10 });
-  // collection.each(this.addView);
-  //
-  // `Function#apply` can be slow so we use the method's arg count, if we know it.
-  var addMethod = function(length, method, attribute) {
-    switch (length) {
-      case 1: return function() {
-        return _[method](this[attribute]);
-      };
-      case 2: return function(value) {
-        return _[method](this[attribute], value);
-      };
-      case 3: return function(iteratee, context) {
-        return _[method](this[attribute], cb(iteratee, this), context);
-      };
-      case 4: return function(iteratee, defaultVal, context) {
-        return _[method](this[attribute], cb(iteratee, this), defaultVal, context);
-      };
-      default: return function() {
-        var args = slice.call(arguments);
-        args.unshift(this[attribute]);
-        return _[method].apply(_, args);
-      };
-    }
-  };
-  var addUnderscoreMethods = function(Class, methods, attribute) {
-    _.each(methods, function(length, method) {
-      if (_[method]) Class.prototype[method] = addMethod(length, method, attribute);
-    });
-  };
-
-  // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`.
-  var cb = function(iteratee, instance) {
-    if (_.isFunction(iteratee)) return iteratee;
-    if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
-    if (_.isString(iteratee)) return function(model) { return model.get(iteratee); };
-    return iteratee;
-  };
-  var modelMatcher = function(attrs) {
-    var matcher = _.matches(attrs);
-    return function(model) {
-      return matcher(model.attributes);
-    };
-  };
-
   // Backbone.Events
   // Backbone.Events
   // ---------------
   // ---------------
 
 
@@ -1607,6 +1585,9 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // Regular expression used to split event strings.
   // Regular expression used to split event strings.
   var eventSplitter = /\s+/;
   var eventSplitter = /\s+/;
 
 
+  // A private global variable to share between listeners and listenees.
+  var _listening;
+
   // Iterates over the standard `event, callback` (as well as the fancy multiple
   // Iterates over the standard `event, callback` (as well as the fancy multiple
   // space-separated events `"change blur", callback` and jQuery-style event
   // space-separated events `"change blur", callback` and jQuery-style event
   // maps `{event: callback}`).
   // maps `{event: callback}`).
@@ -1633,23 +1614,21 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // Bind an event to a `callback` function. Passing `"all"` will bind
   // Bind an event to a `callback` function. Passing `"all"` will bind
   // the callback to all events fired.
   // the callback to all events fired.
   Events.on = function(name, callback, context) {
   Events.on = function(name, callback, context) {
-    return internalOn(this, name, callback, context);
-  };
-
-  // Guard the `listening` argument from the public API.
-  var internalOn = function(obj, name, callback, context, listening) {
-    obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
+    this._events = eventsApi(onApi, this._events || {}, name, callback, {
       context: context,
       context: context,
-      ctx: obj,
-      listening: listening
+      ctx: this,
+      listening: _listening
     });
     });
 
 
-    if (listening) {
-      var listeners = obj._listeners || (obj._listeners = {});
-      listeners[listening.id] = listening;
+    if (_listening) {
+      var listeners = this._listeners || (this._listeners = {});
+      listeners[_listening.id] = _listening;
+      // Allow the listening to use a counter, instead of tracking
+      // callbacks for library interop
+      _listening.interop = false;
     }
     }
 
 
-    return obj;
+    return this;
   };
   };
 
 
   // Inversion-of-control versions of `on`. Tell *this* object to listen to
   // Inversion-of-control versions of `on`. Tell *this* object to listen to
@@ -1659,17 +1638,23 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     if (!obj) return this;
     if (!obj) return this;
     var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
     var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
     var listeningTo = this._listeningTo || (this._listeningTo = {});
     var listeningTo = this._listeningTo || (this._listeningTo = {});
-    var listening = listeningTo[id];
+    var listening = _listening = listeningTo[id];
 
 
     // This object is not listening to any other events on `obj` yet.
     // This object is not listening to any other events on `obj` yet.
     // Setup the necessary references to track the listening callbacks.
     // Setup the necessary references to track the listening callbacks.
     if (!listening) {
     if (!listening) {
-      var thisId = this._listenId || (this._listenId = _.uniqueId('l'));
-      listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0};
+      this._listenId || (this._listenId = _.uniqueId('l'));
+      listening = _listening = listeningTo[id] = new Listening(this, obj);
     }
     }
 
 
-    // Bind callbacks on obj, and keep track of them on listening.
-    internalOn(obj, name, callback, this, listening);
+    // Bind callbacks on obj.
+    var error = tryCatchOn(obj, name, callback, this);
+    _listening = void 0;
+
+    if (error) throw error;
+    // If the target obj is not Backbone.Events, track events manually.
+    if (listening.interop) listening.on(name, callback);
+
     return this;
     return this;
   };
   };
 
 
@@ -1685,6 +1670,16 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     return events;
     return events;
   };
   };
 
 
+  // An try-catch guarded #on function, to prevent poisoning the global
+  // `_listening` variable.
+  var tryCatchOn = function(obj, name, callback, context) {
+    try {
+      obj.on(name, callback, context);
+    } catch (e) {
+      return e;
+    }
+  };
+
   // Remove one or many callbacks. If `context` is null, removes all
   // Remove one or many callbacks. If `context` is null, removes all
   // callbacks with that function. If `callback` is null, removes all
   // callbacks with that function. If `callback` is null, removes all
   // callbacks for the event. If `name` is null, removes all bound
   // callbacks for the event. If `name` is null, removes all bound
@@ -1695,6 +1690,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       context: context,
       context: context,
       listeners: this._listeners
       listeners: this._listeners
     });
     });
+
     return this;
     return this;
   };
   };
 
 
@@ -1705,7 +1701,6 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     if (!listeningTo) return this;
     if (!listeningTo) return this;
 
 
     var ids = obj ? [obj._listenId] : _.keys(listeningTo);
     var ids = obj ? [obj._listenId] : _.keys(listeningTo);
-
     for (var i = 0; i < ids.length; i++) {
     for (var i = 0; i < ids.length; i++) {
       var listening = listeningTo[ids[i]];
       var listening = listeningTo[ids[i]];
 
 
@@ -1714,7 +1709,9 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       if (!listening) break;
       if (!listening) break;
 
 
       listening.obj.off(name, callback, this);
       listening.obj.off(name, callback, this);
+      if (listening.interop) listening.off(name, callback);
     }
     }
+    if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
 
 
     return this;
     return this;
   };
   };
@@ -1723,21 +1720,18 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   var offApi = function(events, name, callback, options) {
   var offApi = function(events, name, callback, options) {
     if (!events) return;
     if (!events) return;
 
 
-    var i = 0, listening;
     var context = options.context, listeners = options.listeners;
     var context = options.context, listeners = options.listeners;
+    var i = 0, names;
 
 
-    // Delete all events listeners and "drop" events.
-    if (!name && !callback && !context) {
-      var ids = _.keys(listeners);
-      for (; i < ids.length; i++) {
-        listening = listeners[ids[i]];
-        delete listeners[listening.id];
-        delete listening.listeningTo[listening.objId];
+    // Delete all event listeners and "drop" events.
+    if (!name && !context && !callback) {
+      for (names = _.keys(listeners); i < names.length; i++) {
+        listeners[names[i]].cleanup();
       }
       }
       return;
       return;
     }
     }
 
 
-    var names = name ? [name] : _.keys(events);
+    names = name ? [name] : _.keys(events);
     for (; i < names.length; i++) {
     for (; i < names.length; i++) {
       name = names[i];
       name = names[i];
       var handlers = events[name];
       var handlers = events[name];
@@ -1745,7 +1739,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       // Bail out if there are no events stored.
       // Bail out if there are no events stored.
       if (!handlers) break;
       if (!handlers) break;
 
 
-      // Replace events if there are any remaining.  Otherwise, clean up.
+      // Find any remaining events.
       var remaining = [];
       var remaining = [];
       for (var j = 0; j < handlers.length; j++) {
       for (var j = 0; j < handlers.length; j++) {
         var handler = handlers[j];
         var handler = handlers[j];
@@ -1756,21 +1750,19 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
         ) {
         ) {
           remaining.push(handler);
           remaining.push(handler);
         } else {
         } else {
-          listening = handler.listening;
-          if (listening && --listening.count === 0) {
-            delete listeners[listening.id];
-            delete listening.listeningTo[listening.objId];
-          }
+          var listening = handler.listening;
+          if (listening) listening.off(name, callback);
         }
         }
       }
       }
 
 
-      // Update tail event if the list has any events.  Otherwise, clean up.
+      // Replace events if there are any remaining.  Otherwise, clean up.
       if (remaining.length) {
       if (remaining.length) {
         events[name] = remaining;
         events[name] = remaining;
       } else {
       } else {
         delete events[name];
         delete events[name];
       }
       }
     }
     }
+
     return events;
     return events;
   };
   };
 
 
@@ -1780,7 +1772,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // once for each event, not once for a combination of all events.
   // once for each event, not once for a combination of all events.
   Events.once = function(name, callback, context) {
   Events.once = function(name, callback, context) {
     // Map the event into a `{event: once}` object.
     // Map the event into a `{event: once}` object.
-    var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
+    var events = eventsApi(onceMap, {}, name, callback, this.off.bind(this));
     if (typeof name === 'string' && context == null) callback = void 0;
     if (typeof name === 'string' && context == null) callback = void 0;
     return this.on(events, callback, context);
     return this.on(events, callback, context);
   };
   };
@@ -1788,7 +1780,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // Inversion-of-control versions of `once`.
   // Inversion-of-control versions of `once`.
   Events.listenToOnce = function(obj, name, callback) {
   Events.listenToOnce = function(obj, name, callback) {
     // Map the event into a `{event: once}` object.
     // Map the event into a `{event: once}` object.
-    var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
+    var events = eventsApi(onceMap, {}, name, callback, this.stopListening.bind(this, obj));
     return this.listenTo(obj, events);
     return this.listenTo(obj, events);
   };
   };
 
 
@@ -1846,6 +1838,44 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     }
     }
   };
   };
 
 
+  // A listening class that tracks and cleans up memory bindings
+  // when all callbacks have been offed.
+  var Listening = function(listener, obj) {
+    this.id = listener._listenId;
+    this.listener = listener;
+    this.obj = obj;
+    this.interop = true;
+    this.count = 0;
+    this._events = void 0;
+  };
+
+  Listening.prototype.on = Events.on;
+
+  // Offs a callback (or several).
+  // Uses an optimized counter if the listenee uses Backbone.Events.
+  // Otherwise, falls back to manual tracking to support events
+  // library interop.
+  Listening.prototype.off = function(name, callback) {
+    var cleanup;
+    if (this.interop) {
+      this._events = eventsApi(offApi, this._events, name, callback, {
+        context: void 0,
+        listeners: void 0
+      });
+      cleanup = !this._events;
+    } else {
+      this.count--;
+      cleanup = this.count === 0;
+    }
+    if (cleanup) this.cleanup();
+  };
+
+  // Cleans up memory bindings between the listener and the listenee.
+  Listening.prototype.cleanup = function() {
+    delete this.listener._listeningTo[this.obj._listenId];
+    if (!this.interop) delete this.obj._listeners[this.id];
+  };
+
   // Aliases for backwards compatibility.
   // Aliases for backwards compatibility.
   Events.bind   = Events.on;
   Events.bind   = Events.on;
   Events.unbind = Events.off;
   Events.unbind = Events.off;
@@ -1867,6 +1897,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   var Model = Backbone.Model = function(attributes, options) {
   var Model = Backbone.Model = function(attributes, options) {
     var attrs = attributes || {};
     var attrs = attributes || {};
     options || (options = {});
     options || (options = {});
+    this.preinitialize.apply(this, arguments);
     this.cid = _.uniqueId(this.cidPrefix);
     this.cid = _.uniqueId(this.cidPrefix);
     this.attributes = {};
     this.attributes = {};
     if (options.collection) this.collection = options.collection;
     if (options.collection) this.collection = options.collection;
@@ -1895,6 +1926,10 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     // You may want to override this if you're experiencing name clashes with model ids.
     // You may want to override this if you're experiencing name clashes with model ids.
     cidPrefix: 'c',
     cidPrefix: 'c',
 
 
+    // preinitialize is an empty function by default. You can override it with a function
+    // or object.  preinitialize will run before any instantiation logic is run in the Model.
+    preinitialize: function(){},
+
     // Initialize is an empty function by default. Override it with your own
     // Initialize is an empty function by default. Override it with your own
     // initialization logic.
     // initialization logic.
     initialize: function(){},
     initialize: function(){},
@@ -2035,12 +2070,14 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
       if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
       var old = this._changing ? this._previousAttributes : this.attributes;
       var old = this._changing ? this._previousAttributes : this.attributes;
       var changed = {};
       var changed = {};
+      var hasChanged;
       for (var attr in diff) {
       for (var attr in diff) {
         var val = diff[attr];
         var val = diff[attr];
         if (_.isEqual(old[attr], val)) continue;
         if (_.isEqual(old[attr], val)) continue;
         changed[attr] = val;
         changed[attr] = val;
+        hasChanged = true;
       }
       }
-      return _.size(changed) ? changed : false;
+      return hasChanged ? changed : false;
     },
     },
 
 
     // Get the previous value of an attribute, recorded at the time the last
     // Get the previous value of an attribute, recorded at the time the last
@@ -2116,7 +2153,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       // Set temporary attributes if `{wait: true}` to properly find new ids.
       // Set temporary attributes if `{wait: true}` to properly find new ids.
       if (attrs && wait) this.attributes = _.extend({}, attributes, attrs);
       if (attrs && wait) this.attributes = _.extend({}, attributes, attrs);
 
 
-      var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
+      var method = this.isNew() ? 'create' : options.patch ? 'patch' : 'update';
       if (method === 'patch' && !options.attrs) options.attrs = attrs;
       if (method === 'patch' && !options.attrs) options.attrs = attrs;
       var xhr = this.sync(method, this, options);
       var xhr = this.sync(method, this, options);
 
 
@@ -2204,14 +2241,6 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
 
 
   });
   });
 
 
-  // Underscore methods that we want to implement on the Model, mapped to the
-  // number of arguments they take.
-  var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
-      omit: 0, chain: 1, isEmpty: 1};
-
-  // Mix in each Underscore method as a proxy to `Model#attributes`.
-  addUnderscoreMethods(Model, modelMethods, 'attributes');
-
   // Backbone.Collection
   // Backbone.Collection
   // -------------------
   // -------------------
 
 
@@ -2227,6 +2256,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // its models in sort order, as they're added and removed.
   // its models in sort order, as they're added and removed.
   var Collection = Backbone.Collection = function(models, options) {
   var Collection = Backbone.Collection = function(models, options) {
     options || (options = {});
     options || (options = {});
+    this.preinitialize.apply(this, arguments);
     if (options.model) this.model = options.model;
     if (options.model) this.model = options.model;
     if (options.comparator !== void 0) this.comparator = options.comparator;
     if (options.comparator !== void 0) this.comparator = options.comparator;
     this._reset();
     this._reset();
@@ -2256,6 +2286,11 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     // This should be overridden in most cases.
     // This should be overridden in most cases.
     model: Model,
     model: Model,
 
 
+
+    // preinitialize is an empty function by default. You can override it with a function
+    // or object.  preinitialize will run before any instantiation logic is run in the Collection.
+    preinitialize: function(){},
+
     // Initialize is an empty function by default. Override it with your own
     // Initialize is an empty function by default. Override it with your own
     // initialization logic.
     // initialization logic.
     initialize: function(){},
     initialize: function(){},
@@ -2458,7 +2493,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     get: function(obj) {
     get: function(obj) {
       if (obj == null) return void 0;
       if (obj == null) return void 0;
       return this._byId[obj] ||
       return this._byId[obj] ||
-        this._byId[this.modelId(obj.attributes || obj)] ||
+        this._byId[this.modelId(this._isModel(obj) ? obj.attributes : obj)] ||
         obj.cid && this._byId[obj.cid];
         obj.cid && this._byId[obj.cid];
     },
     },
 
 
@@ -2494,7 +2529,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       options || (options = {});
       options || (options = {});
 
 
       var length = comparator.length;
       var length = comparator.length;
-      if (_.isFunction(comparator)) comparator = _.bind(comparator, this);
+      if (_.isFunction(comparator)) comparator = comparator.bind(this);
 
 
       // Run sort based on type of `comparator`.
       // Run sort based on type of `comparator`.
       if (length === 1 || _.isString(comparator)) {
       if (length === 1 || _.isString(comparator)) {
@@ -2566,6 +2601,21 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       return attrs[this.model.prototype.idAttribute || 'id'];
       return attrs[this.model.prototype.idAttribute || 'id'];
     },
     },
 
 
+    // Get an iterator of all models in this collection.
+    values: function() {
+      return new CollectionIterator(this, ITERATOR_VALUES);
+    },
+
+    // Get an iterator of all model IDs in this collection.
+    keys: function() {
+      return new CollectionIterator(this, ITERATOR_KEYS);
+    },
+
+    // Get an iterator of all [ID, model] tuples in this collection.
+    entries: function() {
+      return new CollectionIterator(this, ITERATOR_KEYSVALUES);
+    },
+
     // Private method to reset all internal state. Called when the collection
     // Private method to reset all internal state. Called when the collection
     // is first initialized or reset.
     // is first initialized or reset.
     _reset: function() {
     _reset: function() {
@@ -2662,20 +2712,71 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
 
 
   });
   });
 
 
-  // Underscore methods that we want to implement on the Collection.
-  // 90% of the core usefulness of Backbone Collections is actually implemented
-  // right here:
-  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,
-      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};
+  // Defining an @@iterator method implements JavaScript's Iterable protocol.
+  // In modern ES2015 browsers, this value is found at Symbol.iterator.
+  /* global Symbol */
+  var $$iterator = typeof Symbol === 'function' && Symbol.iterator;
+  if ($$iterator) {
+    Collection.prototype[$$iterator] = Collection.prototype.values;
+  }
 
 
-  // Mix in each Underscore method as a proxy to `Collection#models`.
-  addUnderscoreMethods(Collection, collectionMethods, 'models');
+  // CollectionIterator
+  // ------------------
+
+  // A CollectionIterator implements JavaScript's Iterator protocol, allowing the
+  // use of `for of` loops in modern browsers and interoperation between
+  // Backbone.Collection and other JavaScript functions and third-party libraries
+  // which can operate on Iterables.
+  var CollectionIterator = function(collection, kind) {
+    this._collection = collection;
+    this._kind = kind;
+    this._index = 0;
+  };
+
+  // This "enum" defines the three possible kinds of values which can be emitted
+  // by a CollectionIterator that correspond to the values(), keys() and entries()
+  // methods on Collection, respectively.
+  var ITERATOR_VALUES = 1;
+  var ITERATOR_KEYS = 2;
+  var ITERATOR_KEYSVALUES = 3;
+
+  // All Iterators should themselves be Iterable.
+  if ($$iterator) {
+    CollectionIterator.prototype[$$iterator] = function() {
+      return this;
+    };
+  }
+
+  CollectionIterator.prototype.next = function() {
+    if (this._collection) {
+
+      // Only continue iterating if the iterated collection is long enough.
+      if (this._index < this._collection.length) {
+        var model = this._collection.at(this._index);
+        this._index++;
+
+        // Construct a value depending on what kind of values should be iterated.
+        var value;
+        if (this._kind === ITERATOR_VALUES) {
+          value = model;
+        } else {
+          var id = this._collection.modelId(model.attributes);
+          if (this._kind === ITERATOR_KEYS) {
+            value = id;
+          } else { // ITERATOR_KEYSVALUES
+            value = [id, model];
+          }
+        }
+        return {value: value, done: false};
+      }
+
+      // Once exhausted, remove the reference to the collection so future
+      // calls to the next method always return done.
+      this._collection = void 0;
+    }
+
+    return {value: void 0, done: true};
+  };
 
 
   // Backbone.View
   // Backbone.View
   // -------------
   // -------------
@@ -2692,6 +2793,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // if an existing element is not provided...
   // if an existing element is not provided...
   var View = Backbone.View = function(options) {
   var View = Backbone.View = function(options) {
     this.cid = _.uniqueId('view');
     this.cid = _.uniqueId('view');
+    this.preinitialize.apply(this, arguments);
     _.extend(this, _.pick(options, viewOptions));
     _.extend(this, _.pick(options, viewOptions));
     this._ensureElement();
     this._ensureElement();
     this.initialize.apply(this, arguments);
     this.initialize.apply(this, arguments);
@@ -2715,6 +2817,10 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       return this.$el.find(selector);
       return this.$el.find(selector);
     },
     },
 
 
+    // preinitialize is an empty function by default. You can override it with a function
+    // or object.  preinitialize will run before any instantiation logic is run in the View
+    preinitialize: function(){},
+
     // Initialize is an empty function by default. Override it with your own
     // Initialize is an empty function by default. Override it with your own
     // initialization logic.
     // initialization logic.
     initialize: function(){},
     initialize: function(){},
@@ -2782,7 +2888,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
         if (!_.isFunction(method)) method = this[method];
         if (!_.isFunction(method)) method = this[method];
         if (!method) continue;
         if (!method) continue;
         var match = key.match(delegateEventSplitter);
         var match = key.match(delegateEventSplitter);
-        this.delegate(match[1], match[2], _.bind(method, this));
+        this.delegate(match[1], match[2], method.bind(this));
       }
       }
       return this;
       return this;
     },
     },
@@ -2840,6 +2946,94 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
 
 
   });
   });
 
 
+  // Proxy Backbone class methods to Underscore functions, wrapping the model's
+  // `attributes` object or collection's `models` array behind the scenes.
+  //
+  // collection.filter(function(model) { return model.get('age') > 10 });
+  // collection.each(this.addView);
+  //
+  // `Function#apply` can be slow so we use the method's arg count, if we know it.
+  var addMethod = function(base, length, method, attribute) {
+    switch (length) {
+      case 1: return function() {
+        return base[method](this[attribute]);
+      };
+      case 2: return function(value) {
+        return base[method](this[attribute], value);
+      };
+      case 3: return function(iteratee, context) {
+        return base[method](this[attribute], cb(iteratee, this), context);
+      };
+      case 4: return function(iteratee, defaultVal, context) {
+        return base[method](this[attribute], cb(iteratee, this), defaultVal, context);
+      };
+      default: return function() {
+        var args = slice.call(arguments);
+        args.unshift(this[attribute]);
+        return base[method].apply(base, args);
+      };
+    }
+  };
+
+  var addUnderscoreMethods = function(Class, base, methods, attribute) {
+    _.each(methods, function(length, method) {
+      if (base[method]) Class.prototype[method] = addMethod(base, length, method, attribute);
+    });
+  };
+
+  // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`.
+  var cb = function(iteratee, instance) {
+    if (_.isFunction(iteratee)) return iteratee;
+    if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
+    if (_.isString(iteratee)) return function(model) { return model.get(iteratee); };
+    return iteratee;
+  };
+  var modelMatcher = function(attrs) {
+    var matcher = _.matches(attrs);
+    return function(model) {
+      return matcher(model.attributes);
+    };
+  };
+
+  // Underscore methods that we want to implement on the Collection.
+  // 90% of the core usefulness of Backbone Collections is actually implemented
+  // right here:
+  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,
+    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};
+
+
+  // Underscore methods that we want to implement on the Model, mapped to the
+  // number of arguments they take.
+  var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
+    omit: 0, chain: 1, isEmpty: 1};
+
+  // Mix in each Underscore method as a proxy to `Collection#models`.
+
+  _.each([
+    [Collection, collectionMethods, 'models'],
+    [Model, modelMethods, 'attributes']
+  ], function(config) {
+    var Base = config[0],
+        methods = config[1],
+        attribute = config[2];
+
+    Base.mixin = function(obj) {
+      var mappings = _.reduce(_.functions(obj), function(memo, name) {
+        memo[name] = 0;
+        return memo;
+      }, {});
+      addUnderscoreMethods(Base, obj, mappings, attribute);
+    };
+
+    addUnderscoreMethods(Base, _, methods, attribute);
+  });
+
   // Backbone.sync
   // Backbone.sync
   // -------------
   // -------------
 
 
@@ -2920,11 +3114,11 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
 
 
   // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
   // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
   var methodMap = {
   var methodMap = {
-    'create': 'POST',
-    'update': 'PUT',
-    'patch': 'PATCH',
-    'delete': 'DELETE',
-    'read': 'GET'
+    create: 'POST',
+    update: 'PUT',
+    patch: 'PATCH',
+    delete: 'DELETE',
+    read: 'GET'
   };
   };
 
 
   // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
   // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
@@ -2940,6 +3134,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // matched. Creating a new one sets its `routes` hash, if not set statically.
   // matched. Creating a new one sets its `routes` hash, if not set statically.
   var Router = Backbone.Router = function(options) {
   var Router = Backbone.Router = function(options) {
     options || (options = {});
     options || (options = {});
+    this.preinitialize.apply(this, arguments);
     if (options.routes) this.routes = options.routes;
     if (options.routes) this.routes = options.routes;
     this._bindRoutes();
     this._bindRoutes();
     this.initialize.apply(this, arguments);
     this.initialize.apply(this, arguments);
@@ -2955,6 +3150,10 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // Set up all inheritable **Backbone.Router** properties and methods.
   // Set up all inheritable **Backbone.Router** properties and methods.
   _.extend(Router.prototype, Events, {
   _.extend(Router.prototype, Events, {
 
 
+    // preinitialize is an empty function by default. You can override it with a function
+    // or object.  preinitialize will run before any instantiation logic is run in the Router.
+    preinitialize: function(){},
+
     // Initialize is an empty function by default. Override it with your own
     // Initialize is an empty function by default. Override it with your own
     // initialization logic.
     // initialization logic.
     initialize: function(){},
     initialize: function(){},
@@ -3012,11 +3211,11 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
     // against the current location hash.
     // against the current location hash.
     _routeToRegExp: function(route) {
     _routeToRegExp: function(route) {
       route = route.replace(escapeRegExp, '\\$&')
       route = route.replace(escapeRegExp, '\\$&')
-                   .replace(optionalParam, '(?:$1)?')
-                   .replace(namedParam, function(match, optional) {
-                     return optional ? match : '([^/?]+)';
-                   })
-                   .replace(splatParam, '([^?]*?)');
+        .replace(optionalParam, '(?:$1)?')
+        .replace(namedParam, function(match, optional) {
+          return optional ? match : '([^/?]+)';
+        })
+        .replace(splatParam, '([^?]*?)');
       return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
       return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
     },
     },
 
 
@@ -3044,7 +3243,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
   // falls back to polling.
   // falls back to polling.
   var History = Backbone.History = function() {
   var History = Backbone.History = function() {
     this.handlers = [];
     this.handlers = [];
-    this.checkUrl = _.bind(this.checkUrl, this);
+    this.checkUrl = this.checkUrl.bind(this);
 
 
     // Ensure that `History` can be used outside of the browser.
     // Ensure that `History` can be used outside of the browser.
     if (typeof window !== 'undefined') {
     if (typeof window !== 'undefined') {
@@ -3285,11 +3484,14 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
       }
       }
       var url = rootPath + fragment;
       var url = rootPath + fragment;
 
 
-      // Strip the hash and decode for matching.
-      fragment = this.decodeFragment(fragment.replace(pathStripper, ''));
+      // Strip the fragment of the query and hash for matching.
+      fragment = fragment.replace(pathStripper, '');
+
+      // Decode for matching.
+      var decodedFragment = this.decodeFragment(fragment);
 
 
-      if (this.fragment === fragment) return;
-      this.fragment = fragment;
+      if (this.fragment === decodedFragment) return;
+      this.fragment = decodedFragment;
 
 
       // If pushState is available, we use it to set the fragment as a real URL.
       // If pushState is available, we use it to set the fragment as a real URL.
       if (this._usePushState) {
       if (this._usePushState) {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 316 - 316
package-lock.json


+ 2 - 2
package.json

@@ -39,7 +39,7 @@
     "@fortawesome/fontawesome-free": "5.3.1",
     "@fortawesome/fontawesome-free": "5.3.1",
     "awesomplete-avoid-xss": "^1.1.2",
     "awesomplete-avoid-xss": "^1.1.2",
     "babel-loader": "^8.0.4",
     "babel-loader": "^8.0.4",
-    "backbone.nativeview": "^0.3.3",
+    "backbone.nativeview": "conversejs/Backbone.NativeView#5997c8197ca594e6b8469447f28310c78bd1d95e",
     "backbone.overview": "^1.0.2",
     "backbone.overview": "^1.0.2",
     "backbone.vdomview": "^1.0.1",
     "backbone.vdomview": "^1.0.1",
     "bootstrap": "^4.0.0",
     "bootstrap": "^4.0.0",
@@ -63,7 +63,7 @@
     "jed": "1.1.1",
     "jed": "1.1.1",
     "jquery": "3.2.1",
     "jquery": "3.2.1",
     "jsdoc": "^3.5.5",
     "jsdoc": "^3.5.5",
-    "lerna": "^3.11.1",
+    "lerna": "^3.13.1",
     "lodash-template-loader": "^2.0.0",
     "lodash-template-loader": "^2.0.0",
     "lodash-template-webpack-loader": "jcbrand/lodash-template-webpack-loader",
     "lodash-template-webpack-loader": "jcbrand/lodash-template-webpack-loader",
     "long": "^3.1.0",
     "long": "^3.1.0",

+ 1 - 1
src/headless/package.json

@@ -22,7 +22,7 @@
   },
   },
   "gitHead": "9641dcdc820e029b05930479c242d2b707bbe8e2",
   "gitHead": "9641dcdc820e029b05930479c242d2b707bbe8e2",
   "devDependencies": {
   "devDependencies": {
-    "backbone": "1.3.3",
+    "backbone": "1.4",
     "backbone.browserStorage": "0.0.5",
     "backbone.browserStorage": "0.0.5",
     "es6-promise": "^4.1.0",
     "es6-promise": "^4.1.0",
     "filesize": "^3.6.1",
     "filesize": "^3.6.1",

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.