PageSourceSearch

https://nationaltrailraceway.com/modules/contrib/webform/js/webform.states.js?v=8.9.11

js nationaltrailraceway.com collected 2026-10-02 05:51:56 UTC 19,590 bytes, 558 lines download raw bytes

1/**
2 * @file
3 * JavaScript behaviors for custom webform #states.
4 */
5
6(function ($, Drupal) {
7
8  'use strict';
9
10  Drupal.webform = Drupal.webform || {};
11  Drupal.webform.states = Drupal.webform.states || {};
12  Drupal.webform.states.slideDown = Drupal.webform.states.slideDown || {};
13  Drupal.webform.states.slideDown.duration = 'slow';
14  Drupal.webform.states.slideUp = Drupal.webform.states.slideUp || {};
15  Drupal.webform.states.slideUp.duration = 'fast';
16
17  /* ************************************************************************ */
18  // jQuery functions.
19  /* ************************************************************************ */
20
21  /**
22   * Check if an element has a specified data attribute.
23   *
24   * @param {string} data
25   *   The data attribute name.
26   *
27   * @return {boolean}
28   *   TRUE if an element has a specified data attribute.
29   */
30  $.fn.hasData = function (data) {
31    return (typeof this.data(data) !== 'undefined');
32  };
33
34  /**
35   * Check if element is within the webform or not.
36   *
37   * @return {boolean}
38   *   TRUE if element is within the webform.
39   */
40  $.fn.isWebform = function () {
41    return $(this).closest('form[id^="webform"], form[data-is-webform]').length ? true : false;
42  };
43
44  /**
45   * Check if element is to be treated as a webform element.
46   *
47   * @return {boolean}
48   *   TRUE if element is to be treated as a webform element.
49   */
50  $.fn.isWebformElement = function () {
51    return ($(this).isWebform() || $(this).closest('[data-is-webform-element]').length) ? true : false;
52  };
53
54  /* ************************************************************************ */
55  // Trigger.
56  /* ************************************************************************ */
57
58  // The change event is triggered by cut-n-paste and select menus.
59  // Issue #2445271: #states element empty check not triggered on mouse
60  // based paste.
61  // @see https://www.drupal.org/node/2445271
62  Drupal.states.Trigger.states.empty.change = function change() {
63    return this.val() === '';
64  };
65
66  /* ************************************************************************ */
67  // Dependents.
68  /* ************************************************************************ */
69
70
71  // Apply solution included in #1962800 patch.
72  // Issue #1962800: Form #states not working with literal integers as
73  // values in IE11.
74  // @see https://www.drupal.org/project/drupal/issues/1962800
75  // @see https://www.drupal.org/files/issues/core-states-not-working-with-integers-ie11_1962800_46.patch
76  //
77  // This issue causes pattern, less than, and greater than support to break.
78  // @see https://www.drupal.org/project/webform/issues/2981724
79  var states = Drupal.states;
80  Drupal.states.Dependent.prototype.compare = function compare(reference, selector, state) {
81    var value = this.values[selector][state.name];
82
83    var name = reference.constructor.name;
84    if (!name) {
85      name = $.type(reference);
86
87      name = name.charAt(0).toUpperCase() + name.slice(1);
88    }
89    if (name in states.Dependent.comparisons) {
90      return states.Dependent.comparisons[name](reference, value);
91    }
92
93    if (reference.constructor.name in states.Dependent.comparisons) {
94      return states.Dependent.comparisons[reference.constructor.name](reference, value);
95    }
96
97    return _compare2(reference, value);
98  };
99  function _compare2(a, b) {
100    if (a === b) {
101      return typeof a === 'undefined' ? a : true;
102    }
103
104    return typeof a === 'undefined' || typeof b === 'undefined';
105  }
106
107  // Adds pattern, less than, and greater than support to #state API.
108  // @see http://drupalsun.com/julia-evans/2012/03/09/extending-form-api-states-regular-expressions
109  Drupal.states.Dependent.comparisons.Object = function (reference, value) {
110    if ('pattern' in reference) {
111      return (new RegExp(reference['pattern'])).test(value);
112    }
113    else if ('!pattern' in reference) {
114      return !((new RegExp(reference['!pattern'])).test(value));
115    }
116    else if ('less' in reference) {
117      return (value !== '' && parseFloat(reference['less']) > parseFloat(value));
118    }
119    else if ('less_equal' in reference) {
120      return (value !== '' && parseFloat(reference['less_equal']) >= parseFloat(value));
121    }
122    else if ('greater' in reference) {
123      return (value !== '' && parseFloat(reference['greater']) < parseFloat(value));
124    }
125    else if ('greater_equal' in reference) {
126      return (value !== '' && parseFloat(reference['greater_equal']) <= parseFloat(value));
127    }
128    else if ('between' in reference || '!between' in reference) {
129      if (value === '') {
130        return false;
131      }
132
133      var between = reference['between'] || reference['!between'];
134      var betweenParts = between.split(':');
135      var greater = betweenParts[0];
136      var less = (typeof betweenParts[1] !== 'undefined') ? betweenParts[1] : null;
137      var isGreaterThan = (greater === null || greater === '' || parseFloat(value) >= parseFloat(greater));
138      var isLessThan = (less === null || less === '' || parseFloat(value) <= parseFloat(less));
139      var result = (isGreaterThan && isLessThan);
140      return (reference['!between']) ? !result : result;
141    }
142    else {
143      return reference.indexOf(value) !== false;
144    }
145  };
146
147  /* ************************************************************************ */
148  // States events.
149  /* ************************************************************************ */
150
151  var $document = $(document);
152
153  $document.on('state:required', function (e) {
154    if (e.trigger && $(e.target).isWebformElement()) {
155      var $target = $(e.target);
156      // Fix #required file upload.
157      // @see Issue #2860529: Conditional required File upload field don't work.
158      toggleRequired($target.find('input[type="file"]'), e.value);
159
160      // Fix #required for radios.
161      // @see Issue #2856795: If radio buttons are required but not filled form is nevertheless submitted.
162      if ($target.is('.js-form-type-radios, .js-form-type-webform-radios-other, .js-webform-type-radios, .js-webform-type-webform-radios-other')) {
163        toggleRequired($target.find('input[type="radio"]'), e.value);
164      }
165
166      // Fix #required for checkboxes.
167      // @see Issue #2938414: Checkboxes don't support #states required.
168      // @see checkboxRequiredhandler
169      if ($target.is('.js-form-type-checkboxes, .js-form-type-webform-checkboxes-other, .js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other')) {
170        var $checkboxes = $target.find('input[type="checkbox"]');
171        if (e.value) {
172          // Add event handler.
173          $checkboxes.on('click', statesCheckboxesRequiredEventHandler);
174          // Initialize and add required attribute.
175          checkboxesRequired($target);
176        }
177        else {
178          // Remove event handler.
179          $checkboxes.off('click', statesCheckboxesRequiredEventHandler);
180          // Remove required attribute.
181          toggleRequired($checkboxes, false);
182        }
183      }
184
185      // Fix required label for elements without the for attribute.
186      // @see Issue #3145300: Conditional Visible Select Other not working.
187      if ($target.is('.js-form-type-webform-select-other, .js-webform-type-webform-select-other')) {
188        var $select = $target.find('select');
189        toggleRequired($select, e.value);
190        copyRequireMessage($target, $select);
191      }
192      if ($target.find('> label:not([for])').length) {
193        $target.find('> label').toggleClass('js-form-required form-required', e.value);
194      }
195
196      // Fix required label for checkboxes and radios.
197      // @see Issue #2938414: Checkboxes don't support #states required
198      // @see Issue #2731991: Setting required on radios marks all options required.
199      // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset.
200      // Fix #required for fieldsets.
201      // @see Issue #2977569: Hidden fieldsets that become visible with conditional logic cannot be made required.
202      if ($target.is('.js-webform-type-radios, .js-webform-type-checkboxes, fieldset')) {
203        $target.find('legend span.fieldset-legend:not(.visually-hidden)').toggleClass('js-form-required form-required', e.value);
204      }
205
206      // Issue #2986017: Fieldsets shouldn't have required attribute.
207      if ($target.is('fieldset')) {
208        $target.removeAttr('required aria-required');
209      }
210    }
211  });
212
213  $document.on('state:checked', function (e) {
214    if (e.trigger) {
215      $(e.target).trigger('change');
216    }
217  });
218
219  $document.on('state:readonly', function (e) {
220    if (e.trigger && $(e.target).isWebformElement()) {
221      $(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);
222
223      // Trigger webform:readonly.
224      $(e.target).trigger('webform:readonly')
225        .find('select, input, textarea, button').trigger('webform:readonly');
226    }
227  });
228
229  $document.on('state:visible state:visible-slide', function (e) {
230    if (e.trigger && $(e.target).isWebformElement()) {
231      if (e.value) {
232        $(':input', e.target).addBack().each(function () {
233          restoreValueAndRequired(this);
234          triggerEventHandlers(this);
235        });
236      }
237      else {
238        // @see https://www.sitepoint.com/jquery-function-clear-form-data/
239        $(':input', e.target).addBack().each(function () {
240          backupValueAndRequired(this);
241          clearValueAndRequired(this);
242          triggerEventHandlers(this);
243        });
244      }
245    }
246  });
247
248  $document.on('state:visible-slide', function (e) {
249    if (e.trigger && $(e.target).isWebformElement()) {
250      var effect = e.value ? 'slideDown' : 'slideUp';
251      var duration = Drupal.webform.states[effect].duration;
252      $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper')[effect](duration);
253    }
254  });
255  Drupal.states.State.aliases['invisible-slide'] = '!visible-slide';
256
257  $document.on('state:disabled', function (e) {
258    if (e.trigger && $(e.target).isWebformElement()) {
259      // Make sure disabled property is set before triggering webform:disabled.
260      // Copied from: core/misc/states.js
261      $(e.target)
262        .prop('disabled', e.value)
263        .closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value)
264        .find('select, input, textarea, button').prop('disabled', e.value);
265
266      // Never disable hidden file[fids] because the existing values will
267      // be completely lost when the webform is submitted.
268      var fileElements = $(e.target)
269        .find(':input[type="hidden"][name$="[fids]"]');
270      if (fileElements.length) {
271        // Remove 'disabled' attribute from fieldset which will block
272        // all disabled elements from being submitted.
273        if ($(e.target).is('fieldset')) {
274          $(e.target).prop('disabled', false);
275        }
276        fileElements.removeAttr('disabled');
277      }
278
279      // Trigger webform:disabled.
280      $(e.target).trigger('webform:disabled')
281        .find('select, input, textarea, button').trigger('webform:disabled');
282    }
283  });
284
285  /* ************************************************************************ */
286  // Behaviors.
287  /* ************************************************************************ */
288
289  /**
290   * Adds HTML5 validation to required checkboxes.
291   *
292   * @type {Drupal~behavior}
293   *
294   * @see https://www.drupal.org/project/webform/issues/3068998
295   */
296  Drupal.behaviors.webformCheckboxesRequired = {
297    attach: function (context) {
298      $('.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)
299        .once('webform-checkboxes-required')
300        .each(function () {
301          var $element = $(this);
302          $element.find('input[type="checkbox"]').on('click', statesCheckboxesRequiredEventHandler);
303          setTimeout(function () {checkboxesRequired($element);});
304        });
305    }
306  };
307
308  /**
309   * Adds HTML5 validation to required radios.
310   *
311   * @type {Drupal~behavior}
312   *
313   * @see https://www.drupal.org/project/webform/issues/2856795
314   */
315  Drupal.behaviors.webformRadiosRequired = {
316    attach: function (context) {
317      $('.js-form-type-radios, .js-form-type-webform-radios-other, .js-webform-type-radios, .js-webform-type-webform-radios-other', context)
318        .once('webform-radios-required')
319        .each(function () {
320          var $element = $(this);
321          setTimeout(function () {radiosRequired($element);});
322        });
323    }
324  };
325
326  /**
327   * Add HTML5 multiple checkboxes required validation.
328   *
329   * @param {jQuery} $element
330   *   An jQuery object containing HTML5 radios.
331   *
332   * @see https://stackoverflow.com/a/37825072/145846
333   */
334  function checkboxesRequired($element) {
335    var $firstCheckbox = $element.find('input[type="checkbox"]').first();
336    var isChecked = $element.find('input[type="checkbox"]').is(':checked');
337    toggleRequired($firstCheckbox, !isChecked);
338    copyRequireMessage($element, $firstCheckbox);
339  }
340
341  /**
342   * Add HTML5 radios required validation.
343   *
344   * @param {jQuery} $element
345   *   An jQuery object containing HTML5 radios.
346   *
347   * @see https://www.drupal.org/project/webform/issues/2856795
348   */
349  function radiosRequired($element) {
350    var $radios = $element.find('input[type="radio"]');
351    var isRequired = $element.hasClass('required');
352    toggleRequired($radios, isRequired);
353    copyRequireMessage($element, $radios);
354  }
355
356  /* ************************************************************************ */
357  // Event handlers.
358  /* ************************************************************************ */
359
360  /**
361   * Trigger #states API HTML5 multiple checkboxes required validation.
362   *
363   * @see https://stackoverflow.com/a/37825072/145846
364   */
365  function statesCheckboxesRequiredEventHandler() {
366    var $element = $(this).closest('.js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other');
367    checkboxesRequired($element);
368  }
369
370  /**
371   * Trigger an input's event handlers.
372   *
373   * @param {element} input
374   *   An input.
375   */
376  function triggerEventHandlers(input) {
377    var $input = $(input);
378    var type = input.type;
379    var tag = input.tagName.toLowerCase();
380    // Add 'webform.states' as extra parameter to event handlers.
381    // @see Drupal.behaviors.webformUnsaved
382    var extraParameters = ['webform.states'];
383    if (type === 'checkbox' || type === 'radio') {
384      $input
385        .trigger('change', extraParameters)
386        .trigger('blur', extraParameters);
387    }
388    else if (tag === 'select') {
389      $input
390        .trigger('change', extraParameters)
391        .trigger('blur', extraParameters);
392    }
393    else if (type !== 'submit' && type !== 'button' && type !== 'file') {
394      $input
395        .trigger('input', extraParameters)
396        .trigger('change', extraParameters)
397        .trigger('keydown', extraParameters)
398        .trigger('keyup', extraParameters)
399        .trigger('blur', extraParameters);
400
401      // Make sure input mask is reset when value is restored.
402      // @see https://www.drupal.org/project/webform/issues/3124155
403      if ($input.attr('data-inputmask-mask')) {
404        setTimeout(function () {$input.inputmask('remove').inputmask();});
405      }
406    }
407  }
408
409  /* ************************************************************************ */
410  // Backup and restore value functions.
411  /* ************************************************************************ */
412
413  /**
414   * Backup an input's current value and required attribute
415   *
416   * @param {element} input
417   *   An input.
418   */
419  function backupValueAndRequired(input) {
420    var $input = $(input);
421    var type = input.type;
422    var tag = input.tagName.toLowerCase(); // Normalize case.
423
424    // Backup required.
425    if ($input.prop('required') && !$input.hasData('webform-required')) {
426      $input.data('webform-required', true);
427    }
428
429    // Backup value.
430    if (!$input.hasData('webform-value')) {
431      if (type === 'checkbox' || type === 'radio') {
432        $input.data('webform-value', $input.prop('checked'));
433      }
434      else if (tag === 'select') {
435        var values = [];
436        $input.find('option:selected').each(function (i, option) {
437          values[i] = option.value;
438        });
439        $input.data('webform-value', values);
440      }
441      else if (type !== 'submit' && type !== 'button') {
442        $input.data('webform-value', input.value);
443      }
444    }
445  }
446
447  /**
448   * Restore an input's value and required attribute.
449   *
450   * @param {element} input
451   *   An input.
452   */
453  function restoreValueAndRequired(input) {
454    var $input = $(input);
455
456    // Restore value.
457    var value = $input.data('webform-value');
458    if (typeof value !== 'undefined') {
459      var type = input.type;
460      var tag = input.tagName.toLowerCase(); // Normalize case.
461
462      if (type === 'checkbox' || type === 'radio') {
463        $input.prop('checked', value);
464      }
465      else if (tag === 'select') {
466        $.each(value, function (i, option_value) {
467          $input.find("option[value='" + option_value + "']").prop('selected', true);
468        });
469      }
470      else if (type !== 'submit' && type !== 'button') {
471        input.value = value;
472      }
473      $input.removeData('webform-value');
474    }
475
476    // Restore required.
477    var required = $input.data('webform-required');
478    if (typeof required !== 'undefined') {
479      if (required) {
480        $input.prop('required', true);
481      }
482      $input.removeData('webform-required');
483    }
484  }
485
486  /**
487   * Clear an input's value and required attributes.
488   *
489   * @param {element} input
490   *   An input.
491   */
492  function clearValueAndRequired(input) {
493    var $input = $(input);
494
495    // Check for #states no clear attribute.
496    // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/
497    if ($input.closest('[data-webform-states-no-clear]').length) {
498      return;
499    }
500
501    // Clear value.
502    var type = input.type;
503    var tag = input.tagName.toLowerCase(); // Normalize case.
504    if (type === 'checkbox' || type === 'radio') {
505      $input.prop('checked', false);
506    }
507    else if (tag === 'select') {
508      if ($input.find('option[value=""]').length) {
509        $input.val('');
510      }
511      else {
512        input.selectedIndex = -1;
513      }
514    }
515    else if (type !== 'submit' && type !== 'button') {
516      input.value = (type === 'color') ? '#000000' : '';
517    }
518
519    // Clear required.
520    $input.prop('required', false);
521  }
522
523  /* ************************************************************************ */
524  // Helper functions.
525  /* ************************************************************************ */
526
527  /**
528   * Toggle an input's required attributes.
529   *
530   * @param {element} $input
531   *   An input.
532   * @param {boolean} required
533   *   Is input required.
534   */
535  function toggleRequired($input, required) {
536    if (required) {
537      $input.attr({'required': 'required', 'aria-required': 'true'});
538    }
539    else {
540      $input.removeAttr('required aria-required');
541    }
542  }
543
544  /**
545   * Copy the clientside_validation.module's message.
546   *
547   * @param {jQuery} $source
548   *   The source element.
549   * @param {jQuery} $destination
550   *   The destination element.
551   */
552  function copyRequireMessage($source, $destination) {
553    if ($source.attr('data-msg-required')) {
554      $destination.attr('data-msg-required', $source.attr('data-msg-required'));
555    }
556  }
557
558})(jQuery, Drupal);

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.