@joint/core 4.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/LICENSE +376 -0
- package/README.md +49 -0
- package/dist/geometry.js +6486 -0
- package/dist/geometry.min.js +8 -0
- package/dist/joint.d.ts +5536 -0
- package/dist/joint.js +39629 -0
- package/dist/joint.min.js +8 -0
- package/dist/joint.nowrap.js +39626 -0
- package/dist/joint.nowrap.min.js +8 -0
- package/dist/vectorizer.js +9135 -0
- package/dist/vectorizer.min.js +8 -0
- package/dist/version.mjs +3 -0
- package/index.js +3 -0
- package/joint.mjs +27 -0
- package/package.json +192 -0
- package/src/V/annotation.mjs +0 -0
- package/src/V/index.mjs +2642 -0
- package/src/anchors/index.mjs +123 -0
- package/src/config/index.mjs +12 -0
- package/src/connectionPoints/index.mjs +202 -0
- package/src/connectionStrategies/index.mjs +73 -0
- package/src/connectors/curve.mjs +553 -0
- package/src/connectors/index.mjs +6 -0
- package/src/connectors/jumpover.mjs +452 -0
- package/src/connectors/normal.mjs +12 -0
- package/src/connectors/rounded.mjs +17 -0
- package/src/connectors/smooth.mjs +44 -0
- package/src/connectors/straight.mjs +110 -0
- package/src/dia/Cell.mjs +945 -0
- package/src/dia/CellView.mjs +1316 -0
- package/src/dia/Element.mjs +519 -0
- package/src/dia/ElementView.mjs +859 -0
- package/src/dia/Graph.mjs +1112 -0
- package/src/dia/HighlighterView.mjs +319 -0
- package/src/dia/Link.mjs +565 -0
- package/src/dia/LinkView.mjs +2207 -0
- package/src/dia/Paper.mjs +3171 -0
- package/src/dia/PaperLayer.mjs +75 -0
- package/src/dia/ToolView.mjs +69 -0
- package/src/dia/ToolsView.mjs +128 -0
- package/src/dia/attributes/calc.mjs +128 -0
- package/src/dia/attributes/connection.mjs +75 -0
- package/src/dia/attributes/defs.mjs +76 -0
- package/src/dia/attributes/eval.mjs +64 -0
- package/src/dia/attributes/index.mjs +69 -0
- package/src/dia/attributes/legacy.mjs +148 -0
- package/src/dia/attributes/offset.mjs +53 -0
- package/src/dia/attributes/props.mjs +30 -0
- package/src/dia/attributes/shape.mjs +92 -0
- package/src/dia/attributes/text.mjs +180 -0
- package/src/dia/index.mjs +13 -0
- package/src/dia/layers/GridLayer.mjs +176 -0
- package/src/dia/ports.mjs +874 -0
- package/src/elementTools/Control.mjs +153 -0
- package/src/elementTools/HoverConnect.mjs +37 -0
- package/src/elementTools/index.mjs +5 -0
- package/src/env/index.mjs +43 -0
- package/src/g/bezier.mjs +175 -0
- package/src/g/curve.mjs +956 -0
- package/src/g/ellipse.mjs +245 -0
- package/src/g/extend.mjs +64 -0
- package/src/g/geometry.helpers.mjs +58 -0
- package/src/g/index.mjs +17 -0
- package/src/g/intersection.mjs +511 -0
- package/src/g/line.bearing.mjs +30 -0
- package/src/g/line.length.mjs +5 -0
- package/src/g/line.mjs +356 -0
- package/src/g/line.squaredLength.mjs +10 -0
- package/src/g/path.mjs +2260 -0
- package/src/g/point.mjs +375 -0
- package/src/g/points.mjs +247 -0
- package/src/g/polygon.mjs +51 -0
- package/src/g/polyline.mjs +523 -0
- package/src/g/rect.mjs +556 -0
- package/src/g/types.mjs +10 -0
- package/src/highlighters/addClass.mjs +27 -0
- package/src/highlighters/index.mjs +5 -0
- package/src/highlighters/list.mjs +111 -0
- package/src/highlighters/mask.mjs +220 -0
- package/src/highlighters/opacity.mjs +17 -0
- package/src/highlighters/stroke.mjs +100 -0
- package/src/layout/index.mjs +4 -0
- package/src/layout/ports/port.mjs +188 -0
- package/src/layout/ports/portLabel.mjs +224 -0
- package/src/linkAnchors/index.mjs +76 -0
- package/src/linkTools/Anchor.mjs +235 -0
- package/src/linkTools/Arrowhead.mjs +103 -0
- package/src/linkTools/Boundary.mjs +48 -0
- package/src/linkTools/Button.mjs +121 -0
- package/src/linkTools/Connect.mjs +85 -0
- package/src/linkTools/HoverConnect.mjs +161 -0
- package/src/linkTools/Segments.mjs +393 -0
- package/src/linkTools/Vertices.mjs +253 -0
- package/src/linkTools/helpers.mjs +33 -0
- package/src/linkTools/index.mjs +8 -0
- package/src/mvc/Collection.mjs +560 -0
- package/src/mvc/Data.mjs +46 -0
- package/src/mvc/Dom/Dom.mjs +587 -0
- package/src/mvc/Dom/Event.mjs +130 -0
- package/src/mvc/Dom/animations.mjs +122 -0
- package/src/mvc/Dom/events.mjs +69 -0
- package/src/mvc/Dom/index.mjs +13 -0
- package/src/mvc/Dom/methods.mjs +392 -0
- package/src/mvc/Dom/props.mjs +77 -0
- package/src/mvc/Dom/vars.mjs +5 -0
- package/src/mvc/Events.mjs +337 -0
- package/src/mvc/Listener.mjs +33 -0
- package/src/mvc/Model.mjs +239 -0
- package/src/mvc/View.mjs +323 -0
- package/src/mvc/ViewBase.mjs +182 -0
- package/src/mvc/index.mjs +9 -0
- package/src/mvc/mvcUtils.mjs +90 -0
- package/src/polyfills/array.js +4 -0
- package/src/polyfills/base64.js +68 -0
- package/src/polyfills/index.mjs +5 -0
- package/src/polyfills/number.js +3 -0
- package/src/polyfills/string.js +3 -0
- package/src/polyfills/typedArray.js +47 -0
- package/src/routers/index.mjs +6 -0
- package/src/routers/manhattan.mjs +856 -0
- package/src/routers/metro.mjs +91 -0
- package/src/routers/normal.mjs +6 -0
- package/src/routers/oneSide.mjs +60 -0
- package/src/routers/orthogonal.mjs +323 -0
- package/src/routers/rightAngle.mjs +1056 -0
- package/src/shapes/index.mjs +3 -0
- package/src/shapes/standard.mjs +755 -0
- package/src/util/cloneCells.mjs +67 -0
- package/src/util/getRectPoint.mjs +65 -0
- package/src/util/index.mjs +5 -0
- package/src/util/svgTagTemplate.mjs +110 -0
- package/src/util/util.mjs +1754 -0
- package/src/util/utilHelpers.mjs +2402 -0
- package/src/util/wrappers.mjs +56 -0
- package/types/geometry.d.ts +815 -0
- package/types/index.d.ts +53 -0
- package/types/joint.d.ts +4391 -0
- package/types/joint.head.d.ts +12 -0
- package/types/vectorizer.d.ts +327 -0
package/src/mvc/View.mjs
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import $ from './Dom/index.mjs';
|
|
2
|
+
|
|
3
|
+
import * as util from '../util/index.mjs';
|
|
4
|
+
import V from '../V/index.mjs';
|
|
5
|
+
import { ViewBase } from './ViewBase.mjs';
|
|
6
|
+
import { config } from '../config/index.mjs';
|
|
7
|
+
|
|
8
|
+
export const views = {};
|
|
9
|
+
|
|
10
|
+
export const View = ViewBase.extend({
|
|
11
|
+
|
|
12
|
+
options: {},
|
|
13
|
+
theme: null,
|
|
14
|
+
themeClassNamePrefix: util.addClassNamePrefix('theme-'),
|
|
15
|
+
requireSetThemeOverride: false,
|
|
16
|
+
defaultTheme: config.defaultTheme,
|
|
17
|
+
children: null,
|
|
18
|
+
childNodes: null,
|
|
19
|
+
|
|
20
|
+
DETACHABLE: true,
|
|
21
|
+
UPDATE_PRIORITY: 2,
|
|
22
|
+
FLAG_INSERT: 1<<30,
|
|
23
|
+
FLAG_REMOVE: 1<<29,
|
|
24
|
+
FLAG_INIT: 1<<28,
|
|
25
|
+
|
|
26
|
+
constructor: function(options) {
|
|
27
|
+
|
|
28
|
+
this.requireSetThemeOverride = options && !!options.theme;
|
|
29
|
+
this.options = util.assign({}, this.options, options);
|
|
30
|
+
|
|
31
|
+
ViewBase.call(this, options);
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
initialize: function() {
|
|
35
|
+
|
|
36
|
+
views[this.cid] = this;
|
|
37
|
+
|
|
38
|
+
this.setTheme(this.options.theme || this.defaultTheme);
|
|
39
|
+
this.init();
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
unmount: function() {
|
|
43
|
+
if (this.svgElement) {
|
|
44
|
+
this.vel.remove();
|
|
45
|
+
} else {
|
|
46
|
+
this.$el.remove();
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
isMounted: function() {
|
|
51
|
+
return this.el.parentNode !== null;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
renderChildren: function(children) {
|
|
55
|
+
children || (children = util.result(this, 'children'));
|
|
56
|
+
if (children) {
|
|
57
|
+
var isSVG = this.svgElement;
|
|
58
|
+
var namespace = V.namespace[isSVG ? 'svg' : 'xhtml'];
|
|
59
|
+
var doc = util.parseDOMJSON(children, namespace);
|
|
60
|
+
(isSVG ? this.vel : this.$el).empty().append(doc.fragment);
|
|
61
|
+
this.childNodes = doc.selectors;
|
|
62
|
+
}
|
|
63
|
+
return this;
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
findAttribute: function(attributeName, node) {
|
|
67
|
+
|
|
68
|
+
var currentNode = node;
|
|
69
|
+
|
|
70
|
+
while (currentNode && currentNode.nodeType === 1) {
|
|
71
|
+
var attributeValue = currentNode.getAttribute(attributeName);
|
|
72
|
+
// attribute found
|
|
73
|
+
if (attributeValue) return attributeValue;
|
|
74
|
+
// do not climb up the DOM
|
|
75
|
+
if (currentNode === this.el) return null;
|
|
76
|
+
// try parent node
|
|
77
|
+
currentNode = currentNode.parentNode;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return null;
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// Override the mvc ViewBase `_ensureElement()` method in order to create an
|
|
84
|
+
// svg element (e.g., `<g>`) node that wraps all the nodes of the Cell view.
|
|
85
|
+
// Expose class name setter as a separate method.
|
|
86
|
+
_ensureElement: function() {
|
|
87
|
+
if (!this.el) {
|
|
88
|
+
var tagName = util.result(this, 'tagName');
|
|
89
|
+
var attrs = util.assign({}, util.result(this, 'attributes'));
|
|
90
|
+
var style = util.assign({}, util.result(this, 'style'));
|
|
91
|
+
if (this.id) attrs.id = util.result(this, 'id');
|
|
92
|
+
this.setElement(this._createElement(tagName));
|
|
93
|
+
this._setAttributes(attrs);
|
|
94
|
+
this._setStyle(style);
|
|
95
|
+
} else {
|
|
96
|
+
this.setElement(util.result(this, 'el'));
|
|
97
|
+
}
|
|
98
|
+
this._ensureElClassName();
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
_setAttributes: function(attrs) {
|
|
102
|
+
if (this.svgElement) {
|
|
103
|
+
this.vel.attr(attrs);
|
|
104
|
+
} else {
|
|
105
|
+
this.$el.attr(attrs);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
_setStyle: function(style) {
|
|
110
|
+
this.$el.css(style);
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
_createElement: function(tagName) {
|
|
114
|
+
if (this.svgElement) {
|
|
115
|
+
return document.createElementNS(V.namespace.svg, tagName);
|
|
116
|
+
} else {
|
|
117
|
+
return document.createElement(tagName);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
// Utilize an alternative DOM manipulation API by
|
|
122
|
+
// adding an element reference wrapped in Vectorizer.
|
|
123
|
+
_setElement: function(el) {
|
|
124
|
+
this.$el = el instanceof $ ? el : $(el);
|
|
125
|
+
this.el = this.$el[0];
|
|
126
|
+
if (this.svgElement) this.vel = V(this.el);
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
_ensureElClassName: function() {
|
|
130
|
+
var className = util.result(this, 'className');
|
|
131
|
+
if (!className) return;
|
|
132
|
+
var prefixedClassName = util.addClassNamePrefix(className);
|
|
133
|
+
// Note: className removal here kept for backwards compatibility only
|
|
134
|
+
if (this.svgElement) {
|
|
135
|
+
this.vel.removeClass(className).addClass(prefixedClassName);
|
|
136
|
+
} else {
|
|
137
|
+
this.$el.removeClass(className).addClass(prefixedClassName);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
init: function() {
|
|
142
|
+
// Intentionally empty.
|
|
143
|
+
// This method is meant to be overridden.
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
onRender: function() {
|
|
147
|
+
// Intentionally empty.
|
|
148
|
+
// This method is meant to be overridden.
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
confirmUpdate: function() {
|
|
152
|
+
// Intentionally empty.
|
|
153
|
+
// This method is meant to be overridden.
|
|
154
|
+
return 0;
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
setTheme: function(theme, opt) {
|
|
158
|
+
|
|
159
|
+
opt = opt || {};
|
|
160
|
+
|
|
161
|
+
// Theme is already set, override is required, and override has not been set.
|
|
162
|
+
// Don't set the theme.
|
|
163
|
+
if (this.theme && this.requireSetThemeOverride && !opt.override) {
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.removeThemeClassName();
|
|
168
|
+
this.addThemeClassName(theme);
|
|
169
|
+
this.onSetTheme(this.theme/* oldTheme */, theme/* newTheme */);
|
|
170
|
+
this.theme = theme;
|
|
171
|
+
|
|
172
|
+
return this;
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
addThemeClassName: function(theme) {
|
|
176
|
+
|
|
177
|
+
theme = theme || this.theme;
|
|
178
|
+
if (!theme) return this;
|
|
179
|
+
|
|
180
|
+
var className = this.themeClassNamePrefix + theme;
|
|
181
|
+
|
|
182
|
+
if (this.svgElement) {
|
|
183
|
+
this.vel.addClass(className);
|
|
184
|
+
} else {
|
|
185
|
+
this.$el.addClass(className);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return this;
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
removeThemeClassName: function(theme) {
|
|
192
|
+
|
|
193
|
+
theme = theme || this.theme;
|
|
194
|
+
|
|
195
|
+
var className = this.themeClassNamePrefix + theme;
|
|
196
|
+
|
|
197
|
+
if (this.svgElement) {
|
|
198
|
+
this.vel.removeClass(className);
|
|
199
|
+
} else {
|
|
200
|
+
this.$el.removeClass(className);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return this;
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
onSetTheme: function(oldTheme, newTheme) {
|
|
207
|
+
// Intentionally empty.
|
|
208
|
+
// This method is meant to be overridden.
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
remove: function() {
|
|
212
|
+
|
|
213
|
+
this.onRemove();
|
|
214
|
+
this.undelegateDocumentEvents();
|
|
215
|
+
|
|
216
|
+
views[this.cid] = null;
|
|
217
|
+
|
|
218
|
+
ViewBase.prototype.remove.apply(this, arguments);
|
|
219
|
+
|
|
220
|
+
return this;
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
onRemove: function() {
|
|
224
|
+
// Intentionally empty.
|
|
225
|
+
// This method is meant to be overridden.
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
getEventNamespace: function() {
|
|
229
|
+
// Returns a per-session unique namespace
|
|
230
|
+
return '.joint-event-ns-' + this.cid;
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
delegateElementEvents: function(element, events, data) {
|
|
234
|
+
if (!events) return this;
|
|
235
|
+
data || (data = {});
|
|
236
|
+
var eventNS = this.getEventNamespace();
|
|
237
|
+
for (var eventName in events) {
|
|
238
|
+
var method = events[eventName];
|
|
239
|
+
if (typeof method !== 'function') method = this[method];
|
|
240
|
+
if (!method) continue;
|
|
241
|
+
$(element).on(eventName + eventNS, data, method.bind(this));
|
|
242
|
+
}
|
|
243
|
+
return this;
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
undelegateElementEvents: function(element) {
|
|
247
|
+
$(element).off(this.getEventNamespace());
|
|
248
|
+
return this;
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
delegateDocumentEvents: function(events, data) {
|
|
252
|
+
events || (events = util.result(this, 'documentEvents'));
|
|
253
|
+
return this.delegateElementEvents(document, events, data);
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
undelegateDocumentEvents: function() {
|
|
257
|
+
return this.undelegateElementEvents(document);
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
eventData: function(evt, data) {
|
|
261
|
+
if (!evt) throw new Error('eventData(): event object required.');
|
|
262
|
+
var currentData = evt.data;
|
|
263
|
+
var key = '__' + this.cid + '__';
|
|
264
|
+
if (data === undefined) {
|
|
265
|
+
if (!currentData) return {};
|
|
266
|
+
return currentData[key] || {};
|
|
267
|
+
}
|
|
268
|
+
currentData || (currentData = evt.data = {});
|
|
269
|
+
currentData[key] || (currentData[key] = {});
|
|
270
|
+
util.assign(currentData[key], data);
|
|
271
|
+
return this;
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
stopPropagation: function(evt) {
|
|
275
|
+
this.eventData(evt, { propagationStopped: true });
|
|
276
|
+
return this;
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
isPropagationStopped: function(evt) {
|
|
280
|
+
return !!this.eventData(evt).propagationStopped;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
}, {
|
|
284
|
+
|
|
285
|
+
extend: function() {
|
|
286
|
+
|
|
287
|
+
var args = Array.from(arguments);
|
|
288
|
+
|
|
289
|
+
// Deep clone the prototype and static properties objects.
|
|
290
|
+
// This prevents unexpected behavior where some properties are overwritten outside of this function.
|
|
291
|
+
var protoProps = args[0] && util.assign({}, args[0]) || {};
|
|
292
|
+
var staticProps = args[1] && util.assign({}, args[1]) || {};
|
|
293
|
+
|
|
294
|
+
// Need the real render method so that we can wrap it and call it later.
|
|
295
|
+
var renderFn = protoProps.render || (this.prototype && this.prototype.render) || null;
|
|
296
|
+
|
|
297
|
+
/*
|
|
298
|
+
Wrap the real render method so that:
|
|
299
|
+
.. `onRender` is always called.
|
|
300
|
+
.. `this` is always returned.
|
|
301
|
+
*/
|
|
302
|
+
protoProps.render = function() {
|
|
303
|
+
|
|
304
|
+
if (typeof renderFn === 'function') {
|
|
305
|
+
// Call the original render method.
|
|
306
|
+
renderFn.apply(this, arguments);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (this.render.__render__ === renderFn) {
|
|
310
|
+
// Should always call onRender() method.
|
|
311
|
+
// Should call it only once when renderFn is actual prototype method i.e. not the wrapper
|
|
312
|
+
this.onRender();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Should always return itself.
|
|
316
|
+
return this;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
protoProps.render.__render__ = renderFn;
|
|
320
|
+
|
|
321
|
+
return ViewBase.extend.call(this, protoProps, staticProps);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import $ from './Dom/index.mjs';
|
|
2
|
+
|
|
3
|
+
import { Events } from './Events.mjs';
|
|
4
|
+
import { extend } from './mvcUtils.mjs';
|
|
5
|
+
import {
|
|
6
|
+
assign,
|
|
7
|
+
isFunction,
|
|
8
|
+
pick,
|
|
9
|
+
result,
|
|
10
|
+
uniqueId
|
|
11
|
+
} from '../util/util.mjs';
|
|
12
|
+
|
|
13
|
+
// ViewBase
|
|
14
|
+
// -------------
|
|
15
|
+
|
|
16
|
+
// ViewBases are almost more convention than they are actual code. A View
|
|
17
|
+
// is simply a JavaScript object that represents a logical chunk of UI in the
|
|
18
|
+
// DOM. This might be a single item, an entire list, a sidebar or panel, or
|
|
19
|
+
// even the surrounding frame which wraps your whole app. Defining a chunk of
|
|
20
|
+
// UI as a **View** allows you to define your DOM events declaratively, without
|
|
21
|
+
// having to worry about render order ... and makes it easy for the view to
|
|
22
|
+
// react to specific changes in the state of your models.
|
|
23
|
+
|
|
24
|
+
// Creating a ViewBase creates its initial element outside of the DOM,
|
|
25
|
+
// if an existing element is not provided...
|
|
26
|
+
export var ViewBase = function(options) {
|
|
27
|
+
this.cid = uniqueId('view');
|
|
28
|
+
this.preinitialize.apply(this, arguments);
|
|
29
|
+
assign(this, pick(options, viewOptions));
|
|
30
|
+
this._ensureElement();
|
|
31
|
+
this.initialize.apply(this, arguments);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Cached regex to split keys for `delegate`.
|
|
35
|
+
var delegateEventSplitter = /^(\S+)\s*(.*)$/;
|
|
36
|
+
|
|
37
|
+
// List of view options to be set as properties.
|
|
38
|
+
var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
|
|
39
|
+
|
|
40
|
+
// Set up all inheritable **ViewBase** properties and methods.
|
|
41
|
+
assign(ViewBase.prototype, Events, {
|
|
42
|
+
|
|
43
|
+
// The default `tagName` of a View's element is `"div"`.
|
|
44
|
+
tagName: 'div',
|
|
45
|
+
|
|
46
|
+
// mvc.$ delegate for element lookup, scoped to DOM elements within the
|
|
47
|
+
// current view. This should be preferred to global lookups where possible.
|
|
48
|
+
$: function(selector) {
|
|
49
|
+
return this.$el.find(selector);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
// preinitialize is an empty function by default. You can override it with a function
|
|
53
|
+
// or object. preinitialize will run before any instantiation logic is run in the View
|
|
54
|
+
preinitialize: function(){},
|
|
55
|
+
|
|
56
|
+
// Initialize is an empty function by default. Override it with your own
|
|
57
|
+
// initialization logic.
|
|
58
|
+
initialize: function(){},
|
|
59
|
+
|
|
60
|
+
// **render** is the core function that your view should override, in order
|
|
61
|
+
// to populate its element (`this.el`), with the appropriate HTML. The
|
|
62
|
+
// convention is for **render** to always return `this`.
|
|
63
|
+
render: function() {
|
|
64
|
+
return this;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// Remove this view by taking the element out of the DOM, and removing any
|
|
68
|
+
// applicable Events listeners.
|
|
69
|
+
remove: function() {
|
|
70
|
+
this._removeElement();
|
|
71
|
+
this.stopListening();
|
|
72
|
+
return this;
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Remove this view's element from the document and all event listeners
|
|
76
|
+
// attached to it. Exposed for subclasses using an alternative DOM
|
|
77
|
+
// manipulation API.
|
|
78
|
+
_removeElement: function() {
|
|
79
|
+
this.$el.remove();
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
// Change the view's element (`this.el` property) and re-delegate the
|
|
83
|
+
// view's events on the new element.
|
|
84
|
+
setElement: function(element) {
|
|
85
|
+
this.undelegateEvents();
|
|
86
|
+
this._setElement(element);
|
|
87
|
+
this.delegateEvents();
|
|
88
|
+
return this;
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
// Creates the `this.el` and `this.$el` references for this view using the
|
|
92
|
+
// given `el`. `el` can be a CSS selector or an HTML string, a mvc.$
|
|
93
|
+
// context or an element. Subclasses can override this to utilize an
|
|
94
|
+
// alternative DOM manipulation API and are only required to set the
|
|
95
|
+
// `this.el` property.
|
|
96
|
+
_setElement: function(el) {
|
|
97
|
+
this.$el = el instanceof $ ? el : $(el);
|
|
98
|
+
this.el = this.$el[0];
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
// Set callbacks, where `this.events` is a hash of
|
|
102
|
+
//
|
|
103
|
+
// *{"event selector": "callback"}*
|
|
104
|
+
//
|
|
105
|
+
// {
|
|
106
|
+
// 'mousedown .title': 'edit',
|
|
107
|
+
// 'click .button': 'save',
|
|
108
|
+
// 'click .open': function(e) { ... }
|
|
109
|
+
// }
|
|
110
|
+
//
|
|
111
|
+
// pairs. Callbacks will be bound to the view, with `this` set properly.
|
|
112
|
+
// Uses event delegation for efficiency.
|
|
113
|
+
// Omitting the selector binds the event to `this.el`.
|
|
114
|
+
delegateEvents: function(events) {
|
|
115
|
+
events || (events = result(this, 'events'));
|
|
116
|
+
if (!events) return this;
|
|
117
|
+
this.undelegateEvents();
|
|
118
|
+
for (var key in events) {
|
|
119
|
+
var method = events[key];
|
|
120
|
+
if (!isFunction(method)) method = this[method];
|
|
121
|
+
if (!method) continue;
|
|
122
|
+
var match = key.match(delegateEventSplitter);
|
|
123
|
+
this.delegate(match[1], match[2], method.bind(this));
|
|
124
|
+
}
|
|
125
|
+
return this;
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// Add a single event listener to the view's element (or a child element
|
|
129
|
+
// using `selector`). This only works for delegate-able events: not `focus`,
|
|
130
|
+
// `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.
|
|
131
|
+
delegate: function(eventName, selector, listener) {
|
|
132
|
+
this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
|
|
133
|
+
return this;
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
// Clears all callbacks previously bound to the view by `delegateEvents`.
|
|
137
|
+
// You usually don't need to use this, but may wish to if you have multiple
|
|
138
|
+
// viewbases attached to the same DOM element.
|
|
139
|
+
undelegateEvents: function() {
|
|
140
|
+
if (this.$el) this.$el.off('.delegateEvents' + this.cid);
|
|
141
|
+
return this;
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
// A finer-grained `undelegateEvents` for removing a single delegated event.
|
|
145
|
+
// `selector` and `listener` are both optional.
|
|
146
|
+
undelegate: function(eventName, selector, listener) {
|
|
147
|
+
this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener);
|
|
148
|
+
return this;
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// Produces a DOM element to be assigned to your view. Exposed for
|
|
152
|
+
// subclasses using an alternative DOM manipulation API.
|
|
153
|
+
_createElement: function(tagName) {
|
|
154
|
+
return document.createElement(tagName);
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
// Ensure that the View has a DOM element to render into.
|
|
158
|
+
// If `this.el` is a string, pass it through `$()`, take the first
|
|
159
|
+
// matching element, and re-assign it to `el`. Otherwise, create
|
|
160
|
+
// an element from the `id`, `className` and `tagName` properties.
|
|
161
|
+
_ensureElement: function() {
|
|
162
|
+
if (!this.el) {
|
|
163
|
+
var attrs = assign({}, result(this, 'attributes'));
|
|
164
|
+
if (this.id) attrs.id = result(this, 'id');
|
|
165
|
+
if (this.className) attrs['class'] = result(this, 'className');
|
|
166
|
+
this.setElement(this._createElement(result(this, 'tagName')));
|
|
167
|
+
this._setAttributes(attrs);
|
|
168
|
+
} else {
|
|
169
|
+
this.setElement(result(this, 'el'));
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
// Set attributes from a hash on this view's element. Exposed for
|
|
174
|
+
// subclasses using an alternative DOM manipulation API.
|
|
175
|
+
_setAttributes: function(attributes) {
|
|
176
|
+
this.$el.attr(attributes);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Set up inheritance for the view.
|
|
182
|
+
ViewBase.extend = extend;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './View.mjs';
|
|
2
|
+
export * from './Listener.mjs';
|
|
3
|
+
export * from './Events.mjs';
|
|
4
|
+
export * from './Collection.mjs';
|
|
5
|
+
export * from './Model.mjs';
|
|
6
|
+
export * from './ViewBase.mjs';
|
|
7
|
+
export { default as Data } from './Data.mjs';
|
|
8
|
+
export { default as $ } from './Dom/index.mjs';
|
|
9
|
+
export * from './Dom/Event.mjs';
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assign,
|
|
3
|
+
forIn,
|
|
4
|
+
has,
|
|
5
|
+
isFunction,
|
|
6
|
+
isObject,
|
|
7
|
+
isString
|
|
8
|
+
} from '../util/util.mjs';
|
|
9
|
+
import { matches } from '../util/utilHelpers.mjs';
|
|
10
|
+
|
|
11
|
+
// Helpers
|
|
12
|
+
// -------
|
|
13
|
+
|
|
14
|
+
// Helper function to correctly set up the prototype chain for subclasses.
|
|
15
|
+
// Similar to `goog.inherits`, but uses a hash of prototype properties and
|
|
16
|
+
// class properties to be extended.
|
|
17
|
+
export var extend = function(protoProps, staticProps) {
|
|
18
|
+
var parent = this;
|
|
19
|
+
var child;
|
|
20
|
+
|
|
21
|
+
// The constructor function for the new subclass is either defined by you
|
|
22
|
+
// (the "constructor" property in your `extend` definition), or defaulted
|
|
23
|
+
// by us to simply call the parent constructor.
|
|
24
|
+
if (protoProps && has(protoProps, 'constructor')) {
|
|
25
|
+
child = protoProps.constructor;
|
|
26
|
+
} else {
|
|
27
|
+
child = function(){ return parent.apply(this, arguments); };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Add static properties to the constructor function, if supplied.
|
|
31
|
+
assign(child, parent, staticProps);
|
|
32
|
+
|
|
33
|
+
// Set the prototype chain to inherit from `parent`, without calling
|
|
34
|
+
// `parent`'s constructor function and add the prototype properties.
|
|
35
|
+
child.prototype = Object.assign(Object.create(parent.prototype), protoProps);
|
|
36
|
+
child.prototype.constructor = child;
|
|
37
|
+
|
|
38
|
+
// Set a convenience property in case the parent's prototype is needed
|
|
39
|
+
// later.
|
|
40
|
+
child.__super__ = parent.prototype;
|
|
41
|
+
|
|
42
|
+
return child;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Proxy class methods to functions, wrapping the model's
|
|
46
|
+
// `attributes` object or collection's `models` array behind the scenes.
|
|
47
|
+
//
|
|
48
|
+
// `Function#apply` can be slow so we use the method's arg count, if we know it.
|
|
49
|
+
var addMethod = function(base, length, method, attribute) {
|
|
50
|
+
switch (length) {
|
|
51
|
+
case 1: return function() {
|
|
52
|
+
return base[method](this[attribute]);
|
|
53
|
+
};
|
|
54
|
+
case 2: return function(value) {
|
|
55
|
+
return base[method](this[attribute], value);
|
|
56
|
+
};
|
|
57
|
+
case 3: return function(iteratee, context) {
|
|
58
|
+
return base[method](this[attribute], cb(iteratee, this), context);
|
|
59
|
+
};
|
|
60
|
+
case 4: return function(iteratee, defaultVal, context) {
|
|
61
|
+
return base[method](this[attribute], cb(iteratee, this), defaultVal, context);
|
|
62
|
+
};
|
|
63
|
+
default: return function() {
|
|
64
|
+
var args = Array.prototype.slice.call(arguments);
|
|
65
|
+
args.unshift(this[attribute]);
|
|
66
|
+
return base[method].apply(base, args);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export var addMethodsUtil = function(Class, base, methods, attribute) {
|
|
72
|
+
forIn(methods, function(length, method) {
|
|
73
|
+
if (base[method]) Class.prototype[method] = addMethod(base, length, method, attribute);
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Support `collection.sortBy('attr')`.
|
|
78
|
+
var cb = function(iteratee, instance) {
|
|
79
|
+
if (isFunction(iteratee)) return iteratee;
|
|
80
|
+
if (isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
|
|
81
|
+
if (isString(iteratee)) return function(model) { return model.get(iteratee); };
|
|
82
|
+
return iteratee;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
var modelMatcher = function(attrs) {
|
|
86
|
+
var matcher = matches(attrs);
|
|
87
|
+
return function(model) {
|
|
88
|
+
return matcher(model.attributes);
|
|
89
|
+
};
|
|
90
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* version: 0.3.0
|
|
5
|
+
* git://github.com/davidchambers/Base64.js.git
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
var object = typeof exports != 'undefined' ? exports : this; // #8: web workers
|
|
9
|
+
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
10
|
+
|
|
11
|
+
function InvalidCharacterError(message) {
|
|
12
|
+
this.message = message;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
InvalidCharacterError.prototype = new Error;
|
|
16
|
+
InvalidCharacterError.prototype.name = 'InvalidCharacterError';
|
|
17
|
+
|
|
18
|
+
// encoder
|
|
19
|
+
// [https://gist.github.com/999166] by [https://github.com/nignag]
|
|
20
|
+
object.btoa || (
|
|
21
|
+
object.btoa = function(input) {
|
|
22
|
+
var str = String(input);
|
|
23
|
+
for (
|
|
24
|
+
// initialize result and counter
|
|
25
|
+
var block, charCode, idx = 0, map = chars, output = '';
|
|
26
|
+
// if the next str index does not exist:
|
|
27
|
+
// change the mapping table to "="
|
|
28
|
+
// check if d has no fractional digits
|
|
29
|
+
str.charAt(idx | 0) || (map = '=', idx % 1);
|
|
30
|
+
// "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
|
|
31
|
+
output += map.charAt(63 & block >> 8 - idx % 1 * 8)
|
|
32
|
+
) {
|
|
33
|
+
charCode = str.charCodeAt(idx += 3 / 4);
|
|
34
|
+
if (charCode > 0xFF) {
|
|
35
|
+
throw new InvalidCharacterError('\'btoa\' failed: The string to be encoded contains characters outside of the Latin1 range.');
|
|
36
|
+
}
|
|
37
|
+
block = block << 8 | charCode;
|
|
38
|
+
}
|
|
39
|
+
return output;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// decoder
|
|
43
|
+
// [https://gist.github.com/1020396] by [https://github.com/atk]
|
|
44
|
+
object.atob || (
|
|
45
|
+
object.atob = function(input) {
|
|
46
|
+
var str = String(input).replace(/=+$/, '');
|
|
47
|
+
if (str.length % 4 == 1) {
|
|
48
|
+
throw new InvalidCharacterError('\'atob\' failed: The string to be decoded is not correctly encoded.');
|
|
49
|
+
}
|
|
50
|
+
for (
|
|
51
|
+
// initialize result and counters
|
|
52
|
+
var bc = 0, bs, buffer, idx = 0, output = '';
|
|
53
|
+
// get next character
|
|
54
|
+
// eslint-disable-next-line no-cond-assign
|
|
55
|
+
buffer = str.charAt(idx++);
|
|
56
|
+
// character found in table? initialize bit storage and add its ascii value;
|
|
57
|
+
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
|
|
58
|
+
// and if not first of each 4 characters,
|
|
59
|
+
// convert the first 8 bits to one ascii character
|
|
60
|
+
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
|
|
61
|
+
) {
|
|
62
|
+
// try to find character in table (0-63, not found => -1)
|
|
63
|
+
buffer = chars.indexOf(buffer);
|
|
64
|
+
}
|
|
65
|
+
return output;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
}());
|