PageSourceSearch

https://whetstone.coop/sites/default/files/js/js_7G5IA9XalJ6krLJbSrWewjSYUxNyl4dLJSRcrgwpkJY.js

js whetstone.coop collected 2026-10-06 11:13:08 UTC 131,310 bytes, 3,793 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')) {
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      // Stop a glyphicon throbber.
2121      if (this.progress.glyphicon) {
2122        this.glyphiconStop(this.progress.element);
2123      }
2124      // Remove the progress element.
2125      else {
2126        this.progress.element.remove();
2127      }
2128
2129      // Remove any message set.
2130      this.progress.element.parent().find('.message').remove();
2131    }
2132
2133    // Invoke the original success handler.
2134    return success.apply(this, [response, status]);
2135  };
2136
2137})(jQuery, this, Drupal, drupalSettings);
2138;
2139/**
2140* DO NOT EDIT THIS FILE.
2141* See the following change record for more information,
2142* https://www.drupal.org/node/2815083
2143* @preserve
2144**/
2145(function ($, Drupal, _ref) {
2146  var isTabbable = _ref.isTabbable;
2147  $.extend($.expr[':'], {
2148    tabbable: function tabbable(element) {
2149      Drupal.deprecationError({
2150        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'
2151      });
2152      if (element.tagName === 'SUMMARY' || element.tagName === 'DETAILS') {
2153        var tabIndex = element.getAttribute('tabIndex');
2154        if (tabIndex === null || tabIndex < 0) {
2155          return false;
2156        }
2157      }
2158      return isTabbable(element);
2159    }
2160  });
2161})(jQuery, Drupal, window.tabbable);;
vendor: 327 bytes, lines 2161-2162
2161
2162(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','
2162GTM-KMLH4SZ
vendor: 3 bytes, line 2162
2162');
2162;
2163// Custom scripts file
2164
2165(function ($) {
2166
2167  'use strict';
2168
2169  // Generic function that runs on window resize.
2170  function resizeStuff() {
2171
2172  }
2173
2174  // Runs function once on window resize.
2175  var TO = false;
2176  $(window).resize(function () {
2177    if (TO !== false) {
2178      clearTimeout(TO);
2179    }
2180
2181    // 200 is time in miliseconds.
2182    TO = setTimeout(resizeStuff, 200);
2183  }).resize();
2184
2185  // Count function for the infographic component types
2186  $('.count').each(function () {
2187    $(this).prop('Counter',0).animate({
2188      Counter: $(this).text()
2189    }, {
2190      duration: 3000,
2191      easing: 'swing',
2192      step: function (now) {
2193        $(this).text(Math.ceil(now).toLocaleString('en'));
2194      }
2195    });
2196  });
2197  $("#closeit").click(function() {
2198    $("#shoutbar").slideUp();
2199  });
2200  // $(document).ready(function(){$("#openit").click(function(){$("#shoutbar").effect("bounce","slow");$("#openit").slideUp()})});
2201  // $(document).ready(function(){$("#shoutbar").effect("bounce","slow");$("#closeit").click(function(){$("#shoutbar").slideUp();$("#openit").slideDown()})});
2202})(jQuery);;
2203$ = jQuery;
2204$(function(){
2205    // Add classes to header elements so they can shrink when the page scrolls
2206    var shrinkHeader = 0;
2207    var glitchHeader = 150;
2208    $(window).scroll(function() {
2209        var scroll = getCurrentScroll();
2210        if ( scroll >= glitchHeader ) {
2211            $('header.header').addClass('shrink');
2212            $('.site-logo__grid').addClass('shrink');
2213            // $('.region-midline').addClass('shrink');
2214            // $('.page-wrapper').addClass('shrink');
2215            // $('body.user-logged-in header.header').removeClass('shrink');
2216            // $('body.user-logged-in .site-logo__grid').removeClass('shrink');
2217            // $('body.user-logged-in .region-midline').removeClass('shrink');
2218        }
2219        else if ( scroll <= shrinkHeader ) {
2220            $('header.header').removeClass('shrink');
2221            $('.site-logo__grid').removeClass('shrink');
2222            // $('.region-midline').removeClass('shrink');
2223            // $('.page-wrapper').removeClass('shrink');
2224        }
2225        document.onscroll = scroll;
2226    });
2227    function getCurrentScroll() {
2228        // console.log(scroll);
2229        return window.pageYOffset || document.documentElement.scrollTop;
2230    }
2231
2232    // Add a click function for the ... icon in the footer of the sliding navigation
2233    $("a#toggle").click(function()
2234    {
2235        $(".mm-search").slideToggle();
2236        $(".mm-searchfield").slideToggle();
2237        $(".mmenu_tsesearch").slideToggle();
2238        $(".mmenu_tsecoop").slideToggle();
2239        return false;
2240    });
2241
2242    // Create a clone of the menu, right next to original.
2243    // Clone is used to sync up elements when the header becomes fixed after scrolling 50 pixels vertically down the page
2244    // $('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();
2245    //
2246    // scrollIntervalID = setInterval(stickIt, 10);
2247    //
2248    // function stickIt() {
2249    //
2250    //     var orgElementPos = $('.original').offset();
2251    //     orgElementTop = orgElementPos.top;
2252    //
2253    //     if ($(window).scrollTop() >= (orgElementTop)) {
2254    //         // scrolled past the original position; now only show the cloned, sticky element.
2255    //
2256    //         // Cloned element should always have same left position and width as original element.
2257    //         orgElement = $('.original');
2258    //         coordsOrgElement = orgElement.offset();
2259    //         leftOrgElement = coordsOrgElement.left;
2260    //         widthOrgElement = orgElement.css('width');
2261    //         $('.cloned').css('left',leftOrgElement+'px').css('top',0).css('width',widthOrgElement).show();
2262    //         $('.original').css('visibility','hidden');
2263    //     } else {
2264    //         // not scrolled past the menu; only show the original menu.
2265    //         $('.cloned').hide();
2266    //         $('.original').css('visibility','visible');
2267    //     }
2268    // }
2269});
2270
2271// function rotateCard(btn){
2272//     var $card = $(btn).closest('.card-container');
2273//     console.log($card);
2274//     if($card.hasClass('hover')){
2275//         $card.removeClass('hover');
2276//     } else {
2277//         $card.addClass('hover');
2278//     }
2279// }
2280
2281function rotateCard(btn){
2282    var $card = $(btn).closest('.card-container');
2283    console.log($card);
2284    if($card.hasClass('hover')){
2285        $card.removeClass('hover');
2286    } else {
2287        $card.addClass('hover');
2288    }
2289}
2290
2291// (function ($, undefined) {
2292//     function rotateCard(btn){
2293//         var
2294//             $card = $(btn).closest('.card-container'),
2295//             $toggle = $card.hasClass('hover');
2296//             $card.toggleClass(!$toggle, 'hover');
2297//     }
2298// })(jQuery);;
2299/**
2300 * Due to the construction of the responsive_menu module, there exists no
2301 * API or method of injecting navbar information
2302 */
2303(function ($, undefined) {
2304  'use strict';
2305  /**
2306   * Provides the off-canvas menu.
2307   *
2308   * @type {Drupal~behavior}
2309   *
2310   * @prop {Drupal~behaviorAttach} attach
2311   *   Attaches the behavior for the off-canvas menu.
2312   */
2313  Drupal.behaviors.responsive_menu_mmenu = {
2314    attach: function (context) {
2315      $('body').once('cwb-responsive-menu-mmenu').each(function () {
2316        const mmenuId = '#off-canvas';
2317        const offCanvas = document.querySelector(mmenuId);
2318        const settings = drupalSettings.responsive_menu;
2319        const position = settings.position,
2320          theme = settings.theme,
2321          pagedim = settings.pagedim;
2322
2323        const options = {
2324          extensions: [
2325            theme,
2326            'fx-menu-slide',
2327            position === 'left' ? 'position-left' : 'position-right'
2328          ],
2329          keyboardNavigation: {
2330            enable: true,
2331            enhance: true,
2332          },
2333          drag: {
2334            open: settings.drag
2335          },
2336          navbars: [
2337            {
2338              "position": "bottom",
2339              "content": [
2340                "<a class='glyphicon glyphicon-option-horizontal' href='#' id='toggle' aria-hidden='true'></a>",
2341                "searchfield",
2342                "<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>",
2343                "<div class='mmenu_tsecoop'>Touchstone Energy® Cooperatives</div></div>"
2344              ]
2345            }
2346          ]
2347        };
2348
2349        if (pagedim !== 'none') {
2350          options.extensions.push(pagedim);
2351        }
2352
2353        const config = {
2354          classNames: {
2355            selected: 'menu-item--active-trail'
2356          }
2357        };
2358
2359        // Allow the settings and options to be extended or overridden.
2360        if (typeof settings.custom !== 'undefined') {
2361          if (typeof settings.custom.options !== 'undefined') {
2362            extend(options, drupalSettings.responsive_menu.custom.options);
2363          }
2364          if (typeof drupalSettings.responsive_menu.custom.config !== 'undefined') {
2365            extend(config, drupalSettings.responsive_menu.custom.config);
2366          }
2367        }
2368
2369        // Set up the off canvas menu.
2370        const mmenu = new Mmenu(mmenuId, options, config);
2371
2372        // Due to a rendering issue with Chrome the page needs the viewport
2373        // metatag to have a value including initial-scale=1.0 otherwise it
2374        // won't render properly.
2375        // @see issue #3153145
2376        const mmenuApi = mmenu.API;
2377        const viewports = document.getElementsByName('viewport');
2378
2379        if (viewports.length !== 0 && settings.modifyViewport) {
2380          const viewportMeta = viewports[0];
2381          const defaultViewport = viewports[0].content;
2382          const staticViewport = "width=device-width, initial-scale=1.0, minimum-scale=1.0";
2383
2384          mmenuApi.bind('open:start', function () {
2385            viewportMeta.setAttribute('content', staticViewport);
2386          });
2387          mmenuApi.bind('close:start', function () {
2388            viewportMeta.setAttribute('content', defaultViewport);
2389          });
2390        }
2391      });
2392    }
2393  };
2394})(jQuery);
2395;
2396var timeOut;
2397function scrollToTop() {
2398    if (document.body.scrollTop!=0 || document.documentElement.scrollTop!=0){
2399        window.scrollBy(0,-50);
2400        timeOut=setTimeout('scrollToTop()',10);
2401    }
2402    else clearTimeout(timeOut);
2403};
2404(function ($) {
2405
2406    'use strict';
2407
2408    Drupal.behaviors.timeline = {
2409        attach: function (context, settings) {
2410
2411            var $timeline_block = $('.cd-timeline-block');
2412
2413            $('main .cd-timeline-block', context).once('timeline').each(function(){
2414                console.log($(this));
2415
2416                //hide any timeline blocks that are outside of the viewport
2417                if($(this).offset().top > $(window).scrollTop()+$(window).height()*0.75) {
2418                    $(this).find('.cd-timeline-img, .cd-timeline-content').addClass('is-hidden');
2419                }
2420
2421                //on scrolling, show/animate the timeline blocks as they enter the viewport
2422                $(window).on('scroll', function(){
2423                    $timeline_block.each(function(){
2424                        if( $(this).offset().top <= $(window).scrollTop()+$(window).height()*0.75 && $(this).find('.cd-timeline-img').hasClass('is-hidden') ) {
2425                            $(this).find('.cd-timeline-img, .cd-timeline-content').removeClass('is-hidden').addClass('bounce-in');
2426                        }
2427                    });
2428                });
2429            });
2430        }
2431    };
2432})(jQuery);;
2433/**
2434 * @file
2435 * External links js file.
2436 */
2437
2438(function ($, Drupal, drupalSettings) {
2439
2440  'use strict';
2441
2442  Drupal.extlink = Drupal.extlink || {};
2443
2444  Drupal.extlink.attach = function (context, drupalSettings) {
2445    if (typeof drupalSettings.data === 'undefined' || !drupalSettings.data.hasOwnProperty('extlink')) {
2446      return;
2447    }
2448
2449    // Define the jQuery method (either 'append' or 'prepend') of placing the
2450    // icon, defaults to 'append'.
2451    var extIconPlacement = 'append';
2452    if (drupalSettings.data.extlink.extIconPlacement && drupalSettings.data.extlink.extIconPlacement != '0') {
2453          extIconPlacement = drupalSettings.data.extlink.extIconPlacement;
2454        }
2455
2456    // Strip the host name down, removing ports, subdomains, or www.
2457    var pattern = /^(([^\/:]+?\.)*)([^\.:]{1,})((\.[a-z0-9]{1,253})*)(:[0-9]{1,5})?$/;
2458    var host = window.location.host.replace(pattern, '$2$3$6');
2459    var subdomain = window.location.host.replace(host, '');
2460
2461    // Determine what subdomains are considered internal.
2462    var subdomains;
2463    if (drupalSettings.data.extlink.extSubdomains) {
2464      subdomains = '([^/]*\\.)?';
2465    }
2466    else if (subdomain === 'www.' || subdomain === '') {
2467      subdomains = '(www\\.)?';
2468    }
2469    else {
2470      subdomains = subdomain.replace('.', '\\.');
2471    }
2472
2473    // Whitelisted domains.
2474    var whitelistedDomains = false;
2475    if (drupalSettings.data.extlink.whitelistedDomains) {
2476      whitelistedDomains = [];
2477      for (var i = 0; i < drupalSettings.data.extlink.whitelistedDomains.length; i++) {
2478        whitelistedDomains.push(new RegExp('^https?:\\/\\/' + drupalSettings.data.extlink.whitelistedDomains[i].replace(/(\r\n|\n|\r)/gm,'') + '.*$', 'i'));
2479      }
2480    }
2481
2482    // Build regular expressions that define an internal link.
2483    var internal_link = new RegExp('^https?://([^@]*@)?' + subdomains + host, 'i');
2484
2485    // Extra internal link matching.
2486    var extInclude = false;
2487    if (drupalSettings.data.extlink.extInclude) {
2488      extInclude = new RegExp(drupalSettings.data.extlink.extInclude.replace(/\\/, '\\'), 'i');
2489    }
2490
2491    // Extra external link matching.
2492    var extExclude = false;
2493    if (drupalSettings.data.extlink.extExclude) {
2494      extExclude = new RegExp(drupalSettings.data.extlink.extExclude.replace(/\\/, '\\'), 'i');
2495    }
2496
2497    // Extra external link CSS selector exclusion.
2498    var extCssExclude = false;
2499    if (drupalSettings.data.extlink.extCssExclude) {
2500      extCssExclude = drupalSettings.data.extlink.extCssExclude;
2501    }
2502
2503    // Extra external link CSS selector explicit.
2504    var extCssExplicit = false;
2505    if (drupalSettings.data.extlink.extCssExplicit) {
2506      extCssExplicit = drupalSettings.data.extlink.extCssExplicit;
2507    }
2508
2509    // Find all links which are NOT internal and begin with http as opposed
2510    // to ftp://, javascript:, etc. other kinds of links.
2511    // When operating on the 'this' variable, the host has been appended to
2512    // all links by the browser, even local ones.
2513    // In jQuery 1.1 and higher, we'd use a filter method here, but it is not
2514    // available in jQuery 1.0 (Drupal 5 default).
2515    var external_links = [];
2516    var mailto_links = [];
2517    $('a:not([data-extlink]), area:not([data-extlink])', context).each(function (el) {
2518      try {
2519        var url = '';
2520        if (typeof this.href == 'string') {
2521          url = this.href.toLowerCase();
2522        }
2523        // Handle SVG links (xlink:href).
2524        else if (typeof this.href == 'object') {
2525          url = this.href.baseVal;
2526        }
2527        if (url.indexOf('http') === 0
2528          && ((!internal_link.test(url) && !(extExclude && extExclude.test(url))) || (extInclude && extInclude.test(url)))
2529          && !(extCssExclude && $(this).is(extCssExclude))
2530          && !(extCssExclude && $(this).parents(extCssExclude).length > 0)
2531          && !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
2532          var match = false;
2533          if (whitelistedDomains) {
2534            for (var i = 0; i < whitelistedDomains.length; i++) {
2535              if (whitelistedDomains[i].test(url)) {
2536                match = true;
2537                break;
2538              }
2539            }
2540          }
2541          if (!match) {
2542            external_links.push(this);
2543          }
2544        }
2545        // Do not include area tags with begin with mailto: (this prohibits
2546        // icons from being added to image-maps).
2547        else if (this.tagName !== 'AREA'
2548          && url.indexOf('mailto:') === 0
2549          && !(extCssExclude && $(this).parents(extCssExclude).length > 0)
2550          && !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
2551          mailto_links.push(this);
2552        }
2553      }
2554      // IE7 throws errors often when dealing with irregular links, such as:
2555      // <a href="node/10"></a> Empty tags.
2556      // <a href="http://user:[email protected]">example</a> User:pass syntax.
2557      catch (error) {
2558        return false;
2559      }
2560    });
2561
2562    if (drupalSettings.data.extlink.extClass !== '0' && drupalSettings.data.extlink.extClass !== '') {
2563      Drupal.extlink.applyClassAndSpan(external_links, drupalSettings.data.extlink.extClass, extIconPlacement);
2564    }
2565
2566    if (drupalSettings.data.extlink.mailtoClass !== '0' && drupalSettings.data.extlink.mailtoClass !== '') {
2567      Drupal.extlink.applyClassAndSpan(mailto_links, drupalSettings.data.extlink.mailtoClass, extIconPlacement);
2568    }
2569
2570    if (drupalSettings.data.extlink.extTarget) {
2571      // Apply the target attribute to all links.
2572      $(external_links).filter(function () {
2573        // Filter out links with target set if option specified.
2574        return !(drupalSettings.data.extlink.extTargetNoOverride && $(this).is('a[target]'));
2575      }).attr({target: '_blank'});
2576
2577      // Add noopener rel attribute to combat phishing.
2578      $(external_links).attr('rel', function (i, val) {
2579        // If no rel attribute is present, create one with the value noopener.
2580        if (val === null || typeof val === 'undefined') {
2581          return 'noopener';
2582        }
2583        // Check to see if rel contains noopener. Add what doesn't exist.
2584        if (val.indexOf('noopener') > -1) {
2585          if (val.indexOf('noopener') === -1) {
2586            return val + ' noopener';
2587          }
2588          // Noopener exists. Nothing needs to be added.
2589          else {
2590            return val;
2591          }
2592        }
2593        // Else, append noopener to val.
2594        else {
2595          return val + ' noopener';
2596        }
2597      });
2598    }
2599
2600    if (drupalSettings.data.extlink.extNofollow) {
2601      $(external_links).attr('rel', function (i, val) {
2602        // When the link does not have a rel attribute set it to 'nofollow'.
2603        if (val === null || typeof val === 'undefined') {
2604          return 'nofollow';
2605        }
2606        var target = 'nofollow';
2607        // Change the target, if not overriding follow.
2608        if (drupalSettings.data.extlink.extFollowNoOverride) {
2609          target = 'follow';
2610        }
2611        if (val.indexOf(target) === -1) {
2612          return val + ' nofollow';
2613        }
2614        return val;
2615      });
2616    }
2617
2618    if (drupalSettings.data.extlink.extNoreferrer) {
2619      $(external_links).attr('rel', function (i, val) {
2620        // When the link does not have a rel attribute set it to 'noreferrer'.
2621        if (val === null || typeof val === 'undefined') {
2622          return 'noreferrer';
2623        }
2624        if (val.indexOf('noreferrer') === -1) {
2625          return val + ' noreferrer';
2626        }
2627        return val;
2628      });
2629    }
2630
2631    Drupal.extlink = Drupal.extlink || {};
2632
2633    // Set up default click function for the external links popup. This should be
2634    // overridden by modules wanting to alter the popup.
2635    Drupal.extlink.popupClickHandler = Drupal.extlink.popupClickHandler || function () {
2636      if (drupalSettings.data.extlink.extAlert) {
2637        return confirm(drupalSettings.data.extlink.extAlertText);
2638      }
2639    };
2640
2641    $(external_links).off("click.extlink");
2642    $(external_links).on("click.extlink", function (e) {
2643      return Drupal.extlink.popupClickHandler(e, this);
2644    });
2645  };
2646
2647  /**
2648   * Apply a class and a trailing <span> to all links not containing images.
2649   *
2650   * @param {object[]} links
2651   *   An array of DOM elements representing the links.
2652   * @param {string} class_name
2653   *   The class to apply to the links.
2654   * @param {string} icon_placement
2655   *   'append' or 'prepend' the icon to the link.
2656   */
2657  Drupal.extlink.applyClassAndSpan = function (links, class_name, icon_placement) {
2658    var $links_to_process;
2659    if (drupalSettings.data.extlink.extImgClass) {
2660      $links_to_process = $(links);
2661    }
2662    else {
2663      var links_with_images = $(links).find('img, svg').parents('a');
2664      $links_to_process = $(links).not(links_with_images);
2665    }
2666
2667    if (class_name !== '0') {
2668      $links_to_process.addClass(class_name);
2669    }
2670
2671    // Add data-extlink attribute.
2672    $links_to_process.attr('data-extlink', '');
2673
2674    var i;
2675    var length = $links_to_process.length;
2676    for (i = 0; i < length; i++) {
2677      var $link = $($links_to_process[i]);
2678      if (drupalSettings.data.extlink.extUseFontAwesome) {
2679        if (class_name === drupalSettings.data.extlink.mailtoClass) {
2680          $link[icon_placement]('<span class="fa-' + class_name + ' extlink"><span class="' + drupalSettings.data.extlink.extFaMailtoClasses + '" aria-label="' + drupalSettings.data.extlink.mailtoLabel + '"></span></span>');
2681        }
2682        else {
2683          $link[icon_placement]('<span class="fa-' + class_name + ' extlink"><span class="' + drupalSettings.data.extlink.extFaLinkClasses + '" aria-label="' + drupalSettings.data.extlink.extLabel + '"></span></span>');
2684        }
2685      }
2686      else {
2687        if (class_name === drupalSettings.data.extlink.mailtoClass) {
2688          $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>');
2689        }
2690        else {
2691          $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>');
2692        }
2693      }
2694    }
2695  };
2696
2697  Drupal.behaviors.extlink = Drupal.behaviors.extlink || {};
2698  Drupal.behaviors.extlink.attach = function (context, drupalSettings) {
2699    // Backwards compatibility, for the benefit of modules overriding extlink
2700    // functionality by defining an "extlinkAttach" global function.
2701    if (typeof extlinkAttach === 'function') {
2702      extlinkAttach(context);
2703    }
2704    else {
2705      Drupal.extlink.attach(context, drupalSettings);
2706    }
2707  };
2708
2709})(jQuery, Drupal, drupalSettings);
2710;
2711/**
2712 * @file
2713 * Webform behaviors.
2714 */
2715
2716(function ($, Drupal) {
2717
2718  'use strict';
2719
2720  // Trigger Drupal's attaching of behaviors after the page is
2721  // completely loaded.
2722  // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button
2723  // @see https://stackoverflow.com/questions/20899274/how-to-refresh-page-on-back-button-click/20899422#20899422
2724  var isChrome = (/chrom(e|ium)/.test(window.navigator.userAgent.toLowerCase()));
2725  if (isChrome) {
2726    // Track back button in navigation.
2727    // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button
2728    var backButton = false;
2729    if (window.performance) {
2730      var navEntries = window.performance.getEntriesByType('navigation');
2731      if (navEntries.length > 0 && navEntries[0].type === 'back_forward') {
2732        backButton = true;
2733      }
2734      else if (window.performance.navigation
2735        && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) {
2736        backButton = true;
2737      }
2738    }
2739
2740    // If the back button is pressed, delay Drupal's attaching of behaviors.
2741    if (backButton) {
2742      var attachBehaviors = Drupal.attachBehaviors;
2743      Drupal.attachBehaviors = function (context, settings) {
2744        setTimeout(function (context, settings) {
2745          attachBehaviors(context, settings);
2746        }, 300);
2747      };
2748    }
2749  }
2750
2751})(jQuery, Drupal);
2752;
2753/**
2754* DO NOT EDIT THIS FILE.
2755* See the following change record for more information,
2756* https://www.drupal.org/node/2815083
2757* @preserve
2758**/
2759(function ($, Drupal) {
2760  var states = {
2761    postponed: []
2762  };
2763  Drupal.states = states;
2764  function invert(a, invertState) {
2765    return invertState && typeof a !== 'undefined' ? !a : a;
2766  }
2767  function _compare2(a, b) {
2768    if (a === b) {
2769      return typeof a === 'undefined' ? a : true;
2770    }
2771    return typeof a === 'undefined' || typeof b === 'undefined';
2772  }
2773  function ternary(a, b) {
2774    if (typeof a === 'undefined') {
2775      return b;
2776    }
2777    if (typeof b === 'undefined') {
2778      return a;
2779    }
2780    return a && b;
2781  }
2782  Drupal.behaviors.states = {
2783    attach: function attach(context, settings) {
2784      var $states = $(context).find('[data-drupal-states]');
2785      var il = $states.length;
2786      var _loop = function _loop(i) {
2787        var config = JSON.parse($states[i].getAttribute('data-drupal-states'));
2788        Object.keys(config || {}).forEach(function (state) {
2789          new states.Dependent({
2790            element: $($states[i]),
2791            state: states.State.sanitize(state),
2792            constraints: config[state]
2793          });
2794        });
2795      };
2796      for (var i = 0; i < il; i++) {
2797        _loop(i);
2798      }
2799      while (states.postponed.length) {
2800        states.postponed.shift()();
2801      }
2802    }
2803  };
2804  states.Dependent = function (args) {
2805    var _this = this;
2806    $.extend(this, {
2807      values: {},
2808      oldValue: null
2809    }, args);
2810    this.dependees = this.getDependees();
2811    Object.keys(this.dependees || {}).forEach(function (selector) {
2812      _this.initializeDependee(selector, _this.dependees[selector]);
2813    });
2814  };
2815  states.Dependent.comparisons = {
2816    RegExp: function RegExp(reference, value) {
2817      return reference.test(value);
2818    },
2819    Function: function Function(reference, value) {
2820      return reference(value);
2821    },
2822    Number: function Number(reference, value) {
2823      return typeof value === 'string' ? _compare2(reference.toString(), value) : _compare2(reference, value);
2824    }
2825  };
2826  states.Dependent.prototype = {
2827    initializeDependee: function initializeDependee(selector, dependeeStates) {
2828      var _this2 = this;
2829      this.values[selector] = {};
2830      Object.keys(dependeeStates).forEach(function (i) {
2831        var state = dependeeStates[i];
2832        if ($.inArray(state, dependeeStates) === -1) {
2833          return;
2834        }
2835        state = states.State.sanitize(state);
2836        _this2.values[selector][state.name] = null;
2837        $(selector).on("state:".concat(state), {
2838          selector: selector,
2839          state: state
2840        }, function (e) {
2841          _this2.update(e.data.selector, e.data.state, e.value);
2842        });
2843        new states.Trigger({
2844          selector: selector,
2845          state: state
2846        });
2847      });
2848    },
2849    compare: function compare(reference, selector, state) {
2850      var value = this.values[selector][state.name];
2851      if (reference.constructor.name in states.Dependent.comparisons) {
2852        return states.Dependent.comparisons[reference.constructor.name](reference, value);
2853      }
2854      return _compare2(reference, value);
2855    },
2856    update: function update(selector, state, value) {
2857      if (value !== this.values[selector][state.name]) {
2858        this.values[selector][state.name] = value;
2859        this.reevaluate();
2860      }
2861    },
2862    reevaluate: function reevaluate() {
2863      var value = this.verifyConstraints(this.constraints);
2864      if (value !== this.oldValue) {
2865        this.oldValue = value;
2866        value = invert(value, this.state.invert);
2867        this.element.trigger({
2868          type: "state:".concat(this.state),
2869          value: value,
2870          trigger: true
2871        });
2872      }
2873    },
2874    verifyConstraints: function verifyConstraints(constraints, selector) {
2875      var result;
2876      if ($.isArray(constraints)) {
2877        var hasXor = $.inArray('xor', constraints) === -1;
2878        var len = constraints.length;
2879        for (var i = 0; i < len; i++) {
2880          if (constraints[i] !== 'xor') {
2881            var constraint = this.checkConstraints(constraints[i], selector, i);
2882            if (constraint && (hasXor || result)) {
2883              return hasXor;
2884            }
2885            result = result || constraint;
2886          }
2887        }
2888      } else if ($.isPlainObject(constraints)) {
2889        for (var n in constraints) {
2890          if (constraints.hasOwnProperty(n)) {
2891            result = ternary(result, this.checkConstraints(constraints[n], selector, n));
2892            if (result === false) {
2893              return false;
2894            }
2895          }
2896        }
2897      }
2898      return result;
2899    },
2900    checkConstraints: function checkConstraints(value, selector, state) {
2901      if (typeof state !== 'string' || /[0-9]/.test(state[0])) {
2902        state = null;
2903      } else if (typeof selector === 'undefined') {
2904        selector = state;
2905        state = null;
2906      }
2907      if (state !== null) {
2908        state = states.State.sanitize(state);
2909        return invert(this.compare(value, selector, state), state.invert);
2910      }
2911      return this.verifyConstraints(value, selector);
2912    },
2913    getDependees: function getDependees() {
2914      var cache = {};
2915      var _compare = this.compare;
2916      this.compare = function (reference, selector, state) {
2917        (cache[selector] || (cache[selector] = [])).push(state.name);
2918      };
2919      this.verifyConstraints(this.constraints);
2920      this.compare = _compare;
2921      return cache;
2922    }
2923  };
2924  states.Trigger = function (args) {
2925    $.extend(this, args);
2926    if (this.state in states.Trigger.states) {
2927      this.element = $(this.selector);
2928      if (!this.element.data("trigger:".concat(this.state))) {
2929        this.initialize();
2930      }
2931    }
2932  };
2933  states.Trigger.prototype = {
2934    initialize: function initialize() {
2935      var _this3 = this;
2936      var trigger = states.Trigger.states[this.state];
2937      if (typeof trigger === 'function') {
2938        trigger.call(window, this.element);
2939      } else {
2940        Object.keys(trigger || {}).forEach(function (event) {
2941          _this3.defaultTrigger(event, trigger[event]);
2942        });
2943      }
2944      this.element.data("trigger:".concat(this.state), true);
2945    },
2946    defaultTrigger: function defaultTrigger(event, valueFn) {
2947      var oldValue = valueFn.call(this.element);
2948      this.element.on(event, $.proxy(function (e) {
2949        var value = valueFn.call(this.element, e);
2950        if (oldValue !== value) {
2951          this.element.trigger({
2952            type: "state:".concat(this.state),
2953            value: value,
2954            oldValue: oldValue
2955          });
2956          oldValue = value;
2957        }
2958      }, this));
2959      states.postponed.push($.proxy(function () {
2960        this.element.trigger({
2961          type: "state:".concat(this.state),
2962          value: oldValue,
2963          oldValue: null
2964        });
2965      }, this));
2966    }
2967  };
2968  states.Trigger.states = {
2969    empty: {
2970      keyup: function keyup() {
2971        return this.val() === '';
2972      },
2973      change: function change() {
2974        return this.val() === '';
2975      }
2976    },
2977    checked: {
2978      change: function change() {
2979        var checked = false;
2980        this.each(function () {
2981          checked = $(this).prop('checked');
2982          return !checked;
2983        });
2984        return checked;
2985      }
2986    },
2987    value: {
2988      keyup: function keyup() {
2989        if (this.length > 1) {
2990          return this.filter(':checked').val() || false;
2991        }
2992        return this.val();
2993      },
2994      change: function change() {
2995        if (this.length > 1) {
2996          return this.filter(':checked').val() || false;
2997        }
2998        return this.val();
2999      }
3000    },
3001    collapsed: {
3002      collapsed: function collapsed(e) {
3003        return typeof e !== 'undefined' && 'value' in e ? e.value : !this.is('[open]');
3004      }
3005    }
3006  };
3007  states.State = function (state) {
3008    this.pristine = state;
3009    this.name = state;
3010    var process = true;
3011    do {
3012      while (this.name.charAt(0) === '!') {
3013        this.name = this.name.substring(1);
3014        this.invert = !this.invert;
3015      }
3016      if (this.name in states.State.aliases) {
3017        this.name = states.State.aliases[this.name];
3018      } else {
3019        process = false;
3020      }
3021    } while (process);
3022  };
3023  states.State.sanitize = function (state) {
3024    if (state instanceof states.State) {
3025      return state;
3026    }
3027    return new states.State(state);
3028  };
3029  states.State.aliases = {
3030    enabled: '!disabled',
3031    invisible: '!visible',
3032    invalid: '!valid',
3033    untouched: '!touched',
3034    optional: '!required',
3035    filled: '!empty',
3036    unchecked: '!checked',
3037    irrelevant: '!relevant',
3038    expanded: '!collapsed',
3039    open: '!collapsed',
3040    closed: 'collapsed',
3041    readwrite: '!readonly'
3042  };
3043  states.State.prototype = {
3044    invert: false,
3045    toString: function toString() {
3046      return this.name;
3047    }
3048  };
3049  var $document = $(document);
3050  $document.on('state:disabled', function (e) {
3051    if (e.trigger) {
3052      $(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);
3053    }
3054  });
3055  $document.on('state:required', function (e) {
3056    if (e.trigger) {
3057      if (e.value) {
3058        var label = "label".concat(e.target.id ? "[for=".concat(e.target.id, "]") : '');
3059        var $label = $(e.target).attr({
3060          required: 'required',
3061          'aria-required': 'true'
3062        }).closest('.js-form-item, .js-form-wrapper').find(label);
3063        if (!$label.hasClass('js-form-required').length) {
3064          $label.addClass('js-form-required form-required');
3065        }
3066      } else {
3067        $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required');
3068      }
3069    }
3070  });
3071  $document.on('state:visible', function (e) {
3072    if (e.trigger) {
3073      $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggle(e.value);
3074    }
3075  });
3076  $document.on('state:checked', function (e) {
3077    if (e.trigger) {
3078      $(e.target).closest('.js-form-item, .js-form-wrapper').find('input').prop('checked', e.value).trigger('change');
3079    }
3080  });
3081  $document.on('state:collapsed', function (e) {
3082    if (e.trigger) {
3083      if ($(e.target).is('[open]') === e.value) {
3084        $(e.target).find('> summary').trigger('click');
3085      }
3086    }
3087  });
3088})(jQuery, Drupal);;
3089/**
3090 * @file
3091 * Extends core/misc/states.js.
3092 */
3093(function($) {
3094
3095  // Unbind core state.js from document first so we can then override below.
3096  $(document).unbind('state:disabled');
3097
3098  /**
3099   * Global state change handlers. These are bound to "document" to cover all
3100   * elements whose state changes. Events sent to elements within the page
3101   * bubble up to these handlers. We use this system so that themes and modules
3102   * can override these state change handlers for particular parts of a page.
3103   */
3104  $(document).bind('state:disabled', function(e) {
3105    // Only act when this change was triggered by a dependency and not by the
3106    // element monitoring itself.
3107    if (e.trigger) {
3108      $(e.target)
3109        .attr('disabled', e.value)
3110        .closest('.form-item, .form-submit, .form-wrapper').toggleClass('form-disabled', e.value)
3111        .find(':input').attr('disabled', e.value);
3112
3113      // Note: WebKit nightlies don't reflect that change correctly.
3114      // See https://bugs.webkit.org/show_bug.cgi?id=23789
3115    }
3116  });
3117
3118})(jQuery);
3119;
3120/**
3121 * @file
3122 * JavaScript behaviors for custom webform #states.
3123 */
3124
3125(function ($, Drupal, once) {
3126
3127  'use strict';
3128
3129  Drupal.webform = Drupal.webform || {};
3130  Drupal.webform.states = Drupal.webform.states || {};
3131  Drupal.webform.states.slideDown = Drupal.webform.states.slideDown || {};
3132  Drupal.webform.states.slideDown.duration = 'slow';
3133  Drupal.webform.states.slideUp = Drupal.webform.states.slideUp || {};
3134  Drupal.webform.states.slideUp.duration = 'fast';
3135
3136  /* ************************************************************************ */
3137  // jQuery functions.
3138  /* ************************************************************************ */
3139
3140  /**
3141   * Check if an element has a specified data attribute.
3142   *
3143   * @param {string} data
3144   *   The data attribute name.
3145   *
3146   * @return {boolean}
3147   *   TRUE if an element has a specified data attribute.
3148   */
3149  $.fn.hasData = function (data) {
3150    return (typeof this.data(data) !== 'undefined');
3151  };
3152
3153  /**
3154   * Check if element is within the webform or not.
3155   *
3156   * @return {boolean}
3157   *   TRUE if element is within the webform.
3158   */
3159  $.fn.isWebform = function () {
3160    return $(this).closest('form.webform-submission-form, form[id^="webform"], form[data-is-webform]').length ? true : false;
3161  };
3162
3163  /**
3164   * Check if element is to be treated as a webform element.
3165   *
3166   * @return {boolean}
3167   *   TRUE if element is to be treated as a webform element.
3168   */
3169  $.fn.isWebformElement = function () {
3170    return ($(this).isWebform() || $(this).closest('[data-is-webform-element]').length) ? true : false;
3171  };
3172
3173  /* ************************************************************************ */
3174  // Trigger.
3175  /* ************************************************************************ */
3176
3177  // The change event is triggered by cut-n-paste and select menus.
3178  // Issue #2445271: #states element empty check not triggered on mouse
3179  // based paste.
3180  // @see https://www.drupal.org/node/2445271
3181  Drupal.states.Trigger.states.empty.change = function change() {
3182    return this.val() === '';
3183  };
3184
3185  /* ************************************************************************ */
3186  // Dependents.
3187  /* ************************************************************************ */
3188
3189  // Apply solution included in #1962800 patch.
3190  // Issue #1962800: Form #states not working with literal integers as
3191  // values in IE11.
3192  // @see https://www.drupal.org/project/drupal/issues/1962800
3193  // @see https://www.drupal.org/files/issues/core-states-not-working-with-integers-ie11_1962800_46.patch
3194  //
3195  // This issue causes pattern, less than, and greater than support to break.
3196  // @see https://www.drupal.org/project/webform/issues/2981724
3197  var states = Drupal.states;
3198  Drupal.states.Dependent.prototype.compare = function compare(reference, selector, state) {
3199    var value = this.values[selector][state.name];
3200
3201    var name = reference.constructor.name;
3202    if (!name) {
3203      name = $.type(reference);
3204
3205      name = name.charAt(0).toUpperCase() + name.slice(1);
3206    }
3207    if (name in states.Dependent.comparisons) {
3208      return states.Dependent.comparisons[name](reference, value);
3209    }
3210
3211    if (reference.constructor.name in states.Dependent.comparisons) {
3212      return states.Dependent.comparisons[reference.constructor.name](reference, value);
3213    }
3214
3215    return _compare2(reference, value);
3216  };
3217  function _compare2(a, b) {
3218    if (a === b) {
3219      return typeof a === 'undefined' ? a : true;
3220    }
3221
3222    return typeof a === 'undefined' || typeof b === 'undefined';
3223  }
3224
3225  // Adds pattern, less than, and greater than support to #state API.
3226  // @see http://drupalsun.com/julia-evans/2012/03/09/extending-form-api-states-regular-expressions
3227  Drupal.states.Dependent.comparisons.Object = function (reference, value) {
3228    if ('pattern' in reference) {
3229      return (new RegExp(reference['pattern'])).test(value);
3230    }
3231    else if ('!pattern' in reference) {
3232      return !((new RegExp(reference['!pattern'])).test(value));
3233    }
3234    else if ('less' in reference) {
3235      return (value !== '' && parseFloat(reference['less']) > parseFloat(value));
3236    }
3237    else if ('less_equal' in reference) {
3238      return (value !== '' && parseFloat(reference['less_equal']) >= parseFloat(value));
3239    }
3240    else if ('greater' in reference) {
3241      return (value !== '' && parseFloat(reference['greater']) < parseFloat(value));
3242    }
3243    else if ('greater_equal' in reference) {
3244      return (value !== '' && parseFloat(reference['greater_equal']) <= parseFloat(value));
3245    }
3246    else if ('between' in reference || '!between' in reference) {
3247      if (value === '') {
3248        return false;
3249      }
3250
3251      var between = reference['between'] || reference['!between'];
3252      var betweenParts = between.split(':');
3253      var greater = betweenParts[0];
3254      var less = (typeof betweenParts[1] !== 'undefined') ? betweenParts[1] : null;
3255      var isGreaterThan = (greater === null || greater === '' || parseFloat(value) >= parseFloat(greater));
3256      var isLessThan = (less === null || less === '' || parseFloat(value) <= parseFloat(less));
3257      var result = (isGreaterThan && isLessThan);
3258      return (reference['!between']) ? !result : result;
3259    }
3260    else {
3261      return reference.indexOf(value) !== false;
3262    }
3263  };
3264
3265  /* ************************************************************************ */
3266  // States events.
3267  /* ************************************************************************ */
3268
3269  var $document = $(document);
3270
3271  $document.on('state:required', function (e) {
3272    if (e.trigger && $(e.target).isWebformElement()) {
3273      var $target = $(e.target);
3274      // Fix #required file upload.
3275      // @see Issue #2860529: Conditional required File upload field don't work.
3276      toggleRequired($target.find('input[type="file"]'), e.value);
3277
3278      // Fix #required for radios and likert.
3279      // @see Issue #2856795: If radio buttons are required but not filled form is nevertheless submitted.
3280      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')) {
3281        $target.toggleClass('required', e.value);
3282        toggleRequired($target.find('input[type="radio"]'), e.value);
3283      }
3284
3285      // Fix #required for checkboxes.
3286      // @see Issue #2938414: Checkboxes don't support #states required.
3287      // @see checkboxRequiredhandler
3288      if ($target.is('.js-form-type-checkboxes, .js-form-type-webform-checkboxes-other, .js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other')) {
3289        $target.toggleClass('required', e.value);
3290        var $checkboxes = $target.find('input[type="checkbox"]');
3291        if (e.value) {
3292          // Add event handler.
3293          $checkboxes.on('click', statesCheckboxesRequiredEventHandler);
3294          // Initialize and add required attribute.
3295          checkboxesRequired($target);
3296        }
3297        else {
3298          // Remove event handler.
3299          $checkboxes.off('click', statesCheckboxesRequiredEventHandler);
3300          // Remove required attribute.
3301          toggleRequired($checkboxes, false);
3302        }
3303      }
3304
3305      // Fix #required for tableselect.
3306      // @see Issue #3212581: Table select does not trigger client side validation
3307      if ($target.is('.js-webform-tableselect')) {
3308        $target.toggleClass('required', e.value);
3309        var isMultiple = $target.is('[multiple]');
3310        if (isMultiple) {
3311          // Checkboxes.
3312          var $tbody = $target.find('tbody');
3313          var $checkboxes = $tbody.find('input[type="checkbox"]');
3314          copyRequireMessage($target, $checkboxes);
3315          if (e.value) {
3316            $checkboxes.on('click change', statesCheckboxesRequiredEventHandler);
3317            checkboxesRequired($tbody);
3318          }
3319          else {
3320            $checkboxes.off('click change ', statesCheckboxesRequiredEventHandler);
3321            toggleRequired($tbody, false);
3322          }
3323        }
3324        else {
3325          // Radios.
3326          var $radios = $target.find('input[type="radio"]');
3327          copyRequireMessage($target, $radios);
3328          toggleRequired($radios, e.value);
3329        }
3330      }
3331
3332      // Fix required label for elements without the for attribute.
3333      // @see Issue #3145300: Conditional Visible Select Other not working.
3334      if ($target.is('.js-form-type-webform-select-other, .js-webform-type-webform-select-other')) {
3335        var $select = $target.find('select');
3336        toggleRequired($select, e.value);
3337        copyRequireMessage($target, $select);
3338      }
3339      if ($target.find('> label:not([for])').length) {
3340        $target.find('> label').toggleClass('js-form-required form-required', e.value);
3341      }
3342
3343      // Fix required label for checkboxes and radios.
3344      // @see Issue #2938414: Checkboxes don't support #states required
3345      // @see Issue #2731991: Setting required on radios marks all options required.
3346      // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset.
3347      // Fix #required for fieldsets.
3348      // @see Issue #2977569: Hidden fieldsets that become visible with conditional logic cannot be made required.
3349      if ($target.is('.js-webform-type-radios, .js-webform-type-checkboxes, fieldset')) {
3350        $target.find('legend span.fieldset-legend:not(.visually-hidden)').toggleClass('js-form-required form-required', e.value);
3351      }
3352
3353      // Issue #2986017: Fieldsets shouldn't have required attribute.
3354      if ($target.is('fieldset')) {
3355        $target.removeAttr('required aria-required');
3356      }
3357    }
3358  });
3359
3360  $document.on('state:checked', function (e) {
3361    if (e.trigger) {
3362      $(e.target).trigger('change');
3363    }
3364  });
3365
3366  $document.on('state:readonly', function (e) {
3367    if (e.trigger && $(e.target).isWebformElement()) {
3368      $(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);
3369
3370      // Trigger webform:readonly.
3371      $(e.target).trigger('webform:readonly')
3372        .find('select, input, textarea, button').trigger('webform:readonly');
3373    }
3374  });
3375
3376  $document.on('state:visible state:visible-slide', function (e) {
3377    if (e.trigger && $(e.target).isWebformElement()) {
3378      if (e.value) {
3379        $(':input', e.target).addBack().each(function () {
3380          restoreValueAndRequired(this);
3381          triggerEventHandlers(this);
3382        });
3383      }
3384      else {
3385        // @see https://www.sitepoint.com/jquery-function-clear-form-data/
3386        $(':input', e.target).addBack().each(function () {
3387          backupValueAndRequired(this);
3388          clearValueAndRequired(this);
3389          triggerEventHandlers(this);
3390        });
3391      }
3392    }
3393  });
3394
3395  $document.on('state:visible-slide', function (e) {
3396    if (e.trigger && $(e.target).isWebformElement()) {
3397      var effect = e.value ? 'slideDown' : 'slideUp';
3398      var duration = Drupal.webform.states[effect].duration;
3399      $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper')[effect](duration);
3400    }
3401  });
3402  Drupal.states.State.aliases['invisible-slide'] = '!visible-slide';
3403
3404  $document.on('state:disabled', function (e) {
3405    if (e.trigger && $(e.target).isWebformElement()) {
3406      // Make sure disabled property is set before triggering webform:disabled.
3407      // Copied from: core/misc/states.js
3408      $(e.target)
3409        .prop('disabled', e.value)
3410        .closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value)
3411        .find('select, input, textarea, button').prop('disabled', e.value);
3412
3413      // Never disable hidden file[fids] because the existing values will
3414      // be completely lost when the webform is submitted.
3415      var fileElements = $(e.target)
3416        .find(':input[type="hidden"][name$="[fids]"]');
3417      if (fileElements.length) {
3418        // Remove 'disabled' attribute from fieldset which will block
3419        // all disabled elements from being submitted.
3420        if ($(e.target).is('fieldset')) {
3421          $(e.target).prop('disabled', false);
3422        }
3423        fileElements.removeAttr('disabled');
3424      }
3425
3426      // Trigger webform:disabled.
3427      $(e.target).trigger('webform:disabled')
3428        .find('select, input, textarea, button').trigger('webform:disabled');
3429    }
3430  });
3431
3432  /* ************************************************************************ */
3433  // Behaviors.
3434  /* ************************************************************************ */
3435
3436  /**
3437   * Adds HTML5 validation to required checkboxes.
3438   *
3439   * @type {Drupal~behavior}
3440   *
3441   * @see https://www.drupal.org/project/webform/issues/3068998
3442   */
3443  Drupal.behaviors.webformCheckboxesRequired = {
3444    attach: function (context) {
3445      $(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))
3446        .each(function () {
3447          var $element = $(this);
3448          $element.find('input[type="checkbox"]').on('click', statesCheckboxesRequiredEventHandler);
3449          setTimeout(function () {checkboxesRequired($element);});
3450        });
3451    }
3452  };
3453
3454  /**
3455   * Adds HTML5 validation to required radios.
3456   *
3457   * @type {Drupal~behavior}
3458   *
3459   * @see https://www.drupal.org/project/webform/issues/2856795
3460   */
3461  Drupal.behaviors.webformRadiosRequired = {
3462    attach: function (context) {
3463      $(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))
3464        .each(function () {
3465          var $element = $(this);
3466          setTimeout(function () {radiosRequired($element);});
3467        });
3468    }
3469  };
3470
3471 /**
3472   * Adds HTML5 validation to required table select.
3473   *
3474   * @type {Drupal~behavior}
3475   *
3476   * @see https://www.drupal.org/project/webform/issues/2856795
3477   */
3478  Drupal.behaviors.webformTableSelectRequired = {
3479    attach: function (context) {
3480      $(once('webform-tableselect-required','.js-webform-tableselect.required', context))
3481        .each(function () {
3482          var $element = $(this);
3483          var $tbody = $element.find('tbody');
3484          var isMultiple = $element.is('[multiple]');
3485
3486          if (isMultiple) {
3487            // Check all checkbox triggers checkbox 'change' event on
3488            // select and deselect all.
3489            // @see Drupal.tableSelect
3490            $tbody.find('input[type="checkbox"]').on('click change', function () {
3491              checkboxesRequired($tbody);
3492            });
3493          }
3494
3495          setTimeout(function () {
3496            isMultiple ? checkboxesRequired($tbody) : radiosRequired($element);
3497          });
3498        });
3499    }
3500  };
3501
3502  /**
3503   * Add HTML5 multiple checkboxes required validation.
3504   *
3505   * @param {jQuery} $element
3506   *   An jQuery object containing HTML5 radios.
3507   *
3508   * @see https://stackoverflow.com/a/37825072/145846
3509   */
3510  function checkboxesRequired($element) {
3511    var $firstCheckbox = $element.find('input[type="checkbox"]').first();
3512    var isChecked = $element.find('input[type="checkbox"]').is(':checked');
3513    toggleRequired($firstCheckbox, !isChecked);
3514    copyRequireMessage($element, $firstCheckbox);
3515  }
3516
3517  /**
3518   * Add HTML5 radios required validation.
3519   *
3520   * @param {jQuery} $element
3521   *   An jQuery object containing HTML5 radios.
3522   *
3523   * @see https://www.drupal.org/project/webform/issues/2856795
3524   */
3525  function radiosRequired($element) {
3526    var $radios = $element.find('input[type="radio"]');
3527    var isRequired = $element.hasClass('required');
3528    toggleRequired($radios, isRequired);
3529    copyRequireMessage($element, $radios);
3530  }
3531
3532  /* ************************************************************************ */
3533  // Event handlers.
3534  /* ************************************************************************ */
3535
3536  /**
3537   * Trigger #states API HTML5 multiple checkboxes required validation.
3538   *
3539   * @see https://stackoverflow.com/a/37825072/145846
3540   */
3541  function statesCheckboxesRequiredEventHandler() {
3542    var $element = $(this).closest('.js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other');
3543    checkboxesRequired($element);
3544  }
3545
3546  /**
3547   * Trigger an input's event handlers.
3548   *
3549   * @param {element} input
3550   *   An input.
3551   */
3552  function triggerEventHandlers(input) {
3553    var $input = $(input);
3554    var type = input.type;
3555    var tag = input.tagName.toLowerCase();
3556    // Add 'webform.states' as extra parameter to event handlers.
3557    // @see Drupal.behaviors.webformUnsaved
3558    var extraParameters = ['webform.states'];
3559    if (type === 'checkbox' || type === 'radio') {
3560      $input
3561        .trigger('change', extraParameters)
3562        .trigger('blur', extraParameters);
3563    }
3564    else if (tag === 'select') {
3565      // Do not trigger the onchange event for Address element's country code
3566      // when it is initialized.
3567      // @see \Drupal\address\Element\Country
3568      if ($input.closest('.webform-type-address').length) {
3569        if (!$input.data('webform-states-address-initialized')
3570          && $input.attr('autocomplete') === 'country'
3571          && $input.val() === $input.find("option[selected]").attr('value')) {
3572          return;
3573        }
3574        $input.data('webform-states-address-initialized', true);
3575      }
3576
3577      $input
3578        .trigger('change', extraParameters)
3579        .trigger('blur', extraParameters);
3580    }
3581    else if (type !== 'submit' && type !== 'button' && type !== 'file') {
3582      // Make sure input mask is removed and then reset when value is restored.
3583      // @see https://www.drupal.org/project/webform/issues/3124155
3584      // @see https://www.drupal.org/project/webform/issues/3202795
3585      var hasInputMask = ($.fn.inputmask && $input.hasClass('js-webform-input-mask'));
3586      hasInputMask && $input.inputmask('remove');
3587
3588      $input
3589        .trigger('input', extraParameters)
3590        .trigger('change', extraParameters)
3591        .trigger('keydown', extraParameters)
3592        .trigger('keyup', extraParameters)
3593        .trigger('blur', extraParameters);
3594
3595      hasInputMask && $input.inputmask();
3596    }
3597  }
3598
3599  /* ************************************************************************ */
3600  // Backup and restore value functions.
3601  /* ************************************************************************ */
3602
3603  /**
3604   * Backup an input's current value and required attribute
3605   *
3606   * @param {element} input
3607   *   An input.
3608   */
3609  function backupValueAndRequired(input) {
3610    var $input = $(input);
3611    var type = input.type;
3612    var tag = input.tagName.toLowerCase(); // Normalize case.
3613
3614    // Backup required.
3615    if ($input.prop('required') && !$input.hasData('webform-required')) {
3616      $input.data('webform-required', true);
3617    }
3618
3619    // Backup value.
3620    if (!$input.hasData('webform-value')) {
3621      if (type === 'checkbox' || type === 'radio') {
3622        $input.data('webform-value', $input.prop('checked'));
3623      }
3624      else if (tag === 'select') {
3625        var values = [];
3626        $input.find('option:selected').each(function (i, option) {
3627          values[i] = option.value;
3628        });
3629        $input.data('webform-value', values);
3630      }
3631      else if (type !== 'submit' && type !== 'button') {
3632        $input.data('webform-value', input.value);
3633      }
3634    }
3635  }
3636
3637  /**
3638   * Restore an input's value and required attribute.
3639   *
3640   * @param {element} input
3641   *   An input.
3642   */
3643  function restoreValueAndRequired(input) {
3644    var $input = $(input);
3645
3646    // Restore value.
3647    var value = $input.data('webform-value');
3648    if (typeof value !== 'undefined') {
3649      var type = input.type;
3650      var tag = input.tagName.toLowerCase(); // Normalize case.
3651
3652      if (type === 'checkbox' || type === 'radio') {
3653        $input.prop('checked', value);
3654      }
3655      else if (tag === 'select') {
3656        $.each(value, function (i, option_value) {
3657          // Prevent "Syntax error, unrecognized expression" error by
3658          // escaping single quotes.
3659          // @see https://forum.jquery.com/topic/escape-characters-prior-to-using-selector
3660          option_value = option_value.replace(/'/g, "\\\'");
3661          $input.find("option[value='" + option_value + "']").prop('selected', true);
3662        });
3663      }
3664      else if (type !== 'submit' && type !== 'button') {
3665        input.value = value;
3666      }
3667      $input.removeData('webform-value');
3668    }
3669
3670    // Restore required.
3671    var required = $input.data('webform-required');
3672    if (typeof required !== 'undefined') {
3673      if (required) {
3674        $input.prop('required', true);
3675      }
3676      $input.removeData('webform-required');
3677    }
3678  }
3679
3680  /**
3681   * Clear an input's value and required attributes.
3682   *
3683   * @param {element} input
3684   *   An input.
3685   */
3686  function clearValueAndRequired(input) {
3687    var $input = $(input);
3688
3689    // Check for #states no clear attribute.
3690    // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/
3691    if ($input.closest('[data-webform-states-no-clear]').length) {
3692      return;
3693    }
3694
3695    // Clear value.
3696    var type = input.type;
3697    var tag = input.tagName.toLowerCase(); // Normalize case.
3698    if (type === 'checkbox' || type === 'radio') {
3699      $input.prop('checked', false);
3700    }
3701    else if (tag === 'select') {
3702      if ($input.find('option[value=""]').length) {
3703        $input.val('');
3704      }
3705      else {
3706        input.selectedIndex = -1;
3707      }
3708    }
3709    else if (type !== 'submit' && type !== 'button') {
3710      input.value = (type === 'color') ? '#000000' : '';
3711    }
3712
3713    // Clear required.
3714    $input.prop('required', false);
3715  }
3716
3717  /* ************************************************************************ */
3718  // Helper functions.
3719  /* ************************************************************************ */
3720
3721  /**
3722   * Toggle an input's required attributes.
3723   *
3724   * @param {element} $input
3725   *   An input.
3726   * @param {boolean} required
3727   *   Is input required.
3728   */
3729  function toggleRequired($input, required) {
3730    var isCheckboxOrRadio = ($input.attr('type') === 'radio' || $input.attr('type') === 'checkbox');
3731    if (required) {
3732      if (isCheckboxOrRadio) {
3733        $input.attr({'required': 'required'});
3734      }
3735      else {
3736        $input.attr({'required': 'required', 'aria-required': 'true'});
3737      }
3738    }
3739    else {
3740      if (isCheckboxOrRadio) {
3741        $input.removeAttr('required');
3742      }
3743      else {
3744        $input.removeAttr('required aria-required');
3745      }
3746    }
3747  }
3748
3749  /**
3750   * Copy the clientside_validation.module's message.
3751   *
3752   * @param {jQuery} $source
3753   *   The source element.
3754   * @param {jQuery} $destination
3755   *   The destination element.
3756   */
3757  function copyRequireMessage($source, $destination) {
3758    if ($source.attr('data-msg-required')) {
3759      $destination.attr('data-msg-required', $source.attr('data-msg-required'));
3760    }
3761  }
3762
3763})(jQuery, Drupal, once);
3764;
3765/**
3766 * @file
3767 * JavaScript behaviors for custom webform #states.
3768 */
3769
3770(function ($, Drupal) {
3771
3772  'use strict';
3773
3774  $(document).on('state:required', function (e) {
3775    if (e.trigger && $(e.target).isWebform()) {
3776      var $target = $(e.target);
3777
3778      // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset.
3779      // Fix #required for fieldsets.
3780      if ($target.is('.js-form-wrapper.panel')) {
3781        if (e.value) {
3782          $target.find('.panel-heading .panel-title').addClass('js-form-required form-required');
3783        }
3784        else {
3785          $target.find('.panel-heading .panel-title').removeClass('js-form-required form-required');
3786        }
3787      }
3788
3789    }
3790  });
3791
3792})(jQuery, Drupal);
3793;

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.