stimulus-rails 1.1.0 → 1.1.1
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/stimulus.js +188 -132
- data/app/assets/javascripts/stimulus.min.js +1 -1
- data/app/assets/javascripts/stimulus.min.js.map +1 -1
- data/lib/stimulus/version.rb +1 -1
- metadata +3 -3
@@ -3,7 +3,7 @@
|
|
3
3
|
//= link ./stimulus-loading.js
|
4
4
|
|
5
5
|
/*
|
6
|
-
Stimulus 3.1.
|
6
|
+
Stimulus 3.1.1
|
7
7
|
Copyright © 2022 Basecamp, LLC
|
8
8
|
*/
|
9
9
|
class EventListener {
|
@@ -36,6 +36,9 @@ class EventListener {
|
|
36
36
|
}
|
37
37
|
}
|
38
38
|
}
|
39
|
+
hasBindings() {
|
40
|
+
return this.unorderedBindings.size > 0;
|
41
|
+
}
|
39
42
|
get bindings() {
|
40
43
|
return Array.from(this.unorderedBindings).sort((left, right) => {
|
41
44
|
const leftIndex = left.index, rightIndex = right.index;
|
@@ -54,7 +57,7 @@ function extendEvent(event) {
|
|
54
57
|
stopImmediatePropagation() {
|
55
58
|
this.immediatePropagationStopped = true;
|
56
59
|
stopImmediatePropagation.call(this);
|
57
|
-
}
|
60
|
+
},
|
58
61
|
});
|
59
62
|
}
|
60
63
|
}
|
@@ -62,34 +65,50 @@ function extendEvent(event) {
|
|
62
65
|
class Dispatcher {
|
63
66
|
constructor(application) {
|
64
67
|
this.application = application;
|
65
|
-
this.eventListenerMaps = new Map;
|
68
|
+
this.eventListenerMaps = new Map();
|
66
69
|
this.started = false;
|
67
70
|
}
|
68
71
|
start() {
|
69
72
|
if (!this.started) {
|
70
73
|
this.started = true;
|
71
|
-
this.eventListeners.forEach(eventListener => eventListener.connect());
|
74
|
+
this.eventListeners.forEach((eventListener) => eventListener.connect());
|
72
75
|
}
|
73
76
|
}
|
74
77
|
stop() {
|
75
78
|
if (this.started) {
|
76
79
|
this.started = false;
|
77
|
-
this.eventListeners.forEach(eventListener => eventListener.disconnect());
|
80
|
+
this.eventListeners.forEach((eventListener) => eventListener.disconnect());
|
78
81
|
}
|
79
82
|
}
|
80
83
|
get eventListeners() {
|
81
|
-
return Array.from(this.eventListenerMaps.values())
|
82
|
-
.reduce((listeners, map) => listeners.concat(Array.from(map.values())), []);
|
84
|
+
return Array.from(this.eventListenerMaps.values()).reduce((listeners, map) => listeners.concat(Array.from(map.values())), []);
|
83
85
|
}
|
84
86
|
bindingConnected(binding) {
|
85
87
|
this.fetchEventListenerForBinding(binding).bindingConnected(binding);
|
86
88
|
}
|
87
|
-
bindingDisconnected(binding) {
|
89
|
+
bindingDisconnected(binding, clearEventListeners = false) {
|
88
90
|
this.fetchEventListenerForBinding(binding).bindingDisconnected(binding);
|
91
|
+
if (clearEventListeners)
|
92
|
+
this.clearEventListenersForBinding(binding);
|
89
93
|
}
|
90
94
|
handleError(error, message, detail = {}) {
|
91
95
|
this.application.handleError(error, `Error ${message}`, detail);
|
92
96
|
}
|
97
|
+
clearEventListenersForBinding(binding) {
|
98
|
+
const eventListener = this.fetchEventListenerForBinding(binding);
|
99
|
+
if (!eventListener.hasBindings()) {
|
100
|
+
eventListener.disconnect();
|
101
|
+
this.removeMappedEventListenerFor(binding);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
removeMappedEventListenerFor(binding) {
|
105
|
+
const { eventTarget, eventName, eventOptions } = binding;
|
106
|
+
const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget);
|
107
|
+
const cacheKey = this.cacheKey(eventName, eventOptions);
|
108
|
+
eventListenerMap.delete(cacheKey);
|
109
|
+
if (eventListenerMap.size == 0)
|
110
|
+
this.eventListenerMaps.delete(eventTarget);
|
111
|
+
}
|
93
112
|
fetchEventListenerForBinding(binding) {
|
94
113
|
const { eventTarget, eventName, eventOptions } = binding;
|
95
114
|
return this.fetchEventListener(eventTarget, eventName, eventOptions);
|
@@ -114,20 +133,42 @@ class Dispatcher {
|
|
114
133
|
fetchEventListenerMapForEventTarget(eventTarget) {
|
115
134
|
let eventListenerMap = this.eventListenerMaps.get(eventTarget);
|
116
135
|
if (!eventListenerMap) {
|
117
|
-
eventListenerMap = new Map;
|
136
|
+
eventListenerMap = new Map();
|
118
137
|
this.eventListenerMaps.set(eventTarget, eventListenerMap);
|
119
138
|
}
|
120
139
|
return eventListenerMap;
|
121
140
|
}
|
122
141
|
cacheKey(eventName, eventOptions) {
|
123
142
|
const parts = [eventName];
|
124
|
-
Object.keys(eventOptions)
|
143
|
+
Object.keys(eventOptions)
|
144
|
+
.sort()
|
145
|
+
.forEach((key) => {
|
125
146
|
parts.push(`${eventOptions[key] ? "" : "!"}${key}`);
|
126
147
|
});
|
127
148
|
return parts.join(":");
|
128
149
|
}
|
129
150
|
}
|
130
151
|
|
152
|
+
const defaultActionDescriptorFilters = {
|
153
|
+
stop({ event, value }) {
|
154
|
+
if (value)
|
155
|
+
event.stopPropagation();
|
156
|
+
return true;
|
157
|
+
},
|
158
|
+
prevent({ event, value }) {
|
159
|
+
if (value)
|
160
|
+
event.preventDefault();
|
161
|
+
return true;
|
162
|
+
},
|
163
|
+
self({ event, value, element }) {
|
164
|
+
if (value) {
|
165
|
+
return element === event.target;
|
166
|
+
}
|
167
|
+
else {
|
168
|
+
return true;
|
169
|
+
}
|
170
|
+
},
|
171
|
+
};
|
131
172
|
const descriptorPattern = /^((.+?)(@(window|document))?->)?(.+?)(#([^:]+?))(:(.+))?$/;
|
132
173
|
function parseActionDescriptorString(descriptorString) {
|
133
174
|
const source = descriptorString.trim();
|
@@ -137,7 +178,7 @@ function parseActionDescriptorString(descriptorString) {
|
|
137
178
|
eventName: matches[2],
|
138
179
|
eventOptions: matches[9] ? parseEventOptions(matches[9]) : {},
|
139
180
|
identifier: matches[5],
|
140
|
-
methodName: matches[7]
|
181
|
+
methodName: matches[7],
|
141
182
|
};
|
142
183
|
}
|
143
184
|
function parseEventTarget(eventTargetName) {
|
@@ -149,7 +190,9 @@ function parseEventTarget(eventTargetName) {
|
|
149
190
|
}
|
150
191
|
}
|
151
192
|
function parseEventOptions(eventOptions) {
|
152
|
-
return eventOptions
|
193
|
+
return eventOptions
|
194
|
+
.split(":")
|
195
|
+
.reduce((options, token) => Object.assign(options, { [token.replace(/^!/, "")]: !/^!/.test(token) }), {});
|
153
196
|
}
|
154
197
|
function stringifyEventTarget(eventTarget) {
|
155
198
|
if (eventTarget == window) {
|
@@ -192,7 +235,7 @@ class Action {
|
|
192
235
|
}
|
193
236
|
get params() {
|
194
237
|
const params = {};
|
195
|
-
const pattern = new RegExp(`^data-${this.identifier}-(.+)-param
|
238
|
+
const pattern = new RegExp(`^data-${this.identifier}-(.+)-param$`, "i");
|
196
239
|
for (const { name, value } of Array.from(this.element.attributes)) {
|
197
240
|
const match = name.match(pattern);
|
198
241
|
const key = match && match[1];
|
@@ -207,13 +250,13 @@ class Action {
|
|
207
250
|
}
|
208
251
|
}
|
209
252
|
const defaultEventNames = {
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
253
|
+
a: () => "click",
|
254
|
+
button: () => "click",
|
255
|
+
form: () => "submit",
|
256
|
+
details: () => "toggle",
|
257
|
+
input: (e) => (e.getAttribute("type") == "submit" ? "click" : "input"),
|
258
|
+
select: () => "change",
|
259
|
+
textarea: () => "input",
|
217
260
|
};
|
218
261
|
function getDefaultEventNameForElement(element) {
|
219
262
|
const tagName = element.tagName.toLowerCase();
|
@@ -251,9 +294,7 @@ class Binding {
|
|
251
294
|
return this.context.identifier;
|
252
295
|
}
|
253
296
|
handleEvent(event) {
|
254
|
-
if (this.willBeInvokedByEvent(event) && this.
|
255
|
-
this.processStopPropagation(event);
|
256
|
-
this.processPreventDefault(event);
|
297
|
+
if (this.willBeInvokedByEvent(event) && this.applyEventModifiers(event)) {
|
257
298
|
this.invokeWithEvent(event);
|
258
299
|
}
|
259
300
|
}
|
@@ -267,15 +308,20 @@ class Binding {
|
|
267
308
|
}
|
268
309
|
throw new Error(`Action "${this.action}" references undefined method "${this.methodName}"`);
|
269
310
|
}
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
311
|
+
applyEventModifiers(event) {
|
312
|
+
const { element } = this.action;
|
313
|
+
const { actionDescriptorFilters } = this.context.application;
|
314
|
+
let passes = true;
|
315
|
+
for (const [name, value] of Object.entries(this.eventOptions)) {
|
316
|
+
if (name in actionDescriptorFilters) {
|
317
|
+
const filter = actionDescriptorFilters[name];
|
318
|
+
passes = passes && filter({ name, value, event, element });
|
319
|
+
}
|
320
|
+
else {
|
321
|
+
continue;
|
322
|
+
}
|
278
323
|
}
|
324
|
+
return passes;
|
279
325
|
}
|
280
326
|
invokeWithEvent(event) {
|
281
327
|
const { target, currentTarget } = event;
|
@@ -291,14 +337,6 @@ class Binding {
|
|
291
337
|
this.context.handleError(error, `invoking action "${this.action}"`, detail);
|
292
338
|
}
|
293
339
|
}
|
294
|
-
shouldBeInvokedPerSelf(event) {
|
295
|
-
if (this.action.eventOptions.self === true) {
|
296
|
-
return this.action.element === event.target;
|
297
|
-
}
|
298
|
-
else {
|
299
|
-
return true;
|
300
|
-
}
|
301
|
-
}
|
302
340
|
willBeInvokedByEvent(event) {
|
303
341
|
const eventTarget = event.target;
|
304
342
|
if (this.element === eventTarget) {
|
@@ -331,7 +369,7 @@ class ElementObserver {
|
|
331
369
|
this.element = element;
|
332
370
|
this.started = false;
|
333
371
|
this.delegate = delegate;
|
334
|
-
this.elements = new Set;
|
372
|
+
this.elements = new Set();
|
335
373
|
this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations));
|
336
374
|
}
|
337
375
|
start() {
|
@@ -519,8 +557,8 @@ class StringMapObserver {
|
|
519
557
|
this.element = element;
|
520
558
|
this.delegate = delegate;
|
521
559
|
this.started = false;
|
522
|
-
this.stringMap = new Map;
|
523
|
-
this.mutationObserver = new MutationObserver(mutations => this.processMutations(mutations));
|
560
|
+
this.stringMap = new Map();
|
561
|
+
this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations));
|
524
562
|
}
|
525
563
|
start() {
|
526
564
|
if (!this.started) {
|
@@ -596,7 +634,7 @@ class StringMapObserver {
|
|
596
634
|
return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames)));
|
597
635
|
}
|
598
636
|
get currentAttributeNames() {
|
599
|
-
return Array.from(this.element.attributes).map(attribute => attribute.name);
|
637
|
+
return Array.from(this.element.attributes).map((attribute) => attribute.name);
|
600
638
|
}
|
601
639
|
get recordedAttributeNames() {
|
602
640
|
return Array.from(this.stringMap.keys());
|
@@ -655,7 +693,7 @@ class Multimap {
|
|
655
693
|
}
|
656
694
|
hasValue(value) {
|
657
695
|
const sets = Array.from(this.valuesByKey.values());
|
658
|
-
return sets.some(set => set.has(value));
|
696
|
+
return sets.some((set) => set.has(value));
|
659
697
|
}
|
660
698
|
getValuesForKey(key) {
|
661
699
|
const values = this.valuesByKey.get(key);
|
@@ -663,15 +701,15 @@ class Multimap {
|
|
663
701
|
}
|
664
702
|
getKeysForValue(value) {
|
665
703
|
return Array.from(this.valuesByKey)
|
666
|
-
.filter(([
|
667
|
-
.map(([key,
|
704
|
+
.filter(([_key, values]) => values.has(value))
|
705
|
+
.map(([key, _values]) => key);
|
668
706
|
}
|
669
707
|
}
|
670
708
|
|
671
709
|
class IndexedMultimap extends Multimap {
|
672
710
|
constructor() {
|
673
711
|
super();
|
674
|
-
this.keysByValue = new Map;
|
712
|
+
this.keysByValue = new Map();
|
675
713
|
}
|
676
714
|
get values() {
|
677
715
|
return Array.from(this.keysByValue.keys());
|
@@ -697,7 +735,7 @@ class TokenListObserver {
|
|
697
735
|
constructor(element, attributeName, delegate) {
|
698
736
|
this.attributeObserver = new AttributeObserver(element, attributeName, this);
|
699
737
|
this.delegate = delegate;
|
700
|
-
this.tokensByElement = new Multimap;
|
738
|
+
this.tokensByElement = new Multimap();
|
701
739
|
}
|
702
740
|
get started() {
|
703
741
|
return this.attributeObserver.started;
|
@@ -732,10 +770,10 @@ class TokenListObserver {
|
|
732
770
|
this.tokensUnmatched(this.tokensByElement.getValuesForKey(element));
|
733
771
|
}
|
734
772
|
tokensMatched(tokens) {
|
735
|
-
tokens.forEach(token => this.tokenMatched(token));
|
773
|
+
tokens.forEach((token) => this.tokenMatched(token));
|
736
774
|
}
|
737
775
|
tokensUnmatched(tokens) {
|
738
|
-
tokens.forEach(token => this.tokenUnmatched(token));
|
776
|
+
tokens.forEach((token) => this.tokenUnmatched(token));
|
739
777
|
}
|
740
778
|
tokenMatched(token) {
|
741
779
|
this.delegate.tokenMatched(token);
|
@@ -748,8 +786,7 @@ class TokenListObserver {
|
|
748
786
|
refreshTokensForElement(element) {
|
749
787
|
const previousTokens = this.tokensByElement.getValuesForKey(element);
|
750
788
|
const currentTokens = this.readTokensForElement(element);
|
751
|
-
const firstDifferingIndex = zip(previousTokens, currentTokens)
|
752
|
-
.findIndex(([previousToken, currentToken]) => !tokensAreEqual(previousToken, currentToken));
|
789
|
+
const firstDifferingIndex = zip(previousTokens, currentTokens).findIndex(([previousToken, currentToken]) => !tokensAreEqual(previousToken, currentToken));
|
753
790
|
if (firstDifferingIndex == -1) {
|
754
791
|
return [[], []];
|
755
792
|
}
|
@@ -764,7 +801,10 @@ class TokenListObserver {
|
|
764
801
|
}
|
765
802
|
}
|
766
803
|
function parseTokenString(tokenString, element, attributeName) {
|
767
|
-
return tokenString
|
804
|
+
return tokenString
|
805
|
+
.trim()
|
806
|
+
.split(/\s+/)
|
807
|
+
.filter((content) => content.length)
|
768
808
|
.map((content, index) => ({ element, attributeName, content, index }));
|
769
809
|
}
|
770
810
|
function zip(left, right) {
|
@@ -779,8 +819,8 @@ class ValueListObserver {
|
|
779
819
|
constructor(element, attributeName, delegate) {
|
780
820
|
this.tokenListObserver = new TokenListObserver(element, attributeName, this);
|
781
821
|
this.delegate = delegate;
|
782
|
-
this.parseResultsByToken = new WeakMap;
|
783
|
-
this.valuesByTokenByElement = new WeakMap;
|
822
|
+
this.parseResultsByToken = new WeakMap();
|
823
|
+
this.valuesByTokenByElement = new WeakMap();
|
784
824
|
}
|
785
825
|
get started() {
|
786
826
|
return this.tokenListObserver.started;
|
@@ -827,7 +867,7 @@ class ValueListObserver {
|
|
827
867
|
fetchValuesByTokenForElement(element) {
|
828
868
|
let valuesByToken = this.valuesByTokenByElement.get(element);
|
829
869
|
if (!valuesByToken) {
|
830
|
-
valuesByToken = new Map;
|
870
|
+
valuesByToken = new Map();
|
831
871
|
this.valuesByTokenByElement.set(element, valuesByToken);
|
832
872
|
}
|
833
873
|
return valuesByToken;
|
@@ -847,7 +887,7 @@ class BindingObserver {
|
|
847
887
|
constructor(context, delegate) {
|
848
888
|
this.context = context;
|
849
889
|
this.delegate = delegate;
|
850
|
-
this.bindingsByAction = new Map;
|
890
|
+
this.bindingsByAction = new Map();
|
851
891
|
}
|
852
892
|
start() {
|
853
893
|
if (!this.valueListObserver) {
|
@@ -890,7 +930,7 @@ class BindingObserver {
|
|
890
930
|
}
|
891
931
|
}
|
892
932
|
disconnectAllActions() {
|
893
|
-
this.bindings.forEach(binding => this.delegate.bindingDisconnected(binding));
|
933
|
+
this.bindings.forEach((binding) => this.delegate.bindingDisconnected(binding, true));
|
894
934
|
this.bindingsByAction.clear();
|
895
935
|
}
|
896
936
|
parseValueForToken(token) {
|
@@ -977,19 +1017,20 @@ class ValueObserver {
|
|
977
1017
|
changedMethod.call(this.receiver, value, oldValue);
|
978
1018
|
}
|
979
1019
|
catch (error) {
|
980
|
-
if (
|
981
|
-
|
982
|
-
|
1020
|
+
if (error instanceof TypeError) {
|
1021
|
+
error.message = `Stimulus Value "${this.context.identifier}.${descriptor.name}" - ${error.message}`;
|
1022
|
+
}
|
1023
|
+
throw error;
|
983
1024
|
}
|
984
1025
|
}
|
985
1026
|
}
|
986
1027
|
get valueDescriptors() {
|
987
1028
|
const { valueDescriptorMap } = this;
|
988
|
-
return Object.keys(valueDescriptorMap).map(key => valueDescriptorMap[key]);
|
1029
|
+
return Object.keys(valueDescriptorMap).map((key) => valueDescriptorMap[key]);
|
989
1030
|
}
|
990
1031
|
get valueDescriptorNameMap() {
|
991
1032
|
const descriptors = {};
|
992
|
-
Object.keys(this.valueDescriptorMap).forEach(key => {
|
1033
|
+
Object.keys(this.valueDescriptorMap).forEach((key) => {
|
993
1034
|
const descriptor = this.valueDescriptorMap[key];
|
994
1035
|
descriptors[descriptor.name] = descriptor;
|
995
1036
|
});
|
@@ -1006,7 +1047,7 @@ class TargetObserver {
|
|
1006
1047
|
constructor(context, delegate) {
|
1007
1048
|
this.context = context;
|
1008
1049
|
this.delegate = delegate;
|
1009
|
-
this.targetsByName = new Multimap;
|
1050
|
+
this.targetsByName = new Multimap();
|
1010
1051
|
}
|
1011
1052
|
start() {
|
1012
1053
|
if (!this.tokenListObserver) {
|
@@ -1146,9 +1187,9 @@ class Context {
|
|
1146
1187
|
function readInheritableStaticArrayValues(constructor, propertyName) {
|
1147
1188
|
const ancestors = getAncestorsForConstructor(constructor);
|
1148
1189
|
return Array.from(ancestors.reduce((values, constructor) => {
|
1149
|
-
getOwnStaticArrayValues(constructor, propertyName).forEach(name => values.add(name));
|
1190
|
+
getOwnStaticArrayValues(constructor, propertyName).forEach((name) => values.add(name));
|
1150
1191
|
return values;
|
1151
|
-
}, new Set));
|
1192
|
+
}, new Set()));
|
1152
1193
|
}
|
1153
1194
|
function readInheritableStaticObjectPairs(constructor, propertyName) {
|
1154
1195
|
const ancestors = getAncestorsForConstructor(constructor);
|
@@ -1171,7 +1212,7 @@ function getOwnStaticArrayValues(constructor, propertyName) {
|
|
1171
1212
|
}
|
1172
1213
|
function getOwnStaticObjectPairs(constructor, propertyName) {
|
1173
1214
|
const definition = constructor[propertyName];
|
1174
|
-
return definition ? Object.keys(definition).map(key => [key, definition[key]]) : [];
|
1215
|
+
return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : [];
|
1175
1216
|
}
|
1176
1217
|
|
1177
1218
|
function bless(constructor) {
|
@@ -1217,10 +1258,7 @@ function getShadowedDescriptor(prototype, properties, key) {
|
|
1217
1258
|
}
|
1218
1259
|
const getOwnKeys = (() => {
|
1219
1260
|
if (typeof Object.getOwnPropertySymbols == "function") {
|
1220
|
-
return (object) => [
|
1221
|
-
...Object.getOwnPropertyNames(object),
|
1222
|
-
...Object.getOwnPropertySymbols(object)
|
1223
|
-
];
|
1261
|
+
return (object) => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)];
|
1224
1262
|
}
|
1225
1263
|
else {
|
1226
1264
|
return Object.getOwnPropertyNames;
|
@@ -1232,16 +1270,18 @@ const extend = (() => {
|
|
1232
1270
|
return Reflect.construct(constructor, arguments, new.target);
|
1233
1271
|
}
|
1234
1272
|
extended.prototype = Object.create(constructor.prototype, {
|
1235
|
-
constructor: { value: extended }
|
1273
|
+
constructor: { value: extended },
|
1236
1274
|
});
|
1237
1275
|
Reflect.setPrototypeOf(extended, constructor);
|
1238
1276
|
return extended;
|
1239
1277
|
}
|
1240
1278
|
function testReflectExtension() {
|
1241
|
-
const a = function () {
|
1279
|
+
const a = function () {
|
1280
|
+
this.a.call(this);
|
1281
|
+
};
|
1242
1282
|
const b = extendWithReflect(a);
|
1243
1283
|
b.prototype.a = function () { };
|
1244
|
-
return new b;
|
1284
|
+
return new b();
|
1245
1285
|
}
|
1246
1286
|
try {
|
1247
1287
|
testReflectExtension();
|
@@ -1256,7 +1296,7 @@ const extend = (() => {
|
|
1256
1296
|
function blessDefinition(definition) {
|
1257
1297
|
return {
|
1258
1298
|
identifier: definition.identifier,
|
1259
|
-
controllerConstructor: bless(definition.controllerConstructor)
|
1299
|
+
controllerConstructor: bless(definition.controllerConstructor),
|
1260
1300
|
};
|
1261
1301
|
}
|
1262
1302
|
|
@@ -1264,8 +1304,8 @@ class Module {
|
|
1264
1304
|
constructor(application, definition) {
|
1265
1305
|
this.application = application;
|
1266
1306
|
this.definition = blessDefinition(definition);
|
1267
|
-
this.contextsByScope = new WeakMap;
|
1268
|
-
this.connectedContexts = new Set;
|
1307
|
+
this.contextsByScope = new WeakMap();
|
1308
|
+
this.connectedContexts = new Set();
|
1269
1309
|
}
|
1270
1310
|
get identifier() {
|
1271
1311
|
return this.definition.identifier;
|
@@ -1363,13 +1403,13 @@ class DataMap {
|
|
1363
1403
|
|
1364
1404
|
class Guide {
|
1365
1405
|
constructor(logger) {
|
1366
|
-
this.warnedKeysByObject = new WeakMap;
|
1406
|
+
this.warnedKeysByObject = new WeakMap();
|
1367
1407
|
this.logger = logger;
|
1368
1408
|
}
|
1369
1409
|
warn(object, key, message) {
|
1370
1410
|
let warnedKeys = this.warnedKeysByObject.get(object);
|
1371
1411
|
if (!warnedKeys) {
|
1372
|
-
warnedKeys = new Set;
|
1412
|
+
warnedKeys = new Set();
|
1373
1413
|
this.warnedKeysByObject.set(object, warnedKeys);
|
1374
1414
|
}
|
1375
1415
|
if (!warnedKeys.has(key)) {
|
@@ -1400,15 +1440,13 @@ class TargetSet {
|
|
1400
1440
|
return this.find(targetName) != null;
|
1401
1441
|
}
|
1402
1442
|
find(...targetNames) {
|
1403
|
-
return targetNames.reduce((target, targetName) => target
|
1404
|
-
|| this.findTarget(targetName)
|
1405
|
-
|| this.findLegacyTarget(targetName), undefined);
|
1443
|
+
return targetNames.reduce((target, targetName) => target || this.findTarget(targetName) || this.findLegacyTarget(targetName), undefined);
|
1406
1444
|
}
|
1407
1445
|
findAll(...targetNames) {
|
1408
1446
|
return targetNames.reduce((targets, targetName) => [
|
1409
1447
|
...targets,
|
1410
1448
|
...this.findAllTargets(targetName),
|
1411
|
-
...this.findAllLegacyTargets(targetName)
|
1449
|
+
...this.findAllLegacyTargets(targetName),
|
1412
1450
|
], []);
|
1413
1451
|
}
|
1414
1452
|
findTarget(targetName) {
|
@@ -1429,7 +1467,7 @@ class TargetSet {
|
|
1429
1467
|
}
|
1430
1468
|
findAllLegacyTargets(targetName) {
|
1431
1469
|
const selector = this.getLegacySelectorForTargetName(targetName);
|
1432
|
-
return this.scope.findAllElements(selector).map(element => this.deprecate(element, targetName));
|
1470
|
+
return this.scope.findAllElements(selector).map((element) => this.deprecate(element, targetName));
|
1433
1471
|
}
|
1434
1472
|
getLegacySelectorForTargetName(targetName) {
|
1435
1473
|
const targetDescriptor = `${this.identifier}.${targetName}`;
|
@@ -1464,14 +1502,12 @@ class Scope {
|
|
1464
1502
|
this.guide = new Guide(logger);
|
1465
1503
|
}
|
1466
1504
|
findElement(selector) {
|
1467
|
-
return this.element.matches(selector)
|
1468
|
-
? this.element
|
1469
|
-
: this.queryElements(selector).find(this.containsElement);
|
1505
|
+
return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement);
|
1470
1506
|
}
|
1471
1507
|
findAllElements(selector) {
|
1472
1508
|
return [
|
1473
|
-
...this.element.matches(selector) ? [this.element] : [],
|
1474
|
-
...this.queryElements(selector).filter(this.containsElement)
|
1509
|
+
...(this.element.matches(selector) ? [this.element] : []),
|
1510
|
+
...this.queryElements(selector).filter(this.containsElement),
|
1475
1511
|
];
|
1476
1512
|
}
|
1477
1513
|
queryElements(selector) {
|
@@ -1488,8 +1524,8 @@ class ScopeObserver {
|
|
1488
1524
|
this.schema = schema;
|
1489
1525
|
this.delegate = delegate;
|
1490
1526
|
this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this);
|
1491
|
-
this.scopesByIdentifierByElement = new WeakMap;
|
1492
|
-
this.scopeReferenceCounts = new WeakMap;
|
1527
|
+
this.scopesByIdentifierByElement = new WeakMap();
|
1528
|
+
this.scopeReferenceCounts = new WeakMap();
|
1493
1529
|
}
|
1494
1530
|
start() {
|
1495
1531
|
this.valueListObserver.start();
|
@@ -1529,7 +1565,7 @@ class ScopeObserver {
|
|
1529
1565
|
fetchScopesByIdentifierForElement(element) {
|
1530
1566
|
let scopesByIdentifier = this.scopesByIdentifierByElement.get(element);
|
1531
1567
|
if (!scopesByIdentifier) {
|
1532
|
-
scopesByIdentifier = new Map;
|
1568
|
+
scopesByIdentifier = new Map();
|
1533
1569
|
this.scopesByIdentifierByElement.set(element, scopesByIdentifier);
|
1534
1570
|
}
|
1535
1571
|
return scopesByIdentifier;
|
@@ -1540,8 +1576,8 @@ class Router {
|
|
1540
1576
|
constructor(application) {
|
1541
1577
|
this.application = application;
|
1542
1578
|
this.scopeObserver = new ScopeObserver(this.element, this.schema, this);
|
1543
|
-
this.scopesByIdentifier = new Multimap;
|
1544
|
-
this.modulesByIdentifier = new Map;
|
1579
|
+
this.scopesByIdentifier = new Multimap();
|
1580
|
+
this.modulesByIdentifier = new Map();
|
1545
1581
|
}
|
1546
1582
|
get element() {
|
1547
1583
|
return this.application.element;
|
@@ -1581,7 +1617,7 @@ class Router {
|
|
1581
1617
|
getContextForElementAndIdentifier(element, identifier) {
|
1582
1618
|
const module = this.modulesByIdentifier.get(identifier);
|
1583
1619
|
if (module) {
|
1584
|
-
return module.contexts.find(context => context.element == element);
|
1620
|
+
return module.contexts.find((context) => context.element == element);
|
1585
1621
|
}
|
1586
1622
|
}
|
1587
1623
|
handleError(error, message, detail) {
|
@@ -1607,12 +1643,12 @@ class Router {
|
|
1607
1643
|
connectModule(module) {
|
1608
1644
|
this.modulesByIdentifier.set(module.identifier, module);
|
1609
1645
|
const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier);
|
1610
|
-
scopes.forEach(scope => module.connectContextForScope(scope));
|
1646
|
+
scopes.forEach((scope) => module.connectContextForScope(scope));
|
1611
1647
|
}
|
1612
1648
|
disconnectModule(module) {
|
1613
1649
|
this.modulesByIdentifier.delete(module.identifier);
|
1614
1650
|
const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier);
|
1615
|
-
scopes.forEach(scope => module.disconnectContextForScope(scope));
|
1651
|
+
scopes.forEach((scope) => module.disconnectContextForScope(scope));
|
1616
1652
|
}
|
1617
1653
|
}
|
1618
1654
|
|
@@ -1620,7 +1656,7 @@ const defaultSchema = {
|
|
1620
1656
|
controllerAttribute: "data-controller",
|
1621
1657
|
actionAttribute: "data-action",
|
1622
1658
|
targetAttribute: "data-target",
|
1623
|
-
targetAttributeForScope: identifier => `data-${identifier}-target
|
1659
|
+
targetAttributeForScope: (identifier) => `data-${identifier}-target`,
|
1624
1660
|
};
|
1625
1661
|
|
1626
1662
|
class Application {
|
@@ -1636,6 +1672,7 @@ class Application {
|
|
1636
1672
|
this.schema = schema;
|
1637
1673
|
this.dispatcher = new Dispatcher(this);
|
1638
1674
|
this.router = new Router(this);
|
1675
|
+
this.actionDescriptorFilters = Object.assign({}, defaultActionDescriptorFilters);
|
1639
1676
|
}
|
1640
1677
|
static start(element, schema) {
|
1641
1678
|
const application = new Application(element, schema);
|
@@ -1658,9 +1695,12 @@ class Application {
|
|
1658
1695
|
register(identifier, controllerConstructor) {
|
1659
1696
|
this.load({ identifier, controllerConstructor });
|
1660
1697
|
}
|
1698
|
+
registerActionOption(name, filter) {
|
1699
|
+
this.actionDescriptorFilters[name] = filter;
|
1700
|
+
}
|
1661
1701
|
load(head, ...rest) {
|
1662
1702
|
const definitions = Array.isArray(head) ? head : [head, ...rest];
|
1663
|
-
definitions.forEach(definition => {
|
1703
|
+
definitions.forEach((definition) => {
|
1664
1704
|
if (definition.controllerConstructor.shouldLoad) {
|
1665
1705
|
this.router.loadDefinition(definition);
|
1666
1706
|
}
|
@@ -1668,10 +1708,10 @@ class Application {
|
|
1668
1708
|
}
|
1669
1709
|
unload(head, ...rest) {
|
1670
1710
|
const identifiers = Array.isArray(head) ? head : [head, ...rest];
|
1671
|
-
identifiers.forEach(identifier => this.router.unloadIdentifier(identifier));
|
1711
|
+
identifiers.forEach((identifier) => this.router.unloadIdentifier(identifier));
|
1672
1712
|
}
|
1673
1713
|
get controllers() {
|
1674
|
-
return this.router.contexts.map(context => context.controller);
|
1714
|
+
return this.router.contexts.map((context) => context.controller);
|
1675
1715
|
}
|
1676
1716
|
getControllerForElementAndIdentifier(element, identifier) {
|
1677
1717
|
const context = this.router.getContextForElementAndIdentifier(element, identifier);
|
@@ -1690,7 +1730,7 @@ class Application {
|
|
1690
1730
|
}
|
1691
1731
|
}
|
1692
1732
|
function domReady() {
|
1693
|
-
return new Promise(resolve => {
|
1733
|
+
return new Promise((resolve) => {
|
1694
1734
|
if (document.readyState == "loading") {
|
1695
1735
|
document.addEventListener("DOMContentLoaded", () => resolve());
|
1696
1736
|
}
|
@@ -1718,18 +1758,18 @@ function propertiesForClassDefinition(key) {
|
|
1718
1758
|
const attribute = classes.getAttributeName(key);
|
1719
1759
|
throw new Error(`Missing attribute "${attribute}"`);
|
1720
1760
|
}
|
1721
|
-
}
|
1761
|
+
},
|
1722
1762
|
},
|
1723
1763
|
[`${key}Classes`]: {
|
1724
1764
|
get() {
|
1725
1765
|
return this.classes.getAll(key);
|
1726
|
-
}
|
1766
|
+
},
|
1727
1767
|
},
|
1728
1768
|
[`has${capitalize(key)}Class`]: {
|
1729
1769
|
get() {
|
1730
1770
|
return this.classes.has(key);
|
1731
|
-
}
|
1732
|
-
}
|
1771
|
+
},
|
1772
|
+
},
|
1733
1773
|
};
|
1734
1774
|
}
|
1735
1775
|
|
@@ -1750,18 +1790,18 @@ function propertiesForTargetDefinition(name) {
|
|
1750
1790
|
else {
|
1751
1791
|
throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`);
|
1752
1792
|
}
|
1753
|
-
}
|
1793
|
+
},
|
1754
1794
|
},
|
1755
1795
|
[`${name}Targets`]: {
|
1756
1796
|
get() {
|
1757
1797
|
return this.targets.findAll(name);
|
1758
|
-
}
|
1798
|
+
},
|
1759
1799
|
},
|
1760
1800
|
[`has${capitalize(name)}Target`]: {
|
1761
1801
|
get() {
|
1762
1802
|
return this.targets.has(name);
|
1763
|
-
}
|
1764
|
-
}
|
1803
|
+
},
|
1804
|
+
},
|
1765
1805
|
};
|
1766
1806
|
}
|
1767
1807
|
|
@@ -1775,8 +1815,8 @@ function ValuePropertiesBlessing(constructor) {
|
|
1775
1815
|
const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key);
|
1776
1816
|
return Object.assign(result, { [attributeName]: valueDescriptor });
|
1777
1817
|
}, {});
|
1778
|
-
}
|
1779
|
-
}
|
1818
|
+
},
|
1819
|
+
},
|
1780
1820
|
};
|
1781
1821
|
return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => {
|
1782
1822
|
return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair));
|
@@ -1803,13 +1843,13 @@ function propertiesForValueDefinitionPair(valueDefinitionPair, controller) {
|
|
1803
1843
|
else {
|
1804
1844
|
this.data.set(key, write(value));
|
1805
1845
|
}
|
1806
|
-
}
|
1846
|
+
},
|
1807
1847
|
},
|
1808
1848
|
[`has${capitalize(name)}`]: {
|
1809
1849
|
get() {
|
1810
1850
|
return this.data.has(key) || definition.hasCustomDefaultValue;
|
1811
|
-
}
|
1812
|
-
}
|
1851
|
+
},
|
1852
|
+
},
|
1813
1853
|
};
|
1814
1854
|
}
|
1815
1855
|
function parseValueDefinitionPair([token, typeDefinition], controller) {
|
@@ -1821,18 +1861,26 @@ function parseValueDefinitionPair([token, typeDefinition], controller) {
|
|
1821
1861
|
}
|
1822
1862
|
function parseValueTypeConstant(constant) {
|
1823
1863
|
switch (constant) {
|
1824
|
-
case Array:
|
1825
|
-
|
1826
|
-
case
|
1827
|
-
|
1828
|
-
case
|
1864
|
+
case Array:
|
1865
|
+
return "array";
|
1866
|
+
case Boolean:
|
1867
|
+
return "boolean";
|
1868
|
+
case Number:
|
1869
|
+
return "number";
|
1870
|
+
case Object:
|
1871
|
+
return "object";
|
1872
|
+
case String:
|
1873
|
+
return "string";
|
1829
1874
|
}
|
1830
1875
|
}
|
1831
1876
|
function parseValueTypeDefault(defaultValue) {
|
1832
1877
|
switch (typeof defaultValue) {
|
1833
|
-
case "boolean":
|
1834
|
-
|
1835
|
-
case "
|
1878
|
+
case "boolean":
|
1879
|
+
return "boolean";
|
1880
|
+
case "number":
|
1881
|
+
return "number";
|
1882
|
+
case "string":
|
1883
|
+
return "string";
|
1836
1884
|
}
|
1837
1885
|
if (Array.isArray(defaultValue))
|
1838
1886
|
return "array";
|
@@ -1854,7 +1902,7 @@ function parseValueTypeDefinition(payload) {
|
|
1854
1902
|
const typeFromObject = parseValueTypeObject({
|
1855
1903
|
controller: payload.controller,
|
1856
1904
|
token: payload.token,
|
1857
|
-
typeObject: payload.typeDefinition
|
1905
|
+
typeObject: payload.typeDefinition,
|
1858
1906
|
});
|
1859
1907
|
const typeFromDefaultValue = parseValueTypeDefault(payload.typeDefinition);
|
1860
1908
|
const typeFromConstant = parseValueTypeConstant(payload.typeDefinition);
|
@@ -1880,18 +1928,26 @@ function valueDescriptorForTokenAndTypeDefinition(payload) {
|
|
1880
1928
|
type,
|
1881
1929
|
key,
|
1882
1930
|
name: camelize(key),
|
1883
|
-
get defaultValue() {
|
1884
|
-
|
1931
|
+
get defaultValue() {
|
1932
|
+
return defaultValueForDefinition(payload.typeDefinition);
|
1933
|
+
},
|
1934
|
+
get hasCustomDefaultValue() {
|
1935
|
+
return parseValueTypeDefault(payload.typeDefinition) !== undefined;
|
1936
|
+
},
|
1885
1937
|
reader: readers[type],
|
1886
|
-
writer: writers[type] || writers.default
|
1938
|
+
writer: writers[type] || writers.default,
|
1887
1939
|
};
|
1888
1940
|
}
|
1889
1941
|
const defaultValuesByType = {
|
1890
|
-
get array() {
|
1942
|
+
get array() {
|
1943
|
+
return [];
|
1944
|
+
},
|
1891
1945
|
boolean: false,
|
1892
1946
|
number: 0,
|
1893
|
-
get object() {
|
1894
|
-
|
1947
|
+
get object() {
|
1948
|
+
return {};
|
1949
|
+
},
|
1950
|
+
string: "",
|
1895
1951
|
};
|
1896
1952
|
const readers = {
|
1897
1953
|
array(value) {
|
@@ -1916,12 +1972,12 @@ const readers = {
|
|
1916
1972
|
},
|
1917
1973
|
string(value) {
|
1918
1974
|
return value;
|
1919
|
-
}
|
1975
|
+
},
|
1920
1976
|
};
|
1921
1977
|
const writers = {
|
1922
1978
|
default: writeString,
|
1923
1979
|
array: writeJSON,
|
1924
|
-
object: writeJSON
|
1980
|
+
object: writeJSON,
|
1925
1981
|
};
|
1926
1982
|
function writeJSON(value) {
|
1927
1983
|
return JSON.stringify(value);
|