comparison core/misc/states.js @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children a9cd425dd02b
comparison
equal deleted inserted replaced
-1:000000000000 0:c75dbcec494b
1 /**
2 * DO NOT EDIT THIS FILE.
3 * See the following change record for more information,
4 * https://www.drupal.org/node/2815083
5 * @preserve
6 **/
7
8 (function ($, Drupal) {
9 var states = {
10 postponed: []
11 };
12
13 Drupal.states = states;
14
15 Drupal.behaviors.states = {
16 attach: function attach(context, settings) {
17 var $states = $(context).find('[data-drupal-states]');
18 var il = $states.length;
19
20 var _loop = function _loop(i) {
21 var config = JSON.parse($states[i].getAttribute('data-drupal-states'));
22 Object.keys(config || {}).forEach(function (state) {
23 new states.Dependent({
24 element: $($states[i]),
25 state: states.State.sanitize(state),
26 constraints: config[state]
27 });
28 });
29 };
30
31 for (var i = 0; i < il; i++) {
32 _loop(i);
33 }
34
35 while (states.postponed.length) {
36 states.postponed.shift()();
37 }
38 }
39 };
40
41 states.Dependent = function (args) {
42 var _this = this;
43
44 $.extend(this, { values: {}, oldValue: null }, args);
45
46 this.dependees = this.getDependees();
47 Object.keys(this.dependees || {}).forEach(function (selector) {
48 _this.initializeDependee(selector, _this.dependees[selector]);
49 });
50 };
51
52 states.Dependent.comparisons = {
53 RegExp: function RegExp(reference, value) {
54 return reference.test(value);
55 },
56 Function: function Function(reference, value) {
57 return reference(value);
58 },
59 Number: function Number(reference, value) {
60 return typeof value === 'string' ? _compare2(reference.toString(), value) : _compare2(reference, value);
61 }
62 };
63
64 states.Dependent.prototype = {
65 initializeDependee: function initializeDependee(selector, dependeeStates) {
66 var state = void 0;
67 var self = this;
68
69 function stateEventHandler(e) {
70 self.update(e.data.selector, e.data.state, e.value);
71 }
72
73 this.values[selector] = {};
74
75 for (var i in dependeeStates) {
76 if (dependeeStates.hasOwnProperty(i)) {
77 state = dependeeStates[i];
78
79 if ($.inArray(state, dependeeStates) === -1) {
80 continue;
81 }
82
83 state = states.State.sanitize(state);
84
85 this.values[selector][state.name] = null;
86
87 $(selector).on('state:' + state, { selector: selector, state: state }, stateEventHandler);
88
89 new states.Trigger({ selector: selector, state: state });
90 }
91 }
92 },
93 compare: function compare(reference, selector, state) {
94 var value = this.values[selector][state.name];
95 if (reference.constructor.name in states.Dependent.comparisons) {
96 return states.Dependent.comparisons[reference.constructor.name](reference, value);
97 }
98
99 return _compare2(reference, value);
100 },
101 update: function update(selector, state, value) {
102 if (value !== this.values[selector][state.name]) {
103 this.values[selector][state.name] = value;
104 this.reevaluate();
105 }
106 },
107 reevaluate: function reevaluate() {
108 var value = this.verifyConstraints(this.constraints);
109
110 if (value !== this.oldValue) {
111 this.oldValue = value;
112
113 value = invert(value, this.state.invert);
114
115 this.element.trigger({ type: 'state:' + this.state, value: value, trigger: true });
116 }
117 },
118 verifyConstraints: function verifyConstraints(constraints, selector) {
119 var result = void 0;
120 if ($.isArray(constraints)) {
121 var hasXor = $.inArray('xor', constraints) === -1;
122 var len = constraints.length;
123 for (var i = 0; i < len; i++) {
124 if (constraints[i] !== 'xor') {
125 var constraint = this.checkConstraints(constraints[i], selector, i);
126
127 if (constraint && (hasXor || result)) {
128 return hasXor;
129 }
130 result = result || constraint;
131 }
132 }
133 } else if ($.isPlainObject(constraints)) {
134 for (var n in constraints) {
135 if (constraints.hasOwnProperty(n)) {
136 result = ternary(result, this.checkConstraints(constraints[n], selector, n));
137
138 if (result === false) {
139 return false;
140 }
141 }
142 }
143 }
144 return result;
145 },
146 checkConstraints: function checkConstraints(value, selector, state) {
147 if (typeof state !== 'string' || /[0-9]/.test(state[0])) {
148 state = null;
149 } else if (typeof selector === 'undefined') {
150 selector = state;
151 state = null;
152 }
153
154 if (state !== null) {
155 state = states.State.sanitize(state);
156 return invert(this.compare(value, selector, state), state.invert);
157 }
158
159 return this.verifyConstraints(value, selector);
160 },
161 getDependees: function getDependees() {
162 var cache = {};
163
164 var _compare = this.compare;
165 this.compare = function (reference, selector, state) {
166 (cache[selector] || (cache[selector] = [])).push(state.name);
167 };
168
169 this.verifyConstraints(this.constraints);
170
171 this.compare = _compare;
172
173 return cache;
174 }
175 };
176
177 states.Trigger = function (args) {
178 $.extend(this, args);
179
180 if (this.state in states.Trigger.states) {
181 this.element = $(this.selector);
182
183 if (!this.element.data('trigger:' + this.state)) {
184 this.initialize();
185 }
186 }
187 };
188
189 states.Trigger.prototype = {
190 initialize: function initialize() {
191 var _this2 = this;
192
193 var trigger = states.Trigger.states[this.state];
194
195 if (typeof trigger === 'function') {
196 trigger.call(window, this.element);
197 } else {
198 Object.keys(trigger || {}).forEach(function (event) {
199 _this2.defaultTrigger(event, trigger[event]);
200 });
201 }
202
203 this.element.data('trigger:' + this.state, true);
204 },
205 defaultTrigger: function defaultTrigger(event, valueFn) {
206 var oldValue = valueFn.call(this.element);
207
208 this.element.on(event, $.proxy(function (e) {
209 var value = valueFn.call(this.element, e);
210
211 if (oldValue !== value) {
212 this.element.trigger({ type: 'state:' + this.state, value: value, oldValue: oldValue });
213 oldValue = value;
214 }
215 }, this));
216
217 states.postponed.push($.proxy(function () {
218 this.element.trigger({ type: 'state:' + this.state, value: oldValue, oldValue: null });
219 }, this));
220 }
221 };
222
223 states.Trigger.states = {
224 empty: {
225 keyup: function keyup() {
226 return this.val() === '';
227 }
228 },
229
230 checked: {
231 change: function change() {
232 var checked = false;
233 this.each(function () {
234 checked = $(this).prop('checked');
235
236 return !checked;
237 });
238 return checked;
239 }
240 },
241
242 value: {
243 keyup: function keyup() {
244 if (this.length > 1) {
245 return this.filter(':checked').val() || false;
246 }
247 return this.val();
248 },
249 change: function change() {
250 if (this.length > 1) {
251 return this.filter(':checked').val() || false;
252 }
253 return this.val();
254 }
255 },
256
257 collapsed: {
258 collapsed: function collapsed(e) {
259 return typeof e !== 'undefined' && 'value' in e ? e.value : !this.is('[open]');
260 }
261 }
262 };
263
264 states.State = function (state) {
265 this.pristine = state;
266 this.name = state;
267
268 var process = true;
269 do {
270 while (this.name.charAt(0) === '!') {
271 this.name = this.name.substring(1);
272 this.invert = !this.invert;
273 }
274
275 if (this.name in states.State.aliases) {
276 this.name = states.State.aliases[this.name];
277 } else {
278 process = false;
279 }
280 } while (process);
281 };
282
283 states.State.sanitize = function (state) {
284 if (state instanceof states.State) {
285 return state;
286 }
287
288 return new states.State(state);
289 };
290
291 states.State.aliases = {
292 enabled: '!disabled',
293 invisible: '!visible',
294 invalid: '!valid',
295 untouched: '!touched',
296 optional: '!required',
297 filled: '!empty',
298 unchecked: '!checked',
299 irrelevant: '!relevant',
300 expanded: '!collapsed',
301 open: '!collapsed',
302 closed: 'collapsed',
303 readwrite: '!readonly'
304 };
305
306 states.State.prototype = {
307 invert: false,
308
309 toString: function toString() {
310 return this.name;
311 }
312 };
313
314 var $document = $(document);
315 $document.on('state:disabled', function (e) {
316 if (e.trigger) {
317 $(e.target).prop('disabled', e.value).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value).find('select, input, textarea').prop('disabled', e.value);
318 }
319 });
320
321 $document.on('state:required', function (e) {
322 if (e.trigger) {
323 if (e.value) {
324 var label = 'label' + (e.target.id ? '[for=' + e.target.id + ']' : '');
325 var $label = $(e.target).attr({ required: 'required', 'aria-required': 'aria-required' }).closest('.js-form-item, .js-form-wrapper').find(label);
326
327 if (!$label.hasClass('js-form-required').length) {
328 $label.addClass('js-form-required form-required');
329 }
330 } else {
331 $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required');
332 }
333 }
334 });
335
336 $document.on('state:visible', function (e) {
337 if (e.trigger) {
338 $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggle(e.value);
339 }
340 });
341
342 $document.on('state:checked', function (e) {
343 if (e.trigger) {
344 $(e.target).prop('checked', e.value);
345 }
346 });
347
348 $document.on('state:collapsed', function (e) {
349 if (e.trigger) {
350 if ($(e.target).is('[open]') === e.value) {
351 $(e.target).find('> summary').trigger('click');
352 }
353 }
354 });
355
356 function ternary(a, b) {
357 if (typeof a === 'undefined') {
358 return b;
359 } else if (typeof b === 'undefined') {
360 return a;
361 }
362
363 return a && b;
364 }
365
366 function invert(a, invertState) {
367 return invertState && typeof a !== 'undefined' ? !a : a;
368 }
369
370 function _compare2(a, b) {
371 if (a === b) {
372 return typeof a === 'undefined' ? a : true;
373 }
374
375 return typeof a === 'undefined' || typeof b === 'undefined';
376 }
377 })(jQuery, Drupal);