Update to Backbone 1.4.0 and use fork of Backbone.NativeView

with `_setElement` fix.

See https://github.com/akre54/Backbone.NativeView/pull/29
This commit is contained in:
JC Brand 2019-03-01 08:56:46 +01:00
parent 310b2c723b
commit b15ebdde40
5 changed files with 714 additions and 510 deletions

View File

@ -2,6 +2,8 @@
## 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`
- 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)

484
dist/converse.js vendored
View File

@ -893,12 +893,12 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
// https://github.com/akre54/Backbone.NativeView
(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_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {}
}(function (Backbone) {
}(function (_, Backbone) {
// Cached regex to match an opening '<' of an HTML tag, possibly left-padded
// with whitespace.
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) || {};
// 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);
}
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);
}
@ -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,
// 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) {
if (typeof element == 'string') {
if (paddedLt.test(element)) {
@ -969,6 +975,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
} else {
this.el = document.querySelector(element);
}
} else if (element && !_.isElement(element) && element.length) {
this.el = element[0];
} else {
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
// handler.
delegate: function(eventName, selector, listener) {
var root = this.el;
if (!root) {
return;
}
if (typeof selector === 'function') {
listener = selector;
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 node = e.target || e.srcElement;
for (; node && node != root; node = node.parentNode) {
@ -1008,7 +1032,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
} : listener;
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;
},
@ -1022,7 +1046,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
if (this.el) {
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 match = item.eventName === eventName &&
@ -1031,8 +1056,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
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;
@ -1043,7 +1068,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
if (this.el) {
for (var i = 0, len = this._domEvents.length; i < len; 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;
}
@ -1057,6 +1082,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}));
/***/ }),
/***/ "./node_modules/backbone.overview/backbone.orderedlistview.js":
@ -1478,9 +1504,9 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
/*! no static exports found */
/***/ (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.
// For all details and documentation:
// 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.
// 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.
if (true) {
@ -1517,7 +1543,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
var slice = Array.prototype.slice;
// 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
// the `$` variable.
@ -1541,54 +1567,6 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// form param named `model`.
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
// ---------------
@ -1607,6 +1585,9 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// Regular expression used to split event strings.
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
// space-separated events `"change blur", callback` and jQuery-style event
// 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
// the callback to all events fired.
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,
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
@ -1659,17 +1638,23 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
if (!obj) return this;
var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
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.
// Setup the necessary references to track the listening callbacks.
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;
};
@ -1685,6 +1670,16 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
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
// callbacks with that function. If `callback` is null, removes all
// 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,
listeners: this._listeners
});
return this;
};
@ -1705,7 +1701,6 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
if (!listeningTo) return this;
var ids = obj ? [obj._listenId] : _.keys(listeningTo);
for (var i = 0; i < ids.length; i++) {
var listening = listeningTo[ids[i]];
@ -1714,7 +1709,9 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
if (!listening) break;
listening.obj.off(name, callback, this);
if (listening.interop) listening.off(name, callback);
}
if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
return this;
};
@ -1723,21 +1720,18 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
var offApi = function(events, name, callback, options) {
if (!events) return;
var i = 0, listening;
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;
}
var names = name ? [name] : _.keys(events);
names = name ? [name] : _.keys(events);
for (; i < names.length; i++) {
name = names[i];
var handlers = events[name];
@ -1745,7 +1739,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// Bail out if there are no events stored.
if (!handlers) break;
// Replace events if there are any remaining. Otherwise, clean up.
// Find any remaining events.
var remaining = [];
for (var j = 0; j < handlers.length; j++) {
var handler = handlers[j];
@ -1756,21 +1750,19 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
) {
remaining.push(handler);
} 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) {
events[name] = remaining;
} else {
delete events[name];
}
}
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.
Events.once = function(name, callback, context) {
// 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;
return this.on(events, callback, context);
};
@ -1788,7 +1780,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// Inversion-of-control versions of `once`.
Events.listenToOnce = function(obj, name, callback) {
// 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);
};
@ -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.
Events.bind = Events.on;
Events.unbind = Events.off;
@ -1867,6 +1897,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
var Model = Backbone.Model = function(attributes, options) {
var attrs = attributes || {};
options || (options = {});
this.preinitialize.apply(this, arguments);
this.cid = _.uniqueId(this.cidPrefix);
this.attributes = {};
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.
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
// initialization logic.
initialize: function(){},
@ -2035,12 +2070,14 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
var old = this._changing ? this._previousAttributes : this.attributes;
var changed = {};
var hasChanged;
for (var attr in diff) {
var val = diff[attr];
if (_.isEqual(old[attr], val)) continue;
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
@ -2116,7 +2153,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// Set temporary attributes if `{wait: true}` to properly find new ids.
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;
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
// -------------------
@ -2227,6 +2256,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// its models in sort order, as they're added and removed.
var Collection = Backbone.Collection = function(models, options) {
options || (options = {});
this.preinitialize.apply(this, arguments);
if (options.model) this.model = options.model;
if (options.comparator !== void 0) this.comparator = options.comparator;
this._reset();
@ -2256,6 +2286,11 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// This should be overridden in most cases.
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
// initialization logic.
initialize: function(){},
@ -2458,7 +2493,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
get: function(obj) {
if (obj == null) return void 0;
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];
},
@ -2494,7 +2529,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
options || (options = {});
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`.
if (length === 1 || _.isString(comparator)) {
@ -2566,6 +2601,21 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
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
// is first initialized or reset.
_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
// -------------
@ -2692,6 +2793,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// if an existing element is not provided...
var View = Backbone.View = function(options) {
this.cid = _.uniqueId('view');
this.preinitialize.apply(this, arguments);
_.extend(this, _.pick(options, viewOptions));
this._ensureElement();
this.initialize.apply(this, arguments);
@ -2715,6 +2817,10 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
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
// initialization logic.
initialize: function(){},
@ -2782,7 +2888,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
if (!_.isFunction(method)) method = this[method];
if (!method) continue;
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;
},
@ -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
// -------------
@ -2920,11 +3114,11 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// Map from CRUD to HTTP for our default `Backbone.sync` implementation.
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 `$`.
@ -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.
var Router = Backbone.Router = function(options) {
options || (options = {});
this.preinitialize.apply(this, arguments);
if (options.routes) this.routes = options.routes;
this._bindRoutes();
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.
_.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
// initialization logic.
initialize: function(){},
@ -3012,11 +3211,11 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// against the current location hash.
_routeToRegExp: function(route) {
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]*))?$');
},
@ -3044,7 +3243,7 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
// falls back to polling.
var History = Backbone.History = function() {
this.handlers = [];
this.checkUrl = _.bind(this.checkUrl, this);
this.checkUrl = this.checkUrl.bind(this);
// Ensure that `History` can be used outside of the browser.
if (typeof window !== 'undefined') {
@ -3285,11 +3484,14 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
}
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, '');
if (this.fragment === fragment) return;
this.fragment = fragment;
// Decode for matching.
var decodedFragment = this.decodeFragment(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 (this._usePushState) {

732
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

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