PageSourceSearch

https://www.mvec.coop/sites/default/files/js/js_mlmBs4mY26bizt6zMHP21z_nDK06miFiYARC5LrHH74.js

js mvec.coop collected 2026-09-30 08:29:08 UTC 131,153 bytes, 3,784 lines download raw bytes

1/**
2 * @file
3 * Drupal Bootstrap object.
4 */
5
6/**
7 * All Drupal Bootstrap JavaScript APIs are contained in this namespace.
8 *
9 * @param {underscore} _
10 * @param {jQuery} $
11 * @param {Drupal} Drupal
12 * @param {drupalSettings} drupalSettings
13 */
14(function (_, $, Drupal, drupalSettings) {
15  'use strict';
16
17  /**
18   * @typedef Drupal.bootstrap
19   */
20  var Bootstrap = {
21    processedOnce: {},
22    settings: drupalSettings.bootstrap || {}
23  };
24
25  /**
26   * Wraps Drupal.checkPlain() to ensure value passed isn't empty.
27   *
28   * Encodes special characters in a plain-text string for display as HTML.
29   *
30   * @param {string} str
31   *   The string to be encoded.
32   *
33   * @return {string}
34   *   The encoded string.
35   *
36   * @ingroup sanitization
37   */
38  Bootstrap.checkPlain = function (str) {
39    return str && Drupal.checkPlain(str) || '';
40  };
41
42  /**
43   * Creates a jQuery plugin.
44   *
45   * @param {String} id
46   *   A jQuery plugin identifier located in $.fn.
47   * @param {Function} plugin
48   *   A constructor function used to initialize the for the jQuery plugin.
49   * @param {Boolean} [noConflict]
50   *   Flag indicating whether or not to create a ".noConflict()" helper method
51   *   for the plugin.
52   */
53  Bootstrap.createPlugin = function (id, plugin, noConflict) {
54    // Immediately return if plugin doesn't exist.
55    if ($.fn[id] !== void 0) {
56      return this.fatal('Specified jQuery plugin identifier already exists: @id. Use Drupal.bootstrap.replacePlugin() instead.', {'@id': id});
57    }
58
59    // Immediately return if plugin isn't a function.
60    if (typeof plugin !== 'function') {
61      return this.fatal('You must provide a constructor function to create a jQuery plugin "@id": @plugin', {'@id': id, '@plugin':  plugin});
62    }
63
64    // Add a ".noConflict()" helper method.
65    this.pluginNoConflict(id, plugin, noConflict);
66
67    $.fn[id] = plugin;
68  };
69
70  /**
71   * Diff object properties.
72   *
73   * @param {...Object} objects
74   *   Two or more objects. The first object will be used to return properties
75   *   values.
76   *
77   * @return {Object}
78   *   Returns the properties of the first passed object that are not present
79   *   in all other passed objects.
80   */
81  Bootstrap.diffObjects = function (objects) {
82    var args = Array.prototype.slice.call(arguments);
83    return _.pick(args[0], _.difference.apply(_, _.map(args, function (obj) {
84      return Object.keys(obj);
85    })));
86  };
87
88  /**
89   * Map of supported events by regular expression.
90   *
91   * @type {Object<Event|MouseEvent|KeyboardEvent|TouchEvent,RegExp>}
92   */
93  Bootstrap.eventMap = {
94    Event: /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
95    MouseEvent: /^(?:click|dblclick|mouse(?:down|enter|leave|up|over|move|out))$/,
96    KeyboardEvent: /^(?:key(?:down|press|up))$/,
97    TouchEvent: /^(?:touch(?:start|end|move|cancel))$/
98  };
99
100  /**
101   * Extends a jQuery Plugin.
102   *
103   * @param {String} id
104   *   A jQuery plugin identifier located in $.fn.
105   * @param {Function} callback
106   *   A constructor function used to initialize the for the jQuery plugin.
107   *
108   * @return {Function|Boolean}
109   *   The jQuery plugin constructor or FALSE if the plugin does not exist.
110   */
111  Bootstrap.extendPlugin = function (id, callback) {
112    // Immediately return if plugin doesn't exist.
113    if (typeof $.fn[id] !== 'function') {
114      return this.fatal('Specified jQuery plugin identifier does not exist: @id', {'@id':  id});
115    }
116
117    // Immediately return if callback isn't a function.
118    if (typeof callback !== 'function') {
119      return this.fatal('You must provide a callback function to extend the jQuery plugin "@id": @callback', {'@id': id, '@callback':  callback});
120    }
121
122    // Determine existing plugin constructor.
123    var constructor = $.fn[id] && $.fn[id].Constructor || $.fn[id];
124    var plugin = callback.apply(constructor, [this.settings]);
125    if (!$.isPlainObject(plugin)) {
126      return this.fatal('Returned value from callback is not a plain object that can be used to extend the jQuery plugin "@id": @obj', {'@obj':  plugin});
127    }
128
129    this.wrapPluginConstructor(constructor, plugin, true);
130
131    return $.fn[id];
132  };
133
134  Bootstrap.superWrapper = function (parent, fn) {
135    return function () {
136      var previousSuper = this.super;
137      this.super = parent;
138      var ret = fn.apply(this, arguments);
139      if (previousSuper) {
140        this.super = previousSuper;
141      }
142      else {
143        delete this.super;
144      }
145      return ret;
146    };
147  };
148
149  /**
150   * Provide a helper method for displaying when something is went wrong.
151   *
152   * @param {String} message
153   *   The message to display.
154   * @param {Object} [args]
155   *   An arguments to use in message.
156   *
157   * @return {Boolean}
158   *   Always returns FALSE.
159   */
160  Bootstrap.fatal = function (message, args) {
161    if (this.settings.dev && console.warn) {
162      for (var name in args) {
163        if (args.hasOwnProperty(name) && typeof args[name] === 'object') {
164          args[name] = JSON.stringify(args[name]);
165        }
166      }
167      Drupal.throwError(new Error(Drupal.formatString(message, args)));
168    }
169    return false;
170  };
171
172  /**
173   * Intersects object properties.
174   *
175   * @param {...Object} objects
176   *   Two or more objects. The first object will be used to return properties
177   *   values.
178   *
179   * @return {Object}
180   *   Returns the properties of first passed object that intersects with all
181   *   other passed objects.
182   */
183  Bootstrap.intersectObjects = function (objects) {
184    var args = Array.prototype.slice.call(arguments);
185    return _.pick(args[0], _.intersection.apply(_, _.map(args, function (obj) {
186      return Object.keys(obj);
187    })));
188  };
189
190  /**
191   * Normalizes an object's values.
192   *
193   * @param {Object} obj
194   *   The object to normalize.
195   *
196   * @return {Object}
197   *   The normalized object.
198   */
199  Bootstrap.normalizeObject = function (obj) {
200    if (!$.isPlainObject(obj)) {
201      return obj;
202    }
203
204    for (var k in obj) {
205      if (typeof obj[k] === 'string') {
206        if (obj[k] === 'true') {
207          obj[k] = true;
208        }
209        else if (obj[k] === 'false') {
210          obj[k] = false;
211        }
212        else if (obj[k].match(/^[\d-.]$/)) {
213          obj[k] = parseFloat(obj[k]);
214        }
215      }
216      else if ($.isPlainObject(obj[k])) {
217        obj[k] = Bootstrap.normalizeObject(obj[k]);
218      }
219    }
220
221    return obj;
222  };
223
224  /**
225   * An object based once plugin (similar to jquery.once, but without the DOM).
226   *
227   * @param {String} id
228   *   A unique identifier.
229   * @param {Function} callback
230   *   The callback to invoke if the identifier has not yet been seen.
231   *
232   * @return {Bootstrap}
233   */
234  Bootstrap.once = function (id, callback) {
235    // Immediately return if identifier has already been processed.
236    if (this.processedOnce[id]) {
237      return this;
238    }
239    callback.call(this, this.settings);
240    this.processedOnce[id] = true;
241    return this;
242  };
243
244  /**
245   * Provide jQuery UI like ability to get/set options for Bootstrap plugins.
246   *
247   * @param {string|object} key
248   *   A string value of the option to set, can be dot like to a nested key.
249   *   An object of key/value pairs.
250   * @param {*} [value]
251   *   (optional) A value to set for key.
252   *
253   * @returns {*}
254   *   - Returns nothing if key is an object or both key and value parameters
255   *   were provided to set an option.
256   *   - Returns the a value for a specific setting if key was provided.
257   *   - Returns an object of key/value pairs of all the options if no key or
258   *   value parameter was provided.
259   *
260   * @see https://github.com/jquery/jquery-ui/blob/master/ui/widget.js
261   */
262  Bootstrap.option = function (key, value) {
263    var options = $.isPlainObject(key) ? $.extend({}, key) : {};
264
265    // Get all options (clone so it doesn't reference the internal object).
266    if (arguments.length === 0) {
267      return $.extend({}, this.options);
268    }
269
270    // Get/set single option.
271    if (typeof key === "string") {
272      // Handle nested keys in dot notation.
273      // e.g., "foo.bar" => { foo: { bar: true } }
274      var parts = key.split('.');
275      key = parts.shift();
276      var obj = options;
277      if (parts.length) {
278        for (var i = 0; i < parts.length - 1; i++) {
279          obj[parts[i]] = obj[parts[i]] || {};
280          obj = obj[parts[i]];
281        }
282        key = parts.pop();
283      }
284
285      // Get.
286      if (arguments.length === 1) {
287        return obj[key] === void 0 ? null : obj[key];
288      }
289
290      // Set.
291      obj[key] = value;
292    }
293
294    // Set multiple options.
295    $.extend(true, this.options, options);
296  };
297
298  /**
299   * Adds a ".noConflict()" helper method if needed.
300   *
301   * @param {String} id
302   *   A jQuery plugin identifier located in $.fn.
303   * @param {Function} plugin
304   * @param {Function} plugin
305   *   A constructor function used to initialize the for the jQuery plugin.
306   * @param {Boolean} [noConflict]
307   *   Flag indicating whether or not to create a ".noConflict()" helper method
308   *   for the plugin.
309   */
310  Bootstrap.pluginNoConflict = function (id, plugin, noConflict) {
311    if (plugin.noConflict === void 0 && (noConflict === void 0 || noConflict)) {
312      var old = $.fn[id];
313      plugin.noConflict = function () {
314        $.fn[id] = old;
315        return this;
316      };
317    }
318  };
319
320  /**
321   * Creates a handler that relays to another event name.
322   *
323   * @param {HTMLElement|jQuery} target
324   *   A target element.
325   * @param {String} name
326   *   The name of the event to trigger.
327   * @param {Boolean} [stopPropagation=true]
328   *   Flag indicating whether to stop the propagation of the event, defaults
329   *   to true.
330   *
331   * @return {Function}
332   *   An even handler callback function.
333   */
334  Bootstrap.relayEvent = function (target, name, stopPropagation) {
335    return function (e) {
336      if (stopPropagation === void 0 || stopPropagation) {
337        e.stopPropagation();
338      }
339      var $target = $(target);
340      var parts = name.split('.').filter(Boolean);
341      var type = parts.shift();
342      e.target = $target[0];
343      e.currentTarget = $target[0];
344      e.namespace = parts.join('.');
345      e.type = type;
346      $target.trigger(e);
347    };
348  };
349
350  /**
351   * Replaces a Bootstrap jQuery plugin definition.
352   *
353   * @param {String} id
354   *   A jQuery plugin identifier located in $.fn.
355   * @param {Function} callback
356   *   A callback function that is immediately invoked and must return a
357   *   function that will be used as the plugin constructor.
358   * @param {Boolean} [noConflict]
359   *   Flag indicating whether or not to create a ".noConflict()" helper method
360   *   for the plugin.
361   */
362  Bootstrap.replacePlugin = function (id, callback, noConflict) {
363    // Immediately return if plugin doesn't exist.
364    if (typeof $.fn[id] !== 'function') {
365      return this.fatal('Specified jQuery plugin identifier does not exist: @id', {'@id':  id});
366    }
367
368    // Immediately return if callback isn't a function.
369    if (typeof callback !== 'function') {
370      return this.fatal('You must provide a valid callback function to replace a jQuery plugin: @callback', {'@callback': callback});
371    }
372
373    // Determine existing plugin constructor.
374    var constructor = $.fn[id] && $.fn[id].Constructor || $.fn[id];
375    var plugin = callback.apply(constructor, [this.settings]);
376
377    // Immediately return if plugin isn't a function.
378    if (typeof plugin !== 'function') {
379      return this.fatal('Returned value from callback is not a usable function to replace a jQuery plugin "@id": @plugin', {'@id': id, '@plugin': plugin});
380    }
381
382    this.wrapPluginConstructor(constructor, plugin);
383
384    // Add a ".noConflict()" helper method.
385    this.pluginNoConflict(id, plugin, noConflict);
386
387    $.fn[id] = plugin;
388  };
389
390  /**
391   * Simulates a native event on an element in the browser.
392   *
393   * Note: This is a fairly complete modern implementation. If things aren't
394   * working quite the way you intend (in older browsers), you may wish to use
395   * the jQuery.simulate plugin. If it's available, this method will defer to
396   * that plugin.
397   *
398   * @see https://github.com/jquery/jquery-simulate
399   *
400   * @param {HTMLElement|jQuery} element
401   *   A DOM element to dispatch event on. Note: this may be a jQuery object,
402   *   however be aware that this will trigger the same event for each element
403   *   inside the jQuery collection; use with caution.
404   * @param {String|String[]} type
405   *   The type(s) of event to simulate.
406   * @param {Object} [options]
407   *   An object of options to pass to the event constructor. Typically, if
408   *   an event is being proxied, you should just pass the original event
409   *   object here. This allows, if the browser supports it, to be a truly
410   *   simulated event.
411   *
412   * @return {Boolean}
413   *   The return value is false if event is cancelable and at least one of the
414   *   event handlers which handled this event called Event.preventDefault().
415   *   Otherwise it returns true.
416   */
417  Bootstrap.simulate = function (element, type, options) {
418    // Handle jQuery object wrappers so it triggers on each element.
419    var ret = true;
420    if (element instanceof $) {
421      element.each(function () {
422        if (!Bootstrap.simulate(this, type, options)) {
423          ret = false;
424        }
425      });
426      return ret;
427    }
428
429    if (!(element instanceof HTMLElement)) {
430      this.fatal('Passed element must be an instance of HTMLElement, got "@type" instead.', {
431        '@type': typeof element,
432      });
433    }
434
435    // Defer to the jQuery.simulate plugin, if it's available.
436    if (typeof $.simulate === 'function') {
437      new $.simulate(element, type, options);
438      return true;
439    }
440
441    var event;
442    var ctor;
443    var types = [].concat(type);
444    for (var i = 0, l = types.length; i < l; i++) {
445      type = types[i];
446      for (var name in this.eventMap) {
447        if (this.eventMap[name].test(type)) {
448          ctor = name;
449          break;
450        }
451      }
452      if (!ctor) {
453        throw new SyntaxError('Only rudimentary HTMLEvents, KeyboardEvents and MouseEvents are supported: ' + type);
454      }
455      var opts = {bubbles: true, cancelable: true};
456      if (ctor === 'KeyboardEvent' || ctor === 'MouseEvent') {
457        $.extend(opts, {ctrlKey: !1, altKey: !1, shiftKey: !1, metaKey: !1});
458      }
459      if (ctor === 'MouseEvent') {
460        $.extend(opts, {button: 0, pointerX: 0, pointerY: 0, view: window});
461      }
462      if (options) {
463        $.extend(opts, options);
464      }
465      if (typeof window[ctor] === 'function') {
466        event = new window[ctor](type, opts);
467        if (!element.dispatchEvent(event)) {
468          ret = false;
469        }
470      }
471      else if (document.createEvent) {
472        event = document.createEvent(ctor);
473        event.initEvent(type, opts.bubbles, opts.cancelable);
474        if (!element.dispatchEvent(event)) {
475          ret = false;
476        }
477      }
478      else if (typeof element.fireEvent === 'function') {
479        event = $.extend(document.createEventObject(), opts);
480        if (!element.fireEvent('on' + type, event)) {
481          ret = false;
482        }
483      }
484      else if (typeof element[type]) {
485        element[type]();
486      }
487    }
488    return ret;
489  };
490
491  /**
492   * Strips HTML and returns just text.
493   *
494   * @param {String|Element|jQuery} html
495   *   A string of HTML content, an Element DOM object or a jQuery object.
496   *
497   * @return {String}
498   *   The text without HTML tags.
499   *
500   * @todo Replace with http://locutus.io/php/strings/strip_tags/
501   */
502  Bootstrap.stripHtml = function (html) {
503    if (html instanceof $) {
504      html = html.html();
505    }
506    else if (html instanceof Element) {
507      html = html.innerHTML;
508    }
509    var tmp = document.createElement('DIV');
510    tmp.innerHTML = html;
511    return (tmp.textContent || tmp.innerText || '').replace(/^[\s\n\t]*|[\s\n\t]*$/, '');
512  };
513
514  /**
515   * Provide a helper method for displaying when something is unsupported.
516   *
517   * @param {String} type
518   *   The type of unsupported object, e.g. method or option.
519   * @param {String} name
520   *   The name of the unsupported object.
521   * @param {*} [value]
522   *   The value of the unsupported object.
523   */
524  Bootstrap.unsupported = function (type, name, value) {
525    Bootstrap.warn('Unsupported by Drupal Bootstrap: (@type) @name -> @value', {
526      '@type': type,
527      '@name': name,
528      '@value': typeof value === 'object' ? JSON.stringify(value) : value
529    });
530  };
531
532  /**
533   * Provide a helper method to display a warning.
534   *
535   * @param {String} message
536   *   The message to display.
537   * @param {Object} [args]
538   *   Arguments to use as replacements in Drupal.formatString.
539   */
540  Bootstrap.warn = function (message, args) {
541    if (this.settings.dev && console.warn) {
542      console.warn(Drupal.formatString(message, args));
543    }
544  };
545
546  /**
547   * Wraps a plugin with common functionality.
548   *
549   * @param {Function} constructor
550   *   A plugin constructor being wrapped.
551   * @param {Object|Function} plugin
552   *   The plugin being wrapped.
553   * @param {Boolean} [extend = false]
554   *   Whether to add super extensibility.
555   */
556  Bootstrap.wrapPluginConstructor = function (constructor, plugin, extend) {
557    var proto = constructor.prototype;
558
559    // Add a jQuery UI like option getter/setter method.
560    var option = this.option;
561    if (proto.option === void(0)) {
562      proto.option = function () {
563        return option.apply(this, arguments);
564      };
565    }
566
567    if (extend) {
568      // Handle prototype properties separately.
569      if (plugin.prototype !== void 0) {
570        for (var key in plugin.prototype) {
571          if (!plugin.prototype.hasOwnProperty(key)) continue;
572          var value = plugin.prototype[key];
573          if (typeof value === 'function') {
574            proto[key] = this.superWrapper(proto[key] || function () {}, value);
575          }
576          else {
577            proto[key] = $.isPlainObject(value) ? $.extend(true, {}, proto[key], value) : value;
578          }
579        }
580      }
581      delete plugin.prototype;
582
583      // Handle static properties.
584      for (key in plugin) {
585        if (!plugin.hasOwnProperty(key)) continue;
586        value = plugin[key];
587        if (typeof value === 'function') {
588          constructor[key] = this.superWrapper(constructor[key] || function () {}, value);
589        }
590        else {
591          constructor[key] = $.isPlainObject(value) ? $.extend(true, {}, constructor[key], value) : value;
592        }
593      }
594    }
595  };
596
597  // Add Bootstrap to the global Drupal object.
598  Drupal.bootstrap = Drupal.bootstrap || Bootstrap;
599
600})(window._, window.jQuery, window.Drupal, window.drupalSettings);
601;
602(function ($, _) {
603
604  /**
605   * @class Attributes
606   *
607   * Modifies attributes.
608   *
609   * @param {Object|Attributes} attributes
610   *   An object to initialize attributes with.
611   */
612  var Attributes = function (attributes) {
613    this.data = {};
614    this.data['class'] = [];
615    this.merge(attributes);
616  };
617
618  /**
619   * Renders the attributes object as a string to inject into an HTML element.
620   *
621   * @return {String}
622   *   A rendered string suitable for inclusion in HTML markup.
623   */
624  Attributes.prototype.toString = function () {
625    var output = '';
626    var name, value;
627    var checkPlain = function (str) {
628      return str && str.toString().replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;') || '';
629    };
630    var data = this.getData();
631    for (name in data) {
632      if (!data.hasOwnProperty(name)) continue;
633      value = data[name];
634      if (_.isFunction(value)) value = value();
635      if (_.isObject(value)) value = _.values(value);
636      if (_.isArray(value)) value = value.join(' ');
637      output += ' ' + checkPlain(name) + '="' + checkPlain(value) + '"';
638    }
639    return output;
640  };
641
642  /**
643   * Renders the Attributes object as a plain object.
644   *
645   * @return {Object}
646   *   A plain object suitable for inclusion in DOM elements.
647   */
648  Attributes.prototype.toPlainObject = function () {
649    var object = {};
650    var name, value;
651    var data = this.getData();
652    for (name in data) {
653      if (!data.hasOwnProperty(name)) continue;
654      value = data[name];
655      if (_.isFunction(value)) value = value();
656      if (_.isObject(value)) value = _.values(value);
657      if (_.isArray(value)) value = value.join(' ');
658      object[name] = value;
659    }
660    return object;
661  };
662
663  /**
664   * Add class(es) to the array.
665   *
666   * @param {string|Array} value
667   *   An individual class or an array of classes to add.
668   *
669   * @return {Attributes}
670   *
671   * @chainable
672   */
673  Attributes.prototype.addClass = function (value) {
674    var args = Array.prototype.slice.call(arguments);
675    this.data['class'] = this.sanitizeClasses(this.data['class'].concat(args));
676    return this;
677  };
678
679  /**
680   * Returns whether the requested attribute exists.
681   *
682   * @param {string} name
683   *   An attribute name to check.
684   *
685   * @return {boolean}
686   *   TRUE or FALSE
687   */
688  Attributes.prototype.exists = function (name) {
689    return this.data[name] !== void(0) && this.data[name] !== null;
690  };
691
692  /**
693   * Retrieve a specific attribute from the array.
694   *
695   * @param {string} name
696   *   The specific attribute to retrieve.
697   * @param {*} defaultValue
698   *   (optional) The default value to set if the attribute does not exist.
699   *
700   * @return {*}
701   *   A specific attribute value, passed by reference.
702   */
703  Attributes.prototype.get = function (name, defaultValue) {
704    if (!this.exists(name)) this.data[name] = defaultValue;
705    return this.data[name];
706  };
707
708  /**
709   * Retrieves a cloned copy of the internal attributes data object.
710   *
711   * @return {Object}
712   */
713  Attributes.prototype.getData = function () {
714    return _.extend({}, this.data);
715  };
716
717  /**
718   * Retrieves classes from the array.
719   *
720   * @return {Array}
721   *   The classes array.
722   */
723  Attributes.prototype.getClasses = function () {
724    return this.get('class', []);
725  };
726
727  /**
728   * Indicates whether a class is present in the array.
729   *
730   * @param {string|Array} className
731   *   The class(es) to search for.
732   *
733   * @return {boolean}
734   *   TRUE or FALSE
735   */
736  Attributes.prototype.hasClass = function (className) {
737    className = this.sanitizeClasses(Array.prototype.slice.call(arguments));
738    var classes = this.getClasses();
739    for (var i = 0, l = className.length; i < l; i++) {
740      // If one of the classes fails, immediately return false.
741      if (_.indexOf(classes, className[i]) === -1) {
742        return false;
743      }
744    }
745    return true;
746  };
747
748  /**
749   * Merges multiple values into the array.
750   *
751   * @param {Attributes|Node|jQuery|Object} object
752   *   An Attributes object with existing data, a Node DOM element, a jQuery
753   *   instance or a plain object where the key is the attribute name and the
754   *   value is the attribute value.
755   * @param {boolean} [recursive]
756   *   Flag determining whether or not to recursively merge key/value pairs.
757   *
758   * @return {Attributes}
759   *
760   * @chainable
761   */
762  Attributes.prototype.merge = function (object, recursive) {
763    // Immediately return if there is nothing to merge.
764    if (!object) {
765      return this;
766    }
767
768    // Get attributes from a jQuery element.
769    if (object instanceof $) {
770      object = object[0];
771    }
772
773    // Get attributes from a DOM element.
774    if (object instanceof Node) {
775      object = Array.prototype.slice.call(object.attributes).reduce(function (attributes, attribute) {
776        attributes[attribute.name] = attribute.value;
777        return attributes;
778      }, {});
779    }
780    // Get attributes from an Attributes instance.
781    else if (object instanceof Attributes) {
782      object = object.getData();
783    }
784    // Otherwise, clone the object.
785    else {
786      object = _.extend({}, object);
787    }
788
789    // By this point, there should be a valid plain object.
790    if (!$.isPlainObject(object)) {
791      setTimeout(function () {
792        throw new Error('Passed object is not supported: ' + object);
793      });
794      return this;
795    }
796
797    // Handle classes separately.
798    if (object && object['class'] !== void 0) {
799      this.addClass(object['class']);
800      delete object['class'];
801    }
802
803    if (recursive === void 0 || recursive) {
804      this.data = $.extend(true, {}, this.data, object);
805    }
806    else {
807      this.data = $.extend({}, this.data, object);
808    }
809
810    return this;
811  };
812
813  /**
814   * Removes an attribute from the array.
815   *
816   * @param {string} name
817   *   The name of the attribute to remove.
818   *
819   * @return {Attributes}
820   *
821   * @chainable
822   */
823  Attributes.prototype.remove = function (name) {
824    if (this.exists(name)) delete this.data[name];
825    return this;
826  };
827
828  /**
829   * Removes a class from the attributes array.
830   *
831   * @param {...string|Array} className
832   *   An individual class or an array of classes to remove.
833   *
834   * @return {Attributes}
835   *
836   * @chainable
837   */
838  Attributes.prototype.removeClass = function (className) {
839    var remove = this.sanitizeClasses(Array.prototype.slice.apply(arguments));
840    this.data['class'] = _.without(this.getClasses(), remove);
841    return this;
842  };
843
844  /**
845   * Replaces a class in the attributes array.
846   *
847   * @param {string} oldValue
848   *   The old class to remove.
849   * @param {string} newValue
850   *   The new class. It will not be added if the old class does not exist.
851   *
852   * @return {Attributes}
853   *
854   * @chainable
855   */
856  Attributes.prototype.replaceClass = function (oldValue, newValue) {
857    var classes = this.getClasses();
858    var i = _.indexOf(this.sanitizeClasses(oldValue), classes);
859    if (i >= 0) {
860      classes[i] = newValue;
861      this.set('class', classes);
862    }
863    return this;
864  };
865
866  /**
867   * Ensures classes are flattened into a single is an array and sanitized.
868   *
869   * @param {...String|Array} classes
870   *   The class or classes to sanitize.
871   *
872   * @return {Array}
873   *   A sanitized array of classes.
874   */
875  Attributes.prototype.sanitizeClasses = function (classes) {
876    return _.chain(Array.prototype.slice.call(arguments))
877      // Flatten in case there's a mix of strings and arrays.
878      .flatten()
879
880      // Split classes that may have been added with a space as a separator.
881      .map(function (string) {
882        return string.split(' ');
883      })
884
885      // Flatten again since it was just split into arrays.
886      .flatten()
887
888      // Filter out empty items.
889      .filter()
890
891      // Clean the class to ensure it's a valid class name.
892      .map(function (value) {
893        return Attributes.cleanClass(value);
894      })
895
896      // Ensure classes are unique.
897      .uniq()
898
899      // Retrieve the final value.
900      .value();
901  };
902
903  /**
904   * Sets an attribute on the array.
905   *
906   * @param {string} name
907   *   The name of the attribute to set.
908   * @param {*} value
909   *   The value of the attribute to set.
910   *
911   * @return {Attributes}
912   *
913   * @chainable
914   */
915  Attributes.prototype.set = function (name, value) {
916    var obj = $.isPlainObject(name) ? name : {};
917    if (typeof name === 'string') {
918      obj[name] = value;
919    }
920    return this.merge(obj);
921  };
922
923  /**
924   * Prepares a string for use as a CSS identifier (element, class, or ID name).
925   *
926   * Note: this is essentially a direct copy from
927   * \Drupal\Component\Utility\Html::cleanCssIdentifier
928   *
929   * @param {string} identifier
930   *   The identifier to clean.
931   * @param {Object} [filter]
932   *   An object of string replacements to use on the identifier.
933   *
934   * @return {string}
935   *   The cleaned identifier.
936   */
937  Attributes.cleanClass = function (identifier, filter) {
938    filter = filter || {
939      ' ': '-',
940      '_': '-',
941      '/': '-',
942      '[': '-',
943      ']': ''
944    };
945
946    identifier = identifier.toLowerCase();
947
948    if (filter['__'] === void 0) {
949      identifier = identifier.replace('__', '#DOUBLE_UNDERSCORE#');
950    }
951
952    identifier = identifier.replace(Object.keys(filter), Object.keys(filter).map(function(key) { return filter[key]; }));
953
954    if (filter['__'] === void 0) {
955      identifier = identifier.replace('#DOUBLE_UNDERSCORE#', '__');
956    }
957
958    identifier = identifier.replace(/[^\u002D\u0030-\u0039\u0041-\u005A\u005F\u0061-\u007A\u00A1-\uFFFF]/g, '');
959    identifier = identifier.replace(['/^[0-9]/', '/^(-[0-9])|^(--)/'], ['_', '__']);
960
961    return identifier;
962  };
963
964  /**
965   * Creates an Attributes instance.
966   *
967   * @param {object|Attributes} [attributes]
968   *   An object to initialize attributes with.
969   *
970   * @return {Attributes}
971   *   An Attributes instance.
972   *
973   * @constructor
974   */
975  Attributes.create = function (attributes) {
976    return new Attributes(attributes);
977  };
978
979  window.Attributes = Attributes;
980
981})(window.jQuery, window._);
982;
983/**
984 * @file
985 * Theme hooks for the Drupal Bootstrap base theme.
986 */
987(function ($, Drupal, Bootstrap, Attributes) {
988
989  /**
990   * Fallback for theming an icon if the Icon API module is not installed.
991   */
992  if (!Drupal.icon) Drupal.icon = { bundles: {} };
993  if (!Drupal.theme.icon || Drupal.theme.prototype.icon) {
994    $.extend(Drupal.theme, /** @lends Drupal.theme */ {
995      /**
996       * Renders an icon.
997       *
998       * @param {string} bundle
999       *   The bundle which the icon belongs to.
1000       * @param {string} icon
1001       *   The name of the icon to render.
1002       * @param {object|Attributes} [attributes]
1003       *   An object of attributes to also apply to the icon.
1004       *
1005       * @returns {string}
1006       */
1007      icon: function (bundle, icon, attributes) {
1008        if (!Drupal.icon.bundles[bundle]) return '';
1009        attributes = Attributes.create(attributes).addClass('icon').set('aria-hidden', 'true');
1010        icon = Drupal.icon.bundles[bundle](icon, attributes);
1011        return '<span' + attributes + '></span>';
1012      }
1013    });
1014  }
1015
1016  /**
1017   * Callback for modifying an icon in the "bootstrap" icon bundle.
1018   *
1019   * @param {string} icon
1020   *   The icon being rendered.
1021   * @param {Attributes} attributes
1022   *   Attributes object for the icon.
1023   */
1024  Drupal.icon.bundles.bootstrap = function (icon, attributes) {
1025    attributes.addClass(['glyphicon', 'glyphicon-' + icon]);
1026  };
1027
1028  /**
1029   * Add necessary theming hooks.
1030   */
1031  $.extend(Drupal.theme, /** @lends Drupal.theme */ {
1032
1033    /**
1034     * Renders a Bootstrap AJAX glyphicon throbber.
1035     *
1036     * @returns {string}
1037     */
1038    ajaxThrobber: function () {
1039      return Drupal.theme('bootstrapIcon', 'refresh', {'class': ['ajax-throbber', 'glyphicon-spin'] });
1040    },
1041
1042    /**
1043     * Renders a button element.
1044     *
1045     * @param {object|Attributes} attributes
1046     *   An object of attributes to apply to the button. If it contains one of:
1047     *   - value: The label of the button.
1048     *   - context: The context type of Bootstrap button, can be one of:
1049     *     - default
1050     *     - primary
1051     *     - success
1052     *     - info
1053     *     - warning
1054     *     - danger
1055     *     - link
1056     *
1057     * @returns {string}
1058     */
1059    button: function (attributes) {
1060      attributes = Attributes.create(attributes).addClass('btn');
1061      var context = attributes.get('context', 'default');
1062      var label = attributes.get('value', '');
1063      attributes.remove('context').remove('value');
1064      if (!attributes.hasClass(['btn-default', 'btn-primary', 'btn-success', 'btn-info', 'btn-warning', 'btn-danger', 'btn-link'])) {
1065        attributes.addClass('btn-' + Bootstrap.checkPlain(context));
1066      }
1067
1068      // Attempt to, intelligently, provide a default button "type".
1069      if (!attributes.exists('type')) {
1070        attributes.set('type', attributes.hasClass('form-submit') ? 'submit' : 'button');
1071      }
1072
1073      return '<button' + attributes + '>' + label + '</button>';
1074    },
1075
1076    /**
1077     * Alias for "button" theme hook.
1078     *
1079     * @param {object|Attributes} attributes
1080     *   An object of attributes to apply to the button.
1081     *
1082     * @see Drupal.theme.button()
1083     *
1084     * @returns {string}
1085     */
1086    btn: function (attributes) {
1087      return Drupal.theme('button', attributes);
1088    },
1089
1090    /**
1091     * Renders a button block element.
1092     *
1093     * @param {object|Attributes} attributes
1094     *   An object of attributes to apply to the button.
1095     *
1096     * @see Drupal.theme.button()
1097     *
1098     * @returns {string}
1099     */
1100    'btn-block': function (attributes) {
1101      return Drupal.theme('button', Attributes.create(attributes).addClass('btn-block'));
1102    },
1103
1104    /**
1105     * Renders a large button element.
1106     *
1107     * @param {object|Attributes} attributes
1108     *   An object of attributes to apply to the button.
1109     *
1110     * @see Drupal.theme.button()
1111     *
1112     * @returns {string}
1113     */
1114    'btn-lg': function (attributes) {
1115      return Drupal.theme('button', Attributes.create(attributes).addClass('btn-lg'));
1116    },
1117
1118    /**
1119     * Renders a small button element.
1120     *
1121     * @param {object|Attributes} attributes
1122     *   An object of attributes to apply to the button.
1123     *
1124     * @see Drupal.theme.button()
1125     *
1126     * @returns {string}
1127     */
1128    'btn-sm': function (attributes) {
1129      return Drupal.theme('button', Attributes.create(attributes).addClass('btn-sm'));
1130    },
1131
1132    /**
1133     * Renders an extra small button element.
1134     *
1135     * @param {object|Attributes} attributes
1136     *   An object of attributes to apply to the button.
1137     *
1138     * @see Drupal.theme.button()
1139     *
1140     * @returns {string}
1141     */
1142    'btn-xs': function (attributes) {
1143      return Drupal.theme('button', Attributes.create(attributes).addClass('btn-xs'));
1144    },
1145
1146    /**
1147     * Renders a glyphicon.
1148     *
1149     * @param {string} name
1150     *   The name of the glyphicon.
1151     * @param {object|Attributes} [attributes]
1152     *   An object of attributes to apply to the icon.
1153     *
1154     * @returns {string}
1155     */
1156    bootstrapIcon: function (name, attributes) {
1157      return Drupal.theme('icon', 'bootstrap', name, attributes);
1158    }
1159
1160  });
1161
1162})(window.jQuery, window.Drupal, window.Drupal.bootstrap, window.Attributes);
1163;
1164/**
1165* DO NOT EDIT THIS FILE.
1166* See the following change record for more information,
1167* https://www.drupal.org/node/2815083
1168* @preserve
1169**/
1170(function ($, Drupal) {
1171  Drupal.theme.progressBar = function (id) {
1172    return "<div id=\"".concat(id, "\" class=\"progress\" aria-live=\"polite\">") + '<div class="progress__label">&nbsp;</div>' + '<div class="progress__track"><div class="progress__bar"></div></div>' + '<div class="progress__percentage"></div>' + '<div class="progress__description">&nbsp;</div>' + '</div>';
1173  };
1174  Drupal.ProgressBar = function (id, updateCallback, method, errorCallback) {
1175    this.id = id;
1176    this.method = method || 'GET';
1177    this.updateCallback = updateCallback;
1178    this.errorCallback = errorCallback;
1179    this.element = $(Drupal.theme('progressBar', id));
1180  };
1181  $.extend(Drupal.ProgressBar.prototype, {
1182    setProgress: function setProgress(percentage, message, label) {
1183      if (percentage >= 0 && percentage <= 100) {
1184        $(this.element).find('div.progress__bar').css('width', "".concat(percentage, "%"));
1185        $(this.element).find('div.progress__percentage').html("".concat(percentage, "%"));
1186      }
1187      $('div.progress__description', this.element).html(message);
1188      $('div.progress__label', this.element).html(label);
1189      if (this.updateCallback) {
1190        this.updateCallback(percentage, message, this);
1191      }
1192    },
1193    startMonitoring: function startMonitoring(uri, delay) {
1194      this.delay = delay;
1195      this.uri = uri;
1196      this.sendPing();
1197    },
1198    stopMonitoring: function stopMonitoring() {
1199      clearTimeout(this.timer);
1200      this.uri = null;
1201    },
1202    sendPing: function sendPing() {
1203      if (this.timer) {
1204        clearTimeout(this.timer);
1205      }
1206      if (this.uri) {
1207        var pb = this;
1208        var uri = this.uri;
1209        if (uri.indexOf('?') === -1) {
1210          uri += '?';
1211        } else {
1212          uri += '&';
1213        }
1214        uri += '_format=json';
1215        $.ajax({
1216          type: this.method,
1217          url: uri,
1218          data: '',
1219          dataType: 'json',
1220          success: function success(progress) {
1221            if (progress.status === 0) {
1222              pb.displayError(progress.data);
1223              return;
1224            }
1225            pb.setProgress(progress.percentage, progress.message, progress.label);
1226            pb.timer = setTimeout(function () {
1227              pb.sendPing();
1228            }, pb.delay);
1229          },
1230          error: function error(xmlhttp) {
1231            var e = new Drupal.AjaxError(xmlhttp, pb.uri);
1232            pb.displayError("<pre>".concat(e.message, "</pre>"));
1233          }
1234        });
1235      }
1236    },
1237    displayError: function displayError(string) {
1238      var error = $('<div class="messages messages--error"></div>').html(string);
1239      $(this.element).before(error).hide();
1240      if (this.errorCallback) {
1241        this.errorCallback(this);
1242      }
1243    }
1244  });
1245})(jQuery, Drupal);;
1246/**
1247 * @file
1248 * Extends methods from core/misc/progress.js.
1249 */
1250
1251(function ($, Drupal) {
1252
1253  'use strict';
1254
1255  /**
1256   * Theme function for the progress bar.
1257   *
1258   * @param {string} id
1259   *
1260   * @return {string}
1261   *   The HTML for the progress bar.
1262   */
1263  Drupal.theme.progressBar = function (id) {
1264    return '<div class="progress-wrapper" aria-live="polite">' +
1265             '<div class="message"></div>'+
1266             '<div id ="' + id + '" class="progress progress-striped active">' +
1267               '<div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">' +
1268                 '<span class="percentage"></span>' +
1269               '</div>' +
1270             '</div>' +
1271             '<div class="progress-label"></div>' +
1272           '</div>';
1273  };
1274
1275  $.extend(Drupal.ProgressBar.prototype, /** @lends Drupal.ProgressBar */{
1276
1277    /**
1278     * Set the percentage and status message for the progressbar.
1279     *
1280     * @param {number} percentage
1281     * @param {string} message
1282     * @param {string} label
1283     */
1284    setProgress: function (percentage, message, label) {
1285      if (percentage >= 0 && percentage <= 100) {
1286        $(this.element).find('.progress-bar').css('width', percentage + '%').attr('aria-valuenow', percentage);
1287        $(this.element).find('.percentage').html(percentage + '%');
1288      }
1289      if (message) {
1290        // Remove the unnecessary whitespace at the end of the message.
1291        message = message.replace(/<br\/>&nbsp;|\s*$/, '');
1292
1293        $('.message', this.element).html(message);
1294      }
1295      if (label) {
1296        $('.progress-label', this.element).html(label);
1297      }
1298      if (this.updateCallback) {
1299        this.updateCallback(percentage, message, this);
1300      }
1301    },
1302
1303    /**
1304     * Display errors on the page.
1305     *
1306     * @param {string} string
1307     */
1308    displayError: function (string) {
1309      var error = $('<div class="alert alert-block alert-error"><button class="close" data-dismiss="alert">&times;</button><h4>' + Drupal.t('Error message') + '</h4></div>').append(string);
1310      $(this.element).before(error).hide();
1311
1312      if (this.errorCallback) {
1313        this.errorCallback(this);
1314      }
1315    }
1316  });
1317
1318})(jQuery, Drupal);
1319;
1320/**
1321* DO NOT EDIT THIS FILE.
1322* See the following change record for more information,
1323* https://www.drupal.org/node/2815083
1324* @preserve
1325**/
1326(function ($, once) {
1327  var deprecatedMessageSuffix = "is deprecated in Drupal 9.3.0 and will be removed in Drupal 10.0.0. Use the core/once library instead. See https://www.drupal.org/node/3158256";
1328  var originalJQOnce = $.fn.once;
1329  var originalJQRemoveOnce = $.fn.removeOnce;
1330  $.fn.once = function jQueryOnce(id) {
1331    Drupal.deprecationError({
1332      message: "jQuery.once() ".concat(deprecatedMessageSuffix)
1333    });
1334    return originalJQOnce.apply(this, [id]);
1335  };
1336  $.fn.removeOnce = function jQueryRemoveOnce(id) {
1337    Drupal.deprecationError({
1338      message: "jQuery.removeOnce() ".concat(deprecatedMessageSuffix)
1339    });
1340    return originalJQRemoveOnce.apply(this, [id]);
1341  };
1342  var drupalOnce = once;
1343  function augmentedOnce(id, selector, context) {
1344    originalJQOnce.apply($(selector, context), [id]);
1345    return drupalOnce(id, selector, context);
1346  }
1347  function remove(id, selector, context) {
1348    originalJQRemoveOnce.apply($(selector, context), [id]);
1349    return drupalOnce.remove(id, selector, context);
1350  }
1351  window.once = Object.assign(augmentedOnce, drupalOnce, {
1352    remove: remove
1353  });
1354})(jQuery, once);;
1355loadjs=function(){var h=function(){},c={},u={},f={};function o(e,n){if(e){var r=f[e];if(u[e]=n,r)for(;r.length;)r[0](e,n),r.splice(0,1)}}function l(e,n){e.call&&(e={success:e}),n.length?(e.error||h)(n):(e.success||h)(e)}function d(r,t,s,i){var c,o,e=document,n=s.async,u=(s.numRetries||0)+1,f=s.before||h,l=r.replace(/[\?|#].*$/,""),a=r.replace(/^(css|img)!/,"");i=i||0,/(^css!|\.css$)/.test(l)?((o=e.createElement("link")).rel="stylesheet",o.href=a,(c="hideFocus"in o)&&o.relList&&(c=0,o.rel="preload",o.as="style")):/(^img!|\.(png|gif|jpg|svg|webp)$)/.test(l)?(o=e.createElement("img")).src=a:((o=e.createElement("script")).src=r,o.async=void 0===n||n),!(o.onload=o.onerror=o.onbeforeload=function(e){var n=e.type[0];if(c)try{o.sheet.cssText.length||(n="e")}catch(e){18!=e.code&&(n="e")}if("e"==n){if((i+=1)<u)return d(r,t,s,i)}else if("preload"==o.rel&&"style"==o.as)return o.rel="stylesheet";t(r,n,e.defaultPrevented)})!==f(r,o)&&e.head.appendChild(o)}function r(e,n,r){var t,s;if(n&&n.trim&&(t=n),s=(t?r:n)||{},t){if(t in c)throw"LoadJS";c[t]=!0}function i(n,r){!function(e,t,n){var r,s,i=(e=e.push?e:[e]).length,c=i,o=[];for(r=function(e,n,r){if("e"==n&&o.push(e),"b"==n){if(!r)return;o.push(e)}--i||t(o)},s=0;s<c;s++)d(e[s],r,n)}(e,function(e){l(s,e),n&&l({success:n,error:r},e),o(t,e)},s)}if(s.returnPromise)return new Promise(i);i()}return r.ready=function(e,n){return function(e,r){e=e.push?e:[e];var n,t,s,i=[],c=e.length,o=c;
1355for(n=function(e,n){n.length&&i.push(e),--o||r(i)};c--;)t=e[c],(s=u[t])?n(t,s):(f[t]=f[t]||[]).push(n)}(e,function(e){l(n,e)}),r},r.done=function(e){o(e,[])},r.reset=function(){c={},u={},f={}},r.isDefined=function(e){return e in c},r}();;
1356/**
1357* DO NOT EDIT THIS FILE.
1358* See the following change record for more information,
1359* https://www.drupal.org/node/2815083
1360* @preserve
1361**/
1362function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
1363function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
1364function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
1365function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
1366function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
1367function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
1368(function ($, window, Drupal, drupalSettings, loadjs, _ref) {
1369  var isFocusable = _ref.isFocusable,
1370    tabbable = _ref.tabbable;
1371  Drupal.behaviors.AJAX = {
1372    attach: function attach(context, settings) {
1373      function loadAjaxBehavior(base) {
1374        var elementSettings = settings.ajax[base];
1375        if (typeof elementSettings.selector === 'undefined') {
1376          elementSettings.selector = "#".concat(base);
1377        }
1378        once('drupal-ajax', $(elementSettings.selector)).forEach(function (el) {
1379          elementSettings.element = el;
1380          elementSettings.base = base;
1381          Drupal.ajax(elementSettings);
1382        });
1383      }
1384      Object.keys(settings.ajax || {}).forEach(function (base) {
1385        return loadAjaxBehavior(base);
1386      });
1387      Drupal.ajax.bindAjaxLinks(document.body);
1388      once('ajax', '.use-ajax-submit').forEach(function (el) {
1389        var elementSettings = {};
1390        elementSettings.url = $(el.form).attr('action');
1391        elementSettings.setClick = true;
1392        elementSettings.event = 'click';
1393        elementSettings.progress = {
1394          type: 'throbber'
1395        };
1396        elementSettings.base = el.id;
1397        elementSettings.element = el;
1398        Drupal.ajax(elementSettings);
1399      });
1400    },
1401    detach: function detach(context, settings, trigger) {
1402      if (trigger === 'unload') {
1403        Drupal.ajax.expired().forEach(function (instance) {
1404          Drupal.ajax.instances[instance.instanceIndex] = null;
1405        });
1406      }
1407    }
1408  };
1409  Drupal.AjaxError = function (xmlhttp, uri, customMessage) {
1410    var statusCode;
1411    var statusText;
1412    var responseText;
1413    if (xmlhttp.status) {
1414      statusCode = "\n".concat(Drupal.t('An AJAX HTTP error occurred.'), "\n").concat(Drupal.t('HTTP Result Code: !status', {
1415        '!status': xmlhttp.status
1416      }));
1417    } else {
1418      statusCode = "\n".concat(Drupal.t('An AJAX HTTP request terminated abnormally.'));
1419    }
1420    statusCode += "\n".concat(Drupal.t('Debugging information follows.'));
1421    var pathText = "\n".concat(Drupal.t('Path: !uri', {
1422      '!uri': uri
1423    }));
1424    statusText = '';
1425    try {
1426      statusText = "\n".concat(Drupal.t('StatusText: !statusText', {
1427        '!statusText': xmlhttp.statusText.trim()
1428      }));
1429    } catch (e) {}
1430    responseText = '';
1431    try {
1432      responseText = "\n".concat(Drupal.t('ResponseText: !responseText', {
1433        '!responseText': xmlhttp.responseText.trim()
1434      }));
1435    } catch (e) {}
1436    responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi, '');
1437    responseText = responseText.replace(/[\n]+\s+/g, '\n');
1438    var readyStateText = xmlhttp.status === 0 ? "\n".concat(Drupal.t('ReadyState: !readyState', {
1439      '!readyState': xmlhttp.readyState
1440    })) : '';
1441    customMessage = customMessage ? "\n".concat(Drupal.t('CustomMessage: !customMessage', {
1442      '!customMessage': customMessage
1443    })) : '';
1444    this.message = statusCode + pathText + statusText + customMessage + responseText + readyStateText;
1445    this.name = 'AjaxError';
1446  };
1447  Drupal.AjaxError.prototype = new Error();
1448  Drupal.AjaxError.prototype.constructor = Drupal.AjaxError;
1449  Drupal.ajax = function (settings) {
1450    if (arguments.length !== 1) {
1451      throw new Error('Drupal.ajax() function must be called with one configuration object only');
1452    }
1453    var base = settings.base || false;
1454    var element = settings.element || false;
1455    delete settings.base;
1456    delete settings.element;
1457    if (!settings.progress && !element) {
1458      settings.progress = false;
1459    }
1460    var ajax = new Drupal.Ajax(base, element, settings);
1461    ajax.instanceIndex = Drupal.ajax.instances.length;
1462    Drupal.ajax.instances.push(ajax);
1463    return ajax;
1464  };
1465  Drupal.ajax.instances = [];
1466  Drupal.ajax.expired = function () {
1467    return Drupal.ajax.instances.filter(function (instance) {
1468      return instance && instance.element !== false && !document.body.contains(instance.element);
1469    });
1470  };
1471  Drupal.ajax.bindAjaxLinks = function (element) {
1472    once('ajax', '.use-ajax', element).forEach(function (ajaxLink) {
1473      var $linkElement = $(ajaxLink);
1474      var elementSettings = {
1475        progress: {
1476          type: 'throbber'
1477        },
1478        dialogType: $linkElement.data('dialog-type'),
1479        dialog: $linkElement.data('dialog-options'),
1480        dialogRenderer: $linkElement.data('dialog-renderer'),
1481        base: $linkElement.attr('id'),
1482        element: ajaxLink
1483      };
1484      var href = $linkElement.attr('href');
1485      if (href) {
1486        elementSettings.url = href;
1487        elementSettings.event = 'click';
1488      }
1489      Drupal.ajax(elementSettings);
1490    });
1491  };
1492  Drupal.Ajax = function (base, element, elementSettings) {
1493    var defaults = {
1494      event: element ? 'mousedown' : null,
1495      keypress: true,
1496      selector: base ? "#".concat(base) : null,
1497      effect: 'none',
1498      speed: 'none',
1499      method: 'replaceWith',
1500      progress: {
1501        type: 'throbber',
1502        message: Drupal.t('Please wait...')
1503      },
1504      submit: {
1505        js: true
1506      }
1507    };
1508    $.extend(this, defaults, elementSettings);
1509    this.commands = new Drupal.AjaxCommands();
1510    this.instanceIndex = false;
1511    if (this.wrapper) {
1512      this.wrapper = "#".concat(this.wrapper);
1513    }
1514    this.element = element;
1515    this.element_settings = elementSettings;
1516    this.elementSettings = elementSettings;
1517    if (this.element && this.element.form) {
1518      this.$form = $(this.element.form);
1519    }
1520    if (!this.url) {
1521      var $element = $(this.element);
1522      if ($element.is('a')) {
1523        this.url = $element.attr('href');
1524      } else if (this.element && element.form) {
1525        this.url = this.$form.attr('action');
1526      }
1527    }
1528    var originalUrl = this.url;
1529    this.url = this.url.replace(/\/nojs(\/|$|\?|#)/, '/ajax$1');
1530    if (drupalSettings.ajaxTrustedUrl[originalUrl]) {
1531      drupalSettings.ajaxTrustedUrl[this.url] = true;
1532    }
1533    var ajax = this;
1534    ajax.options = {
1535      url: ajax.url,
1536      data: ajax.submit,
1537      isInProgress: function isInProgress() {
1538        return ajax.ajaxing;
1539      },
1540      beforeSerialize: function beforeSerialize(elementSettings, options) {
1541        return ajax.beforeSerialize(elementSettings, options);
1542      },
1543      beforeSubmit: function beforeSubmit(formValues, elementSettings, options) {
1544        ajax.ajaxing = true;
1545        return ajax.beforeSubmit(formValues, elementSettings, options);
1546      },
1547      beforeSend: function beforeSend(xmlhttprequest, options) {
1548        ajax.ajaxing = true;
1549        return ajax.beforeSend(xmlhttprequest, options);
1550      },
1551      success: function success(response, status, xmlhttprequest) {
1552        var _this = this;
1553        if (typeof response === 'string') {
1554          response = $.parseJSON(response);
1555        }
1556        if (response !== null && !drupalSettings.ajaxTrustedUrl[ajax.url]) {
1557          if (xmlhttprequest.getResponseHeader('X-Drupal-Ajax-Token') !== '1') {
1558            var customMessage = Drupal.t('The response failed verification so will not be processed.');
1559            return ajax.error(xmlhttprequest, ajax.url, customMessage);
1560          }
1561        }
1562        return Promise.resolve(ajax.success(response, status)).then(function () {
1563          ajax.ajaxing = false;
1564          $(document).trigger('ajaxSuccess', [xmlhttprequest, _this]);
1565          $(document).trigger('ajaxComplete', [xmlhttprequest, _this]);
1566          if (--$.active === 0) {
1567            $(document).trigger('ajaxStop');
1568          }
1569        });
1570      },
1571      error: function error(xmlhttprequest, status, _error) {
1572        ajax.ajaxing = false;
1573      },
1574      complete: function complete(xmlhttprequest, status) {
1575        if (status === 'error' || status === 'parsererror') {
1576          return ajax.error(xmlhttprequest, ajax.url);
1577        }
1578      },
1579      dataType: 'json',
1580      jsonp: false,
1581      type: 'POST'
1582    };
1583    if (elementSettings.dialog) {
1584      ajax.options.data.dialogOptions = elementSettings.dialog;
1585    }
1586    if (ajax.options.url.indexOf('?') === -1) {
1587      ajax.options.url += '?';
1588    } else {
1589      ajax.options.url += '&';
1590    }
1591    var wrapper = "drupal_".concat(elementSettings.dialogType || 'ajax');
1592    if (elementSettings.dialogRenderer) {
1593      wrapper += ".".concat(elementSettings.dialogRenderer);
1594    }
1595    ajax.options.url += "".concat(Drupal.ajax.WRAPPER_FORMAT, "=").concat(wrapper);
1596    $(ajax.element).on(elementSettings.event, function (event) {
1597      if (!drupalSettings.ajaxTrustedUrl[ajax.url] && !Drupal.url.isLocal(ajax.url)) {
1598        throw new Error(Drupal.t('The callback URL is not local and n
1598ot trusted: !url', {
1599          '!url': ajax.url
1600        }));
1601      }
1602      return ajax.eventResponse(this, event);
1603    });
1604    if (elementSettings.keypress) {
1605      $(ajax.element).on('keypress', function (event) {
1606        return ajax.keypressResponse(this, event);
1607      });
1608    }
1609    if (elementSettings.prevent) {
1610      $(ajax.element).on(elementSettings.prevent, false);
1611    }
1612  };
1613  Drupal.ajax.WRAPPER_FORMAT = '_wrapper_format';
1614  Drupal.Ajax.AJAX_REQUEST_PARAMETER = '_drupal_ajax';
1615  Drupal.Ajax.prototype.execute = function () {
1616    if (this.ajaxing) {
1617      return;
1618    }
1619    try {
1620      this.beforeSerialize(this.element, this.options);
1621      return $.ajax(this.options);
1622    } catch (e) {
1623      this.ajaxing = false;
1624      window.alert("An error occurred while attempting to process ".concat(this.options.url, ": ").concat(e.message));
1625      return $.Deferred().reject();
1626    }
1627  };
1628  Drupal.Ajax.prototype.keypressResponse = function (element, event) {
1629    var ajax = this;
1630    if (event.which === 13 || event.which === 32 && element.type !== 'text' && element.type !== 'textarea' && element.type !== 'tel' && element.type !== 'number') {
1631      event.preventDefault();
1632      event.stopPropagation();
1633      $(element).trigger(ajax.elementSettings.event);
1634    }
1635  };
1636  Drupal.Ajax.prototype.eventResponse = function (element, event) {
1637    event.preventDefault();
1638    event.stopPropagation();
1639    var ajax = this;
1640    if (ajax.ajaxing) {
1641      return;
1642    }
1643    try {
1644      if (ajax.$form) {
1645        if (ajax.setClick) {
1646          element.form.clk = element;
1647        }
1648        ajax.$form.ajaxSubmit(ajax.options);
1649      } else {
1650        ajax.beforeSerialize(ajax.element, ajax.options);
1651        $.ajax(ajax.options);
1652      }
1653    } catch (e) {
1654      ajax.ajaxing = false;
1655      window.alert("An error occurred while attempting to process ".concat(ajax.options.url, ": ").concat(e.message));
1656    }
1657  };
1658  Drupal.Ajax.prototype.beforeSerialize = function (element, options) {
1659    if (this.$form && document.body.contains(this.$form.get(0))) {
1660      var settings = this.settings || drupalSettings;
1661      Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize');
1662    }
1663    options.data[Drupal.Ajax.AJAX_REQUEST_PARAMETER] = 1;
1664    var pageState = drupalSettings.ajaxPageState;
1665    options.data['ajax_page_state[theme]'] = pageState.theme;
1666    options.data['ajax_page_state[theme_token]'] = pageState.theme_token;
1667    options.data['ajax_page_state[libraries]'] = pageState.libraries;
1668  };
1669  Drupal.Ajax.prototype.beforeSubmit = function (formValues, element, options) {};
1670  Drupal.Ajax.prototype.beforeSend = function (xmlhttprequest, options) {
1671    if (this.$form) {
1672      options.extraData = options.extraData || {};
1673      options.extraData.ajax_iframe_upload = '1';
1674      var v = $.fieldValue(this.element);
1675      if (v !== null) {
1676        options.extraData[this.element.name] = v;
1677      }
1678    }
1679    $(this.element).prop('disabled', true);
1680    if (!this.progress || !this.progress.type) {
1681      return;
1682    }
1683    var progressIndicatorMethod = "setProgressIndicator".concat(this.progress.type.slice(0, 1).toUpperCase()).concat(this.progress.type.slice(1).toLowerCase());
1684    if (progressIndicatorMethod in this && typeof this[progressIndicatorMethod] === 'function') {
1685      this[progressIndicatorMethod].call(this);
1686    }
1687  };
1688  Drupal.theme.ajaxProgressThrobber = function (message) {
1689    var messageMarkup = typeof message === 'string' ? Drupal.theme('ajaxProgressMessage', message) : '';
1690    var throbber = '<div class="throbber">&nbsp;</div>';
1691    return "<div class=\"ajax-progress ajax-progress-throbber\">".concat(throbber).concat(messageMarkup, "</div>");
1692  };
1693  Drupal.theme.ajaxProgressIndicatorFullscreen = function () {
1694    return '<div class="ajax-progress ajax-progress-fullscreen">&nbsp;</div>';
1695  };
1696  Drupal.theme.ajaxProgressMessage = function (message) {
1697    return "<div class=\"message\">".concat(message, "</div>");
1698  };
1699  Drupal.theme.ajaxProgressBar = function ($element) {
1700    return $('<div class="ajax-progress ajax-progress-bar"></div>').append($element);
1701  };
1702  Drupal.Ajax.prototype.setProgressIndicatorBar = function () {
1703    var progressBar = new Drupal.ProgressBar("ajax-progress-".concat(this.element.i
1703d), $.noop, this.progress.method, $.noop);
1704    if (this.progress.message) {
1705      progressBar.setProgress(-1, this.progress.message);
1706    }
1707    if (this.progress.url) {
1708      progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
1709    }
1710    this.progress.element = $(Drupal.theme('ajaxProgressBar', progressBar.element));
1711    this.progress.object = progressBar;
1712    $(this.element).after(this.progress.element);
1713  };
1714  Drupal.Ajax.prototype.setProgressIndicatorThrobber = function () {
1715    this.progress.element = $(Drupal.theme('ajaxProgressThrobber', this.progress.message));
1716    $(this.element).after(this.progress.element);
1717  };
1718  Drupal.Ajax.prototype.setProgressIndicatorFullscreen = function () {
1719    this.progress.element = $(Drupal.theme('ajaxProgressIndicatorFullscreen'));
1720    $('body').append(this.progress.element);
1721  };
1722  Drupal.Ajax.prototype.commandExecutionQueue = function (response, status) {
1723    var _this2 = this;
1724    var ajaxCommands = this.commands;
1725    return Object.keys(response || {}).reduce(function (executionQueue, key) {
1726      return executionQueue.then(function () {
1727        var command = response[key].command;
1728        if (command && ajaxCommands[command]) {
1729          return ajaxCommands[command](_this2, response[key], status);
1730        }
1731      });
1732    }, Promise.resolve());
1733  };
1734  Drupal.Ajax.prototype.success = function (response, status) {
1735    var _this3 = this;
1736    if (this.progress.element) {
1737      $(this.progress.element).remove();
1738    }
1739    if (this.progress.object) {
1740      this.progress.object.stopMonitoring();
1741    }
1742    $(this.element).prop('disabled', false);
1743    var elementParents = $(this.element).parents('[data-drupal-selector]').addBack().toArray();
1744    var focusChanged = Object.keys(response || {}).some(function (key) {
1745      var _response$key = response[key],
1746        command = _response$key.command,
1747        method = _response$key.method;
1748      return command === 'focusFirst' || command === 'invoke' && method === 'focus';
1749    });
1750    return this.commandExecutionQueue(response, status).then(function () {
1751      if (!focusChanged && _this3.element && !$(_this3.element).data('disable-refocus')) {
1752        var target = false;
1753        for (var n = elementParents.length - 1; !target && n >= 0; n--) {
1754          target = document.querySelector("[data-drupal-selector=\"".concat(elementParents[n].getAttribute('data-drupal-selector'), "\"]"));
1755        }
1756        if (target) {
1757          $(target).trigger('focus');
1758        }
1759      }
1760      if (_this3.$form && document.body.contains(_this3.$form.get(0))) {
1761        var settings = _this3.settings || drupalSettings;
1762        Drupal.attachBehaviors(_this3.$form.get(0), settings);
1763      }
1764      _this3.settings = null;
1765    }).catch(function (error) {
1766      return console.error(Drupal.t('An error occurred during the execution of the Ajax response: !error', {
1767        '!error': error
1768      }));
1769    });
1770  };
1771  Drupal.Ajax.prototype.getEffect = function (response) {
1772    var type = response.effect || this.effect;
1773    var speed = response.speed || this.speed;
1774    var effect = {};
1775    if (type === 'none') {
1776      effect.showEffect = 'show';
1777      effect.hideEffect = 'hide';
1778      effect.showSpeed = '';
1779    } else if (type === 'fade') {
1780      effect.showEffect = 'fadeIn';
1781      effect.hideEffect = 'fadeOut';
1782      effect.showSpeed = speed;
1783    } else {
1784      effect.showEffect = "".concat(type, "Toggle");
1785      effect.hideEffect = "".concat(type, "Toggle");
1786      effect.showSpeed = speed;
1787    }
1788    return effect;
1789  };
1790  Drupal.Ajax.prototype.error = function (xmlhttprequest, uri, customMessage) {
1791    if (this.progress.element) {
1792      $(this.progress.element).remove();
1793    }
1794    if (this.progress.object) {
1795      this.progress.object.stopMonitoring();
1796    }
1797    $(this.wrapper).show();
1798    $(this.element).prop('disabled', false);
1799    if (this.$form && document.body.contains(this.$form.get(0))) {
1800      var settings = this.settings || drupalSettings;
1801      Drupal.attachBehaviors(this.$form.get(0), settings);
1802    }
1803    throw new Drupal.AjaxError(xmlhttprequest, uri, customMessage);
1804  };
1805  Drupal.theme.ajaxWrapperNewContent = function ($newContent, ajax, response) {
1806    return (response.effect || ajax.effect) !== 'none' && $newContent.filter(function (i) {
1807      return !($newContent[i].nodeName === '#comment' || $newContent[i].nodeName === '#text' && /^(\s|\n|\r)*$/.test($newContent[i].textContent));
1808    }).length > 1 ? Drupal.theme('ajaxWrapperMultipleRootElements', $newContent) : $newContent;
1809  };
1810  Drupal.theme.ajaxWrapperMultipleRootElements = function ($elements) {
1811    return $('<div></div>').append($elements);
1812  };
1813  Drupal.AjaxCommands = function () {};
1814  Drupal.AjaxCommands.prototype = {
1815    insert: function insert(ajax, response) {
1816      var $wrapper = response.selector ? $(response.selector) : $(ajax.wrapper);
1817      var method = response.method || ajax.method;
1818      var effect = ajax.getEffect(response);
1819      var settings = response.settings || ajax.settings || drupalSettings;
1820      var $newContent = $($.parseHTML(response.data, document, true));
1821      $newContent = Drupal.theme('ajaxWrapperNewContent', $newContent, ajax, response);
1822      switch (method) {
1823        case 'html':
1824        case 'replaceWith':
1825        case 'replaceAll':
1826        case 'empty':
1827        case 'remove':
1828          Drupal.detachBehaviors($wrapper.get(0), settings);
1829          break;
1830        default:
1831          break;
1832      }
1833      $wrapper[method]($newContent);
1834      if (effect.showEffect !== 'show') {
1835        $newContent.hide();
1836      }
1837      var $ajaxNewContent = $newContent.find('.ajax-new-content');
1838      if ($ajaxNewContent.length) {
1839        $ajaxNewContent.hide();
1840        $newContent.show();
1841        $ajaxNewContent[effect.showEffect](effect.showSpeed);
1842      } else if (effect.showEffect !== 'show') {
1843        $newContent[effect.showEffect](effect.showSpeed);
1844      }
1845      if ($newContent.parents('html').length) {
1846        $newContent.each(function (index, element) {
1847          if (element.nodeType === Node.ELEMENT_NODE) {
1848            Drupal.attachBehaviors(element, settings);
1849          }
1850        });
1851      }
1852    },
1853    remove: function remove(ajax, response, status) {
1854      var settings = response.settings || ajax.settings || drupalSettings;
1855      $(response.selector).each(function () {
1856        Drupal.detachBehaviors(this, settings);
1857      }).remove();
1858    },
1859    changed: function changed(ajax, response, status) {
1860      var $element = $(response.selector);
1861      if (!$element.hasClass('ajax-changed')) {
1862        $element.addClass('ajax-changed');
1863        if (response.asterisk) {
1864          $element.find(response.asterisk).append(" <abbr class=\"ajax-changed\" title=\"".concat(Drupal.t('Changed'), "\">*</abbr> "));
1865        }
1866      }
1867    },
1868    alert: function alert(ajax, response, status) {
1869      window.alert(response.text);
1870    },
1871    announce: function announce(ajax, response) {
1872      if (response.priority) {
1873        Drupal.announce(response.text, response.priority);
1874      } else {
1875        Drupal.announce(response.text);
1876      }
1877    },
1878    redirect: function redirect(ajax, response, status) {
1879      window.location = response.url;
1880    },
1881    css: function css(ajax, response, status) {
1882      $(response.selector).css(response.argument);
1883    },
1884    settings: function settings(ajax, response, status) {
1885      var ajaxSettings = drupalSettings.ajax;
1886      if (ajaxSettings) {
1887        Drupal.ajax.expired().forEach(function (instance) {
1888          if (instance.selector) {
1889            var selector = instance.selector.replace('#', '');
1890            if (selector in ajaxSettings) {
1891              delete ajaxSettings[selector];
1892            }
1893          }
1894        });
1895      }
1896      if (response.merge) {
1897        $.extend(true, drupalSettings, response.settings);
1898      } else {
1899        ajax.settings = response.settings;
1900      }
1901    },
1902    data: function data(ajax, response, status) {
1903      $(response.selector).data(response.name, response.value);
1904    },
1905    focusFirst: function focusFirst(ajax, response, status) {
1906      var focusChanged = false;
1907      var container = document.querySelector(response.selector);
1908      if (container) {
1909        var tabbableElements = tabbable(container);
1910        if (tabbableElements.length) {
1911          tabbableElements[0].focus();
1912          focusChanged = true;
1913        } else if (isFocusable(container)) {
1914          container.focus();
1915          focusChanged = true;
1916        }
1917      }
1918      if (ajax.hasOwnProperty('element') && !focusChanged) {
1919        ajax.element.focus();
1920      }
1921    },
1922    invoke: function invoke(ajax, response, status) {
1923      var $element = $(response.selector);
1924      $element[response.method].apply($element, _toConsumableArray(response.args));
1925    },
1926    restripe: function restripe(ajax, response, status) {
1927      $(response.selector).find('> tbody > tr:visible, > tr:visible').removeClass('odd even').filter(':even').addClass('odd').end().filter(':odd').addClass('even');
1928    },
1929    update_build_id: function update_build_id(ajax, response, status) {
1930      document.querySelectorAll("input[name=\"form_build_id\"][value=\"".concat(response.old, "\"]")).forEach(function (item) {
1931        item.value = response.new;
1932      });
1933    },
1934    add_css: function add_css(ajax, response, status) {
1935      $('head').prepend(response.data);
1936    },
1937    message: function message(ajax, response) {
1938      var messages = new Drupal.Message(document.querySelector(response.messageWrapperQuerySelector));
1939      if (response.clearPrevious) {
1940        messages.clear();
1941      }
1942      messages.add(response.message, response.messageOptions);
1943    },
1944    add_js: function add_js(ajax, response, status) {
1945      var parentEl = document.querySelector(response.selector || 'body');
1946      var settings = ajax.settings || drupalSettings;
1947      var allUniqueBundleIds = response.data.map(function (script) {
1948        var uniqueBundleId = script.src + ajax.instanceIndex;
1949        loadjs(script.src, uniqueBundleId, {
1950          async: false,
1951          before: function before(path, scriptEl) {
1952            Object.keys(script).forEach(function (attributeKey) {
1953              scriptEl.setAttribute(attributeKey, script[attributeKey]);
1954            });
1955            parentEl.appendChild(scriptEl);
1956            return false;
1957          }
1958        });
1959        return uniqueBundleId;
1960      });
1961      return new Promise(function (resolve, reject) {
1962        loadjs.ready(allUniqueBundleIds, {
1963          success: function success() {
1964            Drupal.attachBehaviors(parentEl, settings);
1965            resolve();
1966          },
1967          error: function error(depsNotFound) {
1968            var message = Drupal.t("The following files could not be loaded: @dependencies", {
1969              '@dependencies': depsNotFound.join(', ')
1970            });
1971            reject(message);
1972          }
1973        });
1974      });
1975    }
1976  };
1977  var stopEvent = function stopEvent(xhr, settings) {
1978    return xhr.getResponseHeader('X-Drupal-Ajax-Token') === '1' && settings.isInProgress && settings.isInProgress();
1979  };
1980  $.extend(true, $.event.special, {
1981    ajaxSuccess: {
1982      trigger: function trigger(event, xhr, settings) {
1983        if (stopEvent(xhr, settings)) {
1984          return false;
1985        }
1986      }
1987    },
1988    ajaxComplete: {
1989      trigger: function trigger(event, xhr, settings) {
1990        if (stopEvent(xhr, settings)) {
1991          $.active++;
1992          return false;
1993        }
1994      }
1995    }
1996  });
1997})(jQuery, window, Drupal, drupalSettings, loadjs, window.tabbable);;
1998/**
1999 * @file
2000 * Extends methods from core/misc/ajax.js.
2001 */
2002
2003(function ($, window, Drupal, drupalSettings) {
2004
2005  /**
2006   * Attempts to find the closest glyphicon progress indicator.
2007   *
2008   * @param {jQuery|Element} element
2009   *   A DOM element.
2010   *
2011   * @returns {jQuery}
2012   *   A jQuery object.
2013   */
2014  Drupal.Ajax.prototype.findGlyphicon = function (element) {
2015    return $(element).closest('.form-item').find('.ajax-progress.glyphicon')
2016  };
2017
2018  /**
2019   * Starts the spinning of the glyphicon progress indicator.
2020   *
2021   * @param {jQuery|Element} element
2022   *   A DOM element.
2023   * @param {string} [message]
2024   *   An optional message to display (tooltip) for the progress.
2025   *
2026   * @returns {jQuery}
2027   *   A jQuery object.
2028   */
2029  Drupal.Ajax.prototype.glyphiconStart = function (element, message) {
2030    var $glyphicon = this.findGlyphicon(element);
2031    if ($glyphicon[0]) {
2032      $glyphicon.addClass('glyphicon-spin');
2033
2034      // Add any message as a tooltip to the glyphicon.
2035      if ($.fn.tooltip && drupalSettings.bootstrap.tooltip_enabled) {
2036        $glyphicon
2037          .removeAttr('data-toggle')
2038          .removeAttr('data-original-title')
2039          .removeAttr('title')
2040          .tooltip('destroy')
2041        ;
2042
2043        if (message) {
2044          $glyphicon.attr('data-toggle', 'tooltip').attr('title', message).tooltip();
2045        }
2046      }
2047
2048      // Append a message for screen readers.
2049      if (message) {
2050        $glyphicon.parent().append('<div class="sr-only message">' + message + '</div>');
2051      }
2052    }
2053    return $glyphicon;
2054  };
2055
2056  /**
2057   * Stop the spinning of a glyphicon progress indicator.
2058   *
2059   * @param {jQuery|Element} element
2060   *   A DOM element.
2061   */
2062  Drupal.Ajax.prototype.glyphiconStop = function (element) {
2063    var $glyphicon = this.findGlyphicon(element);
2064    if ($glyphicon[0]) {
2065      $glyphicon.removeClass('glyphicon-spin');
2066      if ($.fn.tooltip && drupalSettings.bootstrap.tooltip_enabled) {
2067        $glyphicon
2068          .removeAttr('data-toggle')
2069          .removeAttr('data-original-title')
2070          .removeAttr('title')
2071          .tooltip('destroy')
2072        ;
2073      }
2074    }
2075  };
2076
2077  /**
2078   * Sets the throbber progress indicator.
2079   */
2080  Drupal.Ajax.prototype.setProgressIndicatorThrobber = function () {
2081    var $element = $(this.element);
2082
2083    // Find an existing glyphicon progress indicator.
2084    var $glyphicon = this.glyphiconStart($element, this.progress.message);
2085    if ($glyphicon[0]) {
2086      this.progress.element = $glyphicon.parent();
2087      this.progress.glyphicon = true;
2088      return;
2089    }
2090
2091    // Otherwise, add a glyphicon throbber after the element.
2092    if (!this.progress.element) {
2093      this.progress.element = $(Drupal.theme('ajaxThrobber'));
2094    }
2095    if (this.progress.message) {
2096      this.progress.element.after('<div class="message">' + this.progress.message + '</div>');
2097    }
2098
2099    // If element is an input DOM element type (not :input), append after.
2100    if ($element.is('input') || $element.is('select')) {
2101      $element.after(this.progress.element);
2102    }
2103    // Otherwise append the throbber inside the element.
2104    else {
2105      $element.append(this.progress.element);
2106    }
2107  };
2108
2109
2110  /**
2111   * Handler for the form redirection completion.
2112   *
2113   * @param {Array.<Drupal.AjaxCommands~commandDefinition>} response
2114   * @param {number} status
2115   */
2116  var success = Drupal.Ajax.prototype.success;
2117  Drupal.Ajax.prototype.success = function (response, status) {
2118    if (this.progress.element) {
2119
2120      // Remove any message set.
2121      this.progress.element.parent().find('.message').remove();
2122    }
2123
2124    // Invoke the original success handler.
2125    return success.apply(this, [response, status]);
2126  };
2127
2128})(jQuery, this, Drupal, drupalSettings);
2129;
2130/**
2131* DO NOT EDIT THIS FILE.
2132* See the following change record for more information,
2133* https://www.drupal.org/node/2815083
2134* @preserve
2135**/
2136(function ($, Drupal, _ref) {
2137  var isTabbable = _ref.isTabbable;
2138  $.extend($.expr[':'], {
2139    tabbable: function tabbable(element) {
2140      Drupal.deprecationError({
2141        message: 'The :tabbable selector is deprecated in Drupal 9.2.0 and will be removed in Drupal 11.0.0. Use the core/tabbable library instead. See https://www.drupal.org/node/3183730'
2142      });
2143      if (element.tagName === 'SUMMARY' || element.tagName === 'DETAILS') {
2144        var tabIndex = element.getAttribute('tabIndex');
2145        if (tabIndex === null || tabIndex < 0) {
2146          return false;
2147        }
2148      }
2149      return isTabbable(element);
2150    }
2151  });
2152})(jQuery, Drupal, window.tabbable);;
vendor: 327 bytes, lines 2152-2153
2152
2153(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','
2153GTM-KMLH4SZ
vendor: 3 bytes, line 2153
2153');
2153;
2154// Custom scripts file
2155
2156(function ($) {
2157
2158  'use strict';
2159
2160  // Generic function that runs on window resize.
2161  function resizeStuff() {
2162
2163  }
2164
2165  // Runs function once on window resize.
2166  var TO = false;
2167  $(window).resize(function () {
2168    if (TO !== false) {
2169      clearTimeout(TO);
2170    }
2171
2172    // 200 is time in miliseconds.
2173    TO = setTimeout(resizeStuff, 200);
2174  }).resize();
2175
2176  // Count function for the infographic component types
2177  $('.count').each(function () {
2178    $(this).prop('Counter',0).animate({
2179      Counter: $(this).text()
2180    }, {
2181      duration: 3000,
2182      easing: 'swing',
2183      step: function (now) {
2184        $(this).text(Math.ceil(now).toLocaleString('en'));
2185      }
2186    });
2187  });
2188  $("#closeit").click(function() {
2189    $("#shoutbar").slideUp();
2190  });
2191  // $(document).ready(function(){$("#openit").click(function(){$("#shoutbar").effect("bounce","slow");$("#openit").slideUp()})});
2192  // $(document).ready(function(){$("#shoutbar").effect("bounce","slow");$("#closeit").click(function(){$("#shoutbar").slideUp();$("#openit").slideDown()})});
2193})(jQuery);;
2194$ = jQuery;
2195$(function(){
2196    // Add classes to header elements so they can shrink when the page scrolls
2197    var shrinkHeader = 0;
2198    var glitchHeader = 150;
2199    $(window).scroll(function() {
2200        var scroll = getCurrentScroll();
2201        if ( scroll >= glitchHeader ) {
2202            $('header.header').addClass('shrink');
2203            $('.site-logo__grid').addClass('shrink');
2204            // $('.region-midline').addClass('shrink');
2205            // $('.page-wrapper').addClass('shrink');
2206            // $('body.user-logged-in header.header').removeClass('shrink');
2207            // $('body.user-logged-in .site-logo__grid').removeClass('shrink');
2208            // $('body.user-logged-in .region-midline').removeClass('shrink');
2209        }
2210        else if ( scroll <= shrinkHeader ) {
2211            $('header.header').removeClass('shrink');
2212            $('.site-logo__grid').removeClass('shrink');
2213            // $('.region-midline').removeClass('shrink');
2214            // $('.page-wrapper').removeClass('shrink');
2215        }
2216        document.onscroll = scroll;
2217    });
2218    function getCurrentScroll() {
2219        // console.log(scroll);
2220        return window.pageYOffset || document.documentElement.scrollTop;
2221    }
2222
2223    // Add a click function for the ... icon in the footer of the sliding navigation
2224    $("a#toggle").click(function()
2225    {
2226        $(".mm-search").slideToggle();
2227        $(".mm-searchfield").slideToggle();
2228        $(".mmenu_tsesearch").slideToggle();
2229        $(".mmenu_tsecoop").slideToggle();
2230        return false;
2231    });
2232
2233    // Create a clone of the menu, right next to original.
2234    // Clone is used to sync up elements when the header becomes fixed after scrolling 50 pixels vertically down the page
2235    // $('header.header').addClass('original').clone().insertAfter('.header').addClass('cloned').css('position','fixed').css('top','0').css('margin-top','0').css('z-index','500').removeClass('original').hide();
2236    //
2237    // scrollIntervalID = setInterval(stickIt, 10);
2238    //
2239    // function stickIt() {
2240    //
2241    //     var orgElementPos = $('.original').offset();
2242    //     orgElementTop = orgElementPos.top;
2243    //
2244    //     if ($(window).scrollTop() >= (orgElementTop)) {
2245    //         // scrolled past the original position; now only show the cloned, sticky element.
2246    //
2247    //         // Cloned element should always have same left position and width as original element.
2248    //         orgElement = $('.original');
2249    //         coordsOrgElement = orgElement.offset();
2250    //         leftOrgElement = coordsOrgElement.left;
2251    //         widthOrgElement = orgElement.css('width');
2252    //         $('.cloned').css('left',leftOrgElement+'px').css('top',0).css('width',widthOrgElement).show();
2253    //         $('.original').css('visibility','hidden');
2254    //     } else {
2255    //         // not scrolled past the menu; only show the original menu.
2256    //         $('.cloned').hide();
2257    //         $('.original').css('visibility','visible');
2258    //     }
2259    // }
2260});
2261
2262// function rotateCard(btn){
2263//     var $card = $(btn).closest('.card-container');
2264//     console.log($card);
2265//     if($card.hasClass('hover')){
2266//         $card.removeClass('hover');
2267//     } else {
2268//         $card.addClass('hover');
2269//     }
2270// }
2271
2272function rotateCard(btn){
2273    var $card = $(btn).closest('.card-container');
2274    console.log($card);
2275    if($card.hasClass('hover')){
2276        $card.removeClass('hover');
2277    } else {
2278        $card.addClass('hover');
2279    }
2280}
2281
2282// (function ($, undefined) {
2283//     function rotateCard(btn){
2284//         var
2285//             $card = $(btn).closest('.card-container'),
2286//             $toggle = $card.hasClass('hover');
2287//             $card.toggleClass(!$toggle, 'hover');
2288//     }
2289// })(jQuery);;
2290/**
2291 * Due to the construction of the responsive_menu module, there exists no
2292 * API or method of injecting navbar information
2293 */
2294(function ($, undefined) {
2295  'use strict';
2296  /**
2297   * Provides the off-canvas menu.
2298   *
2299   * @type {Drupal~behavior}
2300   *
2301   * @prop {Drupal~behaviorAttach} attach
2302   *   Attaches the behavior for the off-canvas menu.
2303   */
2304  Drupal.behaviors.responsive_menu_mmenu = {
2305    attach: function (context) {
2306      $('body').once('cwb-responsive-menu-mmenu').each(function () {
2307        const mmenuId = '#off-canvas';
2308        const offCanvas = document.querySelector(mmenuId);
2309        const settings = drupalSettings.responsive_menu;
2310        const position = settings.position,
2311          theme = settings.theme,
2312          pagedim = settings.pagedim;
2313
2314        const options = {
2315          extensions: [
2316            theme,
2317            'fx-menu-slide',
2318            position === 'left' ? 'position-left' : 'position-right'
2319          ],
2320          keyboardNavigation: {
2321            enable: true,
2322            enhance: true,
2323          },
2324          drag: {
2325            open: settings.drag
2326          },
2327          navbars: [
2328            {
2329              "position": "bottom",
2330              "content": [
2331                "<a class='glyphicon glyphicon-option-horizontal' href='#' id='toggle' aria-hidden='true'></a>",
2332                "searchfield",
2333                "<div class='mmenu_tsesearch'><p>Can't find what you are looking for?</p><p>Use our instant search to find relevant pages.</p></div>",
2334                "<div class='mmenu_tsecoop'>Touchstone Energy® Cooperatives</div></div>"
2335              ]
2336            }
2337          ]
2338        };
2339
2340        if (pagedim !== 'none') {
2341          options.extensions.push(pagedim);
2342        }
2343
2344        const config = {
2345          classNames: {
2346            selected: 'menu-item--active-trail'
2347          }
2348        };
2349
2350        // Allow the settings and options to be extended or overridden.
2351        if (typeof settings.custom !== 'undefined') {
2352          if (typeof settings.custom.options !== 'undefined') {
2353            extend(options, drupalSettings.responsive_menu.custom.options);
2354          }
2355          if (typeof drupalSettings.responsive_menu.custom.config !== 'undefined') {
2356            extend(config, drupalSettings.responsive_menu.custom.config);
2357          }
2358        }
2359
2360        // Set up the off canvas menu.
2361        const mmenu = new Mmenu(mmenuId, options, config);
2362
2363        // Due to a rendering issue with Chrome the page needs the viewport
2364        // metatag to have a value including initial-scale=1.0 otherwise it
2365        // won't render properly.
2366        // @see issue #3153145
2367        const mmenuApi = mmenu.API;
2368        const viewports = document.getElementsByName('viewport');
2369
2370        if (viewports.length !== 0 && settings.modifyViewport) {
2371          const viewportMeta = viewports[0];
2372          const defaultViewport = viewports[0].content;
2373          const staticViewport = "width=device-width, initial-scale=1.0, minimum-scale=1.0";
2374
2375          mmenuApi.bind('open:start', function () {
2376            viewportMeta.setAttribute('content', staticViewport);
2377          });
2378          mmenuApi.bind('close:start', function () {
2379            viewportMeta.setAttribute('content', defaultViewport);
2380          });
2381        }
2382      });
2383    }
2384  };
2385})(jQuery);
2386;
2387var timeOut;
2388function scrollToTop() {
2389    if (document.body.scrollTop!=0 || document.documentElement.scrollTop!=0){
2390        window.scrollBy(0,-50);
2391        timeOut=setTimeout('scrollToTop()',10);
2392    }
2393    else clearTimeout(timeOut);
2394};
2395(function ($) {
2396
2397    'use strict';
2398
2399    Drupal.behaviors.timeline = {
2400        attach: function (context, settings) {
2401
2402            var $timeline_block = $('.cd-timeline-block');
2403
2404            $('main .cd-timeline-block', context).once('timeline').each(function(){
2405                console.log($(this));
2406
2407                //hide any timeline blocks that are outside of the viewport
2408                if($(this).offset().top > $(window).scrollTop()+$(window).height()*0.75) {
2409                    $(this).find('.cd-timeline-img, .cd-timeline-content').addClass('is-hidden');
2410                }
2411
2412                //on scrolling, show/animate the timeline blocks as they enter the viewport
2413                $(window).on('scroll', function(){
2414                    $timeline_block.each(function(){
2415                        if( $(this).offset().top <= $(window).scrollTop()+$(window).height()*0.75 && $(this).find('.cd-timeline-img').hasClass('is-hidden') ) {
2416                            $(this).find('.cd-timeline-img, .cd-timeline-content').removeClass('is-hidden').addClass('bounce-in');
2417                        }
2418                    });
2419                });
2420            });
2421        }
2422    };
2423})(jQuery);;
2424/**
2425 * @file
2426 * External links js file.
2427 */
2428
2429(function ($, Drupal, drupalSettings) {
2430
2431  'use strict';
2432
2433  Drupal.extlink = Drupal.extlink || {};
2434
2435  Drupal.extlink.attach = function (context, drupalSettings) {
2436    if (typeof drupalSettings.data === 'undefined' || !drupalSettings.data.hasOwnProperty('extlink')) {
2437      return;
2438    }
2439
2440    // Define the jQuery method (either 'append' or 'prepend') of placing the
2441    // icon, defaults to 'append'.
2442    var extIconPlacement = 'append';
2443    if (drupalSettings.data.extlink.extIconPlacement && drupalSettings.data.extlink.extIconPlacement != '0') {
2444          extIconPlacement = drupalSettings.data.extlink.extIconPlacement;
2445        }
2446
2447    // Strip the host name down, removing ports, subdomains, or www.
2448    var pattern = /^(([^\/:]+?\.)*)([^\.:]{1,})((\.[a-z0-9]{1,253})*)(:[0-9]{1,5})?$/;
2449    var host = window.location.host.replace(pattern, '$2$3$6');
2450    var subdomain = window.location.host.replace(host, '');
2451
2452    // Determine what subdomains are considered internal.
2453    var subdomains;
2454    if (drupalSettings.data.extlink.extSubdomains) {
2455      subdomains = '([^/]*\\.)?';
2456    }
2457    else if (subdomain === 'www.' || subdomain === '') {
2458      subdomains = '(www\\.)?';
2459    }
2460    else {
2461      subdomains = subdomain.replace('.', '\\.');
2462    }
2463
2464    // Whitelisted domains.
2465    var whitelistedDomains = false;
2466    if (drupalSettings.data.extlink.whitelistedDomains) {
2467      whitelistedDomains = [];
2468      for (var i = 0; i < drupalSettings.data.extlink.whitelistedDomains.length; i++) {
2469        whitelistedDomains.push(new RegExp('^https?:\\/\\/' + drupalSettings.data.extlink.whitelistedDomains[i].replace(/(\r\n|\n|\r)/gm,'') + '.*$', 'i'));
2470      }
2471    }
2472
2473    // Build regular expressions that define an internal link.
2474    var internal_link = new RegExp('^https?://([^@]*@)?' + subdomains + host, 'i');
2475
2476    // Extra internal link matching.
2477    var extInclude = false;
2478    if (drupalSettings.data.extlink.extInclude) {
2479      extInclude = new RegExp(drupalSettings.data.extlink.extInclude.replace(/\\/, '\\'), 'i');
2480    }
2481
2482    // Extra external link matching.
2483    var extExclude = false;
2484    if (drupalSettings.data.extlink.extExclude) {
2485      extExclude = new RegExp(drupalSettings.data.extlink.extExclude.replace(/\\/, '\\'), 'i');
2486    }
2487
2488    // Extra external link CSS selector exclusion.
2489    var extCssExclude = false;
2490    if (drupalSettings.data.extlink.extCssExclude) {
2491      extCssExclude = drupalSettings.data.extlink.extCssExclude;
2492    }
2493
2494    // Extra external link CSS selector explicit.
2495    var extCssExplicit = false;
2496    if (drupalSettings.data.extlink.extCssExplicit) {
2497      extCssExplicit = drupalSettings.data.extlink.extCssExplicit;
2498    }
2499
2500    // Find all links which are NOT internal and begin with http as opposed
2501    // to ftp://, javascript:, etc. other kinds of links.
2502    // When operating on the 'this' variable, the host has been appended to
2503    // all links by the browser, even local ones.
2504    // In jQuery 1.1 and higher, we'd use a filter method here, but it is not
2505    // available in jQuery 1.0 (Drupal 5 default).
2506    var external_links = [];
2507    var mailto_links = [];
2508    $('a:not([data-extlink]), area:not([data-extlink])', context).each(function (el) {
2509      try {
2510        var url = '';
2511        if (typeof this.href == 'string') {
2512          url = this.href.toLowerCase();
2513        }
2514        // Handle SVG links (xlink:href).
2515        else if (typeof this.href == 'object') {
2516          url = this.href.baseVal;
2517        }
2518        if (url.indexOf('http') === 0
2519          && ((!internal_link.test(url) && !(extExclude && extExclude.test(url))) || (extInclude && extInclude.test(url)))
2520          && !(extCssExclude && $(this).is(extCssExclude))
2521          && !(extCssExclude && $(this).parents(extCssExclude).length > 0)
2522          && !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
2523          var match = false;
2524          if (whitelistedDomains) {
2525            for (var i = 0; i < whitelistedDomains.length; i++) {
2526              if (whitelistedDomains[i].test(url)) {
2527                match = true;
2528                break;
2529              }
2530            }
2531          }
2532          if (!match) {
2533            external_links.push(this);
2534          }
2535        }
2536        // Do not include area tags with begin with mailto: (this prohibits
2537        // icons from being added to image-maps).
2538        else if (this.tagName !== 'AREA'
2539          && url.indexOf('mailto:') === 0
2540          && !(extCssExclude && $(this).parents(extCssExclude).length > 0)
2541          && !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
2542          mailto_links.push(this);
2543        }
2544      }
2545      // IE7 throws errors often when dealing with irregular links, such as:
2546      // <a href="node/10"></a> Empty tags.
2547      // <a href="http://user:[email protected]">example</a> User:pass syntax.
2548      catch (error) {
2549        return false;
2550      }
2551    });
2552
2553    if (drupalSettings.data.extlink.extClass !== '0' && drupalSettings.data.extlink.extClass !== '') {
2554      Drupal.extlink.applyClassAndSpan(external_links, drupalSettings.data.extlink.extClass, extIconPlacement);
2555    }
2556
2557    if (drupalSettings.data.extlink.mailtoClass !== '0' && drupalSettings.data.extlink.mailtoClass !== '') {
2558      Drupal.extlink.applyClassAndSpan(mailto_links, drupalSettings.data.extlink.mailtoClass, extIconPlacement);
2559    }
2560
2561    if (drupalSettings.data.extlink.extTarget) {
2562      // Apply the target attribute to all links.
2563      $(external_links).filter(function () {
2564        // Filter out links with target set if option specified.
2565        return !(drupalSettings.data.extlink.extTargetNoOverride && $(this).is('a[target]'));
2566      }).attr({target: '_blank'});
2567
2568      // Add noopener rel attribute to combat phishing.
2569      $(external_links).attr('rel', function (i, val) {
2570        // If no rel attribute is present, create one with the value noopener.
2571        if (val === null || typeof val === 'undefined') {
2572          return 'noopener';
2573        }
2574        // Check to see if rel contains noopener. Add what doesn't exist.
2575        if (val.indexOf('noopener') > -1) {
2576          if (val.indexOf('noopener') === -1) {
2577            return val + ' noopener';
2578          }
2579          // Noopener exists. Nothing needs to be added.
2580          else {
2581            return val;
2582          }
2583        }
2584        // Else, append noopener to val.
2585        else {
2586          return val + ' noopener';
2587        }
2588      });
2589    }
2590
2591    if (drupalSettings.data.extlink.extNofollow) {
2592      $(external_links).attr('rel', function (i, val) {
2593        // When the link does not have a rel attribute set it to 'nofollow'.
2594        if (val === null || typeof val === 'undefined') {
2595          return 'nofollow';
2596        }
2597        var target = 'nofollow';
2598        // Change the target, if not overriding follow.
2599        if (drupalSettings.data.extlink.extFollowNoOverride) {
2600          target = 'follow';
2601        }
2602        if (val.indexOf(target) === -1) {
2603          return val + ' nofollow';
2604        }
2605        return val;
2606      });
2607    }
2608
2609    if (drupalSettings.data.extlink.extNoreferrer) {
2610      $(external_links).attr('rel', function (i, val) {
2611        // When the link does not have a rel attribute set it to 'noreferrer'.
2612        if (val === null || typeof val === 'undefined') {
2613          return 'noreferrer';
2614        }
2615        if (val.indexOf('noreferrer') === -1) {
2616          return val + ' noreferrer';
2617        }
2618        return val;
2619      });
2620    }
2621
2622    Drupal.extlink = Drupal.extlink || {};
2623
2624    // Set up default click function for the external links popup. This should be
2625    // overridden by modules wanting to alter the popup.
2626    Drupal.extlink.popupClickHandler = Drupal.extlink.popupClickHandler || function () {
2627      if (drupalSettings.data.extlink.extAlert) {
2628        return confirm(drupalSettings.data.extlink.extAlertText);
2629      }
2630    };
2631
2632    $(external_links).off("click.extlink");
2633    $(external_links).on("click.extlink", function (e) {
2634      return Drupal.extlink.popupClickHandler(e, this);
2635    });
2636  };
2637
2638  /**
2639   * Apply a class and a trailing <span> to all links not containing images.
2640   *
2641   * @param {object[]} links
2642   *   An array of DOM elements representing the links.
2643   * @param {string} class_name
2644   *   The class to apply to the links.
2645   * @param {string} icon_placement
2646   *   'append' or 'prepend' the icon to the link.
2647   */
2648  Drupal.extlink.applyClassAndSpan = function (links, class_name, icon_placement) {
2649    var $links_to_process;
2650    if (drupalSettings.data.extlink.extImgClass) {
2651      $links_to_process = $(links);
2652    }
2653    else {
2654      var links_with_images = $(links).find('img, svg').parents('a');
2655      $links_to_process = $(links).not(links_with_images);
2656    }
2657
2658    if (class_name !== '0') {
2659      $links_to_process.addClass(class_name);
2660    }
2661
2662    // Add data-extlink attribute.
2663    $links_to_process.attr('data-extlink', '');
2664
2665    var i;
2666    var length = $links_to_process.length;
2667    for (i = 0; i < length; i++) {
2668      var $link = $($links_to_process[i]);
2669      if (drupalSettings.data.extlink.extUseFontAwesome) {
2670        if (class_name === drupalSettings.data.extlink.mailtoClass) {
2671          $link[icon_placement]('<span class="fa-' + class_name + ' extlink"><span class="' + drupalSettings.data.extlink.extFaMailtoClasses + '" aria-label="' + drupalSettings.data.extlink.mailtoLabel + '"></span></span>');
2672        }
2673        else {
2674          $link[icon_placement]('<span class="fa-' + class_name + ' extlink"><span class="' + drupalSettings.data.extlink.extFaLinkClasses + '" aria-label="' + drupalSettings.data.extlink.extLabel + '"></span></span>');
2675        }
2676      }
2677      else {
2678        if (class_name === drupalSettings.data.extlink.mailtoClass) {
2679          $link[icon_placement]('<svg focusable="false" class="' + class_name + '" role="img" aria-label="' + drupalSettings.data.extlink.mailtoLabel + '" xmlns="http://www.w3.org/2000/svg" viewBox="0 10 70 20"><metadata><sfw xmlns="http://ns.adobe.com/SaveForWeb/1.0/"><sliceSourceBounds y="-8160" x="-8165" width="16389" height="16384" bottomLeftOrigin="true"/><optimizationSettings><targetSettings targetSettingsID="0" fileFormat="PNG24Format"><PNG24Format transparency="true" filtered="false" interlaced="false" noMatteColor="false" matteColor="#FFFFFF"/></targetSettings></optimizationSettings></sfw></metadata><title>' + drupalSettings.data.extlink.mailtoLabel + '</title><path d="M56 14H8c-1.1 0-2 0.9-2 2v32c0 1.1 0.9 2 2 2h48c1.1 0 2-0.9 2-2V16C58 14.9 57.1 14 56 14zM50.5 18L32 33.4 13.5 18H50.5zM10 46V20.3l20.7 17.3C31.1 37.8 31.5 38 32 38s0.9-0.2 1.3-0.5L54 20.3V46H10z"/></svg>');
2680        }
2681        else {
2682          $link[icon_placement]('<svg focusable="false" class="' + class_name + '" role="img" aria-label="' + drupalSettings.data.extlink.extLabel + '" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 40"><metadata><sfw xmlns="http://ns.adobe.com/SaveForWeb/1.0/"><sliceSourceBounds y="-8160" x="-8165" width="16389" height="16384" bottomLeftOrigin="true"/><optimizationSettings><targetSettings targetSettingsID="0" fileFormat="PNG24Format"><PNG24Format transparency="true" filtered="false" interlaced="false" noMatteColor="false" matteColor="#FFFFFF"/></targetSettings></optimizationSettings></sfw></metadata><title>' + drupalSettings.data.extlink.extLabel + '</title><path d="M48 26c-1.1 0-2 0.9-2 2v26H10V18h26c1.1 0 2-0.9 2-2s-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v40c0 1.1 0.9 2 2 2h40c1.1 0 2-0.9 2-2V28C50 26.9 49.1 26 48 26z"/><path d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"/></svg>');
2683        }
2684      }
2685    }
2686  };
2687
2688  Drupal.behaviors.extlink = Drupal.behaviors.extlink || {};
2689  Drupal.behaviors.extlink.attach = function (context, drupalSettings) {
2690    // Backwards compatibility, for the benefit of modules overriding extlink
2691    // functionality by defining an "extlinkAttach" global function.
2692    if (typeof extlinkAttach === 'function') {
2693      extlinkAttach(context);
2694    }
2695    else {
2696      Drupal.extlink.attach(context, drupalSettings);
2697    }
2698  };
2699
2700})(jQuery, Drupal, drupalSettings);
2701;
2702/**
2703 * @file
2704 * Webform behaviors.
2705 */
2706
2707(function ($, Drupal) {
2708
2709  'use strict';
2710
2711  // Trigger Drupal's attaching of behaviors after the page is
2712  // completely loaded.
2713  // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button
2714  // @see https://stackoverflow.com/questions/20899274/how-to-refresh-page-on-back-button-click/20899422#20899422
2715  var isChrome = (/chrom(e|ium)/.test(window.navigator.userAgent.toLowerCase()));
2716  if (isChrome) {
2717    // Track back button in navigation.
2718    // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button
2719    var backButton = false;
2720    if (window.performance) {
2721      var navEntries = window.performance.getEntriesByType('navigation');
2722      if (navEntries.length > 0 && navEntries[0].type === 'back_forward') {
2723        backButton = true;
2724      }
2725      else if (window.performance.navigation
2726        && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) {
2727        backButton = true;
2728      }
2729    }
2730
2731    // If the back button is pressed, delay Drupal's attaching of behaviors.
2732    if (backButton) {
2733      var attachBehaviors = Drupal.attachBehaviors;
2734      Drupal.attachBehaviors = function (context, settings) {
2735        setTimeout(function (context, settings) {
2736          attachBehaviors(context, settings);
2737        }, 300);
2738      };
2739    }
2740  }
2741
2742})(jQuery, Drupal);
2743;
2744/**
2745* DO NOT EDIT THIS FILE.
2746* See the following change record for more information,
2747* https://www.drupal.org/node/2815083
2748* @preserve
2749**/
2750(function ($, Drupal) {
2751  var states = {
2752    postponed: []
2753  };
2754  Drupal.states = states;
2755  function invert(a, invertState) {
2756    return invertState && typeof a !== 'undefined' ? !a : a;
2757  }
2758  function _compare2(a, b) {
2759    if (a === b) {
2760      return typeof a === 'undefined' ? a : true;
2761    }
2762    return typeof a === 'undefined' || typeof b === 'undefined';
2763  }
2764  function ternary(a, b) {
2765    if (typeof a === 'undefined') {
2766      return b;
2767    }
2768    if (typeof b === 'undefined') {
2769      return a;
2770    }
2771    return a && b;
2772  }
2773  Drupal.behaviors.states = {
2774    attach: function attach(context, settings) {
2775      var $states = $(context).find('[data-drupal-states]');
2776      var il = $states.length;
2777      var _loop = function _loop(i) {
2778        var config = JSON.parse($states[i].getAttribute('data-drupal-states'));
2779        Object.keys(config || {}).forEach(function (state) {
2780          new states.Dependent({
2781            element: $($states[i]),
2782            state: states.State.sanitize(state),
2783            constraints: config[state]
2784          });
2785        });
2786      };
2787      for (var i = 0; i < il; i++) {
2788        _loop(i);
2789      }
2790      while (states.postponed.length) {
2791        states.postponed.shift()();
2792      }
2793    }
2794  };
2795  states.Dependent = function (args) {
2796    var _this = this;
2797    $.extend(this, {
2798      values: {},
2799      oldValue: null
2800    }, args);
2801    this.dependees = this.getDependees();
2802    Object.keys(this.dependees || {}).forEach(function (selector) {
2803      _this.initializeDependee(selector, _this.dependees[selector]);
2804    });
2805  };
2806  states.Dependent.comparisons = {
2807    RegExp: function RegExp(reference, value) {
2808      return reference.test(value);
2809    },
2810    Function: function Function(reference, value) {
2811      return reference(value);
2812    },
2813    Number: function Number(reference, value) {
2814      return typeof value === 'string' ? _compare2(reference.toString(), value) : _compare2(reference, value);
2815    }
2816  };
2817  states.Dependent.prototype = {
2818    initializeDependee: function initializeDependee(selector, dependeeStates) {
2819      var _this2 = this;
2820      this.values[selector] = {};
2821      Object.keys(dependeeStates).forEach(function (i) {
2822        var state = dependeeStates[i];
2823        if ($.inArray(state, dependeeStates) === -1) {
2824          return;
2825        }
2826        state = states.State.sanitize(state);
2827        _this2.values[selector][state.name] = null;
2828        $(selector).on("state:".concat(state), {
2829          selector: selector,
2830          state: state
2831        }, function (e) {
2832          _this2.update(e.data.selector, e.data.state, e.value);
2833        });
2834        new states.Trigger({
2835          selector: selector,
2836          state: state
2837        });
2838      });
2839    },
2840    compare: function compare(reference, selector, state) {
2841      var value = this.values[selector][state.name];
2842      if (reference.constructor.name in states.Dependent.comparisons) {
2843        return states.Dependent.comparisons[reference.constructor.name](reference, value);
2844      }
2845      return _compare2(reference, value);
2846    },
2847    update: function update(selector, state, value) {
2848      if (value !== this.values[selector][state.name]) {
2849        this.values[selector][state.name] = value;
2850        this.reevaluate();
2851      }
2852    },
2853    reevaluate: function reevaluate() {
2854      var value = this.verifyConstraints(this.constraints);
2855      if (value !== this.oldValue) {
2856        this.oldValue = value;
2857        value = invert(value, this.state.invert);
2858        this.element.trigger({
2859          type: "state:".concat(this.state),
2860          value: value,
2861          trigger: true
2862        });
2863      }
2864    },
2865    verifyConstraints: function verifyConstraints(constraints, selector) {
2866      var result;
2867      if ($.isArray(constraints)) {
2868        var hasXor = $.inArray('xor', constraints) === -1;
2869        var len = constraints.length;
2870        for (var i = 0; i < len; i++) {
2871          if (constraints[i] !== 'xor') {
2872            var constraint = this.checkConstraints(constraints[i], selector, i);
2873            if (constraint && (hasXor || result)) {
2874              return hasXor;
2875            }
2876            result = result || constraint;
2877          }
2878        }
2879      } else if ($.isPlainObject(constraints)) {
2880        for (var n in constraints) {
2881          if (constraints.hasOwnProperty(n)) {
2882            result = ternary(result, this.checkConstraints(constraints[n], selector, n));
2883            if (result === false) {
2884              return false;
2885            }
2886          }
2887        }
2888      }
2889      return result;
2890    },
2891    checkConstraints: function checkConstraints(value, selector, state) {
2892      if (typeof state !== 'string' || /[0-9]/.test(state[0])) {
2893        state = null;
2894      } else if (typeof selector === 'undefined') {
2895        selector = state;
2896        state = null;
2897      }
2898      if (state !== null) {
2899        state = states.State.sanitize(state);
2900        return invert(this.compare(value, selector, state), state.invert);
2901      }
2902      return this.verifyConstraints(value, selector);
2903    },
2904    getDependees: function getDependees() {
2905      var cache = {};
2906      var _compare = this.compare;
2907      this.compare = function (reference, selector, state) {
2908        (cache[selector] || (cache[selector] = [])).push(state.name);
2909      };
2910      this.verifyConstraints(this.constraints);
2911      this.compare = _compare;
2912      return cache;
2913    }
2914  };
2915  states.Trigger = function (args) {
2916    $.extend(this, args);
2917    if (this.state in states.Trigger.states) {
2918      this.element = $(this.selector);
2919      if (!this.element.data("trigger:".concat(this.state))) {
2920        this.initialize();
2921      }
2922    }
2923  };
2924  states.Trigger.prototype = {
2925    initialize: function initialize() {
2926      var _this3 = this;
2927      var trigger = states.Trigger.states[this.state];
2928      if (typeof trigger === 'function') {
2929        trigger.call(window, this.element);
2930      } else {
2931        Object.keys(trigger || {}).forEach(function (event) {
2932          _this3.defaultTrigger(event, trigger[event]);
2933        });
2934      }
2935      this.element.data("trigger:".concat(this.state), true);
2936    },
2937    defaultTrigger: function defaultTrigger(event, valueFn) {
2938      var oldValue = valueFn.call(this.element);
2939      this.element.on(event, $.proxy(function (e) {
2940        var value = valueFn.call(this.element, e);
2941        if (oldValue !== value) {
2942          this.element.trigger({
2943            type: "state:".concat(this.state),
2944            value: value,
2945            oldValue: oldValue
2946          });
2947          oldValue = value;
2948        }
2949      }, this));
2950      states.postponed.push($.proxy(function () {
2951        this.element.trigger({
2952          type: "state:".concat(this.state),
2953          value: oldValue,
2954          oldValue: null
2955        });
2956      }, this));
2957    }
2958  };
2959  states.Trigger.states = {
2960    empty: {
2961      keyup: function keyup() {
2962        return this.val() === '';
2963      },
2964      change: function change() {
2965        return this.val() === '';
2966      }
2967    },
2968    checked: {
2969      change: function change() {
2970        var checked = false;
2971        this.each(function () {
2972          checked = $(this).prop('checked');
2973          return !checked;
2974        });
2975        return checked;
2976      }
2977    },
2978    value: {
2979      keyup: function keyup() {
2980        if (this.length > 1) {
2981          return this.filter(':checked').val() || false;
2982        }
2983        return this.val();
2984      },
2985      change: function change() {
2986        if (this.length > 1) {
2987          return this.filter(':checked').val() || false;
2988        }
2989        return this.val();
2990      }
2991    },
2992    collapsed: {
2993      collapsed: function collapsed(e) {
2994        return typeof e !== 'undefined' && 'value' in e ? e.value : !this.is('[open]');
2995      }
2996    }
2997  };
2998  states.State = function (state) {
2999    this.pristine = state;
3000    this.name = state;
3001    var process = true;
3002    do {
3003      while (this.name.charAt(0) === '!') {
3004        this.name = this.name.substring(1);
3005        this.invert = !this.invert;
3006      }
3007      if (this.name in states.State.aliases) {
3008        this.name = states.State.aliases[this.name];
3009      } else {
3010        process = false;
3011      }
3012    } while (process);
3013  };
3014  states.State.sanitize = function (state) {
3015    if (state instanceof states.State) {
3016      return state;
3017    }
3018    return new states.State(state);
3019  };
3020  states.State.aliases = {
3021    enabled: '!disabled',
3022    invisible: '!visible',
3023    invalid: '!valid',
3024    untouched: '!touched',
3025    optional: '!required',
3026    filled: '!empty',
3027    unchecked: '!checked',
3028    irrelevant: '!relevant',
3029    expanded: '!collapsed',
3030    open: '!collapsed',
3031    closed: 'collapsed',
3032    readwrite: '!readonly'
3033  };
3034  states.State.prototype = {
3035    invert: false,
3036    toString: function toString() {
3037      return this.name;
3038    }
3039  };
3040  var $document = $(document);
3041  $document.on('state:disabled', function (e) {
3042    if (e.trigger) {
3043      $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value).find('select, input, textarea').prop('disabled', e.value);
3044    }
3045  });
3046  $document.on('state:required', function (e) {
3047    if (e.trigger) {
3048      if (e.value) {
3049        var label = "label".concat(e.target.id ? "[for=".concat(e.target.id, "]") : '');
3050        var $label = $(e.target).attr({
3051          required: 'required',
3052          'aria-required': 'true'
3053        }).closest('.js-form-item, .js-form-wrapper').find(label);
3054        if (!$label.hasClass('js-form-required').length) {
3055          $label.addClass('js-form-required form-required');
3056        }
3057      } else {
3058        $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required');
3059      }
3060    }
3061  });
3062  $document.on('state:visible', function (e) {
3063    if (e.trigger) {
3064      $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggle(e.value);
3065    }
3066  });
3067  $document.on('state:checked', function (e) {
3068    if (e.trigger) {
3069      $(e.target).closest('.js-form-item, .js-form-wrapper').find('input').prop('checked', e.value).trigger('change');
3070    }
3071  });
3072  $document.on('state:collapsed', function (e) {
3073    if (e.trigger) {
3074      if ($(e.target).is('[open]') === e.value) {
3075        $(e.target).find('> summary').trigger('click');
3076      }
3077    }
3078  });
3079})(jQuery, Drupal);;
3080/**
3081 * @file
3082 * Extends core/misc/states.js.
3083 */
3084(function($) {
3085
3086  // Unbind core state.js from document first so we can then override below.
3087  $(document).unbind('state:disabled');
3088
3089  /**
3090   * Global state change handlers. These are bound to "document" to cover all
3091   * elements whose state changes. Events sent to elements within the page
3092   * bubble up to these handlers. We use this system so that themes and modules
3093   * can override these state change handlers for particular parts of a page.
3094   */
3095  $(document).bind('state:disabled', function(e) {
3096    // Only act when this change was triggered by a dependency and not by the
3097    // element monitoring itself.
3098    if (e.trigger) {
3099      $(e.target)
3100        .attr('disabled', e.value)
3101        .closest('.form-item, .form-submit, .form-wrapper').toggleClass('form-disabled', e.value)
3102        .find(':input').attr('disabled', e.value);
3103
3104      // Note: WebKit nightlies don't reflect that change correctly.
3105      // See https://bugs.webkit.org/show_bug.cgi?id=23789
3106    }
3107  });
3108
3109})(jQuery);
3110;
3111/**
3112 * @file
3113 * JavaScript behaviors for custom webform #states.
3114 */
3115
3116(function ($, Drupal, once) {
3117
3118  'use strict';
3119
3120  Drupal.webform = Drupal.webform || {};
3121  Drupal.webform.states = Drupal.webform.states || {};
3122  Drupal.webform.states.slideDown = Drupal.webform.states.slideDown || {};
3123  Drupal.webform.states.slideDown.duration = 'slow';
3124  Drupal.webform.states.slideUp = Drupal.webform.states.slideUp || {};
3125  Drupal.webform.states.slideUp.duration = 'fast';
3126
3127  /* ************************************************************************ */
3128  // jQuery functions.
3129  /* ************************************************************************ */
3130
3131  /**
3132   * Check if an element has a specified data attribute.
3133   *
3134   * @param {string} data
3135   *   The data attribute name.
3136   *
3137   * @return {boolean}
3138   *   TRUE if an element has a specified data attribute.
3139   */
3140  $.fn.hasData = function (data) {
3141    return (typeof this.data(data) !== 'undefined');
3142  };
3143
3144  /**
3145   * Check if element is within the webform or not.
3146   *
3147   * @return {boolean}
3148   *   TRUE if element is within the webform.
3149   */
3150  $.fn.isWebform = function () {
3151    return $(this).closest('form.webform-submission-form, form[id^="webform"], form[data-is-webform]').length ? true : false;
3152  };
3153
3154  /**
3155   * Check if element is to be treated as a webform element.
3156   *
3157   * @return {boolean}
3158   *   TRUE if element is to be treated as a webform element.
3159   */
3160  $.fn.isWebformElement = function () {
3161    return ($(this).isWebform() || $(this).closest('[data-is-webform-element]').length) ? true : false;
3162  };
3163
3164  /* ************************************************************************ */
3165  // Trigger.
3166  /* ************************************************************************ */
3167
3168  // The change event is triggered by cut-n-paste and select menus.
3169  // Issue #2445271: #states element empty check not triggered on mouse
3170  // based paste.
3171  // @see https://www.drupal.org/node/2445271
3172  Drupal.states.Trigger.states.empty.change = function change() {
3173    return this.val() === '';
3174  };
3175
3176  /* ************************************************************************ */
3177  // Dependents.
3178  /* ************************************************************************ */
3179
3180  // Apply solution included in #1962800 patch.
3181  // Issue #1962800: Form #states not working with literal integers as
3182  // values in IE11.
3183  // @see https://www.drupal.org/project/drupal/issues/1962800
3184  // @see https://www.drupal.org/files/issues/core-states-not-working-with-integers-ie11_1962800_46.patch
3185  //
3186  // This issue causes pattern, less than, and greater than support to break.
3187  // @see https://www.drupal.org/project/webform/issues/2981724
3188  var states = Drupal.states;
3189  Drupal.states.Dependent.prototype.compare = function compare(reference, selector, state) {
3190    var value = this.values[selector][state.name];
3191
3192    var name = reference.constructor.name;
3193    if (!name) {
3194      name = $.type(reference);
3195
3196      name = name.charAt(0).toUpperCase() + name.slice(1);
3197    }
3198    if (name in states.Dependent.comparisons) {
3199      return states.Dependent.comparisons[name](reference, value);
3200    }
3201
3202    if (reference.constructor.name in states.Dependent.comparisons) {
3203      return states.Dependent.comparisons[reference.constructor.name](reference, value);
3204    }
3205
3206    return _compare2(reference, value);
3207  };
3208  function _compare2(a, b) {
3209    if (a === b) {
3210      return typeof a === 'undefined' ? a : true;
3211    }
3212
3213    return typeof a === 'undefined' || typeof b === 'undefined';
3214  }
3215
3216  // Adds pattern, less than, and greater than support to #state API.
3217  // @see http://drupalsun.com/julia-evans/2012/03/09/extending-form-api-states-regular-expressions
3218  Drupal.states.Dependent.comparisons.Object = function (reference, value) {
3219    if ('pattern' in reference) {
3220      return (new RegExp(reference['pattern'])).test(value);
3221    }
3222    else if ('!pattern' in reference) {
3223      return !((new RegExp(reference['!pattern'])).test(value));
3224    }
3225    else if ('less' in reference) {
3226      return (value !== '' && parseFloat(reference['less']) > parseFloat(value));
3227    }
3228    else if ('less_equal' in reference) {
3229      return (value !== '' && parseFloat(reference['less_equal']) >= parseFloat(value));
3230    }
3231    else if ('greater' in reference) {
3232      return (value !== '' && parseFloat(reference['greater']) < parseFloat(value));
3233    }
3234    else if ('greater_equal' in reference) {
3235      return (value !== '' && parseFloat(reference['greater_equal']) <= parseFloat(value));
3236    }
3237    else if ('between' in reference || '!between' in reference) {
3238      if (value === '') {
3239        return false;
3240      }
3241
3242      var between = reference['between'] || reference['!between'];
3243      var betweenParts = between.split(':');
3244      var greater = betweenParts[0];
3245      var less = (typeof betweenParts[1] !== 'undefined') ? betweenParts[1] : null;
3246      var isGreaterThan = (greater === null || greater === '' || parseFloat(value) >= parseFloat(greater));
3247      var isLessThan = (less === null || less === '' || parseFloat(value) <= parseFloat(less));
3248      var result = (isGreaterThan && isLessThan);
3249      return (reference['!between']) ? !result : result;
3250    }
3251    else {
3252      return reference.indexOf(value) !== false;
3253    }
3254  };
3255
3256  /* ************************************************************************ */
3257  // States events.
3258  /* ************************************************************************ */
3259
3260  var $document = $(document);
3261
3262  $document.on('state:required', function (e) {
3263    if (e.trigger && $(e.target).isWebformElement()) {
3264      var $target = $(e.target);
3265      // Fix #required file upload.
3266      // @see Issue #2860529: Conditional required File upload field don't work.
3267      toggleRequired($target.find('input[type="file"]'), e.value);
3268
3269      // Fix #required for radios and likert.
3270      // @see Issue #2856795: If radio buttons are required but not filled form is nevertheless submitted.
3271      if ($target.is('.js-form-type-radios, .js-form-type-webform-radios-other, .js-webform-type-radios, .js-webform-type-webform-radios-other, .js-webform-type-webform-entity-radios, .webform-likert-table')) {
3272        $target.toggleClass('required', e.value);
3273        toggleRequired($target.find('input[type="radio"]'), e.value);
3274      }
3275
3276      // Fix #required for checkboxes.
3277      // @see Issue #2938414: Checkboxes don't support #states required.
3278      // @see checkboxRequiredhandler
3279      if ($target.is('.js-form-type-checkboxes, .js-form-type-webform-checkboxes-other, .js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other')) {
3280        $target.toggleClass('required', e.value);
3281        var $checkboxes = $target.find('input[type="checkbox"]');
3282        if (e.value) {
3283          // Add event handler.
3284          $checkboxes.on('click', statesCheckboxesRequiredEventHandler);
3285          // Initialize and add required attribute.
3286          checkboxesRequired($target);
3287        }
3288        else {
3289          // Remove event handler.
3290          $checkboxes.off('click', statesCheckboxesRequiredEventHandler);
3291          // Remove required attribute.
3292          toggleRequired($checkboxes, false);
3293        }
3294      }
3295
3296      // Fix #required for tableselect.
3297      // @see Issue #3212581: Table select does not trigger client side validation
3298      if ($target.is('.js-webform-tableselect')) {
3299        $target.toggleClass('required', e.value);
3300        var isMultiple = $target.is('[multiple]');
3301        if (isMultiple) {
3302          // Checkboxes.
3303          var $tbody = $target.find('tbody');
3304          var $checkboxes = $tbody.find('input[type="checkbox"]');
3305          copyRequireMessage($target, $checkboxes);
3306          if (e.value) {
3307            $checkboxes.on('click change', statesCheckboxesRequiredEventHandler);
3308            checkboxesRequired($tbody);
3309          }
3310          else {
3311            $checkboxes.off('click change ', statesCheckboxesRequiredEventHandler);
3312            toggleRequired($tbody, false);
3313          }
3314        }
3315        else {
3316          // Radios.
3317          var $radios = $target.find('input[type="radio"]');
3318          copyRequireMessage($target, $radios);
3319          toggleRequired($radios, e.value);
3320        }
3321      }
3322
3323      // Fix required label for elements without the for attribute.
3324      // @see Issue #3145300: Conditional Visible Select Other not working.
3325      if ($target.is('.js-form-type-webform-select-other, .js-webform-type-webform-select-other')) {
3326        var $select = $target.find('select');
3327        toggleRequired($select, e.value);
3328        copyRequireMessage($target, $select);
3329      }
3330      if ($target.find('> label:not([for])').length) {
3331        $target.find('> label').toggleClass('js-form-required form-required', e.value);
3332      }
3333
3334      // Fix required label for checkboxes and radios.
3335      // @see Issue #2938414: Checkboxes don't support #states required
3336      // @see Issue #2731991: Setting required on radios marks all options required.
3337      // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset.
3338      // Fix #required for fieldsets.
3339      // @see Issue #2977569: Hidden fieldsets that become visible with conditional logic cannot be made required.
3340      if ($target.is('.js-webform-type-radios, .js-webform-type-checkboxes, fieldset')) {
3341        $target.find('legend span.fieldset-legend:not(.visually-hidden),legend span.fieldset__label:not(.visually-hidden)').toggleClass('js-form-required form-required', e.value);
3342      }
3343
3344      // Issue #2986017: Fieldsets shouldn't have required attribute.
3345      if ($target.is('fieldset')) {
3346        $target.removeAttr('required aria-required');
3347      }
3348    }
3349  });
3350
3351  $document.on('state:checked', function (e) {
3352    if (e.trigger) {
3353      $(e.target).trigger('change');
3354    }
3355  });
3356
3357  $document.on('state:readonly', function (e) {
3358    if (e.trigger && $(e.target).isWebformElement()) {
3359      $(e.target).prop('readonly', e.value).closest('.js-form-item, .js-form-wrapper').toggleClass('webform-readonly', e.value).find('input, textarea').prop('readonly', e.value);
3360
3361      // Trigger webform:readonly.
3362      $(e.target).trigger('webform:readonly')
3363        .find('select, input, textarea, button').trigger('webform:readonly');
3364    }
3365  });
3366
3367  $document.on('state:visible state:visible-slide', function (e) {
3368    if (e.trigger && $(e.target).isWebformElement()) {
3369      if (e.value) {
3370        $(':input', e.target).addBack().each(function () {
3371          restoreValueAndRequired(this);
3372          triggerEventHandlers(this);
3373        });
3374      }
3375      else {
3376        // @see https://www.sitepoint.com/jquery-function-clear-form-data/
3377        $(':input', e.target).addBack().each(function () {
3378          backupValueAndRequired(this);
3379          clearValueAndRequired(this);
3380          triggerEventHandlers(this);
3381        });
3382      }
3383    }
3384  });
3385
3386  $document.on('state:visible-slide', function (e) {
3387    if (e.trigger && $(e.target).isWebformElement()) {
3388      var effect = e.value ? 'slideDown' : 'slideUp';
3389      var duration = Drupal.webform.states[effect].duration;
3390      $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper')[effect](duration);
3391    }
3392  });
3393  Drupal.states.State.aliases['invisible-slide'] = '!visible-slide';
3394
3395  $document.on('state:disabled', function (e) {
3396    if (e.trigger && $(e.target).isWebformElement()) {
3397      // Make sure disabled property is set before triggering webform:disabled.
3398      // Copied from: core/misc/states.js
3399      $(e.target)
3400        .prop('disabled', e.value)
3401        .closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value)
3402        .find('select, input, textarea, button').prop('disabled', e.value);
3403
3404      // Never disable hidden file[fids] because the existing values will
3405      // be completely lost when the webform is submitted.
3406      var fileElements = $(e.target)
3407        .find(':input[type="hidden"][name$="[fids]"]');
3408      if (fileElements.length) {
3409        // Remove 'disabled' attribute from fieldset which will block
3410        // all disabled elements from being submitted.
3411        if ($(e.target).is('fieldset')) {
3412          $(e.target).prop('disabled', false);
3413        }
3414        fileElements.removeAttr('disabled');
3415      }
3416
3417      // Trigger webform:disabled.
3418      $(e.target).trigger('webform:disabled')
3419        .find('select, input, textarea, button').trigger('webform:disabled');
3420    }
3421  });
3422
3423  /* ************************************************************************ */
3424  // Behaviors.
3425  /* ************************************************************************ */
3426
3427  /**
3428   * Adds HTML5 validation to required checkboxes.
3429   *
3430   * @type {Drupal~behavior}
3431   *
3432   * @see https://www.drupal.org/project/webform/issues/3068998
3433   */
3434  Drupal.behaviors.webformCheckboxesRequired = {
3435    attach: function (context) {
3436      $(once('webform-checkboxes-required', '.js-form-type-checkboxes.required, .js-form-type-webform-checkboxes-other.required, .js-webform-type-checkboxes.required, .js-webform-type-webform-checkboxes-other.required, .js-webform-type-webform-radios-other.checkboxes', context))
3437        .each(function () {
3438          var $element = $(this);
3439          $element.find('input[type="checkbox"]').on('click', statesCheckboxesRequiredEventHandler);
3440          setTimeout(function () {checkboxesRequired($element);});
3441        });
3442    }
3443  };
3444
3445  /**
3446   * Adds HTML5 validation to required radios.
3447   *
3448   * @type {Drupal~behavior}
3449   *
3450   * @see https://www.drupal.org/project/webform/issues/2856795
3451   */
3452  Drupal.behaviors.webformRadiosRequired = {
3453    attach: function (context) {
3454      $(once('webform-radios-required', '.js-form-type-radios, .js-form-type-webform-radios-other, .js-webform-type-radios, .js-webform-type-webform-radios-other, .js-webform-type-webform-entity-radios, .js-webform-type-webform-scale', context))
3455        .each(function () {
3456          var $element = $(this);
3457          setTimeout(function () {radiosRequired($element);});
3458        });
3459    }
3460  };
3461
3462 /**
3463   * Adds HTML5 validation to required table select.
3464   *
3465   * @type {Drupal~behavior}
3466   *
3467   * @see https://www.drupal.org/project/webform/issues/2856795
3468   */
3469  Drupal.behaviors.webformTableSelectRequired = {
3470    attach: function (context) {
3471      $(once('webform-tableselect-required','.js-webform-tableselect.required', context))
3472        .each(function () {
3473          var $element = $(this);
3474          var $tbody = $element.find('tbody');
3475          var isMultiple = $element.is('[multiple]');
3476
3477          if (isMultiple) {
3478            // Check all checkbox triggers checkbox 'change' event on
3479            // select and deselect all.
3480            // @see Drupal.tableSelect
3481            $tbody.find('input[type="checkbox"]').on('click change', function () {
3482              checkboxesRequired($tbody);
3483            });
3484          }
3485
3486          setTimeout(function () {
3487            isMultiple ? checkboxesRequired($tbody) : radiosRequired($element);
3488          });
3489        });
3490    }
3491  };
3492
3493  /**
3494   * Add HTML5 multiple checkboxes required validation.
3495   *
3496   * @param {jQuery} $element
3497   *   An jQuery object containing HTML5 radios.
3498   *
3499   * @see https://stackoverflow.com/a/37825072/145846
3500   */
3501  function checkboxesRequired($element) {
3502    var $firstCheckbox = $element.find('input[type="checkbox"]').first();
3503    var isChecked = $element.find('input[type="checkbox"]').is(':checked');
3504    toggleRequired($firstCheckbox, !isChecked);
3505    copyRequireMessage($element, $firstCheckbox);
3506  }
3507
3508  /**
3509   * Add HTML5 radios required validation.
3510   *
3511   * @param {jQuery} $element
3512   *   An jQuery object containing HTML5 radios.
3513   *
3514   * @see https://www.drupal.org/project/webform/issues/2856795
3515   */
3516  function radiosRequired($element) {
3517    var $radios = $element.find('input[type="radio"]');
3518    var isRequired = $element.hasClass('required');
3519    toggleRequired($radios, isRequired);
3520    copyRequireMessage($element, $radios);
3521  }
3522
3523  /* ************************************************************************ */
3524  // Event handlers.
3525  /* ************************************************************************ */
3526
3527  /**
3528   * Trigger #states API HTML5 multiple checkboxes required validation.
3529   *
3530   * @see https://stackoverflow.com/a/37825072/145846
3531   */
3532  function statesCheckboxesRequiredEventHandler() {
3533    var $element = $(this).closest('.js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other');
3534    checkboxesRequired($element);
3535  }
3536
3537  /**
3538   * Trigger an input's event handlers.
3539   *
3540   * @param {element} input
3541   *   An input.
3542   */
3543  function triggerEventHandlers(input) {
3544    var $input = $(input);
3545    var type = input.type;
3546    var tag = input.tagName.toLowerCase();
3547    // Add 'webform.states' as extra parameter to event handlers.
3548    // @see Drupal.behaviors.webformUnsaved
3549    var extraParameters = ['webform.states'];
3550    if (type === 'checkbox' || type === 'radio') {
3551      $input
3552        .trigger('change', extraParameters)
3553        .trigger('blur', extraParameters);
3554    }
3555    else if (tag === 'select') {
3556      // Do not trigger the onchange event for Address element's country code
3557      // when it is initialized.
3558      // @see \Drupal\address\Element\Country
3559      if ($input.closest('.webform-type-address').length) {
3560        if (!$input.data('webform-states-address-initialized')
3561          && $input.attr('autocomplete') === 'country'
3562          && $input.val() === $input.find("option[selected]").attr('value')) {
3563          return;
3564        }
3565        $input.data('webform-states-address-initialized', true);
3566      }
3567
3568      $input
3569        .trigger('change', extraParameters)
3570        .trigger('blur', extraParameters);
3571    }
3572    else if (type !== 'submit' && type !== 'button' && type !== 'file') {
3573      // Make sure input mask is removed and then reset when value is restored.
3574      // @see https://www.drupal.org/project/webform/issues/3124155
3575      // @see https://www.drupal.org/project/webform/issues/3202795
3576      var hasInputMask = ($.fn.inputmask && $input.hasClass('js-webform-input-mask'));
3577      hasInputMask && $input.inputmask('remove');
3578
3579      $input
3580        .trigger('input', extraParameters)
3581        .trigger('change', extraParameters)
3582        .trigger('keydown', extraParameters)
3583        .trigger('keyup', extraParameters)
3584        .trigger('blur', extraParameters);
3585
3586      hasInputMask && $input.inputmask();
3587    }
3588  }
3589
3590  /* ************************************************************************ */
3591  // Backup and restore value functions.
3592  /* ************************************************************************ */
3593
3594  /**
3595   * Backup an input's current value and required attribute
3596   *
3597   * @param {element} input
3598   *   An input.
3599   */
3600  function backupValueAndRequired(input) {
3601    var $input = $(input);
3602    var type = input.type;
3603    var tag = input.tagName.toLowerCase(); // Normalize case.
3604
3605    // Backup required.
3606    if ($input.prop('required') && !$input.hasData('webform-required')) {
3607      $input.data('webform-required', true);
3608    }
3609
3610    // Backup value.
3611    if (!$input.hasData('webform-value')) {
3612      if (type === 'checkbox' || type === 'radio') {
3613        $input.data('webform-value', $input.prop('checked'));
3614      }
3615      else if (tag === 'select') {
3616        var values = [];
3617        $input.find('option:selected').each(function (i, option) {
3618          values[i] = option.value;
3619        });
3620        $input.data('webform-value', values);
3621      }
3622      else if (type !== 'submit' && type !== 'button') {
3623        $input.data('webform-value', input.value);
3624      }
3625    }
3626  }
3627
3628  /**
3629   * Restore an input's value and required attribute.
3630   *
3631   * @param {element} input
3632   *   An input.
3633   */
3634  function restoreValueAndRequired(input) {
3635    var $input = $(input);
3636
3637    // Restore value.
3638    var value = $input.data('webform-value');
3639    if (typeof value !== 'undefined') {
3640      var type = input.type;
3641      var tag = input.tagName.toLowerCase(); // Normalize case.
3642
3643      if (type === 'checkbox' || type === 'radio') {
3644        $input.prop('checked', value);
3645      }
3646      else if (tag === 'select') {
3647        $.each(value, function (i, option_value) {
3648          // Prevent "Syntax error, unrecognized expression" error by
3649          // escaping single quotes.
3650          // @see https://forum.jquery.com/topic/escape-characters-prior-to-using-selector
3651          option_value = option_value.replace(/'/g, "\\\'");
3652          $input.find("option[value='" + option_value + "']").prop('selected', true);
3653        });
3654      }
3655      else if (type !== 'submit' && type !== 'button') {
3656        input.value = value;
3657      }
3658      $input.removeData('webform-value');
3659    }
3660
3661    // Restore required.
3662    var required = $input.data('webform-required');
3663    if (typeof required !== 'undefined') {
3664      if (required) {
3665        $input.prop('required', true);
3666      }
3667      $input.removeData('webform-required');
3668    }
3669  }
3670
3671  /**
3672   * Clear an input's value and required attributes.
3673   *
3674   * @param {element} input
3675   *   An input.
3676   */
3677  function clearValueAndRequired(input) {
3678    var $input = $(input);
3679
3680    // Check for #states no clear attribute.
3681    // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/
3682    if ($input.closest('[data-webform-states-no-clear]').length) {
3683      return;
3684    }
3685
3686    // Clear value.
3687    var type = input.type;
3688    var tag = input.tagName.toLowerCase(); // Normalize case.
3689    if (type === 'checkbox' || type === 'radio') {
3690      $input.prop('checked', false);
3691    }
3692    else if (tag === 'select') {
3693      if ($input.find('option[value=""]').length) {
3694        $input.val('');
3695      }
3696      else {
3697        input.selectedIndex = -1;
3698      }
3699    }
3700    else if (type !== 'submit' && type !== 'button') {
3701      input.value = (type === 'color') ? '#000000' : '';
3702    }
3703
3704    // Clear required.
3705    $input.prop('required', false);
3706  }
3707
3708  /* ************************************************************************ */
3709  // Helper functions.
3710  /* ************************************************************************ */
3711
3712  /**
3713   * Toggle an input's required attributes.
3714   *
3715   * @param {element} $input
3716   *   An input.
3717   * @param {boolean} required
3718   *   Is input required.
3719   */
3720  function toggleRequired($input, required) {
3721    var isCheckboxOrRadio = ($input.attr('type') === 'radio' || $input.attr('type') === 'checkbox');
3722    if (required) {
3723      if (isCheckboxOrRadio) {
3724        $input.attr({'required': 'required'});
3725      }
3726      else {
3727        $input.attr({'required': 'required', 'aria-required': 'true'});
3728      }
3729    }
3730    else {
3731      if (isCheckboxOrRadio) {
3732        $input.removeAttr('required');
3733      }
3734      else {
3735        $input.removeAttr('required aria-required');
3736      }
3737    }
3738  }
3739
3740  /**
3741   * Copy the clientside_validation.module's message.
3742   *
3743   * @param {jQuery} $source
3744   *   The source element.
3745   * @param {jQuery} $destination
3746   *   The destination element.
3747   */
3748  function copyRequireMessage($source, $destination) {
3749    if ($source.attr('data-msg-required')) {
3750      $destination.attr('data-msg-required', $source.attr('data-msg-required'));
3751    }
3752  }
3753
3754})(jQuery, Drupal, once);
3755;
3756/**
3757 * @file
3758 * JavaScript behaviors for custom webform #states.
3759 */
3760
3761(function ($, Drupal) {
3762
3763  'use strict';
3764
3765  $(document).on('state:required', function (e) {
3766    if (e.trigger && $(e.target).isWebform()) {
3767      var $target = $(e.target);
3768
3769      // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset.
3770      // Fix #required for fieldsets.
3771      if ($target.is('.js-form-wrapper.panel')) {
3772        if (e.value) {
3773          $target.find('.panel-heading .panel-title').addClass('js-form-required form-required');
3774        }
3775        else {
3776          $target.find('.panel-heading .panel-title').removeClass('js-form-required form-required');
3777        }
3778      }
3779
3780    }
3781  });
3782
3783})(jQuery, Drupal);
3784;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.