1/** 2* DO NOT EDIT THIS FILE. 3* See the following change record for more information, 4* https://www.drupal.org/node/2815083 5* @preserve 6**/ 7 8Drupal.debounce = function (func, wait, immediate) { 9 var timeout = void 0; 10 var result = void 0; 11 return function () { 12 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 13 args[_key] = arguments[_key]; 14 } 15 16 var context = this; 17 var later = function later() { 18 timeout = null; 19 if (!immediate) { 20 result = func.apply(context, args); 21 } 22 }; 23 var callNow = immediate && !timeout; 24 clearTimeout(timeout); 25 timeout = setTimeout(later, wait); 26 if (callNow) { 27 result = func.apply(context, args); 28 } 29 return result; 30 }; 31};; 32/** 33* DO NOT EDIT THIS FILE. 34* See the following change record for more information, 35* https://www.drupal.org/node/2815083 36* @preserve 37**/ 38 39(function ($, Drupal, debounce) { 40 $.fn.drupalGetSummary = function () { 41 var callback = this.data('summaryCallback'); 42 return this[0] && callback ? $.trim(callback(this[0])) : ''; 43 }; 44 45 $.fn.drupalSetSummary = function (callback) { 46 var self = this; 47 48 if (typeof callback !== 'function') { 49 var val = callback; 50 callback = function callback() { 51 return val; 52 }; 53 } 54 55 return this.data('summaryCallback', callback).off('formUpdated.summary').on('formUpdated.summary', function () { 56 self.trigger('summaryUpdated'); 57 }).trigger('summaryUpdated'); 58 }; 59 60 Drupal.behaviors.formSingleSubmit = { 61 attach: function attach() { 62 function onFormSubmit(e) { 63 var $form = $(e.currentTarget); 64 var formValues = $form.serialize(); 65 var previousValues = $form.attr('data-drupal-form-submit-last'); 66 if (previousValues === formValues) { 67 e.preventDefault(); 68 } else { 69 $form.attr('data-drupal-form-submit-last', formValues); 70 } 71 } 72 73 $('body').once('form-single-submit').on('submit.singleSubmit', 'form:not([method~="GET"])', onFormSubmit); 74 } 75 }; 76 77 function triggerFormUpdated(element) { 78 $(element).trigger('formUpdated'); 79 } 80 81 function fieldsList(form) { 82 var $fieldList = $(form).find('[name]').map(function (index, element) { 83 return element.getAttribute('id'); 84 }); 85 86 return $.makeArray($fieldList); 87 } 88 89 Drupal.behaviors.formUpdated = { 90 attach: function attach(context) { 91 var $context = $(context); 92 var contextIsForm = $context.is('form'); 93 var $forms = (contextIsForm ? $context : $context.find('form')).once('form-updated'); 94 var formFields = void 0; 95 96 if ($forms.length) { 97 $.makeArray($forms).forEach(function (form) { 98 var events = 'change.formUpdated input.formUpdated '; 99 var eventHandler = debounce(function (event) { 100 triggerFormUpdated(event.target); 101 }, 300); 102 formFields = fieldsList(form).join(','); 103 104 form.setAttribute('data-drupal-form-fields', formFields); 105 $(form).on(events, eventHandler); 106 }); 107 } 108 109 if (contextIsForm) { 110 formFields = fieldsList(context).join(','); 111 112 var currentFields = $(context).attr('data-drupal-form-fields'); 113 114 if (formFields !== currentFields) { 115 triggerFormUpdated(context); 116 } 117 } 118 }, 119 detach: function detach(context, settings, trigger) { 120 var $context = $(context); 121 var contextIsForm = $context.is('form'); 122 if (trigger === 'unload') { 123 var $forms = (contextIsForm ? $context : $context.find('form')).removeOnce('form-updated'); 124 if ($forms.length) { 125 $.makeArray($forms).forEach(function (form) { 126 form.removeAttribute('data-drupal-form-fields'); 127 $(form).off('.formUpdated'); 128 }); 129 } 130 } 131 } 132 }; 133 134 Drupal.behaviors.fillUserInfoFromBrowser = { 135 attach: function attach(context, settings) { 136 var userInfo = ['name', 'mail', 'homepage']; 137 var $forms = $('[data-user-info-from-browser]').once('user-info-from-browser'); 138 if ($forms.length) { 139 userInfo.forEach(function (info) { 140 var $element = $forms.find('[name=' + info + ']'); 141 var browserData = localStorage.getItem('Drupal.visitor.' + info); 142 var emptyOrDefault = $element.val() === '' || $element.attr('data-drupal-default-value') === $element.val(); 143 if ($element.length && emptyOrDefault && browserData) { 144 $element.val(browserData); 145 } 146 }); 147 } 148 $forms.on('submit', function () { 149 userInfo.forEach(function (info) { 150 var $element = $forms.find('[name=' + info + ']'); 151 if ($element.length) { 152 localStorage.setItem('Drupal.visitor.' + info, $element.val()); 153 } 154 }); 155 }); 156 } 157 }; 158 159 var handleFragmentLinkClickOrHashChange = function handleFragmentLinkClickOrHashChange(e) { 160 var url = void 0; 161 if (e.type === 'click') { 162 url = e.currentTarget.location ? e.currentTarget.location : e.currentTarget; 163 } else { 164 url = window.location; 165 } 166 var hash = url.hash.substr(1); 167 if (hash) { 168 var $target = $('#' + hash); 169 $('body').trigger('formFragmentLinkClickOrHashChange', [$target]); 170 171 setTimeout(function () { 172 return $target.trigger('focus'); 173 }, 300); 174 } 175 }; 176 177 var debouncedHandleFragmentLinkClickOrHashChange = debounce(handleFragmentLinkClickOrHashChange, 300, true); 178 179 $(window).on('hashchange.form-fragment', debouncedHandleFragmentLinkClickOrHashChange); 180 181 $(document).on('click.form-fragment', 'a[href*="#"]', debouncedHandleFragmentLinkClickOrHashChange); 182})(jQuery, Drupal, Drupal.debounce);; 183/** 184* DO NOT EDIT THIS FILE. 185* See the following change record for more information, 186* https://www.drupal.org/node/2815083 187* @preserve 188**/ 189 190(function ($, Drupal) { 191 var states = { 192 postponed: [] 193 }; 194 195 Drupal.states = states; 196 197 function invert(a, invertState) { 198 return invertState && typeof a !== 'undefined' ? !a : a; 199 } 200 201 function _compare2(a, b) { 202 if (a === b) { 203 return typeof a === 'undefined' ? a : true; 204 } 205 206 return typeof a === 'undefined' || typeof b === 'undefined'; 207 } 208 209 function ternary(a, b) { 210 if (typeof a === 'undefined') { 211 return b; 212 } 213 if (typeof b === 'undefined') { 214 return a; 215 } 216 217 return a && b; 218 } 219 220 Drupal.behaviors.states = { 221 attach: function attach(context, settings) { 222 var $states = $(context).find('[data-drupal-states]'); 223 var il = $states.length; 224 225 var _loop = function _loop(i) { 226 var config = JSON.parse($states[i].getAttribute('data-drupal-states')); 227 Object.keys(config || {}
227).forEach(function (state) { 228 new states.Dependent({ 229 element: $($states[i]), 230 state: states.State.sanitize(state), 231 constraints: config[state] 232 }); 233 }); 234 }; 235 236 for (var i = 0; i < il; i++) { 237 _loop(i); 238 } 239 240 while (states.postponed.length) { 241 states.postponed.shift()(); 242 } 243 } 244 }; 245 246 states.Dependent = function (args) { 247 var _this = this; 248 249 $.extend(this, { values: {}, oldValue: null }, args); 250 251 this.dependees = this.getDependees(); 252 Object.keys(this.dependees || {}).forEach(function (selector) { 253 _this.initializeDependee(selector, _this.dependees[selector]); 254 }); 255 }; 256 257 states.Dependent.comparisons = { 258 RegExp: function RegExp(reference, value) { 259 return reference.test(value); 260 }, 261 Function: function Function(reference, value) { 262 return reference(value); 263 }, 264 Number: function Number(reference, value) { 265 return typeof value === 'string' ? _compare2(reference.toString(), value) : _compare2(reference, value); 266 } 267 }; 268 269 states.Dependent.prototype = { 270 initializeDependee: function initializeDependee(selector, dependeeStates) { 271 var _this2 = this; 272 273 this.values[selector] = {}; 274 275 Object.keys(dependeeStates).forEach(function (i) { 276 var state = dependeeStates[i]; 277 278 if ($.inArray(state, dependeeStates) === -1) { 279 return; 280 } 281 282 state = states.State.sanitize(state); 283 284 _this2.values[selector][state.name] = null; 285 286 $(selector).on('state:' + state, { selector: selector, state: state }, function (e) { 287 _this2.update(e.data.selector, e.data.state, e.value); 288 }); 289 290 new states.Trigger({ selector: selector, state: state }); 291 }); 292 }, 293 compare: function compare(reference, selector, state) { 294 var value = this.values[selector][state.name]; 295 if (reference.constructor.name in states.Dependent.comparisons) { 296 return states.Dependent.comparisons[reference.constructor.name](reference, value); 297 } 298 299 return _compare2(reference, value); 300 }, 301 update: function update(selector, state, value) { 302 if (value !== this.values[selector][state.name]) { 303 this.values[selector][state.name] = value; 304 this.reevaluate(); 305 } 306 }, 307 reevaluate: function reevaluate() { 308 var value = this.verifyConstraints(this.constraints); 309 310 if (value !== this.oldValue) { 311 this.oldValue = value; 312 313 value = invert(value, this.state.invert); 314 315 this.element.trigger({ 316 type: 'state:' + this.state, 317 value: value, 318 trigger: true 319 }); 320 } 321 }, 322 verifyConstraints: function verifyConstraints(constraints, selector) { 323 var result = void 0; 324 if ($.isArray(constraints)) { 325 var hasXor = $.inArray('xor', constraints) === -1; 326 var len = constraints.length; 327 for (var i = 0; i < len; i++) { 328 if (constraints[i] !== 'xor') { 329 var constraint = this.checkConstraints(constraints[i], selector, i); 330 331 if (constraint && (hasXor || result)) { 332 return hasXor; 333 } 334 result = result || constraint; 335 } 336 } 337 } else if ($.isPlainObject(constraints)) { 338 for (var n in constraints) { 339 if (constraints.hasOwnProperty(n)) { 340 result = ternary(result, this.checkConstraints(constraints[n], selector, n)); 341 342 if (result === false) { 343 return false; 344 } 345 } 346 } 347 } 348 return result; 349 }, 350 checkConstraints: function checkConstraints(value, selector, state) { 351 if (typeof state !== 'string' || /[0-9]/.test(state[0])) { 352 state = null; 353 } else if (typeof selector === 'undefined') { 354 selector = state; 355 state = null; 356 } 357 358 if (state !== null) { 359 state = states.State.sanitize(state); 360 return invert(this.compare(value, selector, state), state.invert); 361 } 362 363 return this.verifyConstraints(value, selector); 364 }, 365 getDependees: function getDependees() { 366 var cache = {}; 367 368 var _compare = this.compare; 369 this.compare = function (reference, selector, state) { 370 (cache[selector] || (cache[selector] = [])).push(state.name); 371 }; 372 373 this.verifyConstraints(this.constraints); 374 375 this.compare = _compare; 376 377 return cache; 378 } 379 }; 380 381 states.Trigger = function (args) { 382 $.extend(this, args); 383 384 if (this.state in states.Trigger.states) { 385 this.element = $(this.selector); 386 387 if (!this.element.data('trigger:' + this.state)) { 388 this.initialize(); 389 } 390 } 391 }; 392 393 states.Trigger.prototype = { 394 initialize: function initialize() { 395 var _this3 = this; 396 397 var trigger = states.Trigger.states[this.state]; 398 399 if (typeof trigger === 'function') { 400 trigger.call(window, this.element); 401 } else { 402 Object.keys(trigger || {}
402).forEach(function (event) { 403 _this3.defaultTrigger(event, trigger[event]); 404 }); 405 } 406 407 this.element.data('trigger:' + this.state, true); 408 }, 409 defaultTrigger: function defaultTrigger(event, valueFn) { 410 var oldValue = valueFn.call(this.element); 411 412 this.element.on(event, $.proxy(function (e) { 413 var value = valueFn.call(this.element, e); 414 415 if (oldValue !== value) { 416 this.element.trigger({ 417 type: 'state:' + this.state, 418 value: value, 419 oldValue: oldValue 420 }); 421 oldValue = value; 422 } 423 }, this)); 424 425 states.postponed.push($.proxy(function () { 426 this.element.trigger({ 427 type: 'state:' + this.state, 428 value: oldValue, 429 oldValue: null 430 }); 431 }, this)); 432 } 433 }; 434 435 states.Trigger.states = { 436 empty: { 437 keyup: function keyup() { 438 return this.val() === ''; 439 } 440 }, 441 442 checked: { 443 change: function change() { 444 var checked = false; 445 this.each(function () { 446 checked = $(this).prop('checked'); 447 448 return !checked; 449 }); 450 return checked; 451 } 452 }, 453 454 value: { 455 keyup: function keyup() { 456 if (this.length > 1) { 457 return this.filter(':checked').val() || false; 458 } 459 return this.val(); 460 }, 461 change: function change() { 462 if (this.length > 1) { 463 return this.filter(':checked').val() || false; 464 } 465 return this.val(); 466 } 467 }, 468 469 collapsed: { 470 collapsed: function collapsed(e) { 471 return typeof e !== 'undefined' && 'value' in e ? e.value : !this.is('[open]'); 472 } 473 } 474 }; 475 476 states.State = function (state) { 477 this.pristine = state; 478 this.name = state; 479 480 var process = true; 481 do { 482 while (this.name.charAt(0) === '!') { 483 this.name = this.name.substring(1); 484 this.invert = !this.invert; 485 } 486 487 if (this.name in states.State.aliases) { 488 this.name = states.State.aliases[this.name]; 489 } else { 490 process = false; 491 } 492 } while (process); 493 }; 494 495 states.State.sanitize = function (state) { 496 if (state instanceof states.State) { 497 return state; 498 } 499 500 return new states.State(state); 501 }; 502 503 states.State.aliases = { 504 enabled: '!disabled', 505 invisible: '!visible', 506 invalid: '!valid', 507 untouched: '!touched', 508 optional: '!required', 509 filled: '!empty', 510 unchecked: '!checked', 511 irrelevant: '!relevant', 512 expanded: '!collapsed', 513 open: '!collapsed', 514 closed: 'collapsed', 515 readwrite: '!readonly' 516 }; 517 518 states.State.prototype = { 519 invert: false, 520 521 toString: function toString() { 522 return this.name; 523 } 524 }; 525 526 var $document = $(document); 527 $document.on('state:disabled', function (e) { 528 if (e.trigger) { 529 $(e.target).prop('disabled', e.value).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value).find('select, input, textarea').prop('disabled', e.value); 530 } 531 }); 532 533 $document.on('state:required', function (e) { 534 if (e.trigger) { 535 if (e.value) { 536 var label = 'label' + (e.target.id ? '[for=' + e.target.id + ']' : ''); 537 var $label = $(e.target).attr({ required: 'required', 'aria-required': 'true' }).closest('.js-form-item, .js-form-wrapper').find(label); 538 539 if (!$label.hasClass('js-form-required').length) { 540 $label.addClass('js-form-required form-required'); 541 } 542 } else { 543 $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required'); 544 } 545 } 546 }); 547 548 $document.on('state:visible', function (e) { 549 if (e.trigger) { 550 $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggle(e.value); 551 } 552 }); 553 554 $document.on('state:checked', function (e) { 555 if (e.trigger) { 556 $(e.target).prop('checked', e.value); 557 } 558 }); 559 560 $document.on('state:collapsed', function (e) { 561 if (e.trigger) { 562 if ($(e.target).is('[open]') === e.value) { 563 $(e.target).find('> summary').trigger('click'); 564 } 565 } 566 }); 567})(jQuery, Drupal);; 568/** 569 * @file 570 * JavaScript behaviors for custom webform #states. 571 */ 572 573(function ($, Drupal) { 574 575 'use strict'; 576 577 Drupal.webform = Drupal.webform || {}; 578 Drupal.webform.states = Drupal.webform.states || {}; 579 Drupal.webform.states.slideDown = Drupal.webform.states.slideDown || {}; 580 Drupal.webform.states.slideDown.duration = 'slow'; 581 Drupal.webform.states.slideUp = Drupal.webform.states.slideUp || {}; 582 Drupal.webform.states.slideUp.duration = 'fast'; 583 584 /** 585 * Check if an element has a specified data attribute. 586 * 587 * @param {string} data 588 * The data attribute name. 589 * 590 * @return {boolean} 591 * TRUE if an element has a specified data attribute. 592 */ 593 $.fn.hasData = function (data) { 594 return (typeof this.data(data) !== 'undefined'); 595 }; 596 597 /**
598 * Check if element is within the webform or not. 599 * 600 * @return {boolean} 601 * TRUE if element is within the webform. 602 */ 603 $.fn.isWebform = function () { 604 return $(this).closest('form[id^="webform"]').length ? true : false; 605 }; 606 607 // The change event is triggered by cut-n-paste and select menus. 608 // Issue #2445271: #states element empty check not triggered on mouse 609 // based paste. 610 // @see https://www.drupal.org/node/2445271 611 Drupal.states.Trigger.states.empty.change = function change() { 612 return this.val() === ''; 613 }; 614 615 // Apply solution included in #1962800 patch. 616 // Issue #1962800: Form #states not working with literal integers as 617 // values in IE11. 618 // @see https://www.drupal.org/project/drupal/issues/1962800 619 // @see https://www.drupal.org/files/issues/core-states-not-working-with-integers-ie11_1962800_46.patch 620 // 621 // This issue causes pattern, less than, and greater than support to break. 622 // @see https://www.drupal.org/project/webform/issues/2981724 623 var states = Drupal.states; 624 Drupal.states.Dependent.prototype.compare = function compare(reference, selector, state) { 625 var value = this.values[selector][state.name]; 626 627 var name = reference.constructor.name; 628 if (!name) { 629 name = $.type(reference); 630 631 name = name.charAt(0).toUpperCase() + name.slice(1); 632 } 633 if (name in states.Dependent.comparisons) { 634 return states.Dependent.comparisons[name](reference, value); 635 } 636 637 if (reference.constructor.name in states.Dependent.comparisons) { 638 return states.Dependent.comparisons[reference.constructor.name](reference, value); 639 } 640 641 return _compare2(reference, value); 642 }; 643 function _compare2(a, b) { 644 if (a === b) { 645 return typeof a === 'undefined' ? a : true; 646 } 647 648 return typeof a === 'undefined' || typeof b === 'undefined'; 649 } 650 651 // Adds pattern, less than, and greater than support to #state API. 652 // @see http://drupalsun.com/julia-evans/2012/03/09/extending-form-api-states-regular-expressions 653 Drupal.states.Dependent.comparisons.Object = function (reference, value) { 654 if ('pattern' in reference) { 655 return (new RegExp(reference['pattern'])).test(value); 656 } 657 else if ('!pattern' in reference) { 658 return !((new RegExp(reference['!pattern'])).test(value)); 659 } 660 else if ('less' in reference) { 661 return (value !== '' && parseFloat(reference['less']) > parseFloat(value)); 662 } 663 else if ('greater' in reference) { 664 return (value !== '' && parseFloat(reference['greater']) < parseFloat(value)); 665 } 666 else if ('between' in reference) { 667 if (value === '') { 668 return false; 669 } 670 else { 671 var between = reference['between']; 672 var betweenParts = between.split(':'); 673 var greater = betweenParts[0]; 674 var less = (typeof betweenParts[1] !== 'undefined') ? betweenParts[1] : null; 675 var isGreaterThan = (greater === null || greater === '' || parseFloat(value) >= parseFloat(greater)); 676 var isLessThan = (less === null || less === '' || parseFloat(value) <= parseFloat(less)); 677 return (isGreaterThan && isLessThan); 678 } 679 } 680 else { 681 return reference.indexOf(value) !== false; 682 } 683 }; 684 685 var $document = $(document); 686 687 $document.on('state:required', function (e) { 688 if (e.trigger && $(e.target).isWebform()) { 689 var $target = $(e.target); 690 // Fix #required file upload. 691 // @see Issue #2860529: Conditional required File upload field don't work. 692 if (e.value) { 693 $target.find('input[type="file"]').attr({'required': 'required', 'aria-required': 'true'}); 694 } 695 else { 696 $target.find('input[type="file"]').removeAttr('required aria-required'); 697 } 698 699 // Fix required label for checkboxes and radios. 700 // @see Issue #2938414: Checkboxes don't support #states required 701 // @see Issue #2731991: Setting required on radios marks all options required. 702 // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset. 703 // Fix #required for fieldsets. 704 // @see Issue #2977569: Hidden fieldsets that become visible with conditional logic cannot be made required. 705 if ($target.is('.js-webform-type-radios, .js-webform-type-checkboxes, fieldset')) { 706 if (e.value) { 707 $target.find('legend span.fieldset-legend:not(.visually-hidden)').addClass('js-form-required form-required'); 708 } 709 else { 710 $target.find('legend span.fieldset-legend:not(.visually-hidden)').removeClass('js-form-required form-required'); 711 } 712 } 713 714 // Fix #required for radios. 715 // @see Issue #2856795: If radio buttons are required but not filled form is nevertheless submitted. 716 if ($target.is('.js-webform-type-radios, .js-form-type-webform-radios-other')) { 717 if (e.value) { 718 $target.find('input[type="radio"]').attr({'required': 'required', 'aria-required': 'true'}); 719 } 720 else { 721 $target.find('input[type="radio"]').removeAttr('required aria-required'); 722 } 723 } 724 725 // Fix #required for checkboxes. 726 // @see Issue #2938414: Checkboxes don't support #states required. 727 // @see checkboxRequiredhandler 728 if ($target.is('.js-webform-type-checkboxes, .js-form-type-webform-checkboxes-other')) { 729 var $checkboxes = $target.find('input[type="checkbox"]'); 730 if (e.value) { 731 // Bind the event handler and add custom HTML5 required validation 732 // to all checkboxes. 733 $checkboxes.bind('click', checkboxRequiredhandler); 734 if (!$checkboxes.is(':checked')) { 735 $checkboxes.attr({'required': 'required', 'aria-required': 'true'}); 736 } 737 } 738 else { 739 // Remove custom HTML5 required validation from all checkboxes 740 // and unbind the event handler. 741 $checkboxes 742 .removeAttr('required aria-required') 743 .unbind('click', checkboxRequiredhandler); 744 } 745 } 746 747 // Issue #2986017: Fieldsets shouldn't have required attribute. 748 if ($target.is('fieldset')) { 749 $target.removeAttr('required aria-required'); 750 } 751 } 752 753 }); 754 755 $document.on('state:checked', function (e) { 756 if (e.trigger) { 757 $(e.target).change(); 758 } 759 }); 760 761 $document.on('state:readonly', function (e) { 762 if (e.trigger && $(e.target).isWebform()) { 763 $(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); 764 765 // Trigger webform:readonly. 766 $(e.target).trigger('webform:readonly') 767 .find('select, input, textarea, button').trigger('webform:readonly'); 768 } 769 }); 770 771 $document.on('state:visible state:visible-slide', function (e) { 772 if (e.trigger && $(e.target).isWebform()) { 773 if (e.value) { 774 $(':input', e.target).addBack().each(function () { 775 restoreValueAndRequired(this); 776 triggerEventHandlers(this); 777 }); 778 } 779 else { 780 // @see https://www.sitepoint.com/jquery-function-clear-form-data/ 781 $(':input', e.target).addBack().each(function () { 782 backupValueAndRequired(this); 783 clearValueAndRequired(this); 784 triggerEventHandlers(this); 785 }); 786 } 787 } 788 }); 789 790 $document.bind('state:visible-slide', function (e) { 791 if (e.trigger && $(e.target).isWebform()) { 792 var effect = e.value ? 'slideDown' : 'slideUp'; 793 var duration = Drupal.webform.states[effect].duration; 794 $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper')[effect](duration); 795 } 796 }); 797 Drupal.states.State.aliases['invisible-slide'] = '!visible-slide'; 798 799 $document.on('state:disabled', function (e) { 800 if (e.trigger && $(e.target).isWebform()) { 801 // Make sure disabled property is set before triggering webform:disabled. 802 // Copied from: core/misc/states.js 803 $(e.target) 804 .prop('disabled', e.value) 805 .closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value) 806 .find('select, input, textarea, button').prop('disabled', e.value); 807 808 // Never disable hidden file[fids] because the existing values will 809 // be completely lost when the webform is submitted. 810 var fileElements = $(e.target) 811 .find(':input[type="hidden"][name$="[fids]"]'); 812 if (fileElements.length) { 813 // Remove 'disabled' attribute from fieldset which will block 814 // all disabled elements from being submitted. 815 if ($(e.target).is('fieldset')) { 816 $(e.target).prop('disabled', false); 817 } 818 fileElements.removeAttr('disabled'); 819 } 820 821 // Trigger webform:disabled. 822 $(e.target).trigger('webform:disabled') 823 .find('select, input, textarea, button').trigger('webform:disabled'); 824 } 825 }); 826 827 /** 828 * Trigger custom HTML5 multiple checkboxes validation. 829 * 830 * @see https://stackoverflow.com/a/37825072/145846 831 */ 832 function checkboxRequiredhandler() { 833 var $checkboxes = $(this).closest('.js-webform-type-checkboxes, .js-form-type-webform-checkboxes-other').find('input[type="checkbox"]'); 834 if ($checkboxes.is(':checked')) { 835 $checkboxes.removeAttr('required aria-required'); 836 } 837 else { 838 $checkboxes.attr({'required': 'required', 'aria-required': 'true'}); 839 } 840 } 841 842 /** 843 * Trigger an input's event handlers. 844 * 845 * @param {element} input 846 * An input. 847 */ 848 function triggerEventHandlers(input) { 849 var $input = $(input); 850 var type = input.type; 851 var tag = input.tagName.toLowerCase(); 852 // Add 'webform.states' as extra parameter to event handlers. 853 // @see Drupal.behaviors.webformUnsaved 854 var extraParameters = ['webform.states']; 855 if (type === 'checkbox' || type === 'radio') { 856 $input 857 .trigger('change', extraParameters) 858 .trigger('blur', extraParameters); 859 } 860 else if (tag === 'select') { 861 $input 862 .trigger('change', extraParameters) 863 .trigger('blur', extraParameters); 864 } 865 else if (type !== 'submit' && type !== 'button' && type !== 'file') { 866 $input 867 .trigger('input', extraParameters) 868 .trigger('change', extraParameters) 869 .trigger('keydown', extraParameters) 870 .trigger('keyup', extraParameters) 871 .trigger('blur', extraParameters); 872 873 // Make sure input mask is reset when value is restored. 874 // @see https://www.drupal.org/project/webform/issues/3124155 875 if ($input.attr('data-inputmask-mask')) { 876 setTimeout(function () {$input.inputmask('remove').inputmask();}); 877 } 878 } 879 } 880 881 /** 882 * Backup an input's current value and required attribute 883 * 884 * @param {element} input 885 * An input. 886 */ 887 function backupValueAndRequired(input) { 888 var $input = $(input); 889 var type = input.type; 890 var tag = input.tagName.toLowerCase(); // Normalize case. 891 892 // Backup required. 893 if ($input.prop('required') && !$input.hasData('webform-required')) { 894 $input.data('webform-required', true); 895 } 896 897 // Backup value. 898 if (!$input.hasData('webform-value')) { 899 if (type === 'checkbox' || type === 'radio') { 900 $input.data('webform-value', $input.prop('checked')); 901 } 902 else if (tag === 'select') { 903 var values = []; 904 $input.find('option:selected').each(function (i, option) { 905 values[i] = option.value; 906 }); 907 $input.data('webform-value', values); 908 } 909 else if (type !== 'submit' && type !== 'button') { 910 $input.data('webform-value', input.value); 911 } 912 } 913 } 914 915 /** 916 * Restore an input's value and required attribute. 917 * 918 * @param {element} input 919 * An input. 920 */ 921 function restoreValueAndRequired(input) { 922 var $input = $(input); 923 924 // Restore value. 925 var value = $input.data('webform-value'); 926 if (typeof value !== 'undefined') { 927 var type = input.type; 928 var tag = input.tagName.toLowerCase(); // Normalize case. 929 930 if (type === 'checkbox' || type === 'radio') { 931 $input.prop('checked', value); 932 } 933 else if (tag === 'select') { 934 $.each(value, function (i, option_value) { 935 $input.find("option[value='" + option_value + "']").prop('selected', true); 936 }); 937 } 938 else if (type !== 'submit' && type !== 'button') { 939 input.value = value; 940 } 941 $input.removeData('webform-value'); 942 } 943 944 // Restore required. 945 var required = $input.data('webform-required'); 946 if (typeof required !== 'undefined') { 947 if (required) { 948 $input.prop('required', true); 949 } 950 $input.removeData('webform-required'); 951 } 952 } 953 954 /** 955 * Clear an input's value and required attributes. 956 * 957 * @param {element} input 958 * An input. 959 */ 960 function clearValueAndRequired(input) { 961 var $input = $(input); 962 963 // Check for #states no clear attribute.
964 // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/ 965 if ($input.closest('[data-webform-states-no-clear]').length) { 966 return; 967 } 968 969 // Clear value. 970 var type = input.type; 971 var tag = input.tagName.toLowerCase(); // Normalize case. 972 if (type === 'checkbox' || type === 'radio') { 973 $input.prop('checked', false); 974 } 975 else if (tag === 'select') { 976 if ($input.find('option[value=""]').length) { 977 $input.val(''); 978 } 979 else { 980 input.selectedIndex = -1; 981 } 982 } 983 else if (type !== 'submit' && type !== 'button') { 984 input.value = (type === 'color') ? '#000000' : ''; 985 } 986 987 // Clear required. 988 $input.prop('required', false); 989 } 990 991})(jQuery, Drupal); 992; 993/** 994 * @file 995 * JavaScript behaviors for webforms. 996 */ 997 998(function ($, Drupal) { 999 1000 'use strict'; 1001 1002 var isChrome = (/chrom(e|ium)/.test(window.navigator.userAgent.toLowerCase())); 1003 1004 /** 1005 * Remove single submit event listener. 1006 * 1007 * @type {Drupal~behavior} 1008 * 1009 * @prop {Drupal~behaviorAttach} attach 1010 * Attaches the behavior for removing single submit event listener. 1011 * 1012 * @see Drupal.behaviors.formSingleSubmit 1013 */ 1014 Drupal.behaviors.webformRemoveFormSingleSubmit = { 1015 attach: function attach() { 1016 function onFormSubmit(e) { 1017 var $form = $(e.currentTarget); 1018 $form.removeAttr('data-drupal-form-submit-last'); 1019 } 1020 $('body') 1021 .once('webform-single-submit') 1022 .on('submit.singleSubmit', 'form.webform-remove-single-submit', onFormSubmit); 1023 } 1024 }; 1025 1026 /** 1027 * Autocomplete. 1028 * 1029 * @type {Drupal~behavior} 1030 * 1031 * @prop {Drupal~behaviorAttach} attach 1032 * Attaches the behavior for the webform autofocusing. 1033 */ 1034 Drupal.behaviors.webformAutocomplete = { 1035 attach: function (context) { 1036 if (isChrome) { 1037 $(context).find('.webform-submission-form input[autocomplete="off"]') 1038 .attr('autocomplete', 'chrome-off-' + Math.floor(Math.random() * 100000000)); 1039 } 1040 } 1041 }; 1042 1043 /** 1044 * Prevent webform autosubmit on wizard pages. 1045 * 1046 * @type {Drupal~behavior} 1047 * 1048 * @prop {Drupal~behaviorAttach} attach 1049 * Attaches the behavior for disabling webform autosubmit. 1050 * Wizard pages need to be progressed with the Previous or Next buttons, 1051 * not by pressing Enter. 1052 */ 1053 Drupal.behaviors.webformDisableAutoSubmit = { 1054 attach: function (context) { 1055 // Not using context so that inputs loaded via Ajax will have autosubmit 1056 // disabled. 1057 // @see http://stackoverflow.com/questions/11235622/jquery-disable-form-submit-on-enter 1058 $('.js-webform-disable-autosubmit input') 1059 .not(':button, :submit, :reset, :image, :file') 1060 .once('webform-disable-autosubmit') 1061 .on('keyup keypress', function (e) { 1062 if (e.which === 13) { 1063 e.preventDefault(); 1064 return false; 1065 } 1066 }); 1067 } 1068 }; 1069 1070 /** 1071 * Skip client-side validation when submit button is pressed. 1072 * 1073 * @type {Drupal~behavior} 1074 * 1075 * @prop {Drupal~behaviorAttach} attach 1076 * Attaches the behavior for the skipping client-side validation. 1077 * 1078 * @deprecated in Webform 8.x-5.x and will be removed in Webform 8.x-6.x. 1079 * Use 'formnovalidate' attribute instead. 1080 */ 1081 Drupal.behaviors.webformSubmitNoValidate = { 1082 attach: function (context) { 1083 $(context).find(':submit.js-webform-novalidate') 1084 .once('webform-novalidate') 1085 .attr('formnovalidate', 'formnovalidate'); 1086 } 1087 }; 1088 1089 /** 1090 * Custom required and pattern validation error messages. 1091 * 1092 * @type {Drupal~behavior} 1093 * 1094 * @prop {Drupal~behaviorAttach} attach 1095 * Attaches the behavior for the webform custom required and pattern 1096 * validation error messages. 1097 * 1098 * @see http://stackoverflow.com/questions/5272433/html5-form-required-attribute-set-custom-validation-message 1099 **/ 1100 Drupal.behaviors.webformRequiredError = { 1101 attach: function (context) { 1102 $(context).find(':input[data-webform-required-error], :input[data-webform-pattern-error]').once('webform-required-error') 1103 .on('invalid', function () { 1104 this.setCustomValidity(''); 1105 if (this.valid) { 1106 return; 1107 } 1108 1109 if (this.validity.patternMismatch && $(this).attr('data-webform-pattern-error')) { 1110 this.setCustomValidity($(this).attr('data-webform-pattern-error')); 1111 } 1112 else if (this.validity.valueMissing && $(this).attr('data-webform-required-error')) { 1113 this.setCustomValidity($(this).attr('data-webform-required-error')); 1114 } 1115 }) 1116 .on('input change', function () { 1117 // Find all related elements by name and reset custom validity. 1118 // This specifically applies to required radios and checkboxes. 1119 var name = $(this).attr('name'); 1120 $(this.form).find(':input[name="' + name + '"]').each(function () { 1121 this.setCustomValidity(''); 1122 }); 1123 }); 1124 } 1125 }; 1126 1127 // When #state:required is triggered we need to reset the target elements 1128 // custom validity. 1129 $(document).on('state:required', function (e) { 1130 $(e.target).filter('[data-webform-required-error]') 1131 .each(function () {this.setCustomValidity('');}); 1132 }); 1133 1134})(jQuery, Drupal); 1135; 1136/** 1137 * @file 1138 * JavaScript behaviors for details element. 1139 */ 1140 1141(function ($, Drupal) { 1142 1143 'use strict'; 1144 1145 /** 1146 * Attach handler to save details open/close state. 1147 * 1148 * @type {Drupal~behavior} 1149 */ 1150 Drupal.behaviors.webformDetailsSave = { 1151 attach: function (context) { 1152 if (!window.localStorage) { 1153 return; 1154 } 1155 1156 // Summary click event handler. 1157 $('details > summary', context).once('webform-details-summary-save').click(function () { 1158 var $details = $(this).parent(); 1159 1160
1161 // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/ 1162 if ($details[0].hasAttribute('data-webform-details-nosave')) { 1163 return; 1164 } 1165 1166 var name = Drupal.webformDetailsSaveGetName($details); 1167 if (!name) { 1168 return; 1169 } 1170 1171 var open = ($details.attr('open') !== 'open') ? '1' : '0'; 1172 localStorage.setItem(name, open); 1173 }); 1174 1175 // Initialize details open state via local storage. 1176 $('details', context).once('webform-details-save').each(function () { 1177 var $details = $(this); 1178 1179 var name = Drupal.webformDetailsSaveGetName($details); 1180 if (!name) { 1181 return; 1182 } 1183 1184 var open = localStorage.getItem(name); 1185 if (open === null) { 1186 return; 1187 } 1188 1189 if (open === '1') { 1190 $details.attr('open', 'open'); 1191 } 1192 else { 1193 $details.removeAttr('open'); 1194 } 1195 }); 1196 } 1197 1198 }; 1199 1200 /** 1201 * Get the name used to store the state of details element. 1202 * 1203 * @param {jQuery} $details 1204 * A details element. 1205 * 1206 * @return {string} 1207 * The name used to store the state of details element. 1208 */ 1209 Drupal.webformDetailsSaveGetName = function ($details) { 1210 if (!window.localStorage) { 1211 return ''; 1212 } 1213 1214 // Any details element not included a webform must have define its own id. 1215 var webformId = $details.attr('data-webform-element-id'); 1216 if (webformId) { 1217 return 'Drupal.webform.' + webformId.replace('--', '.'); 1218 } 1219 1220 var detailsId = $details.attr('id'); 1221 if (!detailsId) { 1222 return ''; 1223 } 1224 1225 var $form = $details.parents('form'); 1226 if (!$form.length || !$form.attr('id')) { 1227 return ''; 1228 } 1229 1230 var formId = $form.attr('id'); 1231 if (!formId) { 1232 return ''; 1233 } 1234 1235 // ISSUE: When Drupal renders a webform in a modal dialog it appends a unique 1236 // identifier to webform ids and details ids. (i.e. my-form--FeSFISegTUI) 1237 // WORKAROUND: Remove the unique id that delimited using double dashes. 1238 formId = formId.replace(/--.+?$/, '').replace(/-/g, '_'); 1239 detailsId = detailsId.replace(/--.+?$/, '').replace(/-/g, '_'); 1240 return 'Drupal.webform.' + formId + '.' + detailsId; 1241 }; 1242 1243})(jQuery, Drupal); 1244; 1245/** 1246* DO NOT EDIT THIS FILE. 1247* See the following change record for more information, 1248* https://www.drupal.org/node/2815083 1249* @preserve 1250**/ 1251 1252(function (Drupal, debounce) { 1253 var liveElement = void 0; 1254 var announcements = []; 1255 1256 Drupal.behaviors.drupalAnnounce = { 1257 attach: function attach(context) { 1258 if (!liveElement) { 1259 liveElement = document.createElement('div'); 1260 liveElement.id = 'drupal-live-announce'; 1261 liveElement.className = 'visually-hidden'; 1262 liveElement.setAttribute('aria-live', 'polite'); 1263 liveElement.setAttribute('aria-busy', 'false'); 1264 document.body.appendChild(liveElement); 1265 } 1266 } 1267 }; 1268 1269 function announce() { 1270 var text = []; 1271 var priority = 'polite'; 1272 var announcement = void 0; 1273 1274 var il = announcements.length; 1275 for (var i = 0; i < il; i++) { 1276 announcement = announcements.pop(); 1277 text.unshift(announcement.text); 1278 1279 if (announcement.priority === 'assertive') { 1280 priority = 'assertive'; 1281 } 1282 } 1283 1284 if (text.length) { 1285 liveElement.innerHTML = ''; 1286 1287 liveElement.setAttribute('aria-busy', 'true'); 1288 1289 liveElement.setAttribute('aria-live', priority); 1290 1291 liveElement.innerHTML = text.join('\n'); 1292 1293 liveElement.setAttribute('aria-busy', 'false'); 1294 } 1295 } 1296 1297 Drupal.announce = function (text, priority) { 1298 announcements.push({ 1299 text: text, 1300 priority: priority 1301 }); 1302 1303 return debounce(announce, 200)(); 1304 }; 1305})(Drupal, Drupal.debounce);; 1306/** 1307 * @file 1308 * JavaScript behaviors for details element. 1309 */ 1310 1311(function ($, Drupal) { 1312 1313 'use strict'; 1314 1315 Drupal.webform = Drupal.webform || {}; 1316 Drupal.webform.detailsToggle = Drupal.webform.detailsToggle || {}; 1317 Drupal.webform.detailsToggle.options = Drupal.webform.detailsToggle.options || {}; 1318 1319 /** 1320 * Attach handler to toggle details open/close state. 1321 * 1322 * @type {Drupal~behavior} 1323 */ 1324 Drupal.behaviors.webformDetailsToggle = { 1325 attach: function (context) { 1326 $('.js-webform-details-toggle', context).once('webform-details-toggle').each(function () { 1327 var $form = $(this); 1328 var $tabs = $form.find('.webform-tabs'); 1329 1330 // Get only the main details elements and ignore all nested details. 1331 var selector = ($tabs.length) ? '.webform-tab' : '.js-webform-details-toggle'; 1332 var $details = $form.find('details').filter(function () { 1333 var $parents = $(this).parentsUntil(selector); 1334 return ($parents.find('details').length === 0); 1335 }); 1336 1337 // Toggle is only useful when there are two or more details elements. 1338 if ($details.length < 2) { 1339 return; 1340 } 1341 1342 var options = $.extend({ 1343 button: '<button type="button" class="webform-details-toggle-state"></button>' 1344 }, Drupal.webform.detailsToggle.options); 1345 1346 // Create toggle buttons. 1347 var $toggle = $(options.button) 1348 .attr('title', Drupal.t('Toggle details widget state.')) 1349 .on('click', function (e) { 1350 var open; 1351 if (Drupal.webform.detailsToggle.isFormDetailsOpen($form)) { 1352 $form.find('details').removeAttr('open'); 1353 open = 0; 1354 } 1355 else { 1356 $form.find('details').attr('open', 'open'); 1357 open = 1; 1358 } 1359 Drupal.webform.detailsToggle.setDetailsToggleLabel($form); 1360 1361 // Set the saved states for all the details elements. 1362 // @see webform.element.details.save.js 1363 if (Drupal.webformDetailsSaveGetName) { 1364 $form.find('details').each(function () { 1365 var name = Drupal.webformDetailsSaveGetName($(this)); 1366 if (name) {
1367 localStorage.setItem(name, open); 1368 } 1369 }); 1370 } 1371 }) 1372 .wrap('<div class="webform-details-toggle-state-wrapper"></div>') 1373 .parent(); 1374 1375 if ($tabs.length) { 1376 // Add toggle state before the tabs. 1377 $tabs.find('.item-list:first-child').eq(0).before($toggle); 1378 } 1379 else { 1380 // Add toggle state link to first details element. 1381 $details.eq(0).before($toggle); 1382 } 1383 1384 Drupal.webform.detailsToggle.setDetailsToggleLabel($form); 1385 }); 1386 } 1387 }; 1388 1389 /** 1390 * Determine if a webform's details are all opened. 1391 * 1392 * @param {jQuery} $form 1393 * A webform. 1394 * 1395 * @return {boolean} 1396 * TRUE if a webform's details are all opened. 1397 */ 1398 Drupal.webform.detailsToggle.isFormDetailsOpen = function ($form) { 1399 return ($form.find('details[open]').length === $form.find('details').length); 1400 }; 1401 1402 /** 1403 * Set a webform's details toggle state widget label. 1404 * 1405 * @param {jQuery} $form 1406 * A webform. 1407 */ 1408 Drupal.webform.detailsToggle.setDetailsToggleLabel = function ($form) { 1409 var isOpen = Drupal.webform.detailsToggle.isFormDetailsOpen($form); 1410 1411 var label = (isOpen) ? Drupal.t('Collapse all') : Drupal.t('Expand all'); 1412 $form.find('.webform-details-toggle-state').html(label); 1413 1414 var text = (isOpen) ? Drupal.t('All details have been expanded.') : Drupal.t('All details have been collapsed.'); 1415 Drupal.announce(text); 1416 }; 1417 1418})(jQuery, Drupal); 1419; 1420/** 1421 * @file 1422 * JavaScript behaviors for message element integration. 1423 */ 1424 1425(function ($, Drupal) { 1426 1427 'use strict'; 1428 1429 /** 1430 * Behavior for handler message close. 1431 * 1432 * @type {Drupal~behavior} 1433 */ 1434 Drupal.behaviors.webformMessageClose = { 1435 attach: function (context) { 1436 $(context).find('.js-webform-message--close').once('webform-message--close').each(function () { 1437 var $element = $(this); 1438 1439 var id = $element.attr('data-message-id'); 1440 var storage = $element.attr('data-message-storage'); 1441 var effect = $element.attr('data-message-close-effect') || 'hide'; 1442 switch (effect) { 1443 case 'slide': effect = 'slideUp'; break; 1444 1445 case 'fade': effect = 'fadeOut'; break; 1446 } 1447 1448 // Check storage status. 1449 if (isClosed($element, storage, id)) { 1450 return; 1451 } 1452 1453 // Only show element if it's style is not set to 'display: none'. 1454 if ($element.attr('style') !== 'display: none;') { 1455 $element.show(); 1456 } 1457 1458 $element.find('.js-webform-message__link').on('click', function (event) { 1459 $element[effect](); 1460 setClosed($element, storage, id); 1461 $element.trigger('close'); 1462 event.preventDefault(); 1463 }); 1464 }); 1465 } 1466 }; 1467 1468 function isClosed($element, storage, id) { 1469 if (!id || !storage) { 1470 return false; 1471 } 1472 1473 switch (storage) { 1474 case 'local': 1475 if (window.localStorage) { 1476 return localStorage.getItem('Drupal.webform.message.' + id) || false; 1477 } 1478 return false; 1479 1480 case 'session': 1481 if (window.sessionStorage) { 1482 return sessionStorage.getItem('Drupal.webform.message.' + id) || false; 1483 } 1484 return false; 1485 1486 default: 1487 return false; 1488 } 1489 } 1490 1491 function setClosed($element, storage, id) { 1492 if (!id || !storage) { 1493 return; 1494 } 1495 1496 switch (storage) { 1497 case 'local': 1498 if (window.localStorage) { 1499 localStorage.setItem('Drupal.webform.message.' + id, true); 1500 } 1501 break; 1502 1503 case 'session': 1504 if (window.sessionStorage) { 1505 sessionStorage.setItem('Drupal.webform.message.' + id, true); 1506 } 1507 break; 1508 1509 case 'user': 1510 case 'state': 1511 case 'custom': 1512 $.get($element.find('.js-webform-message__link').attr('href')); 1513 return true; 1514 } 1515 } 1516 1517})(jQuery, Drupal); 1518;
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.