@converse/skeletor 0.0.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -92
- package/dist/skeletor.d.ts +764 -0
- package/dist/skeletor.js +10206 -6249
- package/dist/skeletor.min.js +72 -6
- package/package.json +59 -33
- package/src/collection.ts +846 -0
- package/src/drivers/sessionStorage.ts +297 -0
- package/src/eventemitter.ts +172 -0
- package/src/helpers.ts +179 -0
- package/src/index.ts +84 -0
- package/src/listening.ts +86 -0
- package/src/model.ts +520 -0
- package/src/storage.ts +293 -0
- package/src/types.ts +189 -0
- package/src/utils/events.ts +224 -0
- package/dist/skeletor.js.map +0 -1
- package/dist/skeletor.min.js.map +0 -1
- package/src/collection.js +0 -740
- package/src/drivers/sessionStorage.js +0 -306
- package/src/drivers/sessionStorage.js~ +0 -307
- package/src/element.js +0 -188
- package/src/events.js +0 -328
- package/src/helpers.js +0 -167
- package/src/history.js +0 -301
- package/src/main.js +0 -43
- package/src/model.js +0 -437
- package/src/overview.js +0 -191
- package/src/router.js +0 -119
- package/src/storage.js +0 -258
- package/src/view.js +0 -267
package/src/element.js
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import extend from "lodash-es/extend.js";
|
|
2
|
-
import isElement from "lodash-es/isElement.js";
|
|
3
|
-
import isFunction from "lodash-es/isFunction.js";
|
|
4
|
-
import pick from "lodash-es/pick.js";
|
|
5
|
-
import result from "lodash-es/result.js";
|
|
6
|
-
import uniqueId from "lodash-es/uniqueId.js";
|
|
7
|
-
import { Events } from './events.js';
|
|
8
|
-
import { inherits, NotImplementedError } from './helpers.js';
|
|
9
|
-
import { render } from 'lit-html';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const paddedLt = /^\s*</;
|
|
13
|
-
|
|
14
|
-
// Caches a local reference to `Element.prototype` for faster access.
|
|
15
|
-
const ElementProto = (typeof Element !== 'undefined' && Element.prototype) || {};
|
|
16
|
-
|
|
17
|
-
// Cached regex to split keys for `delegate`.
|
|
18
|
-
const delegateEventSplitter = /^(\S+)\s*(.*)$/;
|
|
19
|
-
|
|
20
|
-
// List of view options to be set as properties.
|
|
21
|
-
const viewOptions = ['model', 'collection', 'events'];
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export class ElementView extends HTMLElement {
|
|
25
|
-
|
|
26
|
-
events = {}
|
|
27
|
-
|
|
28
|
-
constructor(options) {
|
|
29
|
-
super();
|
|
30
|
-
// Creating a View creates its initial element outside of the DOM,
|
|
31
|
-
// if an existing element is not provided...
|
|
32
|
-
this.cid = uniqueId('view');
|
|
33
|
-
this._domEvents = [];
|
|
34
|
-
extend(this, pick(options, viewOptions));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
createRenderRoot () {
|
|
38
|
-
// Render without the shadow DOM
|
|
39
|
-
return this;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
connectedCallback () {
|
|
43
|
-
if (!this._initialized) {
|
|
44
|
-
this.preinitialize.apply(this, arguments);
|
|
45
|
-
this.initialize.apply(this, arguments);
|
|
46
|
-
this._initialized = true;
|
|
47
|
-
}
|
|
48
|
-
this.delegateEvents();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
disconnectedCallback () {
|
|
52
|
-
this.undelegateEvents();
|
|
53
|
-
this.stopListening();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// preinitialize is an empty function by default. You can override it with a function
|
|
57
|
-
// or object. preinitialize will run before any instantiation logic is run in the View
|
|
58
|
-
preinitialize () { // eslint-disable-line class-methods-use-this
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Initialize is an empty function by default. Override it with your own
|
|
62
|
-
// initialization logic.
|
|
63
|
-
initialize() {} // eslint-disable-line class-methods-use-this
|
|
64
|
-
|
|
65
|
-
// **render** is the core function that your view should override, in order
|
|
66
|
-
// to populate its element (`this.el`), with the appropriate HTML. The
|
|
67
|
-
// convention is for **render** to always return `this`.
|
|
68
|
-
render() {
|
|
69
|
-
isFunction(this.beforeRender) && this.beforeRender();
|
|
70
|
-
isFunction(this.toHTML) && render(this.toHTML(), this);
|
|
71
|
-
isFunction(this.afterRender) && this.afterRender();
|
|
72
|
-
return this;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Set callbacks, where `this.events` is a hash of
|
|
76
|
-
//
|
|
77
|
-
// *{"event selector": "callback"}*
|
|
78
|
-
//
|
|
79
|
-
// {
|
|
80
|
-
// 'mousedown .title': 'edit',
|
|
81
|
-
// 'click .button': 'save',
|
|
82
|
-
// 'click .open': function(e) { ... }
|
|
83
|
-
// }
|
|
84
|
-
//
|
|
85
|
-
// pairs. Callbacks will be bound to the view, with `this` set properly.
|
|
86
|
-
// Uses event delegation for efficiency.
|
|
87
|
-
// Omitting the selector binds the event to `this.el`.
|
|
88
|
-
delegateEvents() {
|
|
89
|
-
if (!this.events) {
|
|
90
|
-
return this;
|
|
91
|
-
}
|
|
92
|
-
this.undelegateEvents();
|
|
93
|
-
for (const key in this.events) {
|
|
94
|
-
let method = this.events[key];
|
|
95
|
-
if (!isFunction(method)) method = this[method];
|
|
96
|
-
if (!method) continue;
|
|
97
|
-
const match = key.match(delegateEventSplitter);
|
|
98
|
-
this.delegate(match[1], match[2], method.bind(this));
|
|
99
|
-
}
|
|
100
|
-
return this;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Make a event delegation handler for the given `eventName` and `selector`
|
|
104
|
-
// and attach it to `this.el`.
|
|
105
|
-
// If selector is empty, the listener will be bound to `this.el`. If not, a
|
|
106
|
-
// new handler that will recursively traverse up the event target's DOM
|
|
107
|
-
// hierarchy looking for a node that matches the selector. If one is found,
|
|
108
|
-
// the event's `delegateTarget` property is set to it and the return the
|
|
109
|
-
// result of calling bound `listener` with the parameters given to the
|
|
110
|
-
// handler.
|
|
111
|
-
delegate(eventName, selector, listener) {
|
|
112
|
-
const root = this;
|
|
113
|
-
if (!root) {
|
|
114
|
-
return this;
|
|
115
|
-
}
|
|
116
|
-
if (typeof selector === 'function') {
|
|
117
|
-
listener = selector;
|
|
118
|
-
selector = null;
|
|
119
|
-
}
|
|
120
|
-
// Given that `focus` and `blur` events do not bubble, do not delegate these events
|
|
121
|
-
if (['focus', 'blur'].indexOf(eventName) !== -1) {
|
|
122
|
-
const els = this.querySelectorAll(selector);
|
|
123
|
-
for (let i = 0, len = els.length; i < len; i++) {
|
|
124
|
-
const item = els[i];
|
|
125
|
-
item.addEventListener(eventName, listener, false);
|
|
126
|
-
this._domEvents.push({el: item, eventName: eventName, handler: listener});
|
|
127
|
-
}
|
|
128
|
-
return listener;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const handler = selector ? function (e) {
|
|
132
|
-
let node = e.target || e.srcElement;
|
|
133
|
-
for (; node && node != root; node = node.parentNode) {
|
|
134
|
-
if (node.matches(selector)) {
|
|
135
|
-
e.delegateTarget = node;
|
|
136
|
-
listener(e);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
} : listener;
|
|
140
|
-
|
|
141
|
-
this.addEventListener(eventName, handler, false);
|
|
142
|
-
this._domEvents.push({el: this, eventName: eventName, handler: handler, listener: listener, selector: selector});
|
|
143
|
-
return this;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Clears all callbacks previously bound to the view by `delegateEvents`.
|
|
147
|
-
// You usually don't need to use this, but may wish to if you have multiple
|
|
148
|
-
// Backbone views attached to the same DOM element.
|
|
149
|
-
undelegateEvents() {
|
|
150
|
-
if (this) {
|
|
151
|
-
for (let i = 0, len = this._domEvents.length; i < len; i++) {
|
|
152
|
-
const item = this._domEvents[i];
|
|
153
|
-
item.el.removeEventListener(item.eventName, item.handler, false);
|
|
154
|
-
}
|
|
155
|
-
this._domEvents.length = 0;
|
|
156
|
-
}
|
|
157
|
-
return this;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// A finer-grained `undelegateEvents` for removing a single delegated event.
|
|
161
|
-
// `selector` and `listener` are both optional.
|
|
162
|
-
undelegate(eventName, selector, listener) {
|
|
163
|
-
if (typeof selector === 'function') {
|
|
164
|
-
listener = selector;
|
|
165
|
-
selector = null;
|
|
166
|
-
}
|
|
167
|
-
if (this) {
|
|
168
|
-
const handlers = this._domEvents.slice();
|
|
169
|
-
let i = handlers.length;
|
|
170
|
-
while (i--) {
|
|
171
|
-
const item = handlers[i];
|
|
172
|
-
const match = item.eventName === eventName &&
|
|
173
|
-
(listener ? item.listener === listener : true) &&
|
|
174
|
-
(selector ? item.selector === selector : true);
|
|
175
|
-
|
|
176
|
-
if (!match) {
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
item.el.removeEventListener(item.eventName, item.handler, false);
|
|
180
|
-
this._domEvents.splice(i, 1);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return this;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Set up all inheritable **View** properties and methods.
|
|
188
|
-
Object.assign(ElementView.prototype, Events);
|
package/src/events.js
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
// Backbone.js 1.4.0
|
|
2
|
-
// (c) 2010-2019 Jeremy Ashkenas and DocumentCloud
|
|
3
|
-
// Backbone may be freely distributed under the MIT license.
|
|
4
|
-
|
|
5
|
-
// Events
|
|
6
|
-
// ------
|
|
7
|
-
|
|
8
|
-
// A module that can be mixed in to *any object* in order to provide it with
|
|
9
|
-
// a custom event channel. You may bind a callback to an event with `on` or
|
|
10
|
-
// remove with `off`; `trigger`-ing an event fires all callbacks in
|
|
11
|
-
// succession.
|
|
12
|
-
//
|
|
13
|
-
// let object = {};
|
|
14
|
-
// extend(object, Backbone.Events);
|
|
15
|
-
// object.on('expand', function(){ alert('expanded'); });
|
|
16
|
-
// object.trigger('expand');
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
import isEmpty from 'lodash-es/isEmpty.js';
|
|
20
|
-
import keys from 'lodash-es/keys.js';
|
|
21
|
-
import once from 'lodash-es/once.js';
|
|
22
|
-
import uniqueId from 'lodash-es/uniqueId.js';
|
|
23
|
-
|
|
24
|
-
export const Events = {};
|
|
25
|
-
|
|
26
|
-
// Regular expression used to split event strings.
|
|
27
|
-
const eventSplitter = /\s+/;
|
|
28
|
-
|
|
29
|
-
// A private global variable to share between listeners and listenees.
|
|
30
|
-
let _listening;
|
|
31
|
-
|
|
32
|
-
// Iterates over the standard `event, callback` (as well as the fancy multiple
|
|
33
|
-
// space-separated events `"change blur", callback` and jQuery-style event
|
|
34
|
-
// maps `{event: callback}`).
|
|
35
|
-
const eventsApi = function(iteratee, events, name, callback, opts) {
|
|
36
|
-
let i = 0, names;
|
|
37
|
-
if (name && typeof name === 'object') {
|
|
38
|
-
// Handle event maps.
|
|
39
|
-
if (callback !== undefined && 'context' in opts && opts.context === undefined) opts.context = callback;
|
|
40
|
-
for (names = keys(name); i < names.length ; i++) {
|
|
41
|
-
events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
|
|
42
|
-
}
|
|
43
|
-
} else if (name && eventSplitter.test(name)) {
|
|
44
|
-
// Handle space-separated event names by delegating them individually.
|
|
45
|
-
for (names = name.split(eventSplitter); i < names.length; i++) {
|
|
46
|
-
events = iteratee(events, names[i], callback, opts);
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
// Finally, standard events.
|
|
50
|
-
events = iteratee(events, name, callback, opts);
|
|
51
|
-
}
|
|
52
|
-
return events;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// Bind an event to a `callback` function. Passing `"all"` will bind
|
|
56
|
-
// the callback to all events fired.
|
|
57
|
-
Events.on = function(name, callback, context) {
|
|
58
|
-
this._events = eventsApi(onApi, this._events || {}, name, callback, {
|
|
59
|
-
context: context,
|
|
60
|
-
ctx: this,
|
|
61
|
-
listening: _listening
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
if (_listening) {
|
|
65
|
-
const listeners = this._listeners || (this._listeners = {});
|
|
66
|
-
listeners[_listening.id] = _listening;
|
|
67
|
-
// Allow the listening to use a counter, instead of tracking
|
|
68
|
-
// callbacks for library interop
|
|
69
|
-
_listening.interop = false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return this;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Inversion-of-control versions of `on`. Tell *this* object to listen to
|
|
76
|
-
// an event in another object... keeping track of what it's listening to
|
|
77
|
-
// for easier unbinding later.
|
|
78
|
-
Events.listenTo = function(obj, name, callback) {
|
|
79
|
-
if (!obj) return this;
|
|
80
|
-
const id = obj._listenId || (obj._listenId = uniqueId('l'));
|
|
81
|
-
const listeningTo = this._listeningTo || (this._listeningTo = {});
|
|
82
|
-
let listening = _listening = listeningTo[id];
|
|
83
|
-
|
|
84
|
-
// This object is not listening to any other events on `obj` yet.
|
|
85
|
-
// Setup the necessary references to track the listening callbacks.
|
|
86
|
-
if (!listening) {
|
|
87
|
-
this._listenId || (this._listenId = uniqueId('l'));
|
|
88
|
-
listening = _listening = listeningTo[id] = new Listening(this, obj);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Bind callbacks on obj.
|
|
92
|
-
const error = tryCatchOn(obj, name, callback, this);
|
|
93
|
-
_listening = undefined;
|
|
94
|
-
|
|
95
|
-
if (error) throw error;
|
|
96
|
-
// If the target obj is not Backbone.Events, track events manually.
|
|
97
|
-
if (listening.interop) listening.on(name, callback);
|
|
98
|
-
|
|
99
|
-
return this;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// The reducing API that adds a callback to the `events` object.
|
|
103
|
-
const onApi = function(events, name, callback, options) {
|
|
104
|
-
if (callback) {
|
|
105
|
-
const handlers = events[name] || (events[name] = []);
|
|
106
|
-
const context = options.context, ctx = options.ctx, listening = options.listening;
|
|
107
|
-
if (listening) listening.count++;
|
|
108
|
-
|
|
109
|
-
handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening});
|
|
110
|
-
}
|
|
111
|
-
return events;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
// An try-catch guarded #on function, to prevent poisoning the global
|
|
115
|
-
// `_listening` variable.
|
|
116
|
-
const tryCatchOn = function(obj, name, callback, context) {
|
|
117
|
-
try {
|
|
118
|
-
obj.on(name, callback, context);
|
|
119
|
-
} catch (e) {
|
|
120
|
-
return e;
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
// Remove one or many callbacks. If `context` is null, removes all
|
|
125
|
-
// callbacks with that function. If `callback` is null, removes all
|
|
126
|
-
// callbacks for the event. If `name` is null, removes all bound
|
|
127
|
-
// callbacks for all events.
|
|
128
|
-
Events.off = function(name, callback, context) {
|
|
129
|
-
if (!this._events) return this;
|
|
130
|
-
this._events = eventsApi(offApi, this._events, name, callback, {
|
|
131
|
-
context: context,
|
|
132
|
-
listeners: this._listeners
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
return this;
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
// Tell this object to stop listening to either specific events ... or
|
|
139
|
-
// to every object it's currently listening to.
|
|
140
|
-
Events.stopListening = function(obj, name, callback) {
|
|
141
|
-
const listeningTo = this._listeningTo;
|
|
142
|
-
if (!listeningTo) return this;
|
|
143
|
-
|
|
144
|
-
const ids = obj ? [obj._listenId] : keys(listeningTo);
|
|
145
|
-
for (let i = 0; i < ids.length; i++) {
|
|
146
|
-
const listening = listeningTo[ids[i]];
|
|
147
|
-
|
|
148
|
-
// If listening doesn't exist, this object is not currently
|
|
149
|
-
// listening to obj. Break out early.
|
|
150
|
-
if (!listening) break;
|
|
151
|
-
|
|
152
|
-
listening.obj.off(name, callback, this);
|
|
153
|
-
if (listening.interop) listening.off(name, callback);
|
|
154
|
-
}
|
|
155
|
-
if (isEmpty(listeningTo)) this._listeningTo = undefined;
|
|
156
|
-
|
|
157
|
-
return this;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
// The reducing API that removes a callback from the `events` object.
|
|
161
|
-
const offApi = function(events, name, callback, options) {
|
|
162
|
-
if (!events) return;
|
|
163
|
-
|
|
164
|
-
const context = options.context, listeners = options.listeners;
|
|
165
|
-
let i = 0, names;
|
|
166
|
-
|
|
167
|
-
// Delete all event listeners and "drop" events.
|
|
168
|
-
if (!name && !context && !callback) {
|
|
169
|
-
for (names = keys(listeners); i < names.length; i++) {
|
|
170
|
-
listeners[names[i]].cleanup();
|
|
171
|
-
}
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
names = name ? [name] : keys(events);
|
|
176
|
-
for (; i < names.length; i++) {
|
|
177
|
-
name = names[i];
|
|
178
|
-
const handlers = events[name];
|
|
179
|
-
|
|
180
|
-
// Bail out if there are no events stored.
|
|
181
|
-
if (!handlers) {
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Find any remaining events.
|
|
186
|
-
const remaining = [];
|
|
187
|
-
for (let j = 0; j < handlers.length; j++) {
|
|
188
|
-
const handler = handlers[j];
|
|
189
|
-
if (
|
|
190
|
-
callback && callback !== handler.callback &&
|
|
191
|
-
callback !== handler.callback._callback ||
|
|
192
|
-
context && context !== handler.context
|
|
193
|
-
) {
|
|
194
|
-
remaining.push(handler);
|
|
195
|
-
} else {
|
|
196
|
-
const listening = handler.listening;
|
|
197
|
-
if (listening) listening.off(name, callback);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Replace events if there are any remaining. Otherwise, clean up.
|
|
202
|
-
if (remaining.length) {
|
|
203
|
-
events[name] = remaining;
|
|
204
|
-
} else {
|
|
205
|
-
delete events[name];
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return events;
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
// Bind an event to only be triggered a single time. After the first time
|
|
213
|
-
// the callback is invoked, its listener will be removed. If multiple events
|
|
214
|
-
// are passed in using the space-separated syntax, the handler will fire
|
|
215
|
-
// once for each event, not once for a combination of all events.
|
|
216
|
-
Events.once = function(name, callback, context) {
|
|
217
|
-
// Map the event into a `{event: once}` object.
|
|
218
|
-
const events = eventsApi(onceMap, {}, name, callback, this.off.bind(this));
|
|
219
|
-
if (typeof name === 'string' && (context === null || context === undefined)) callback = undefined;
|
|
220
|
-
return this.on(events, callback, context);
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
// Inversion-of-control versions of `once`.
|
|
224
|
-
Events.listenToOnce = function(obj, name, callback) {
|
|
225
|
-
// Map the event into a `{event: once}` object.
|
|
226
|
-
const events = eventsApi(onceMap, {}, name, callback, this.stopListening.bind(this, obj));
|
|
227
|
-
return this.listenTo(obj, events);
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
// Reduces the event callbacks into a map of `{event: onceWrapper}`.
|
|
231
|
-
// `offer` unbinds the `onceWrapper` after it has been called.
|
|
232
|
-
const onceMap = function(map, name, callback, offer) {
|
|
233
|
-
if (callback) {
|
|
234
|
-
const _once = map[name] = once(function() {
|
|
235
|
-
offer(name, _once);
|
|
236
|
-
callback.apply(this, arguments);
|
|
237
|
-
});
|
|
238
|
-
_once._callback = callback;
|
|
239
|
-
}
|
|
240
|
-
return map;
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
// Trigger one or many events, firing all bound callbacks. Callbacks are
|
|
244
|
-
// passed the same arguments as `trigger` is, apart from the event name
|
|
245
|
-
// (unless you're listening on `"all"`, which will cause your callback to
|
|
246
|
-
// receive the true name of the event as the first argument).
|
|
247
|
-
Events.trigger = function(name) {
|
|
248
|
-
if (!this._events) return this;
|
|
249
|
-
|
|
250
|
-
const length = Math.max(0, arguments.length - 1);
|
|
251
|
-
const args = Array(length);
|
|
252
|
-
for (let i = 0; i < length; i++) args[i] = arguments[i + 1];
|
|
253
|
-
|
|
254
|
-
eventsApi(triggerApi, this._events, name, undefined, args);
|
|
255
|
-
return this;
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
// Handles triggering the appropriate event callbacks.
|
|
259
|
-
const triggerApi = function(objEvents, name, callback, args) {
|
|
260
|
-
if (objEvents) {
|
|
261
|
-
const events = objEvents[name];
|
|
262
|
-
let allEvents = objEvents.all;
|
|
263
|
-
if (events && allEvents) allEvents = allEvents.slice();
|
|
264
|
-
if (events) triggerEvents(events, args);
|
|
265
|
-
if (allEvents) triggerEvents(allEvents, [name].concat(args));
|
|
266
|
-
}
|
|
267
|
-
return objEvents;
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
// A difficult-to-believe, but optimized internal dispatch function for
|
|
271
|
-
// triggering events. Tries to keep the usual cases speedy (most internal
|
|
272
|
-
// Backbone events have 3 arguments).
|
|
273
|
-
const triggerEvents = function(events, args) {
|
|
274
|
-
let ev, i = -1;
|
|
275
|
-
const l = events.length,
|
|
276
|
-
a1 = args[0],
|
|
277
|
-
a2 = args[1],
|
|
278
|
-
a3 = args[2];
|
|
279
|
-
switch (args.length) {
|
|
280
|
-
case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
|
|
281
|
-
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
|
|
282
|
-
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
|
|
283
|
-
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
|
|
284
|
-
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
// A listening class that tracks and cleans up memory bindings
|
|
289
|
-
// when all callbacks have been offed.
|
|
290
|
-
const Listening = function(listener, obj) {
|
|
291
|
-
this.id = listener._listenId;
|
|
292
|
-
this.listener = listener;
|
|
293
|
-
this.obj = obj;
|
|
294
|
-
this.interop = true;
|
|
295
|
-
this.count = 0;
|
|
296
|
-
this._events = undefined;
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
Listening.prototype.on = Events.on;
|
|
300
|
-
|
|
301
|
-
// Offs a callback (or several).
|
|
302
|
-
// Uses an optimized counter if the listenee uses Backbone.Events.
|
|
303
|
-
// Otherwise, falls back to manual tracking to support events
|
|
304
|
-
// library interop.
|
|
305
|
-
Listening.prototype.off = function(name, callback) {
|
|
306
|
-
let cleanup;
|
|
307
|
-
if (this.interop) {
|
|
308
|
-
this._events = eventsApi(offApi, this._events, name, callback, {
|
|
309
|
-
context: undefined,
|
|
310
|
-
listeners: undefined
|
|
311
|
-
});
|
|
312
|
-
cleanup = !this._events;
|
|
313
|
-
} else {
|
|
314
|
-
this.count--;
|
|
315
|
-
cleanup = this.count === 0;
|
|
316
|
-
}
|
|
317
|
-
if (cleanup) this.cleanup();
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
// Cleans up memory bindings between the listener and the listenee.
|
|
321
|
-
Listening.prototype.cleanup = function() {
|
|
322
|
-
delete this.listener._listeningTo[this.obj._listenId];
|
|
323
|
-
if (!this.interop) delete this.obj._listeners[this.id];
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
// Aliases for backwards compatibility.
|
|
327
|
-
Events.bind = Events.on;
|
|
328
|
-
Events.unbind = Events.off;
|
package/src/helpers.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
// (c) 2010-2019 Jeremy Ashkenas and DocumentCloud
|
|
2
|
-
|
|
3
|
-
import create from 'lodash-es/create.js';
|
|
4
|
-
import extend from 'lodash-es/extend.js';
|
|
5
|
-
import has from 'lodash-es/has.js';
|
|
6
|
-
import result from 'lodash-es/result.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Custom error for indicating timeouts
|
|
10
|
-
* @namespace _converse
|
|
11
|
-
*/
|
|
12
|
-
export class NotImplementedError extends Error {}
|
|
13
|
-
|
|
14
|
-
function S4() {
|
|
15
|
-
// Generate four random hex digits.
|
|
16
|
-
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function guid() {
|
|
20
|
-
// Generate a pseudo-GUID by concatenating random hexadecimal.
|
|
21
|
-
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Helpers
|
|
25
|
-
// -------
|
|
26
|
-
|
|
27
|
-
// Helper function to correctly set up the prototype chain for subclasses.
|
|
28
|
-
// Similar to `goog.inherits`, but uses a hash of prototype properties and
|
|
29
|
-
// class properties to be extended.
|
|
30
|
-
//
|
|
31
|
-
export function inherits(protoProps, staticProps) {
|
|
32
|
-
const parent = this;
|
|
33
|
-
let child;
|
|
34
|
-
|
|
35
|
-
// The constructor function for the new subclass is either defined by you
|
|
36
|
-
// (the "constructor" property in your `extend` definition), or defaulted
|
|
37
|
-
// by us to simply call the parent constructor.
|
|
38
|
-
if (protoProps && has(protoProps, 'constructor')) {
|
|
39
|
-
child = protoProps.constructor;
|
|
40
|
-
} else {
|
|
41
|
-
child = function(){ return parent.apply(this, arguments); };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Add static properties to the constructor function, if supplied.
|
|
45
|
-
extend(child, parent, staticProps);
|
|
46
|
-
|
|
47
|
-
// Set the prototype chain to inherit from `parent`, without calling
|
|
48
|
-
// `parent`'s constructor function and add the prototype properties.
|
|
49
|
-
child.prototype = create(parent.prototype, protoProps);
|
|
50
|
-
child.prototype.constructor = child;
|
|
51
|
-
|
|
52
|
-
// Set a convenience property in case the parent's prototype is needed
|
|
53
|
-
// later.
|
|
54
|
-
child.__super__ = parent.prototype;
|
|
55
|
-
|
|
56
|
-
return child;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
export function getResolveablePromise () {
|
|
61
|
-
const wrapper = {
|
|
62
|
-
isResolved: false,
|
|
63
|
-
isPending: true,
|
|
64
|
-
isRejected: false
|
|
65
|
-
};
|
|
66
|
-
const promise = new Promise((resolve, reject) => {
|
|
67
|
-
wrapper.resolve = resolve;
|
|
68
|
-
wrapper.reject = reject;
|
|
69
|
-
})
|
|
70
|
-
Object.assign(promise, wrapper);
|
|
71
|
-
promise.then(
|
|
72
|
-
function (v) {
|
|
73
|
-
promise.isResolved = true;
|
|
74
|
-
promise.isPending = false;
|
|
75
|
-
promise.isRejected = false;
|
|
76
|
-
return v;
|
|
77
|
-
},
|
|
78
|
-
function (e) {
|
|
79
|
-
promise.isResolved = false;
|
|
80
|
-
promise.isPending = false;
|
|
81
|
-
promise.isRejected = true;
|
|
82
|
-
throw (e);
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
return promise;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Throw an error when a URL is needed, and none is supplied.
|
|
90
|
-
export function urlError() {
|
|
91
|
-
throw new Error('A "url" property or function must be specified');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Wrap an optional error callback with a fallback error event.
|
|
95
|
-
export function wrapError(model, options) {
|
|
96
|
-
const error = options.error;
|
|
97
|
-
options.error = function(resp) {
|
|
98
|
-
if (error) error.call(options.context, model, resp, options);
|
|
99
|
-
model.trigger('error', model, resp, options);
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Map from CRUD to HTTP for our default `sync` implementation.
|
|
104
|
-
const methodMap = {
|
|
105
|
-
create: 'POST',
|
|
106
|
-
update: 'PUT',
|
|
107
|
-
patch: 'PATCH',
|
|
108
|
-
delete: 'DELETE',
|
|
109
|
-
read: 'GET'
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
export function getSyncMethod(model) {
|
|
113
|
-
const store = result(model, 'browserStorage') || result(model.collection, 'browserStorage');
|
|
114
|
-
return store ? store.sync() : sync;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// sync
|
|
118
|
-
// ----
|
|
119
|
-
|
|
120
|
-
// Override this function to change the manner in which Backbone persists
|
|
121
|
-
// models to the server. You will be passed the type of request, and the
|
|
122
|
-
// model in question. By default, makes a RESTful Ajax request
|
|
123
|
-
// to the model's `url()`. Some possible customizations could be:
|
|
124
|
-
//
|
|
125
|
-
// * Use `setTimeout` to batch rapid-fire updates into a single request.
|
|
126
|
-
// * Send up the models as XML instead of JSON.
|
|
127
|
-
// * Persist models via WebSockets instead of Ajax.
|
|
128
|
-
//
|
|
129
|
-
export function sync(method, model, options={}) {
|
|
130
|
-
const type = methodMap[method];
|
|
131
|
-
|
|
132
|
-
// Default JSON-request options.
|
|
133
|
-
const params = {type: type, dataType: 'json'};
|
|
134
|
-
|
|
135
|
-
// Ensure that we have a URL.
|
|
136
|
-
if (!options.url) {
|
|
137
|
-
params.url = result(model, 'url') || urlError();
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Ensure that we have the appropriate request data.
|
|
141
|
-
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
|
|
142
|
-
params.contentType = 'application/json';
|
|
143
|
-
params.data = JSON.stringify(options.attrs || model.toJSON(options));
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Don't process data on a non-GET request.
|
|
147
|
-
if (params.type !== 'GET') {
|
|
148
|
-
params.processData = false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Pass along `textStatus` and `errorThrown` from jQuery.
|
|
152
|
-
const error = options.error;
|
|
153
|
-
options.error = function(xhr, textStatus, errorThrown) {
|
|
154
|
-
options.textStatus = textStatus;
|
|
155
|
-
options.errorThrown = errorThrown;
|
|
156
|
-
if (error) error.call(options.context, xhr, textStatus, errorThrown);
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// Make the request, allowing the user to override any Ajax options.
|
|
160
|
-
const xhr = options.xhr = ajax(extend(params, options));
|
|
161
|
-
model.trigger('request', model, xhr, options);
|
|
162
|
-
return xhr;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function ajax() {
|
|
166
|
-
return fetch.apply(this, arguments);
|
|
167
|
-
}
|