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**/ 7Drupal.debounce = function (func, wait, immediate) { 8 var timeout; 9 var result; 10 return function () { 11 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 12 args[_key] = arguments[_key]; 13 } 14 var context = this; 15 var later = function later() { 16 timeout = null; 17 if (!immediate) { 18 result = func.apply(context, args); 19 } 20 }; 21 var callNow = immediate && !timeout; 22 clearTimeout(timeout); 23 timeout = setTimeout(later, wait); 24 if (callNow) { 25 result = func.apply(context, args); 26 } 27 return result; 28 }; 29};; 30/** 31* DO NOT EDIT THIS FILE. 32* See the following change record for more information, 33* https://www.drupal.org/node/2815083 34* @preserve 35**/ 36(function ($, Drupal, debounce) { 37 $.fn.drupalGetSummary = function () { 38 var callback = this.data('summaryCallback'); 39 return this[0] && callback ? callback(this[0]).trim() : ''; 40 }; 41 $.fn.drupalSetSummary = function (callback) { 42 var self = this; 43 if (typeof callback !== 'function') { 44 var val = callback; 45 callback = function callback() { 46 return val; 47 }; 48 } 49 return this.data('summaryCallback', callback).off('formUpdated.summary').on('formUpdated.summary', function () { 50 self.trigger('summaryUpdated'); 51 }).trigger('summaryUpdated'); 52 }; 53 Drupal.behaviors.formSingleSubmit = { 54 attach: function attach() { 55 function onFormSubmit(e) { 56 var $form = $(e.currentTarget); 57 var formValues = $form.serialize(); 58 var previousValues = $form.attr('data-drupal-form-submit-last'); 59 if (previousValues === formValues) { 60 e.preventDefault(); 61 } else { 62 $form.attr('data-drupal-form-submit-last', formValues); 63 } 64 } 65 $(once('form-single-submit', 'body')).on('submit.singleSubmit', 'form:not([method~="GET"])', onFormSubmit); 66 } 67 }; 68 function triggerFormUpdated(element) { 69 $(element).trigger('formUpdated'); 70 } 71 function fieldsList(form) { 72 return [].map.call(form.querySelectorAll('[name][id]'), function (el) { 73 return el.id; 74 }); 75 } 76 Drupal.behaviors.formUpdated = { 77 attach: function attach(context) { 78 var $context = $(context); 79 var contextIsForm = $context.is('form'); 80 var $forms = $(once('form-updated', contextIsForm ? $context : $context.find('form'))); 81 var formFields; 82 if ($forms.length) { 83 $.makeArray($forms).forEach(function (form) { 84 var events = 'change.formUpdated input.formUpdated '; 85 var eventHandler = debounce(function (event) { 86 triggerFormUpdated(event.target); 87 }, 300); 88 formFields = fieldsList(form).join(','); 89 form.setAttribute('data-drupal-form-fields', formFields); 90 $(form).on(events, eventHandler); 91 }); 92 } 93 if (contextIsForm) { 94 formFields = fieldsList(context).join(','); 95 var currentFields = $(context).attr('data-drupal-form-fields'); 96 if (formFields !== currentFields) { 97 triggerFormUpdated(context); 98 } 99 } 100 }, 101 detach: function detach(context, settings, trigger) { 102 var $context = $(context); 103 var contextIsForm = $context.is('form'); 104 if (trigger === 'unload') { 105 once.remove('form-updated', contextIsForm ? $context : $context.find('form')).forEac
105h(function (form) { 106 form.removeAttribute('data-drupal-form-fields'); 107 $(form).off('.formUpdated'); 108 }); 109 } 110 } 111 }; 112 Drupal.behaviors.fillUserInfoFromBrowser = { 113 attach: function attach(context, settings) { 114 var userInfo = ['name', 'mail', 'homepage']; 115 var $forms = $(once('user-info-from-browser', '[data-user-info-from-browser]')); 116 if ($forms.length) { 117 userInfo.forEach(function (info) { 118 var $element = $forms.find("[name=".concat(info, "]")); 119 var browserData = localStorage.getItem("Drupal.visitor.".concat(info)); 120 if (!$element.length) { 121 return; 122 } 123 var emptyValue = $element[0].value === ''; 124 var defaultValue = $element.attr('data-drupal-default-value') === $element[0].value; 125 if (browserData && (emptyValue || defaultValue)) { 126 $element.each(function (index, item) { 127 item.value = browserData; 128 }); 129 } 130 }); 131 } 132 $forms.on('submit', function () { 133 userInfo.forEach(function (info) { 134 var $element = $forms.find("[name=".concat(info, "]")); 135 if ($element.length) { 136 localStorage.setItem("Drupal.visitor.".concat(info), $element[0].value); 137 } 138 }); 139 }); 140 } 141 }; 142 var handleFragmentLinkClickOrHashChange = function handleFragmentLinkClickOrHashChange(e) { 143 var url; 144 if (e.type === 'click') { 145 url = e.currentTarget.location ? e.currentTarget.location : e.currentTarget; 146 } else { 147 url = window.location; 148 } 149 var hash = url.hash.substr(1); 150 if (hash) { 151 var $target = $("#".concat(hash)); 152 $('body').trigger('formFragmentLinkClickOrHashChange', [$target]); 153 setTimeout(function () { 154 return $target.trigger('focus'); 155 }, 300); 156 } 157 }; 158 var debouncedHandleFragmentLinkClickOrHashChange = debounce(handleFragmentLinkClickOrHashChange, 300, true); 159 $(window).on('hashchange.form-fragment', debouncedHandleFragmentLinkClickOrHashChange); 160 $(document).on('click.form-fragment', 'a[href*="#"]', debouncedHandleFragmentLinkClickOrHashChange); 161})(jQuery, Drupal, Drupal.debounce);; 162/** 163 * @file 164 * Webform behaviors. 165 */ 166 167(function ($, Drupal) { 168 169 'use strict'; 170 171 // Trigger Drupal's attaching of behaviors after the page is 172 // completely loaded. 173 // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button 174 // @see https://stackoverflow.com/questions/20899274/how-to-refresh-page-on-back-button-click/20899422#20899422 175 var isChrome = (/chrom(e|ium)/.test(window.navigator.userAgent.toLowerCase())); 176 if (isChrome) { 177 // Track back button in navigation. 178 // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button 179 var backButton = false; 180 if (window.performance) { 181 var navEntries = window.performance.getEntriesByType('navigation'); 182 if (navEntries.length > 0 && navEntries[0].type === 'back_forward') { 183 backButton = true; 184 } 185 else if (window.performance.navigation 186 && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) { 187 backButton = true; 188 } 189 } 190 191 // If the back button is pressed, delay Drupal's attaching of behaviors. 192 if (backButton) { 193 var attachBehaviors = Drupal.attachBehaviors; 194 Drupal.attachBehaviors = function (context, settings) { 195 setTimeout(function (context, settings) { 196 attachBehaviors(context, settings); 197 }, 300); 198 }; 199 } 200 } 201 202})(jQuery, Drupal); 203; 204/** 205* DO NOT EDIT THIS FILE. 206* See the following change record for more information, 207* https://www.drupal.org/node/2815083 208* @preserve 209**/ 210(function ($, Drupal) { 211 var states = { 212 postponed: [] 213 }; 214 Drupal.states = states; 215 function invert(a, invertState) { 216 return invertState && typeof a !== 'undefined' ? !a : a; 217 } 218 function _compare2(a, b) { 219 if (a === b) { 220 return typeof a === 'undefined' ? a : true; 221 } 222 return typeof a === 'undefined' || typeof b === 'undefined'; 223 } 224 function ternary(a, b) { 225 if (typeof a === 'undefined') { 226 return b; 227 } 228 if (typeof b === 'undefined') { 229 return a; 230 } 231 return a && b; 232 } 233 Drupal.behaviors.states = { 234 attach: function attach(context, settings) { 235 var $states = $(context).find('[data-drupal-states]'); 236 var il = $states.length; 237 var _loop = function _loop(i) { 238 var config = JSON.parse($states[i].getAttribute('data-drupal-states')); 239 Object.keys(config || {}
239).forEach(function (state) { 240 new states.Dependent({ 241 element: $($states[i]), 242 state: states.State.sanitize(state), 243 constraints: config[state] 244 }); 245 }); 246 }; 247 for (var i = 0; i < il; i++) { 248 _loop(i); 249 } 250 while (states.postponed.length) { 251 states.postponed.shift()(); 252 } 253 } 254 }; 255 states.Dependent = function (args) { 256 var _this = this; 257 $.extend(this, { 258 values: {}, 259 oldValue: null 260 }, args); 261 this.dependees = this.getDependees(); 262 Object.keys(this.dependees || {}).forEach(function (selector) { 263 _this.initializeDependee(selector, _this.dependees[selector]); 264 }); 265 }; 266 states.Dependent.comparisons = { 267 RegExp: function RegExp(reference, value) { 268 return reference.test(value); 269 }, 270 Function: function Function(reference, value) { 271 return reference(value); 272 }, 273 Number: function Number(reference, value) { 274 return typeof value === 'string' ? _compare2(reference.toString(), value) : _compare2(reference, value); 275 } 276 }; 277 states.Dependent.prototype = { 278 initializeDependee: function initializeDependee(selector, dependeeStates) { 279 var _this2 = this; 280 this.values[selector] = {}; 281 Object.keys(dependeeStates).forEach(function (i) { 282 var state = dependeeStates[i]; 283 if ($.inArray(state, dependeeStates) === -1) { 284 return; 285 } 286 state = states.State.sanitize(state); 287 _this2.values[selector][state.name] = null; 288 $(selector).on("state:".concat(state), { 289 selector: selector, 290 state: state 291 }, function (e) { 292 _this2.update(e.data.selector, e.data.state, e.value); 293 }); 294 new states.Trigger({ 295 selector: selector, 296 state: state 297 }); 298 }); 299 }, 300 compare: function compare(reference, selector, state) { 301 var value = this.values[selector][state.name]; 302 if (reference.constructor.name in states.Dependent.comparisons) { 303 return states.Dependent.comparisons[reference.constructor.name](reference, value); 304 } 305 return _compare2(reference, value); 306 }, 307 update: function update(selector, state, value) { 308 if (value !== this.values[selector][state.name]) { 309 this.values[selector][state.name] = value; 310 this.reevaluate(); 311 } 312 }, 313 reevaluate: function reevaluate() { 314 var value = this.verifyConstraints(this.constraints); 315 if (value !== this.oldValue) { 316 this.oldValue = value; 317 value = invert(value, this.state.invert); 318 this.element.trigger({ 319 type: "state:".concat(this.state), 320 value: value, 321 trigger: true 322 }); 323 } 324 }, 325 verifyConstraints: function verifyConstraints(constraints, selector) { 326 var result; 327 if ($.isArray(constraints)) { 328 var hasXor = $.inArray('xor', constraints) === -1; 329 var len = constraints.length; 330 for (var i = 0; i < len; i++) { 331 if (constraints[i] !== 'xor') { 332 var constraint = this.checkConstraints(constraints[i], selector, i); 333 if (constraint && (hasXor || result)) { 334 return hasXor; 335 } 336 result = result || constraint; 337 } 338 } 339 } else if ($.isPlainObject(constraints)) { 340 for (var n in constraints) { 341 if (constraints.hasOwnProperty(n)) { 342 result = ternary(result, this.checkConstraints(constraints[n], selector, n)); 343 if (result === false) { 344 return false; 345 } 346 } 347 } 348 } 349 return result; 350 }, 351 checkConstraints: function checkConstraints(value, selector, state) { 352 if (typeof state !== 'string' || /[0-9]/.test(state[0])) { 353 state = null; 354 } else if (typeof selector === 'undefined') { 355 selector = state; 356 state = null; 357 } 358 if (state !== null) { 359 state = states.State.sanitize(state); 360 return invert(this.compare(value, selector, state), state.invert); 361 } 362 return this.verifyConstraints(value, selector); 363 }, 364 getDependees: function getDependees() { 365 var cache = {}; 366 var _compare = this.compare; 367 this.compare = function (reference, selector, state) { 368 (cache[selector] || (cache[selector] = [])).push(state.name); 369 }; 370 this.verifyConstraints(this.constraints); 371 this.compare = _compare; 372 return cache; 373 } 374 }; 375 states.Trigger = function (args) { 376 $.extend(this, args); 377 if (this.state in states.Trigger.states) { 378 this.element = $(this.selector); 379 if (!this.element.data("trigger:".concat(this.state))) { 380 this.initialize(); 381 } 382 } 383 }; 384 states.Trigger.prototype = { 385 initialize: function initialize() { 386 var _this3 = this; 387 var trigger = states.Trigger.states[this.state]; 388 if (typeof trigger === 'function') { 389 trigger.call(window, this.element); 390 } else { 391 Object.keys(trigger || {}
391).forEach(function (event) { 392 _this3.defaultTrigger(event, trigger[event]); 393 }); 394 } 395 this.element.data("trigger:".concat(this.state), true); 396 }, 397 defaultTrigger: function defaultTrigger(event, valueFn) { 398 var oldValue = valueFn.call(this.element); 399 this.element.on(event, $.proxy(function (e) { 400 var value = valueFn.call(this.element, e); 401 if (oldValue !== value) { 402 this.element.trigger({ 403 type: "state:".concat(this.state), 404 value: value, 405 oldValue: oldValue 406 }); 407 oldValue = value; 408 } 409 }, this)); 410 states.postponed.push($.proxy(function () { 411 this.element.trigger({ 412 type: "state:".concat(this.state), 413 value: oldValue, 414 oldValue: null 415 }); 416 }, this)); 417 } 418 }; 419 states.Trigger.states = { 420 empty: { 421 keyup: function keyup() { 422 return this.val() === ''; 423 }, 424 change: function change() { 425 return this.val() === ''; 426 } 427 }, 428 checked: { 429 change: function change() { 430 var checked = false; 431 this.each(function () { 432 checked = $(this).prop('checked'); 433 return !checked; 434 }); 435 return checked; 436 } 437 }, 438 value: { 439 keyup: function keyup() { 440 if (this.length > 1) { 441 return this.filter(':checked').val() || false; 442 } 443 return this.val(); 444 }, 445 change: function change() { 446 if (this.length > 1) { 447 return this.filter(':checked').val() || false; 448 } 449 return this.val(); 450 } 451 }, 452 collapsed: { 453 collapsed: function collapsed(e) { 454 return typeof e !== 'undefined' && 'value' in e ? e.value : !this.is('[open]'); 455 } 456 } 457 }; 458 states.State = function (state) { 459 this.pristine = state; 460 this.name = state; 461 var process = true; 462 do { 463 while (this.name.charAt(0) === '!') { 464 this.name = this.name.substring(1); 465 this.invert = !this.invert; 466 } 467 if (this.name in states.State.aliases) { 468 this.name = states.State.aliases[this.name]; 469 } else { 470 process = false; 471 } 472 } while (process); 473 }; 474 states.State.sanitize = function (state) { 475 if (state instanceof states.State) { 476 return state; 477 } 478 return new states.State(state); 479 }; 480 states.State.aliases = { 481 enabled: '!disabled', 482 invisible: '!visible', 483 invalid: '!valid', 484 untouched: '!touched', 485 optional: '!required', 486 filled: '!empty', 487 unchecked: '!checked', 488 irrelevant: '!relevant', 489 expanded: '!collapsed', 490 open: '!collapsed', 491 closed: 'collapsed', 492 readwrite: '!readonly' 493 }; 494 states.State.prototype = { 495 invert: false, 496 toString: function toString() { 497 return this.name; 498 } 499 }; 500 var $document = $(document); 501 $document.on('state:disabled', function (e) { 502 if (e.trigger) { 503 $(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); 504 } 505 }); 506 $document.on('state:required', function (e) { 507 if (e.trigger) { 508 if (e.value) { 509 var label = "label".concat(e.target.id ? "[for=".concat(e.target.id, "]") : ''); 510 var $label = $(e.target).attr({ 511 required: 'required', 512 'aria-required': 'true' 513 }).closest('.js-form-item, .js-form-wrapper').find(label); 514 if (!$label.hasClass('js-form-required').length) { 515 $label.addClass('js-form-required form-required'); 516 } 517 } else { 518 $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required'); 519 } 520 } 521 }); 522 $document.on('state:visible', function (e) { 523 if (e.trigger) { 524 $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggle(e.value); 525 } 526 }); 527 $document.on('state:checked', function (e) { 528 if (e.trigger) { 529 $(e.target).closest('.js-form-item, .js-form-wrapper').find('input').prop('checked', e.value).trigger('change'); 530 } 531 }); 532 $document.on('state:collapsed', function (e) { 533 if (e.trigger) { 534 if ($(e.target).is('[open]') === e.value) { 535 $(e.target).find('> summary').trigger('click'); 536 } 537 } 538 }); 539})(jQuery, Drupal);; 540/** 541 * @file 542 * JavaScript behaviors for custom webform #states. 543 */ 544 545(function ($, Drupal, once) { 546 547 'use strict'; 548 549 Drupal.webform = Drupal.webform || {}; 550 Drupal.webform.states = Drupal.webform.states || {}; 551 Drupal.webform.states.slideDown = Drupal.webform.states.slideDown || {}; 552 Drupal.webform.states.slideDown.duration = 'slow'; 553 Drupal.webform.states.slideUp = Drupal.webform.states.slideUp || {}; 554 Drupal.webform.states.slideUp.duration = 'fast'; 555 556 /* ************************************************************************ */ 557 // jQuery functions. 558 /* ************************************************************************ */ 559 560 /** 561 * Check if an element has a specified data attribute. 562 * 563 * @param {string} data 564 * The data attribute name. 565 * 566 * @return {boolean} 567 * TRUE if an element has a specified data attribute. 568 */ 569 $.fn.hasData = function (data) { 570 return (typeof this.data(data) !== 'undefined'); 571 }; 572 573 /**
574 * Check if element is within the webform or not. 575 * 576 * @return {boolean} 577 * TRUE if element is within the webform. 578 */ 579 $.fn.isWebform = function () { 580 return $(this).closest('form.webform-submission-form, form[id^="webform"], form[data-is-webform]').length ? true : false; 581 }; 582 583 /** 584 * Check if element is to be treated as a webform element. 585 * 586 * @return {boolean} 587 * TRUE if element is to be treated as a webform element. 588 */ 589 $.fn.isWebformElement = function () { 590 return ($(this).isWebform() || $(this).closest('[data-is-webform-element]').length) ? true : false; 591 }; 592 593 /* ************************************************************************ */ 594 // Trigger. 595 /* ************************************************************************ */ 596 597 // The change event is triggered by cut-n-paste and select menus. 598 // Issue #2445271: #states element empty check not triggered on mouse 599 // based paste. 600 // @see https://www.drupal.org/node/2445271 601 Drupal.states.Trigger.states.empty.change = function change() { 602 return this.val() === ''; 603 }; 604 605 /* ************************************************************************ */ 606 // Dependents. 607 /* ************************************************************************ */ 608 609 // Apply solution included in #1962800 patch. 610 // Issue #1962800: Form #states not working with literal integers as 611 // values in IE11. 612 // @see https://www.drupal.org/project/drupal/issues/1962800 613 // @see https://www.drupal.org/files/issues/core-states-not-working-with-integers-ie11_1962800_46.patch 614 // 615 // This issue causes pattern, less than, and greater than support to break. 616 // @see https://www.drupal.org/project/webform/issues/2981724 617 var states = Drupal.states; 618 Drupal.states.Dependent.prototype.compare = function compare(reference, selector, state) { 619 var value = this.values[selector][state.name]; 620 621 var name = reference.constructor.name; 622 if (!name) { 623 name = $.type(reference); 624 625 name = name.charAt(0).toUpperCase() + name.slice(1); 626 } 627 if (name in states.Dependent.comparisons) { 628 return states.Dependent.comparisons[name](reference, value); 629 } 630 631 if (reference.constructor.name in states.Dependent.comparisons) { 632 return states.Dependent.comparisons[reference.constructor.name](reference, value); 633 } 634 635 return _compare2(reference, value); 636 }; 637 function _compare2(a, b) { 638 if (a === b) { 639 return typeof a === 'undefined' ? a : true; 640 } 641 642 return typeof a === 'undefined' || typeof b === 'undefined'; 643 } 644 645 // Adds pattern, less than, and greater than support to #state API. 646 // @see http://drupalsun.com/julia-evans/2012/03/09/extending-form-api-states-regular-expressions 647 Drupal.states.Dependent.comparisons.Object = function (reference, value) { 648 if ('pattern' in reference) { 649 return (new RegExp(reference['pattern'])).test(value); 650 } 651 else if ('!pattern' in reference) { 652 return !((new RegExp(reference['!pattern'])).test(value)); 653 } 654 else if ('less' in reference) { 655 return (value !== '' && parseFloat(reference['less']) > parseFloat(value)); 656 } 657 else if ('less_equal' in reference) { 658 return (value !== '' && parseFloat(reference['less_equal']) >= parseFloat(value)); 659 } 660 else if ('greater' in reference) { 661 return (value !== '' && parseFloat(reference['greater']) < parseFloat(value)); 662 } 663 else if ('greater_equal' in reference) { 664 return (value !== '' && parseFloat(reference['greater_equal']) <= parseFloat(value)); 665 } 666 else if ('between' in reference || '!between' in reference) { 667 if (value === '') { 668 return false; 669 } 670 671 var between = reference['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 var result = (isGreaterThan && isLessThan); 678 return (reference['!between']) ? !result : result; 679 } 680 else { 681 return reference.indexOf(value) !== false; 682 } 683 }; 684 685 /* ************************************************************************ */ 686 // States events. 687 /* ************************************************************************ */ 688 689 var $document = $(document); 690 691 $document.on('state:required', function (e) { 692 if (e.trigger && $(e.target).isWebformElement()) { 693 var $target = $(e.target); 694 // Fix #required file upload. 695 // @see Issue #2860529: Conditional required File upload field don't work. 696 toggleRequired($target.find('input[type="file"]'), e.value); 697 698 // Fix #required for radios and likert. 699 // @see Issue #2856795: If radio buttons are required but not filled form is nevertheless submitted. 700 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')) { 701 $target.toggleClass('required', e.value); 702 toggleRequired($target.find('input[type="radio"]'), e.value); 703 } 704 705 // Fix #required for checkboxes. 706 // @see Issue #2938414: Checkboxes don't support #states required. 707 // @see checkboxRequiredhandler 708 if ($target.is('.js-form-type-checkboxes, .js-form-type-webform-checkboxes-other, .js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other')) { 709 $target.toggleClass('required', e.value); 710 var $checkboxes = $target.find('input[type="checkbox"]'); 711 if (e.value) { 712 // Add event handler. 713 $checkboxes.on('click', statesCheckboxesRequiredEventHandler); 714 // Initialize and add required attribute. 715 checkboxesRequired($target); 716 } 717 else { 718 // Remove event handler. 719 $checkboxes.off('click', statesCheckboxesRequiredEventHandler); 720 // Remove required attribute. 721 toggleRequired($checkboxes, false); 722 } 723 } 724 725 // Fix #required for tableselect. 726 // @see Issue #3212581: Table select does not trigger client side validation 727 if ($target.is('.js-webform-tableselect')) { 728 $target.toggleClass('required', e.value); 729 var isMultiple = $target.is('[multiple]'); 730 if (isMultiple) { 731 // Checkboxes. 732 var $tbody = $target.find('tbody'); 733 var $checkboxes = $tbody.find('input[type="checkbox"]'); 734 copyRequireMessage($target, $checkboxes); 735 if (e.value) { 736 $checkboxes.on('click change', statesCheckboxesRequiredEventHandler); 737 checkboxesRequired($tbody); 738 } 739 else { 740 $checkboxes.off('click change ', statesCheckboxesRequiredEventHandler); 741 toggleRequired($tbody, false); 742 } 743 } 744 else { 745 // Radios. 746 var $radios = $target.find('input[type="radio"]'); 747 copyRequireMessage($target, $radios); 748 toggleRequired($radios, e.value); 749 } 750 } 751 752 // Fix required label for elements without the for attribute. 753 // @see Issue #3145300: Conditional Visible Select Other not working. 754 if ($target.is('.js-form-type-webform-select-other, .js-webform-type-webform-select-other')) { 755 var $select = $target.find('select'); 756 toggleRequired($select, e.value); 757 copyRequireMessage($target, $select); 758 } 759 if ($target.find('> label:not([for])').length) { 760 $target.find('> label').toggleClass('js-form-required form-required', e.value); 761 } 762 763 // Fix required label for checkboxes and radios. 764 // @see Issue #2938414: Checkboxes don't support #states required 765 // @see Issue #2731991: Setting required on radios marks all options required. 766 // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset. 767 // Fix #required for fieldsets. 768 // @see Issue #2977569: Hidden fieldsets that become visible with conditional logic cannot be made required. 769 if ($target.is('.js-webform-type-radios, .js-webform-type-checkboxes, fieldset')) { 770 $target.find('legend span.fieldset-legend:not(.visually-hidden),legend span.fieldset__label:not(.visually-hidden)').toggleClass('js-form-required form-required', e.value); 771 } 772 773 // Issue #2986017: Fieldsets shouldn't have required attribute. 774 if ($target.is('fieldset')) { 775 $target.removeAttr('required aria-required'); 776 } 777 } 778 }); 779 780 $document.on('state:checked', function (e) { 781 if (e.trigger) { 782 $(e.target).trigger('change'); 783 } 784 }); 785 786 $document.on('state:readonly', function (e) { 787 if (e.trigger && $(e.target).isWebformElement()) { 788 $(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); 789 790 // Trigger webform:readonly. 791 $(e.target).trigger('webform:readonly') 792 .find('select, input, textarea, button').trigger('webform:readonly'); 793 } 794 }); 795 796 $document.on('state:visible state:visible-slide', function (e) { 797 if (e.trigger && $(e.target).isWebformElement()) { 798 if (e.value) { 799 $(':input', e.target).addBack().each(function () { 800 restoreValueAndRequired(this); 801 triggerEventHandlers(this); 802 }); 803 } 804 else { 805 // @see https://www.sitepoint.com/jquery-function-clear-form-data/ 806 $(':input', e.target).addBack().each(function () { 807 backupValueAndRequired(this); 808 clearValueAndRequired(this); 809 triggerEventHandlers(this); 810 }); 811 } 812 } 813 }); 814 815 $document.on('state:visible-slide', function (e) { 816 if (e.trigger && $(e.target).isWebformElement()) { 817 var effect = e.value ? 'slideDown' : 'slideUp'; 818 var duration = Drupal.webform.states[effect].duration; 819 $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper')[effect](duration); 820 } 821 }); 822 Drupal.states.State.aliases['invisible-slide'] = '!visible-slide'; 823 824 $document.on('state:disabled', function (e) { 825 if (e.trigger && $(e.target).isWebformElement()) { 826 // Make sure disabled property is set before triggering webform:disabled. 827 // Copied from: core/misc/states.js 828 $(e.target) 829 .prop('disabled', e.value) 830 .closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value) 831 .find('select, input, textarea, button').prop('disabled', e.value); 832 833 // Never disable hidden file[fids] because the existing values will 834 // be completely lost when the webform is submitted. 835 var fileElements = $(e.target) 836 .find(':input[type="hidden"][name$="[fids]"]'); 837 if (fileElements.length) { 838 // Remove 'disabled' attribute from fieldset which will block 839 // all disabled elements from being submitted. 840 if ($(e.target).is('fieldset')) { 841 $(e.target).prop('disabled', false); 842 } 843 fileElements.removeAttr('disabled'); 844 } 845 846 // Trigger webform:disabled. 847 $(e.target).trigger('webform:disabled') 848 .find('select, input, textarea, button').trigger('webform:disabled'); 849 } 850 }); 851 852 /* ************************************************************************ */ 853 // Behaviors. 854 /* ************************************************************************ */ 855 856 /** 857 * Adds HTML5 validation to required checkboxes. 858 * 859 * @type {Drupal~behavior} 860 * 861 * @see https://www.drupal.org/project/webform/issues/3068998 862 */ 863 Drupal.behaviors.webformCheckboxesRequired = { 864 attach: function (context) { 865 $(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)) 866 .each(function () { 867 var $element = $(this); 868 $element.find('input[type="checkbox"]').on('click', statesCheckboxesRequiredEventHandler); 869 setTimeout(function () {checkboxesRequired($element);}); 870 }); 871 } 872 }; 873 874 /** 875 * Adds HTML5 validation to required radios. 876 * 877 * @type {Drupal~behavior} 878 * 879 * @see https://www.drupal.org/project/webform/issues/2856795 880 */ 881 Drupal.behaviors.webformRadiosRequired = { 882 attach: function (context) { 883 $(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)) 884 .each(function () { 885 var $element = $(this); 886 setTimeout(function () {radiosRequired($element);}); 887 }); 888 } 889 }; 890 891 /** 892 * Adds HTML5 validation to required table select. 893 * 894 * @type {Drupal~behavior} 895 * 896 * @see https://www.drupal.org/project/webform/issues/2856795 897 */ 898 Drupal.behaviors.webformTableSelectRequired = { 899 attach: function (context) { 900 $(once('webform-tableselect-required','.js-webform-tableselect.required', context)) 901 .each(function () { 902 var $element = $(this); 903 var $tbody = $element.find('tbody'); 904 var isMultiple = $element.is('[multiple]'); 905 906 if (isMultiple) { 907 // Check all checkbox triggers checkbox 'change' event on 908 // select and deselect all. 909 // @see Drupal.tableSelect 910 $tbody.find('input[type="checkbox"]').on('click change', function () { 911 checkboxesRequired($tbody); 912 }); 913 } 914 915 setTimeout(function () { 916 isMultiple ? checkboxesRequired($tbody) : radiosRequired($element); 917 }); 918 }); 919 } 920 }; 921 922 /** 923 * Add HTML5 multiple checkboxes required validation. 924 * 925 * @param {jQuery} $element
926 * An jQuery object containing HTML5 radios. 927 * 928 * @see https://stackoverflow.com/a/37825072/145846 929 */ 930 function checkboxesRequired($element) { 931 var $firstCheckbox = $element.find('input[type="checkbox"]').first(); 932 var isChecked = $element.find('input[type="checkbox"]').is(':checked'); 933 toggleRequired($firstCheckbox, !isChecked); 934 copyRequireMessage($element, $firstCheckbox); 935 } 936 937 /** 938 * Add HTML5 radios required validation. 939 * 940 * @param {jQuery} $element 941 * An jQuery object containing HTML5 radios. 942 * 943 * @see https://www.drupal.org/project/webform/issues/2856795 944 */ 945 function radiosRequired($element) { 946 var $radios = $element.find('input[type="radio"]'); 947 var isRequired = $element.hasClass('required'); 948 toggleRequired($radios, isRequired); 949 copyRequireMessage($element, $radios); 950 } 951 952 /* ************************************************************************ */ 953 // Event handlers. 954 /* ************************************************************************ */ 955 956 /** 957 * Trigger #states API HTML5 multiple checkboxes required validation. 958 * 959 * @see https://stackoverflow.com/a/37825072/145846 960 */ 961 function statesCheckboxesRequiredEventHandler() { 962 var $element = $(this).closest('.js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other'); 963 checkboxesRequired($element); 964 } 965 966 /** 967 * Trigger an input's event handlers. 968 * 969 * @param {element} input 970 * An input. 971 */ 972 function triggerEventHandlers(input) { 973 var $input = $(input); 974 var type = input.type; 975 var tag = input.tagName.toLowerCase(); 976 // Add 'webform.states' as extra parameter to event handlers. 977 // @see Drupal.behaviors.webformUnsaved 978 var extraParameters = ['webform.states']; 979 if (type === 'checkbox' || type === 'radio') { 980 $input 981 .trigger('change', extraParameters) 982 .trigger('blur', extraParameters); 983 } 984 else if (tag === 'select') { 985 // Do not trigger the onchange event for Address element's country code 986 // when it is initialized. 987 // @see \Drupal\address\Element\Country 988 if ($input.closest('.webform-type-address').length) { 989 if (!$input.data('webform-states-address-initialized') 990 && $input.attr('autocomplete') === 'country' 991 && $input.val() === $input.find("option[selected]").attr('value')) { 992 return; 993 } 994 $input.data('webform-states-address-initialized', true); 995 } 996 997 $input 998 .trigger('change', extraParameters) 999 .trigger('blur', extraParameters); 1000 } 1001 else if (type !== 'submit' && type !== 'button' && type !== 'file') { 1002 // Make sure input mask is removed and then reset when value is restored. 1003 // @see https://www.drupal.org/project/webform/issues/3124155 1004 // @see https://www.drupal.org/project/webform/issues/3202795 1005 var hasInputMask = ($.fn.inputmask && $input.hasClass('js-webform-input-mask')); 1006 hasInputMask && $input.inputmask('remove'); 1007 1008 $input 1009 .trigger('input', extraParameters) 1010 .trigger('change', extraParameters) 1011 .trigger('keydown', extraParameters) 1012 .trigger('keyup', extraParameters) 1013 .trigger('blur', extraParameters); 1014 1015 hasInputMask && $input.inputmask(); 1016 } 1017 } 1018 1019 /* ************************************************************************ */ 1020 // Backup and restore value functions. 1021 /* ************************************************************************ */ 1022 1023 /** 1024 * Backup an input's current value and required attribute 1025 * 1026 * @param {element} input 1027 * An input. 1028 */ 1029 function backupValueAndRequired(input) { 1030 var $input = $(input); 1031 var type = input.type; 1032 var tag = input.tagName.toLowerCase(); // Normalize case. 1033 1034 // Backup required. 1035 if ($input.prop('required') && !$input.hasData('webform-required')) { 1036 $input.data('webform-required', true); 1037 } 1038 1039 // Backup value. 1040 if (!$input.hasData('webform-value')) { 1041 if (type === 'checkbox' || type === 'radio') { 1042 $input.data('webform-value', $input.prop('checked')); 1043 } 1044 else if (tag === 'select') { 1045 var values = []; 1046 $input.find('option:selected').each(function (i, option) { 1047 values[i] = option.value; 1048 }); 1049 $input.data('webform-value', values); 1050 } 1051 else if (type !== 'submit' && type !== 'button') { 1052 $input.data('webform-value', input.value); 1053 } 1054 } 1055 } 1056 1057 /** 1058 * Restore an input's value and required attribute. 1059 * 1060 * @param {element} input 1061 * An input. 1062 */ 1063 function restoreValueAndRequired(input) { 1064 var $input = $(input); 1065 1066 // Restore value. 1067 var value = $input.data('webform-value'); 1068 if (typeof value !== 'undefined') { 1069 var type = input.type; 1070 var tag = input.tagName.toLowerCase(); // Normalize case. 1071 1072 if (type === 'checkbox' || type === 'radio') { 1073 $input.prop('checked', value); 1074 } 1075 else if (tag === 'select') { 1076 $.each(value, function (i, option_value) { 1077 // Prevent "Syntax error, unrecognized expression" error by 1078 // escaping single quotes. 1079 // @see https://forum.jquery.com/topic/escape-characters-prior-to-using-selector 1080 option_value = option_value.replace(/'/g, "\\\'"); 1081 $input.find("option[value='" + option_value + "']").prop('selected', true); 1082 }); 1083 } 1084 else if (type !== 'submit' && type !== 'button') { 1085 input.value = value; 1086 } 1087 $input.removeData('webform-value'); 1088 } 1089 1090 // Restore required. 1091 var required = $input.data('webform-required'); 1092 if (typeof required !== 'undefined') { 1093 if (required) { 1094 $input.prop('required', true); 1095 } 1096 $input.removeData('webform-required'); 1097 } 1098 } 1099 1100 /** 1101 * Clear an input's value and required attributes. 1102 * 1103 * @param {element} input 1104 * An input. 1105 */ 1106 function clearValueAndRequired(input) { 1107 var $input = $(input); 1108 1109 // Check for #states no clear attribute.
1110 // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/ 1111 if ($input.closest('[data-webform-states-no-clear]').length) { 1112 return; 1113 } 1114 1115 // Clear value. 1116 var type = input.type; 1117 var tag = input.tagName.toLowerCase(); // Normalize case. 1118 if (type === 'checkbox' || type === 'radio') { 1119 $input.prop('checked', false); 1120 } 1121 else if (tag === 'select') { 1122 if ($input.find('option[value=""]').length) { 1123 $input.val(''); 1124 } 1125 else { 1126 input.selectedIndex = -1; 1127 } 1128 } 1129 else if (type !== 'submit' && type !== 'button') { 1130 input.value = (type === 'color') ? '#000000' : ''; 1131 } 1132 1133 // Clear required. 1134 $input.prop('required', false); 1135 } 1136 1137 /* ************************************************************************ */ 1138 // Helper functions. 1139 /* ************************************************************************ */ 1140 1141 /** 1142 * Toggle an input's required attributes. 1143 * 1144 * @param {element} $input 1145 * An input. 1146 * @param {boolean} required 1147 * Is input required. 1148 */ 1149 function toggleRequired($input, required) { 1150 var isCheckboxOrRadio = ($input.attr('type') === 'radio' || $input.attr('type') === 'checkbox'); 1151 if (required) { 1152 if (isCheckboxOrRadio) { 1153 $input.attr({'required': 'required'}); 1154 } 1155 else { 1156 $input.attr({'required': 'required', 'aria-required': 'true'}); 1157 } 1158 } 1159 else { 1160 if (isCheckboxOrRadio) { 1161 $input.removeAttr('required'); 1162 } 1163 else { 1164 $input.removeAttr('required aria-required'); 1165 } 1166 } 1167 } 1168 1169 /** 1170 * Copy the clientside_validation.module's message. 1171 * 1172 * @param {jQuery} $source 1173 * The source element. 1174 * @param {jQuery} $destination 1175 * The destination element. 1176 */ 1177 function copyRequireMessage($source, $destination) { 1178 if ($source.attr('data-msg-required')) { 1179 $destination.attr('data-msg-required', $source.attr('data-msg-required')); 1180 } 1181 } 1182 1183})(jQuery, Drupal, once); 1184; 1185/** 1186 * @file 1187 * JavaScript behaviors for webforms. 1188 */ 1189 1190(function ($, Drupal, once) { 1191 1192 'use strict'; 1193 1194 /** 1195 * Remove single submit event listener. 1196 * 1197 * @type {Drupal~behavior} 1198 * 1199 * @prop {Drupal~behaviorAttach} attach 1200 * Attaches the behavior for removing single submit event listener. 1201 * 1202 * @see Drupal.behaviors.formSingleSubmit 1203 */ 1204 Drupal.behaviors.webformRemoveFormSingleSubmit = { 1205 attach: function attach() { 1206 function onFormSubmit(e) { 1207 var $form = $(e.currentTarget); 1208 $form.removeAttr('data-drupal-form-submit-last'); 1209 } 1210 $(once('webform-single-submit', 'body')) 1211 .on('submit.singleSubmit', 'form.webform-remove-single-submit', onFormSubmit); 1212 } 1213 }; 1214 1215 /** 1216 * Prevent webform autosubmit on wizard pages. 1217 * 1218 * @type {Drupal~behavior} 1219 * 1220 * @prop {Drupal~behaviorAttach} attach 1221 * Attaches the behavior for disabling webform autosubmit. 1222 * Wizard pages need to be progressed with the Previous or Next buttons, 1223 * not by pressing Enter. 1224 */ 1225 Drupal.behaviors.webformDisableAutoSubmit = { 1226 attach: function (context) { 1227 // Not using context so that inputs loaded via Ajax will have autosubmit 1228 // disabled. 1229 // @see http://stackoverflow.com/questions/11235622/jquery-disable-form-submit-on-enter 1230 $(once('webform-disable-autosubmit', $('.js-webform-disable-autosubmit input').not(':button, :submit, :reset, :image, :file'))) 1231 .on('keyup keypress', function (e) { 1232 if (e.which === 13) { 1233 e.preventDefault(); 1234 return false; 1235 } 1236 }); 1237 } 1238 }; 1239 1240 /** 1241 * Custom required and pattern validation error messages. 1242 * 1243 * @type {Drupal~behavior} 1244 * 1245 * @prop {Drupal~behaviorAttach} attach 1246 * Attaches the behavior for the webform custom required and pattern 1247 * validation error messages. 1248 * 1249 * @see http://stackoverflow.com/questions/5272433/html5-form-required-attribute-set-custom-validation-message 1250 **/ 1251 Drupal.behaviors.webformRequiredError = { 1252 attach: function (context) { 1253 $(once('webform-required-error', $(context).find(':input[data-webform-required-error], :input[data-webform-pattern-error]'))) 1254 .on('invalid', function () { 1255 this.setCustomValidity(''); 1256 if (this.valid) { 1257 return; 1258 } 1259 1260 if (this.validity.patternMismatch && $(this).attr('data-webform-pattern-error')) { 1261 this.setCustomValidity($(this).attr('data-webform-pattern-error')); 1262 } 1263 else if (this.validity.valueMissing && $(this).attr('data-webform-required-error')) { 1264 this.setCustomValidity($(this).attr('data-webform-required-error')); 1265 } 1266 }) 1267 .on('input change', function () { 1268 // Find all related elements by name and reset custom validity. 1269 // This specifically applies to required radios and checkboxes. 1270 var name = $(this).attr('name'); 1271 $(this.form).find(':input[name="' + name + '"]').each(function () { 1272 this.setCustomValidity(''); 1273 }); 1274 }); 1275 } 1276 }; 1277 1278 // When #state:required is triggered we need to reset the target elements 1279 // custom validity. 1280 $(document).on('state:required', function (e) { 1281 $(e.target).filter(':input[data-webform-required-error]') 1282 .each(function () {this.setCustomValidity('');}); 1283 }); 1284 1285})(jQuery, Drupal, once); 1286; 1287/** 1288 * @file 1289 * JavaScript behaviors for preventing duplicate webform submissions. 1290 */ 1291 1292(function ($, Drupal, once) { 1293 1294 'use strict'; 1295 1296 /** 1297 * Submit once. 1298 * 1299 * @type {Drupal~behavior} 1300 * 1301 * @prop {Drupal~behaviorAttach} attach 1302 * Attaches the behavior for preventing duplicate webform submissions. 1303 */ 1304 Drupal.behaviors.webformSubmitOnce = { 1305 clear: function () { 1306 var $form = $('.js-webform-submit-once'); 1307 $form.removeData('webform-submitted'); 1308 $form.find('.js-webform-wizard-pages-links :submit, .form-actions :submit').removeClass('is-disabled');
1309 $form.find('.form-actions .ajax-progress.ajax-progress-throbber').remove(); 1310 }, 1311 attach: function (context) { 1312 $(once('webform-submit-once', '.js-webform-submit-once', context)).each(function () { 1313 var $form = $(this); 1314 // Remove data-webform-submitted. 1315 $form.removeData('webform-submitted'); 1316 // Remove .js-webform-submit-clicked. 1317 $form.find('.js-webform-wizard-pages-links :submit, .form-actions :submit').removeClass('js-webform-submit-clicked'); 1318 1319 // Track which submit button was clicked. 1320 // @see http://stackoverflow.com/questions/5721724/jquery-how-to-get-which-button-was-clicked-upon-form-submission 1321 $form.find('.js-webform-wizard-pages-links :submit, .form-actions :submit').on('click', function () { 1322 $form.find('.js-webform-wizard-pages-links :submit, .form-actions :submit') 1323 .removeClass('js-webform-submit-clicked'); 1324 $(this) 1325 .addClass('js-webform-submit-clicked'); 1326 }); 1327 1328 $(this).on('submit', function () { 1329 // Find clicked button 1330 var $clickedButton = $form.find('.js-webform-wizard-pages-links :submit.js-webform-submit-clicked, .form-actions :submit.js-webform-submit-clicked'); 1331 1332 // Don't submit if client-side validation has failed. 1333 if (!$clickedButton.attr('formnovalidate') && $.isFunction(jQuery.fn.valid) && !($form.valid())) { 1334 return false; 1335 } 1336 1337 // Track webform submitted. 1338 if ($form.data('webform-submitted')) { 1339 return false; 1340 } 1341 $form.data('webform-submitted', 'true'); 1342 1343 // Visually disable all submit buttons. 1344 // Submit buttons can't disabled because their op(eration) must to be posted back to the server. 1345 $form.find('.js-webform-wizard-pages-links :submit, .form-actions :submit').addClass('is-disabled'); 1346 1347 // Set the throbber progress indicator. 1348 $clickedButton.after(Drupal.theme.ajaxProgressThrobber()); 1349 }); 1350 }); 1351 } 1352 }; 1353 1354})(jQuery, Drupal, once); 1355; 1356/** 1357 * @file 1358 * JavaScript behaviors for details element. 1359 */ 1360 1361(function ($, Drupal, once) { 1362 1363 'use strict'; 1364 1365 // Determine if local storage exists and is enabled. 1366 // This approach is copied from Modernizr. 1367 // @see https://github.com/Modernizr/Modernizr/blob/c56fb8b09515f629806ca44742932902ac145302/modernizr.js#L696-731 1368 var hasLocalStorage = (function () { 1369 try { 1370 localStorage.setItem('webform', 'webform'); 1371 localStorage.removeItem('webform'); 1372 return true; 1373 } 1374 catch (e) { 1375 return false; 1376 } 1377 }()); 1378 1379 /** 1380 * Attach handler to save details open/close state. 1381 * 1382 * @type {Drupal~behavior} 1383 */ 1384 Drupal.behaviors.webformDetailsSave = { 1385 attach: function (context) { 1386 if (!hasLocalStorage) { 1387 return; 1388 } 1389 1390 // Summary click event handler. 1391 $(once('webform-details-summary-save', 'details > summary', context)).on('click', function () { 1392 var $details = $(this).parent(); 1393 1394 // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/ 1395 if ($details[0].hasAttribute('data-webform-details-nosave')) { 1396 return; 1397 } 1398 1399 var name = Drupal.webformDetailsSaveGetName($details); 1400 if (!name) { 1401 return; 1402 } 1403 1404 var open = ($details.attr('open') !== 'open') ? '1' : '0'; 1405 localStorage.setItem(name, open); 1406 }); 1407 1408 // Initialize details open state via local storage. 1409 $(once('webform-details-save', 'details', context)).each(function () { 1410 var $details = $(this); 1411 1412 var name = Drupal.webformDetailsSaveGetName($details); 1413 if (!name) { 1414 return; 1415 } 1416 1417 var open = localStorage.getItem(name); 1418 if (open === null) { 1419 return; 1420 } 1421 1422 if (open === '1') { 1423 $details.attr('open', 'open'); 1424 } 1425 else { 1426 $details.removeAttr('open'); 1427 } 1428 }); 1429 } 1430 1431 }; 1432 1433 /** 1434 * Get the name used to store the state of details element. 1435 * 1436 * @param {jQuery} $details 1437 * A details element. 1438 * 1439 * @return {string} 1440 * The name used to store the state of details element. 1441 */ 1442 Drupal.webformDetailsSaveGetName = function ($details) { 1443 if (!hasLocalStorage) { 1444 return ''; 1445 } 1446 1447 // Ignore details that are vertical tabs pane. 1448 if ($details.hasClass('vertical-tabs__pane')) { 1449 return ''; 1450 } 1451 1452 // Any details element not included a webform must have define its own id. 1453 var webformId = $details.attr('data-webform-element-id'); 1454 if (webformId) { 1455 return 'Drupal.webform.' + webformId.replace('--', '.'); 1456 } 1457 1458 var detailsId = $details.attr('id');
1459 if (!detailsId) { 1460 return ''; 1461 } 1462 1463 var $form = $details.parents('form'); 1464 if (!$form.length || !$form.attr('id')) { 1465 return ''; 1466 } 1467 1468 var formId = $form.attr('id'); 1469 if (!formId) { 1470 return ''; 1471 } 1472 1473 // ISSUE: When Drupal renders a webform in a modal dialog it appends a unique 1474 // identifier to webform ids and details ids. (i.e. my-form--FeSFISegTUI) 1475 // WORKAROUND: Remove the unique id that delimited using double dashes. 1476 formId = formId.replace(/--.+?$/, '').replace(/-/g, '_'); 1477 detailsId = detailsId.replace(/--.+?$/, '').replace(/-/g, '_'); 1478 return 'Drupal.webform.' + formId + '.' + detailsId; 1479 }; 1480 1481})(jQuery, Drupal, once); 1482; 1483/** 1484* DO NOT EDIT THIS FILE. 1485* See the following change record for more information, 1486* https://www.drupal.org/node/2815083 1487* @preserve 1488**/ 1489(function (Drupal, debounce) { 1490 var liveElement; 1491 var announcements = []; 1492 Drupal.behaviors.drupalAnnounce = { 1493 attach: function attach(context) { 1494 if (!liveElement) { 1495 liveElement = document.createElement('div'); 1496 liveElement.id = 'drupal-live-announce'; 1497 liveElement.className = 'visually-hidden'; 1498 liveElement.setAttribute('aria-live', 'polite'); 1499 liveElement.setAttribute('aria-busy', 'false'); 1500 document.body.appendChild(liveElement); 1501 } 1502 } 1503 }; 1504 function announce() { 1505 var text = []; 1506 var priority = 'polite'; 1507 var announcement; 1508 var il = announcements.length; 1509 for (var i = 0; i < il; i++) { 1510 announcement = announcements.pop(); 1511 text.unshift(announcement.text); 1512 if (announcement.priority === 'assertive') { 1513 priority = 'assertive'; 1514 } 1515 } 1516 if (text.length) { 1517 liveElement.innerHTML = ''; 1518 liveElement.setAttribute('aria-busy', 'true'); 1519 liveElement.setAttribute('aria-live', priority); 1520 liveElement.innerHTML = text.join('\n'); 1521 liveElement.setAttribute('aria-busy', 'false'); 1522 } 1523 } 1524 Drupal.announce = function (text, priority) { 1525 announcements.push({ 1526 text: text, 1527 priority: priority 1528 }); 1529 return debounce(announce, 200)(); 1530 }; 1531})(Drupal, Drupal.debounce);; 1532/** 1533 * @file 1534 * JavaScript behaviors for details element. 1535 */ 1536 1537(function ($, Drupal, once) { 1538 1539 'use strict'; 1540 1541 Drupal.webform = Drupal.webform || {}; 1542 Drupal.webform.detailsToggle = Drupal.webform.detailsToggle || {}; 1543 Drupal.webform.detailsToggle.options = Drupal.webform.detailsToggle.options || {}; 1544 1545 /** 1546 * Attach handler to toggle details open/close state. 1547 * 1548 * @type {Drupal~behavior} 1549 */ 1550 Drupal.behaviors.webformDetailsToggle = { 1551 attach: function (context) { 1552 $(once('webform-details-toggle', '.js-webform-details-toggle', context)).each(function () { 1553 var $form = $(this); 1554 var $tabs = $form.find('.webform-tabs'); 1555 1556 // Get only the main details elements and ignore all nested details. 1557 var selector = ($tabs.length) ? '.webform-tab' : '.js-webform-details-toggle, .webform-elements'; 1558 var $details = $form.find('details').filter(function () { 1559 var $parents = $(this).parentsUntil(selector); 1560 return ($parents.find('details').length === 0); 1561 }); 1562 1563 // Toggle is only useful when there are two or more details elements. 1564 if ($details.length < 2) { 1565 return; 1566 } 1567 1568 var options = $.extend({ 1569 button: '<button type="button" class="webform-details-toggle-state"></button>' 1570 }, Drupal.webform.detailsToggle.options); 1571 1572 // Create toggle buttons. 1573 var $toggle = $(options.button) 1574 .attr('title', Drupal.t('Toggle details widget state.')) 1575 .on('click', function (e) { 1576 // Get details that are not vertical tabs pane. 1577 var $details = $form.find('details:not(.vertical-tabs__pane)'); 1578 var open; 1579 if (Drupal.webform.detailsToggle.isFormDetailsOpen($form)) { 1580 $details.removeAttr('open'); 1581 open = 0; 1582 } 1583 else { 1584 $details.attr('open', 'open'); 1585 open = 1; 1586 } 1587 Drupal.webform.detailsToggle.setDetailsToggleLabel($form); 1588 1589 // Set the saved states for all the details elements. 1590 // @see webform.element.details.save.js 1591 if (Drupal.webformDetailsSaveGetName) { 1592 $details.each(function () { 1593 // Note: Drupal.webformDetailsSaveGetName checks if localStorage 1594 // exists and is enabled. 1595 // @see webform.element.details.save.js 1596 var name = Drupal.webformDetailsSaveGetName($(this)); 1597 if (name) {
1598 localStorage.setItem(name, open); 1599 } 1600 }); 1601 } 1602 }) 1603 .wrap('<div class="webform-details-toggle-state-wrapper"></div>') 1604 .parent(); 1605 1606 if ($tabs.length) { 1607 // Add toggle state before the tabs. 1608 $tabs.find('.item-list:first-child').eq(0).before($toggle); 1609 } 1610 else { 1611 // Add toggle state link to first details element. 1612 $details.eq(0).before($toggle); 1613 } 1614 1615 Drupal.webform.detailsToggle.setDetailsToggleLabel($form); 1616 }); 1617 } 1618 }; 1619 1620 /** 1621 * Determine if a webform's details are all opened. 1622 * 1623 * @param {jQuery} $form 1624 * A webform. 1625 * 1626 * @return {boolean} 1627 * TRUE if a webform's details are all opened. 1628 */ 1629 Drupal.webform.detailsToggle.isFormDetailsOpen = function ($form) { 1630 return ($form.find('details[open]').length === $form.find('details').length); 1631 }; 1632 1633 /** 1634 * Set a webform's details toggle state widget label. 1635 * 1636 * @param {jQuery} $form 1637 * A webform. 1638 */ 1639 Drupal.webform.detailsToggle.setDetailsToggleLabel = function ($form) { 1640 var isOpen = Drupal.webform.detailsToggle.isFormDetailsOpen($form); 1641 1642 var label = (isOpen) ? Drupal.t('Collapse all') : Drupal.t('Expand all'); 1643 $form.find('.webform-details-toggle-state').html(label); 1644 1645 var text = (isOpen) ? Drupal.t('All details have been expanded.') : Drupal.t('All details have been collapsed.'); 1646 Drupal.announce(text); 1647 }; 1648 1649})(jQuery, Drupal, once); 1650; 1651/** 1652 * @file 1653 * JavaScript behaviors for webform scroll top. 1654 */ 1655 1656(function ($, Drupal) { 1657 1658 'use strict'; 1659 1660 Drupal.webform = Drupal.webform || {}; 1661 // Allow scrollTopOffset to be custom defined or based on whether there is a 1662 // floating toolbar. 1663 Drupal.webform.scrollTopOffset = Drupal.webform.scrollTopOffset || ($('#toolbar-administration').length ? 140 : 10); 1664 1665 /** 1666 * Scroll to top ajax command. 1667 * 1668 * @param {Element} element 1669 * The element to scroll to. 1670 * @param {string} target 1671 * Scroll to target. (form or page) 1672 */ 1673 Drupal.webformScrollTop = function (element, target) { 1674 if (!target) { 1675 return; 1676 } 1677 1678 var $element = $(element); 1679 1680 // Scroll to the top of the view. This will allow users 1681 // to browse newly loaded content after e.g. clicking a pager 1682 // link. 1683 var offset = $element.offset(); 1684 // We can't guarantee that the scrollable object should be 1685 // the body, as the view could be embedded in something 1686 // more complex such as a modal popup. Recurse up the DOM 1687 // and scroll the first element that has a non-zero top. 1688 var $scrollTarget = $element; 1689 while ($scrollTarget.scrollTop() === 0 && $($scrollTarget).parent()) { 1690 $scrollTarget = $scrollTarget.parent(); 1691 } 1692 1693 if (target === 'page' && $scrollTarget.length && $scrollTarget[0].tagName === 'HTML') { 1694 // Scroll to top when scroll target is the entire page. 1695 // @see https://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport 1696 var rect = $($scrollTarget)[0].getBoundingClientRect(); 1697 if (!(rect.top >= 0 && rect.left >= 0 && rect.bottom <= $(window).height() && rect.right <= $(window).width())) { 1698 $scrollTarget.animate({scrollTop: 0}, 500); 1699 } 1700 } 1701 else { 1702 // Only scroll upward. 1703 if (offset.top - Drupal.webform.scrollTopOffset < $scrollTarget.scrollTop()) { 1704 $scrollTarget.animate({scrollTop: (offset.top - Drupal.webform.scrollTopOffset)}, 500); 1705 } 1706 } 1707 }; 1708 1709 /** 1710 * Scroll element into view. 1711 * 1712 * @param {jQuery} $element 1713 * An element. 1714 */ 1715 Drupal.webformScrolledIntoView = function ($element) { 1716 if (!Drupal.webformIsScrolledIntoView($element)) { 1717 $('html, body').animate({scrollTop: $element.offset().top - Drupal.webform.scrollTopOffset}, 500); 1718 } 1719 }; 1720 1721 /** 1722 * Determine if element is visible in the viewport. 1723 * 1724 * @param {Element} element 1725 * An element. 1726 * 1727 * @return {boolean} 1728 * TRUE if element is visible in the viewport. 1729 * 1730 * @see https://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling 1731 */ 1732 Drupal.webformIsScrolledIntoView = function (element) { 1733 var docViewTop = $(window).scrollTop(); 1734 var docViewBottom = docViewTop + $(window).height(); 1735 1736 var elemTop = $(element).offset().top; 1737 var elemBottom = elemTop + $(element).height(); 1738 1739 return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 1740 }; 1741 1742})(jQuery, Drupal); 1743; 1744/** 1745 * @file 1746 * JavaScript behaviors for Ajax. 1747 */ 1748 1749(function ($, Drupal, drupalSettings, once) { 1750 1751 'use strict'; 1752 1753 Drupal.webform = Drupal.webform || {}; 1754 Drupal.webform.ajax = Drupal.webform.ajax || {}; 1755 // Allow scrollTopOffset to be custom defined or based on whether there is a 1756 // floating toolbar. 1757 Drupal.webform.ajax.scrollTopOffset = Drupal.webform.ajax.scrollTopOffset || ($('#toolbar-administration').length ? 140 : 10); 1758 1759 // Set global scroll top offset. 1760 // @todo Remove in Webform 6.x. 1761 Drupal.webform.scrollTopOffset = Drupal.webform.ajax.scrollTopOffset; 1762 1763 /** 1764 * Provide Webform Ajax link behavior. 1765 * 1766 * Display fullscreen progress indicator instead of throbber. 1767 * Copied from: Drupal.behaviors.AJAX 1768 * 1769 * @type {Drupal~behavior} 1770 * 1771 * @prop {Drupal~behaviorAttach} attach 1772 * Attaches the behavior to a.webform-ajax-link. 1773 */ 1774 Drupal.behaviors.webformAjaxLink = { 1775 attach: function (context) { 1776 $(once('webform-ajax-link', '.webform-ajax-link', context)).each(function () { 1777 var element_settings = {}; 1778 element_settings.progress = {type: 'fullscreen'}; 1779 1780 // For anchor tags, these will go to the target of the anch
1780or rather 1781 // than the usual location. 1782 var href = $(this).attr('href'); 1783 if (href) { 1784 element_settings.url = href; 1785 element_settings.event = 'click'; 1786 } 1787 element_settings.dialogType = $(this).data('dialog-type'); 1788 element_settings.dialogRenderer = $(this).data('dialog-renderer'); 1789 element_settings.dialog = $(this).data('dialog-options'); 1790 element_settings.base = $(this).attr('id'); 1791 element_settings.element = this; 1792 Drupal.ajax(element_settings); 1793 1794 // Close all open modal dialogs when opening off-canvas dialog. 1795 if (element_settings.dialogRenderer === 'off_canvas') { 1796 $(this).on('click', function () { 1797 $('.ui-dialog.webform-ui-dialog:visible').find('.ui-dialog-content').dialog('close'); 1798 }); 1799 } 1800 }); 1801 } 1802 }; 1803 1804 /** 1805 * Adds a hash (#) to current pages location for links and buttons 1806 * 1807 * @type {Drupal~behavior} 1808 * 1809 * @prop {Drupal~behaviorAttach} attach 1810 * Attaches the behavior to a[data-hash] or :button[data-hash]. 1811 * 1812 * @see \Drupal\webform_ui\WebformUiEntityElementsForm::getElementRow 1813 * @see Drupal.behaviors.webformFormTabs 1814 */ 1815 Drupal.behaviors.webformAjaxHash = { 1816 attach: function (context) { 1817 $(once('webform-ajax-hash', '[data-hash]', context)).each(function () { 1818 var hash = $(this).data('hash'); 1819 if (hash) { 1820 $(this).on('click', function () { 1821 location.hash = $(this).data('hash'); 1822 }); 1823 } 1824 }); 1825 } 1826 }; 1827 1828 /** 1829 * Provide Ajax callback for confirmation back to link. 1830 * 1831 * @type {Drupal~behavior} 1832 * 1833 * @prop {Drupal~behaviorAttach} attach 1834 * Attaches the behavior to confirmation back to link. 1835 */ 1836 Drupal.behaviors.webformConfirmationBackAjax = { 1837 attach: function (context) { 1838 $(once('webform-confirmation-back-ajax', '.js-webform-confirmation-back-link-ajax', context)) 1839 .on('click', function (event) { 1840 var $form = $(this).parents('form'); 1841 1842 // Trigger the Ajax call back for the hidden submit button. 1843 // @see \Drupal\webform\WebformSubmissionForm::getCustomForm 1844 $form.find('.js-webform-confirmation-back-submit-ajax').trigger('click'); 1845 1846 // Move the progress indicator from the submit button to after this link. 1847 // @todo Figure out a better way to set a progress indicator. 1848 var $progress_indicator = $form.find('.ajax-progress'); 1849 if ($progress_indicator) { 1850 $(this).after($progress_indicator); 1851 } 1852 1853 // Cancel the click event. 1854 event.preventDefault(); 1855 event.stopPropagation(); 1856 }); 1857 } 1858 }; 1859 1860 /** ********************************************************************** **/ 1861 // Ajax commands. 1862 /** ********************************************************************** **/ 1863 1864 /** 1865 * Track the updated table row key. 1866 */ 1867 var updateKey; 1868 1869 /** 1870 * Track the add element key. 1871 */ 1872 var addElement; 1873 1874 /** 1875 * Command to insert new content into the DOM. 1876 * 1877 * @param {Drupal.Ajax} ajax 1878 * {@link Drupal.Ajax} object created by {@link Drupal.ajax}. 1879 * @param {object} response 1880 * The response from the Ajax request. 1881 * @param {string} response.data 1882 * The data to use with the jQuery method. 1883 * @param {string} [response.method] 1884 * The jQuery DOM manipulation method to be used. 1885 * @param {string} [response.selector] 1886 * A optional jQuery selector string. 1887 * @param {object} [response.settings] 1888 * An optional array of settings that will be used. 1889 * @param {number} [status] 1890 * The XMLHttpRequest status. 1891 */ 1892 Drupal.AjaxCommands.prototype.webformInsert = function (ajax, response, status) { 1893 // Insert the HTML. 1894 this.insert(ajax, response, status); 1895 1896 // Add element. 1897 if (addElement) { 1898 var addSelector = (addElement === '_root_') 1899 ? '#webform-ui-add-element' 1900 : '[data-drupal-selector="edit-webform-ui-elements-' + addElement + '-add"]'; 1901 $(addSelector).trigger('click'); 1902 } 1903 1904 // If not add element, then scroll to and highlight the updated table row. 1905 if (!addElement && updateKey) { 1906 var $element = $('tr[data-webform-key="' + updateKey + '"]'); 1907 1908 // Highlight the updated element's row. 1909 $element.addClass('color-success'); 1910 setTimeout(function () {$element.removeClass('color-success');}, 3000); 1911 1912 // Focus first tabbable item for the updated elements and handlers. 1913 $element.find(':tabbable:not(.tabledrag-handle)').eq(0).trigger('focus'); 1914 1915 // Scroll element into view. 1916 Drupal.webformScrolledIntoView($element); 1917 } 1918 else { 1919 // Focus main content. 1920 $('#main-content').trigger('focus'); 1921 } 1922 1923 // Display main page's status message in a floating container. 1924 var $wrapper = $(response.selector); 1925 if ($wrapper.parents('.ui-dialog').length === 0) { 1926 var $messages = $wrapper.find('.messages'); 1927 // If 'add element' don't show any messages. 1928 if (addElement) { 1929 $messages.remove(); 1930 } 1931 else if ($messages.length) { 1932 var $floatingMessage = $('#webform-ajax-messages'); 1933 if ($floatingMessage.length === 0) { 1934 $floatingMessage = $('<div id="webform-ajax-messages" class="webform-ajax-messages"></div>'); 1935 $('body').append($floatingMessage); 1936 } 1937 if ($floatingMessage.is(':animated')) { 1938 $floatingMessage.stop(true, true); 1939 } 1940 $floatingMessage.html($messages).show().delay(3000).fadeOut(1000); 1941 } 1942 } 1943 1944 updateKey = null; // Reset element update. 1945 addElement = null; // Reset add element. 1946 }; 1947 1948 /** 1949 * Scroll to top ajax command. 1950 * 1951 * @param {Drupal.Ajax} [ajax] 1952 * A {@link Drupal.ajax} object. 1953 * @param {object} response 1954 * Ajax response. 1955 * @param {string} response.selector 1956 * Selector to use. 1957 * 1958 * @see Drupal.AjaxCommands.prototype.viewScrollTop 1959 */ 1960 Drupal.AjaxCommands.prototype.webformScrollTop = function (ajax, response) { 1961 // Scroll top. 1962 Drupal.webformScrollTop(response.selector, response.target); 1963 1964 // Focus on the form wrapper content bookmark if 1965 // .js-webform-autofocus is not enabled. 1966 // @see \Drupal\webform\Form\WebformAjaxFormTrait::buildAjaxForm 1967 var $form = $(response.selector + '-content').find('form'); 1968 if (!$form.hasClass('js-webform-autofocus')) { 1969 $(response.selector + '-content').trigger('focus'); 1970 } 1971 }; 1972 1973 /** 1974 * Command to refresh the current webform page. 1975 * 1976 * @param {Drupal.Ajax} [ajax] 1977 * {@link Drupal.Ajax} object created by {@link Drupal.ajax}. 1978 * @param {object} response 1979 * The response from the Ajax request. 1980 * @param {string} response.url 1981 * The URL to redirect to. 1982 * @param {number} [status] 1983 * The XMLHttpRequest status. 1984 */ 1985 Drupal.AjaxCommands.prototype.webformRefresh = function (ajax, response, status) { 1986 // Get URL path name. 1987 // @see https://stackoverflow.com/questions/6944744/javascript-get-portion-of-url-path 1988 var a = document.createElement('a'); 1989 a.href = response.url; 1990 var forceReload = (response.url.match(/\?reload=([^&]+)($|&)/)) ? RegExp.$1 : null; 1991 if (forceReload) { 1992 response.url = response.url.replace(/\?reload=([^&]+)($|&)/, ''); 1993 this.redirect(ajax, response, status); 1994 return; 1995 } 1996 1997 if (a.pathname === window.location.pathname && $('.webform-ajax-refresh').length) { 1998 updateKey = (response.url.match(/[?|&]update=([^&]+)($|&)/)) ? RegExp.$1 : null; 1999 addElement = (response.url.match(/[?|&]add_element=([^&]+)($|&)/)) ? RegExp.$1 : null; 2000 $('.webform-ajax-refresh').trigger('click'); 2001 } 2002 else { 2003 // Clear unsaved information flag so that the current webform page 2004 // can be redirected. 2005 // @see Drupal.behaviors.webformUnsaved.clear 2006 if (Drupal.behaviors.webformUnsaved) { 2007 Drupal.behaviors.webformUnsaved.clear(); 2008 } 2009 2010 // For webform embedded in an iframe, open all redirects in the top 2011 // of the browser window. 2012 // @see \Drupal\webform_share\Controller\WebformShareController::page 2013 if (drupalSettings.webform_share && 2014 drupalSettings.webform_share.page) { 2015 window.top.location = response.url; 2016 } 2017 else { 2018 this.redirect(ajax, response, status); 2019 } 2020 } 2021 }; 2022 2023 /** 2024 * Command to close a off-canvas and modal dialog. 2025 * 2026 * If no selector is given, it defaults to trying to close the modal. 2027 * 2028 * @param {Drupal.Ajax} [ajax] 2029 * {@link Drupal.Ajax} object created by {@link Drupal.ajax}. 2030 * @param {object} response 2031 * The response from the Ajax request. 2032 * @param {string} response.selector 2033 * Selector to use. 2034 * @param {bool} response.persist 2035 * Whether to persist the dialog element or not. 2036 * @param {number} [status] 2037 * The HTTP status code. 2038 */ 2039 Drupal.AjaxCommands.prototype.webformCloseDialog = function (ajax, response, status) { 2040 if ($('#drupal-off-canvas').length) { 2041 // Close off-canvas system tray which is not triggered by close dialog 2042 // command. 2043 // @see Drupal.behaviors.offCanvasEvents 2044 $('#drupal-off-canvas').remove(); 2045 $('body').removeClass('js-tray-open'); 2046 // Remove all *.off-canvas events 2047 $(document).off('.off-canvas'); 2048 $(window).off('.off-canvas'); 2049 var edge = document.documentElement.dir === 'rtl' ? 'left' : 'right'; 2050 var $mainCanvasWrapper = $('[data-off-canvas-main-canvas]'); 2051 $mainCanvasWrapper.css('padding-' + edge, 0); 2052 2053 // Resize tabs when closing off-canvas system tray. 2054 $(window).trigger('resize.tabs'); 2055 } 2056 2057 // https://stackoverflow.com/questions/15763909/jquery-ui-dialog-check-if-exists-by-instance-method 2058 if ($(response.selector).hasClass('ui-dialog-content')) { 2059 this.closeDialog(ajax, response, status); 2060 } 2061 }; 2062 2063 /** 2064 * Triggers confirm page reload. 2065 * 2066 * @param {Drupal.Ajax} [ajax] 2067 * A {@link Drupal.ajax} object. 2068 * @param {object} response 2069 * Ajax response. 2070 * @param {string} response.message 2071 * A message to be displayed in the confirm dialog. 2072 */ 2073 Drupal.AjaxCommands.prototype.webformConfirmReload = function (ajax, response) { 2074 if (window.confirm(response.message)) { 2075 window.location.reload(true); 2076 } 2077 }; 2078 2079})(jQuery, Drupal, drupalSettings, once); 2080; 2081/** 2082 * @file 2083 * JavaScript behaviors for message element integration. 2084 */ 2085 2086(function ($, Drupal, once) { 2087 2088 'use strict'; 2089 2090 // Determine if local storage exists and is enabled. 2091 // This approach is copied from Modernizr. 2092 // @see https://github.com/Modernizr/Modernizr/blob/c56fb8b09515f629806ca44742932902ac145302/modernizr.js#L696-731 2093 var hasLocalStorage = (function () { 2094 try { 2095 localStorage.setItem('webform', 'webform'); 2096 localStorage.removeItem('webform'); 2097 return true; 2098 } 2099 catch (e) { 2100 return false;
2101 } 2102 }()); 2103 2104 // Determine if session storage exists and is enabled. 2105 // This approach is copied from Modernizr. 2106 // @see https://github.com/Modernizr/Modernizr/blob/c56fb8b09515f629806ca44742932902ac145302/modernizr.js#L696-731 2107 var hasSessionStorage = (function () { 2108 try { 2109 sessionStorage.setItem('webform', 'webform'); 2110 sessionStorage.removeItem('webform'); 2111 return true; 2112 } 2113 catch (e) { 2114 return false; 2115 } 2116 }()); 2117 2118 /** 2119 * Behavior for handler message close. 2120 * 2121 * @type {Drupal~behavior} 2122 */ 2123 Drupal.behaviors.webformMessageClose = { 2124 attach: function (context) { 2125 $(once('webform-message--close', '.js-webform-message--close', context)).each(function () { 2126 var $element = $(this); 2127 2128 var id = $element.attr('data-message-id'); 2129 var storage = $element.attr('data-message-storage'); 2130 var effect = $element.attr('data-message-close-effect') || 'hide'; 2131 switch (effect) { 2132 case 'slide': effect = 'slideUp'; break; 2133 2134 case 'fade': effect = 'fadeOut'; break; 2135 } 2136 2137 // Check storage status. 2138 if (isClosed($element, storage, id)) { 2139 return; 2140 } 2141 2142 // Only show element if it's style is not set to 'display: none' 2143 // and it is not hidden via .js-webform-states-hidden. 2144 if ($element.attr('style') !== 'display: none;' && !$element.hasClass('js-webform-states-hidden')) { 2145 $element.show(); 2146 } 2147 2148 $element.find('.js-webform-message__link').on('click', function (event) { 2149 $element[effect](); 2150 setClosed($element, storage, id); 2151 $element.trigger('close'); 2152 event.preventDefault(); 2153 }); 2154 }); 2155 } 2156 }; 2157 2158 function isClosed($element, storage, id) { 2159 if (!id || !storage) { 2160 return false; 2161 } 2162 2163 switch (storage) { 2164 case 'local': 2165 if (hasLocalStorage) { 2166 return localStorage.getItem('Drupal.webform.message.' + id) || false; 2167 } 2168 return false; 2169 2170 case 'session': 2171 if (hasSessionStorage) { 2172 return sessionStorage.getItem('Drupal.webform.message.' + id) || false; 2173 } 2174 return false; 2175 2176 default: 2177 return false; 2178 } 2179 } 2180 2181 function setClosed($element, storage, id) { 2182 if (!id || !storage) { 2183 return; 2184 } 2185 2186 switch (storage) { 2187 case 'local': 2188 if (hasLocalStorage) { 2189 localStorage.setItem('Drupal.webform.message.' + id, true); 2190 } 2191 break; 2192 2193 case 'session': 2194 if (hasSessionStorage) { 2195 sessionStorage.setItem('Drupal.webform.message.' + id, true); 2196 } 2197 break; 2198 2199 case 'user': 2200 case 'state': 2201 case 'custom': 2202 $.get($element.find('.js-webform-message__link').attr('href')); 2203 return true; 2204 } 2205 } 2206 2207})(jQuery, Drupal, once); 2208; 2209/*! 2210 * jQuery Form Plugin 2211 * version: 4.3.0 2212 * Requires jQuery v1.7.2 or later 2213 * Project repository: https://github.com/jquery-form/form 2214 2215 * Copyright 2017 Kevin Morris 2216 * Copyright 2006 M. Alsup 2217 2218 * Dual licensed under the LGPL-2.1+ or MIT licenses 2219 * https://github.com/jquery-form/form#license 2220 2221 * This library is free software; you can redistribute it and/or 2222 * modify it under the terms of the GNU Lesser General Public 2223 * License as published by the Free Software Foundation; either 2224 * version 2.1 of the License, or (at your option) any later version. 2225 * This library is distributed in the hope that it will be useful, 2226 * but WITHOUT ANY WARRANTY; without even the implied warranty of 2227 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2228 * Lesser General Public License for more details. 2229 */ 2230!function(r){"function"==typeof define&&define.amd?define(["jquery"],r):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),r(t),t}:r(jQuery)}(function(q){"use strict";var m=/\r?\n/g,S={};S.fileapi=void 0!==q('<input type="file">').get(0).files,S.formdata=void 0!==window.FormData;var _=!!q.fn.prop;function o(e){var t=e.data;e.isDefaultPrevented()||(e.preventDefault(),q(e.target).closest("form").ajaxSubmit(t))}function i(e){var t=e.target,r=q(t);if(!r.is("[type=submit],[type=image]")){var a=r.closest("[type=submit]");if(0===a.length)return;t=a[0]}var n,o=t.form;"image"===(o.clk=t).type&&(void 0!==e.offsetX?(o.clk_x=e.offsetX,o.clk_y=e.offsetY):"function"==typeof q.fn.offset?(n=r.offset(),o.clk_x=e.pageX-n.left,o.clk_y=e.pageY-n.top):(o.clk_x=e.pageX-t.offsetLeft,o.clk_y=e.pageY-t.offsetTop)),setTimeout(function(){o.clk=o.clk_x=o.clk_y=null},100)}function N(){var e;q.fn.ajaxSubmit.debug&&(e="[jquery.form] "+Array.prototype.join.call(arguments,""),window.console&&window.console.log?window.console.log(e):window.opera&&window.opera.postError&&window.opera.postError(e))}q.fn.attr2=function(){if(!_)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},q.fn.ajaxSubmit=function(M,e,t,r){if(!this.length)return N("ajaxSubmit: ski
2230pping submit process - no element selected"),this;var O,a,n,o,X=this;"function"==typeof M?M={success:M}:"string"==typeof M||!1===M&&0<arguments.length?(M={url:M,data:e,dataType:t},"function"==typeof r&&(M.success=r)):void 0===M&&(M={}),O=M.method||M.type||this.attr2("method"),n=(n=(n="string"==typeof(a=M.url||this.attr2("action"))?q.trim(a):"")||window.location.href||"")&&(n.match(/^([^#]+)/)||[])[1],o=/(MSIE|Trident)/.test(navigator.userAgent||"")&&/^https/i.test(window.location.href||"")?"javascript:false":"about:blank",M=q.extend(!0,{url:n,success:q.ajaxSettings.success,type:O||q.ajaxSettings.type,iframeSrc:o},M);var i={};if(this.trigger("form-pre-serialize",[this,M,i]),i.veto)return N("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(M.beforeSerialize&&!1===M.beforeSerialize(this,M))return N("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var s=M.traditional;void 0===s&&(s=q.ajaxSettings.traditional);var u,c,C=[],l=this.formToArray(M.semantic,C,M.filtering);if(M.data&&(c=q.isFunction(M.data)?M.data(l):M.data,M.extraData=c,u=q.param(c,s)),M.beforeSubmit&&!1===M.beforeSubmit(l,this,M))return N("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[l,this,M,i]),i.veto)return N("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var f=q.param(l,s);u&&(f=f?f+"&"+u:u),"GET"===M.type.toUpperCase()?(M.url+=(0<=M.url.indexOf("?")?"&":"?")+f,M.data=null):M.data=f;var d,m,p,h=[];M.resetForm&&h.push(function(){X.resetForm()}),M.clearForm&&h.push(function(){X.clearForm(M.includeHidden)}),!M.dataType&&M.target?(d=M.success||function(){},h.push(function(e,t,r){var a=arguments,n=M.replaceTarget?"replaceWith":"html";q(M.target)[n](e).each(function(){d.apply(this,a)})})):M.success&&(q.isArray(M.success)?q.merge(h,M.success):h.push(M.success)),M.success=function(e,t,r){for(var a=M.context||this,n=0,o=h.length;n<o;n++)h[n].apply(a,[e,t,r||X,X])},M.error&&(m=M.error,M.error=function(e,t,r){var a=M.context||this;m.apply(a,[e,t,r,X])}),M.complete&&(p=M.complete,M.complete=function(e,t){var r=M.context||this;p.apply(r,[e,t,X])});var v=0<q("input[type=file]:enabled",this).filter(function(){return""!==q(this).val()}).length,g="multipart/form-data",x=X.attr("enctype")===g||X.attr("encoding")===g,y=S.fileapi&&S.formdata;N("fileAPI :"+y);var b,T=(v||x)&&!y;!1!==M.iframe&&(M.iframe||T)?M.closeKeepAlive?q.get(M.closeKeepAlive,function(){b=w(l)}):b=w(l):b=(v||x)&&y?function(e){for(var r=new FormData,t=0;t<e.length;t++)r.append(e[t].name,e[t].value);if(M.extraData){var a=function(e){var t,r,a=q.param(e,M.traditional).split("&"),n=a.length,o=[];for(t=0;t<n;t++)a[t]=a[t].replace(/\+/g," "),r=a[t].split("="),o.push([decodeURIComponent(r[0]),decodeURIComponent(r[1])]);return o}(M.extraData);for(t=0;t<a.length;t++)a[t]&&r.append(a[t][0],a[t][1])}M.data=null;var n=q.extend(!0,{},q.ajaxSettings,M,{contentType:!1,processData:!1,cache:!1,type:O||"POST"});M.uploadProgress&&(n.xhr=function(){var e=q.ajaxSettings.xhr();return e.upload&&e.upload.addEventListener("progress",function(e){var t=0,r=e.loaded||e.position,a=e.total;e.lengthComputable&&(t=Math.ceil(r/a*100)),M.uploadProgress(e,r,a,t)},!1),e});n.data=null;var o=n.beforeSend;return n.beforeSend=function(e,t){M.formData?t.data=M.formData:t.data=r,o&&o.call(this,e,t)},q.ajax(n)}(l):q.ajax(M),X.removeData("jqxhr").data("jqxhr",b);for(var j=0;j<C.length;j++)C[j]=null;return this.trigger("form-submit-notify",[this,M]),this;function w(e){var t,r,l,f,o,d,m,p,a,n,h,v,i=X[0],g=q.Deferred();if(g.abort=function(e){p.abort(e)},e)for(r=0;r<C.length;r++)t=q(C[r]),_?t.prop("disabled",!1):t.removeAttr("disabled");(l=q.extend(!0,{},q.ajaxSettings,M)).context=l.context||l,o="jqFormIO"+(new Date).getTime();var s=i.ownerDocument,u=X.closest("body");if(l.iframeTarget?(n=(d=q(l.iframeTarget,s)).attr2("name"))?o=n:d.attr2("name",o):(d=q('<iframe name="'+o+'" src="'+l.iframeSrc+'" />',s)).css({position:"absolute",top:"-1000px",left:"-1000px"}),m=d[0],p={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(e){var t="timeout"===e?"timeout":"aborted";N("aborting upload... "+t),this.aborted=1;try{m.contentWindow.document.execCommand&&m.contentWindow.document.execCommand("Stop")}catch(e){}d.attr("src",l.iframeSrc),p.error=t,l.error&&l.error.call(l.context,p,t,e),f&&q.event.trigger("ajaxError",[p,l,t]),l.complete&&l.complete.call(l.context,p,t)}},(f=l.global)&&0==q.active++&&q.event.trigger("ajaxStart"),f&&q.event.trigger("ajaxSend",[p,l]),l.beforeSend&&!1===l.beforeSend.c
2230all(l.context,p,l))return l.global&&q.active--,g.reject(),g;if(p.aborted)return g.reject(),g;(a=i.clk)&&(n=a.name)&&!a.disabled&&(l.extraData=l.extraData||{},l.extraData[n]=a.value,"image"===a.type&&(l.extraData[n+".x"]=i.clk_x,l.extraData[n+".y"]=i.clk_y));var x=1,y=2;function b(t){var r=null;try{t.contentWindow&&(r=t.contentWindow.document)}catch(e){N("cannot get iframe.contentWindow document: "+e)}if(r)return r;try{r=t.contentDocument?t.contentDocument:t.document}catch(e){N("cannot get iframe.contentDocument: "+e),r=t.document}return r}var c=q("meta[name=csrf-token]").attr("content"),T=q("meta[name=csrf-param]").attr("content");function j(){var e=X.attr2("target"),t=X.attr2("action"),r=X.attr("enctype")||X.attr("encoding")||"multipart/form-data";i.setAttribute("target",o),O&&!/post/i.test(O)||i.setAttribute("method","POST"),t!==l.url&&i.setAttribute("action",l.url),l.skipEncodingOverride||O&&!/post/i.test(O)||X.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),l.timeout&&(v=setTimeout(function(){h=!0,A(x)},l.timeout));var a=[];try{if(l.extraData)for(var n in l.extraData)l.extraData.hasOwnProperty(n)&&(q.isPlainObject(l.extraData[n])&&l.extraData[n].hasOwnProperty("name")&&l.extraData[n].hasOwnProperty("value")?a.push(q('<input type="hidden" name="'+l.extraData[n].name+'">',s).val(l.extraData[n].value).appendTo(i)[0]):a.push(q('<input type="hidden" name="'+n+'">',s).val(l.extraData[n]).appendTo(i)[0]));l.iframeTarget||d.appendTo(u),m.attachEvent?m.attachEvent("onload",A):m.addEventListener("load",A,!1),setTimeout(function e(){try{var t=b(m).readyState;N("state = "+t),t&&"uninitialized"===t.toLowerCase()&&setTimeout(e,50)}catch(e){N("Server abort: ",e," (",e.name,")"),A(y),v&&clearTimeout(v),v=void 0}},15);try{i.submit()}catch(e){document.createElement("form").submit.apply(i)}}finally{i.setAttribute("action",t),i.setAttribute("enctype",r),e?i.setAttribute("target",e):X.removeAttr("target"),q(a).remove()}}T&&c&&(l.extraData=l.extraData||{},l.extraData[T]=c),l.forceSync?j():setTimeout(j,10);var w,S,k,D=50;function A(e){if(!p.aborted&&!k){if((S=b(m))||(N("cannot access response document"),e=y),e===x&&p)return p.abort("timeout"),void g.reject(p,"timeout");if(e===y&&p)return p.abort("server abort"),void g.reject(p,"error","server abort");if(S&&S.location.href!==l.iframeSrc||h){m.detachEvent?m.detachEvent("onload",A):m.removeEventListener("load",A,!1);var t,r="success";try{if(h)throw"timeout";var a="xml"===l.dataType||S.XMLDocument||q.isXMLDoc(S);if(N("isXml="+a),!a&&window.opera&&(null===S.body||!S.body.innerHTML)&&--D)return N("requeing onLoad callback, DOM not available"),void setTimeout(A,250);var n=S.body?S.body:S.documentElement;p.responseText=n?n.innerHTML:null,p.responseXML=S.XMLDocument?S.XMLDocument:S,a&&(l.dataType="xml"),p.getResponseHeader=function(e){return{"content-type":l.dataType}[e.toLowerCase()]},n&&(p.status=Number(n.getAttribute("status"))||p.status,p.statusText=n.getAttribute("statusText")||p.statusText);var o,i,s,u=(l.dataType||"").toLowerCase(),c=/(json|script|text)/.test(u);c||l.textarea?(o=S.getElementsByTagName("textarea")[0])?(p.responseText=o.value,p.status=Number(o.getAttribute("status"))||p.status,p.statusText=o.getAttribute("statusText")||p.statusText):c&&(i=S.getElementsByTagName("pre")[0],s=S.getElementsByTagName("body")[0],i?p.responseText=i.textContent?i.textContent:i.innerText:s&&(p.responseText=s.textContent?s.textContent:s.innerText)):"xml"===u&&!p.responseXML&&p.responseText&&(p.responseXML=F(p.responseText));try{w=E(p,u,l)}catch(e){r="parsererror",p.error=t=e||r}}catch(e){N("error caught: ",e),r="error",p.error=t=e||r}p.aborted&&(N("upload aborted"),r=null),p.status&&(r=200<=p.status&&p.status<300||304===p.status?"success":"error"),"success"===r?(l.success&&l.success.call(l.context,w,"success",p),g.resolve(p.responseText,"success",p),f&&q.event.trigger("ajaxSuccess",[p,l])):r&&(void 0===t&&(t=p.statusText),l.error&&l.error.call(l.context,p,r,t),g.reject(p,"error",t),f&&q.event.trigger("ajaxError",[p,l,t])),f&&q.event.trigger("ajaxComplete",[p,l]),f&&!--q.active&&q.event.trigger("ajaxStop"),l.complete&&l.complete.call(l.context,p,r),k=!0,l.timeout&&clearTimeout(v),setTimeout(function(){l.iframeTarget?d.attr("src",l.iframeSrc):d.remove(),p.responseXML=null},100)}}}var F=q.parseXML||function(e,t){return window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!==t.documentElement.nodeName?t:null},L=q.parseJSON||function(e){return window.eval("("+e+")")},E=function(e,t,r){var a=e.getResponseHeader("content-type")||"",n=("xml"===t||!t)&&0<=a.indexOf("xml"),o=n?e.responseXML:e.responseText;return n&&"parsererror"===o.documentElement.nodeName&&q.error&&q.error("parsererror"),r&&r.dataFilter&&(
2230o=r.dataFilter(o,t)),"string"==typeof o&&(("json"===t||!t)&&0<=a.indexOf("json")?o=L(o):("script"===t||!t)&&0<=a.indexOf("javascript")&&q.globalEval(o)),o};return g}},q.fn.ajaxForm=function(e,t,r,a){if(("string"==typeof e||!1===e&&0<arguments.length)&&(e={url:e,data:t,dataType:r},"function"==typeof a&&(e.success=a)),(e=e||{}).delegation=e.delegation&&q.isFunction(q.fn.on),e.delegation||0!==this.length)return e.delegation?(q(document).off("submit.form-plugin",this.selector,o).off("click.form-plugin",this.selector,i).on("submit.form-plugin",this.selector,e,o).on("click.form-plugin",this.selector,e,i),this):(e.beforeFormUnbind&&e.beforeFormUnbind(this,e),this.ajaxFormUnbind().on("submit.form-plugin",e,o).on("click.form-plugin",e,i));var n={s:this.selector,c:this.context};return!q.isReady&&n.s?(N("DOM not ready, queuing ajaxForm"),q(function(){q(n.s,n.c).ajaxForm(e)})):N("terminating; zero elements found by selector"+(q.isReady?"":" (DOM not ready)")),this},q.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},q.fn.formToArray=function(e,t,r){var a=[];if(0===this.length)return a;var n,o,i,s,u,c,l,f,d,m,p=this[0],h=this.attr("id"),v=(v=e||void 0===p.elements?p.getElementsByTagName("*"):p.elements)&&q.makeArray(v);if(h&&(e||/(Edge|Trident)\//.test(navigator.userAgent))&&(n=q(':input[form="'+h+'"]').get()).length&&(v=(v||[]).concat(n)),!v||!v.length)return a;for(q.isFunction(r)&&(v=q.map(v,r)),o=0,c=v.length;o<c;o++)if((m=(u=v[o]).name)&&!u.disabled)if(e&&p.clk&&"image"===u.type)p.clk===u&&(a.push({name:m,value:q(u).val(),type:u.type}),a.push({name:m+".x",value:p.clk_x},{name:m+".y",value:p.clk_y}));else if((s=q.fieldValue(u,!0))&&s.constructor===Array)for(t&&t.push(u),i=0,l=s.length;i<l;i++)a.push({name:m,value:s[i]});else if(S.fileapi&&"file"===u.type){t&&t.push(u);var g=u.files;if(g.length)for(i=0;i<g.length;i++)a.push({name:m,value:g[i],type:u.type});else a.push({name:m,value:"",type:u.type})}else null!=s&&(t&&t.push(u),a.push({name:m,value:s,type:u.type,required:u.required}));return e||!p.clk||(m=(d=(f=q(p.clk))[0]).name)&&!d.disabled&&"image"===d.type&&(a.push({name:m,value:f.val()}),a.push({name:m+".x",value:p.clk_x},{name:m+".y",value:p.clk_y})),a},q.fn.formSerialize=function(e){return q.param(this.formToArray(e))},q.fn.fieldSerialize=function(n){var o=[];return this.each(function(){var e=this.name;if(e){var t=q.fieldValue(this,n);if(t&&t.constructor===Array)for(var r=0,a=t.length;r<a;r++)o.push({name:e,value:t[r]});else null!=t&&o.push({name:this.name,value:t})}}),q.param(o)},q.fn.fieldValue=function(e){for(var t=[],r=0,a=this.length;r<a;r++){var n=this[r],o=q.fieldValue(n,e);null==o||o.constructor===Array&&!o.length||(o.constructor===Array?q.merge(t,o):t.push(o))}return t},q.fieldValue=function(e,t){var r=e.name,a=e.type,n=e.tagName.toLowerCase();if(void 0===t&&(t=!0),t&&(!r||e.disabled||"reset"===a||"button"===a||("checkbox"===a||"radio"===a)&&!e.checked||("submit"===a||"image"===a)&&e.form&&e.form.clk!==e||"select"===n&&-1===e.selectedIndex))return null;if("select"!==n)return q(e).val().replace(m,"\r\n");var o=e.selectedIndex;if(o<0)return null;for(var i=[],s=e.options,u="select-one"===a,c=u?o+1:s.length,l=u?o:0;l<c;l++){var f=s[l];if(f.selected&&!f.disabled){var d=(d=f.value)||(f.attributes&&f.attributes.value&&!f.attributes.value.specified?f.text:f.value);if(u)return d;i.push(d)}}return i},q.fn.clearForm=function(e){return this.each(function(){q("input,select,textarea",this).clearFields(e)})},q.fn.clearFields=q.fn.clearInputs=function(r){var a=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var e=this.type,t=this.tagName.toLowerCase();a.test(e)||"textarea"===t?this.value="":"checkbox"===e||"radio"===e?this.checked=!1:"select"===t?this.selectedIndex=-1:"file"===e?/MSIE/.test(navigator.userAgent)?q(this).replaceWith(q(this).clone(!0)):q(this).val(""):r&&(!0===r&&/hidden/.test(e)||"string"==typeof r&&q(this).is(r))&&(this.value="")})},q.fn.resetForm=function(){return this.each(function(){var t=q(this),e=this.tagName.toLowerCase();switch(e){case"input":this.checked=this.defaultChecked;case"textarea":return this.value=this.defaultValue,!0;case"option":case"optgroup":var r=t.parents("select");return r.length&&r[0].multiple?"option"===e?this.selected=this.defaultSelected:t.find("option").resetForm():r.resetForm(),!0;case"select":return t.find("option").each(function(e){if(this.selected=this.defaultSelected,this.defaultSelected&&!t[0].multiple)return t[0].selectedIndex=e,!1}),!0;case"label":var a=q(t.attr("for")),n=t.find("input,select,textarea");return a[0]&&n.unshift(a[0]),n.resetForm(),!0;case"form":return"function"!=typeof this.reset&&("object"!=typeof this.reset||this.reset.nodeType)||this.reset(),!0;default:return t.find("form,input,label,select,textarea").resetForm(),!0}})},q.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},q.fn.selected=function(r){return void 0===r&&(r=!0),this.each(function(){var e,t=this.t
2230ype;"checkbox"===t||"radio"===t?this.checked=r:"option"===this.tagName.toLowerCase()&&(e=q(this).parent("select"),r&&e[0]&&"select-one"===e[0].type&&e.find("option").selected(!1),this.selected=r)})},q.fn.ajaxSubmit.debug=!1}); 2231 2232; 2233/* 2234 * Superfish v1.4.8 - jQuery menu widget 2235 * Copyright (c) 2008 Joel Birch 2236 * 2237 * Dual licensed under the MIT and GPL licenses: 2238 * http://www.opensource.org/licenses/mit-license.php 2239 * http://www.gnu.org/licenses/gpl.html 2240 */ 2241/* 2242 * This is not the original jQuery Superfish plugin. 2243 * Please refer to the README for more information. 2244 */ 2245 2246(function($){ 2247 $.fn.superfish = function(superfish_options){ 2248 const cssClasses = sf.cssClasses; 2249 const $arrow = $(`<span class="${cssClasses.arrowClass}"> »</span>`); 2250 2251 const over = function(){ 2252 const $$ = $(this); 2253 const menu = getMenu($$); 2254 clearTimeout(menu.sfTimer); 2255 $$.showSuperfishUl().siblings().hideSuperfishUl(); 2256 }; 2257 2258 const out = function(){ 2259 const $$ = $(this); 2260 const menu = getMenu($$); 2261 const options = sf.options; 2262 2263 clearTimeout(menu.sfTimer); 2264 menu.sfTimer = setTimeout(function(){ 2265 if ($$.children('.sf-clicked').length === 0){ 2266 options.retainPath = ($.inArray($$[0], options.$path) > -1); 2267 $$.hideSuperfishUl(); 2268 if (options.$path.length && $$.parents(`li.${cssClasse
2268s.hoverClass}`).length < 1){ 2269 over.call(options.$path); 2270 } 2271 } 2272 }, options.delay); 2273 }; 2274 2275 const getMenu = function($menu){ 2276 const menu = $menu.parents(`ul.${cssClasses.menuClass}:first`)[0]; 2277 sf.options = sf.optionsList[menu.serial]; 2278 return menu; 2279 }; 2280 2281 const addArrow = function($a){ 2282 $a.addClass(cssClasses.anchorClass).append($arrow.clone()); 2283 }; 2284 2285 return this.each(function() { 2286 const s = this.serial = sf.optionsList.length; 2287 const options = $.extend({}, sf.defaults, superfish_options); 2288 options.$path = $(`li.${options.pathClass}`, this).slice(0, options.pathLevels); 2289 const path = options.$path; 2290 for (let l = 0; l < path.length; l++){ 2291 path.eq(l).addClass(`${cssClasses.hoverClass} ${cssClasses.bcClass}`).filter('li:has(ul)').removeClass(options.pathClass); 2292 } 2293 sf.optionsList[s] = sf.options = options; 2294 2295 $('li:has(ul)', this)[($.fn.hoverIntent && !options.disableHI) ? 'hoverIntent' : 'hover'](over, out).each(function() { 2296 if (options.autoArrows) { 2297 addArrow( $(this).children('a:first-child, span.nolink:first-child') ); 2298 } 2299 }) 2300 .not('.' + cssClasses.bcClass).hideSuperfishUl(); 2301 2302 const $a = $('a, span.nolink', this); 2303 $a.each(function(i){ 2304 const $li = $a.eq(i).parents('li'); 2305 $a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);}); 2306 }); 2307 options.onInit.call(this); 2308 2309 }).each(function() { 2310 const menuClasses = [cssClasses.menuClass]; 2311 if (sf.options.dropShadows){ 2312 menuClasses.push(cssClasses.shadowClass); 2313 } 2314 $(this).addClass(menuClasses.join(' ')); 2315 }); 2316 }; 2317 2318 const sf = $.fn.superfish; 2319 sf.optionsList = []; 2320 sf.options = {}; 2321 2322 sf.cssClasses = { 2323 bcClass: 'sf-breadcrumb', 2324 menuClass: 'sf-js-enabled', 2325 anchorClass: 'sf-with-ul', 2326 arrowClass: 'sf-sub-indicator', 2327 shadowClass: 'sf-shadow', 2328 hiddenClass: 'sf-hidden', 2329 hoverClass: 'sfHover' 2330 }; 2331 2332 sf.defaults = { 2333 pathClass: 'overideThisToUse', 2334 pathLevels: 1, 2335 delay: 800, 2336 animation: {opacity: 'show'}, 2337 speed: 'fast', 2338 autoArrows: true, 2339 dropShadows: true, 2340 disableHI: false, // true disables hoverIntent detection 2341 onInit: function(){}, // callback functions 2342 onBeforeShow: function(){}, 2343 onShow: function(){}, 2344 onHide: function(){} 2345 }; 2346 2347 $.fn.extend({ 2348 hideSuperfishUl : function(){ 2349 const options = sf.options; 2350 const not = options.retainPath === true ? options.$path : ''; 2351 options.retainPath = false; 2352 const $ul = $(`li.${sf.cssClasses.hoverClass}`, this).add(this).not(not).removeClass(sf.cssClasses.hoverClass) 2353 .children('ul').addClass(sf.cssClasses.hiddenClass); 2354 options.onHide.call($ul); 2355 return this; 2356 }, 2357 showSuperfishUl : function(){ 2358 this.removeClass(sf.cssClasses.hiddenClass); 2359 const options = sf.options; 2360 const $ul = this.addClass(sf.cssClasses.hoverClass).children(`ul.${sf.cssClasses.hiddenClass}`).hide().removeClass(sf.cssClasses.hiddenClass); 2361 options.onBeforeShow.call($ul); 2362 $ul.animate(options.animation, options.speed, function(){ options.onShow.call($ul); }); 2363 return this; 2364 } 2365 }); 2366 2367})(jQuery); 2368; 2369/*! 2370 * hoverIntent v1.10.1 // 2019.10.05 // jQuery v1.7.0+ 2371 * http://briancherne.github.io/jquery-hoverIntent/ 2372 * 2373 * You may use hoverIntent under the terms of the MIT license. Basically that 2374 * means you are free to use hoverIntent as long as this header is left intact. 2375 * Copyright 2007-2019 Brian Cherne 2376 */ 2377!function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery"],factory):"object"==typeof module&&module.exports?module.exports=factory(require("jquery")):jQuery&&!jQuery.fn.hoverIntent&&factory(jQuery)}(function($){"use strict";function track(ev){cX=ev.pageX,cY=ev.pageY}var cX,cY,_cfg={interval:100,sensitivity:6,timeout:0},INSTANCE_COUNT=0,compare=function(ev,$el,s,cfg){if(Math.sqrt((s.pX-cX)*(s.pX-cX)+(s.pY-cY)*(s.pY-cY))<cfg.sensitivity)return $el.off(s.event,track),delete s.timeoutId,s.isActive=!0,ev.pageX=cX,ev.pageY=cY,delete s.pX,delete s.pY,cfg.over.apply($el[0],[ev]);s.pX=cX,s.pY=cY,s.timeoutId=setTimeout(function(){compare(ev,$el,s,cfg)},cfg.interval)};$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var instanceId=INSTANCE_COUNT++,cfg=$.extend({},_cfg);$.isPlainObject(handlerIn)?(cfg=$.extend(cfg,handlerIn),(typeof cfg.out==="function")||(cfg.out=cfg.over)):cfg=(typeof handlerOut==="function")?$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector}):$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut});function handleHover(e){var ev=$.extend({},e),$el=$(this),hoverIntentData=$el.data("hoverIntent");hoverIntentData||$el.data("hoverIntent",hoverIntentData={});var state=hoverIntentData[instanceId];state||(hoverIntentData[instanceId]=state={id:instanceId}),state.timeoutId&&(state.timeoutId=clearTimeout(state.timeoutId));
2377var mousemove=state.event="mousemove.hoverIntent.hoverIntent"+instanceId;if("mouseenter"===e.type){if(state.isActive)return;state.pX=ev.pageX,state.pY=ev.pageY,$el.off(mousemove,track).on(mousemove,track),state.timeoutId=setTimeout(function(){compare(ev,$el,state,cfg)},cfg.interval)}else{if(!state.isActive)return;$el.off(mousemove,track),state.timeoutId=setTimeout(function(){!function(ev,$el,s,out){var data=$el.data("hoverIntent");data&&delete data[s.id],out.apply($el[0],[ev])}(ev,$el,state,cfg.out)},cfg.timeout)}}return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}});; 2378/* 2379 * Supposition v0.2 - an optional enhancer for Superfish jQuery menu widget. 2380 * 2381 * Copyright (c) 2008 Joel Birch - based mostly on work by Jesse Klaasse and credit goes largely to him. 2382 * Special thanks to Karl Swedberg for valuable input. 2383 * 2384 * Dual licensed under the MIT and GPL licenses: 2385 * http://www.opensource.org/licenses/mit-license.php 2386 * http://www.gnu.org/licenses/gpl.html 2387 */ 2388/* 2389 * This is not the original jQuery Supposition plugin. 2390 * Please refer to the README for more information. 2391 */ 2392 2393(function($){ 2394 $.fn.supposition = function(){ 2395 const $w = $(window); /*do this once instead of every onBeforeShow call*/ 2396 2397 const _offset = function(dir) { 2398 return window[dir === 'y' ? 'pageYOffset' : 'pageXOffset'] 2399 || document.documentElement && document.documentElement[dir === 'y' ? 'scrollTop' : 'scrollLeft'] 2400 || document.body[dir === 'y' ? 'scrollTop' : 'scrollLeft']; 2401 }; 2402 2403 const onHide = function(){ 2404 this.css({bottom:''}); 2405 }; 2406 2407 const onBeforeShow = function(){ 2408 this.each(function(){ 2409 const $u = $(this); 2410 $u.css('display','block'); 2411 const $mul = $u.closest('.sf-menu'); 2412 const level = $u.parents('ul').length; 2413 const menuWidth = $u.width(); 2414 const menuParentWidth = $u.closest('li').outerWidth(true); 2415 const menuParentLeft = $u.closest('li').offset().left; 2416 const totalRight = $w.width() + _offset('x'); 2417 const menuRight = $u.offset().left + menuWidth; 2418 const exactMenuWidth = menuRight > (menuParentWidth + menuParentLeft) ? menuWidth - (menuRight - (menuParentWidth + menuParentLeft)) : menuWidth; 2419 2420 if ($u.parents('.sf-js-enabled').hasClass('rtl')) { 2421 if (menuParentLeft < exactMenuWidth) { 2422 if ($mul.hasClass('sf-horizontal') && level === 1 || $mul.hasClass('sf-navbar') && level === 2){ 2423 $u.css({left: 0, right: 'auto'}); 2424 } 2425 else { 2426 $u.css({left: menuParentWidth + 'px', right: 'auto'}); 2427 } 2428 $u.parent().addClass('sf-supposition-active'); 2429 } 2430 } 2431 else { 2432 if (menuRight > totalRight && menuParentLeft > menuWidth) { 2433 if ($mul.hasClass('sf-horizontal') && level === 1 || $mul.hasClass('sf-navbar') && level === 2){ 2434 $u.css({right: 0, left: 'auto'}); 2435 } 2436 else { 2437 $u.css({right: menuParentWidth + 'px', left: 'auto'}); 2438 } 2439 $u.parent().addClass('sf-supposition-active'); 2440 } 2441 } 2442 2443 const windowHeight = $w.height(); 2444 const offsetTop = $u.offset().top; 2445 const menuParentShadow = $mul.hasClass('sf-shadow') && $u.css('padding-bottom').length > 0 ? parseInt($u.css('padding-bottom').slice(0,-2)) : 0; 2446 const menuParentHeight = $mul.hasClass('sf-vertical') ? '-' + menuParentShadow : $u.parent().outerHeight(true) - menuParentShadow; 2447 const menuHeight = $u.height(); 2448 const baseline = windowHeight + _offset('y'); 2449 const expandUp = (offsetTop + menuHeight > baseline) && (offsetTop > menuHeight); 2450 if (expandUp) { 2451 $u.css({bottom:menuParentHeight + 'px',top:'auto'}); 2452 } 2453 $u.css('display','none'); 2454 }); 2455 }; 2456 2457 return this.each(function() { 2458 const options = $.fn.superfish.optionsList[this.serial]; /* get this menu's options */ 2459 2460 /* if callbacks already set, store them */ 2461 const _onBeforeShow = options.onBeforeShow; 2462 const _onHide = options.onHide; 2463 2464 $.extend($.fn.superfish.optionsList[this.serial],{ 2465 onBeforeShow: function() { 2466 onBeforeShow.call(this); /* fire our Supposition callback */ 2467 _onBeforeShow.call(this); /* fire stored callbacks */ 2468 }, 2469 onHide: function() { 2470 onHide.call(this); /* fire our Supposition callback */ 2471 _onHide.call(this); /* fire stored callbacks */ 2472 } 2473 }); 2474 }); 2475 }; 2476})(jQuery); 2477; 2478/* 2479 * Supersubs v0.4b - jQuery plugin 2480 * Copyright (c) 2013 Joel Birch 2481 * 2482 * Dual licensed under the MIT and GPL licenses: 2483 * http://www.opensource.org/licenses/mit-license.php 2484 * http://www.gnu.org/licenses/gpl.html 2485 * 2486 * This plugin automatically adjusts submenu widths of suckerfish-style menus to that of 2487 * their longest list item children. If you use this, please expect bugs and report them 2488 * to the jQuery Google Group with the word 'Superfish' in the subject line. 2489 * 2490 */ 2491/* 2492 * This is not the original jQuery Supersubs plugin. 2493 * Please refer to the README for more information. 2494 */ 2495 2496(function($){ // $ will refer to jQuery within this closure 2497 $.fn.supersubs = function(options){ 2498 const superfish_options = $.extend({}, $.fn.supersubs.defaults, options); 2499 let size; 2500 let o; 2501
2502 // return an original object to support chaining, 2503 // Although this is unnecessary due to the way the module uses these plugins. 2504 for (let a = 0; a < this.length; a++) { 2505 // cache selections 2506 let $$ = $(this).eq(a); 2507 // support metadata 2508 o = $.meta ? $.extend({}, superfish_options, $$.data()) : superfish_options; 2509 // Jump one level if it's a "NavBar" 2510 if ($$.hasClass('sf-navbar')) { 2511 $$ = $$.children('li').children('ul'); 2512 } 2513 // cache all ul elements 2514 let $ULs = $$.find('ul'); 2515 if ($ULs.length) { 2516 // get the font size of menu. 2517 // .css('fontSize') returns various results cross-browser, so measure an em dash instead 2518 let fontsize = $('<li id="menu-fontsize">—</li>'); 2519 size = fontsize.attr('style','padding:0;position:absolute;top:-99999em;width:auto;') 2520 .appendTo($$)[0].clientWidth; //clientWidth is faster than width() 2521 // remove em dash 2522 fontsize.remove(); 2523 2524 // loop through each ul in a menu 2525 for (let b = 0; b < $ULs.length; b++) { 2526 // cache this ul 2527 let $ul = $ULs.eq(b); 2528 // If a multi-column sub-menu, and only if correctly configured. 2529 if (o.multicolumn && $ul.hasClass('sf-multicolumn') && $ul.find('.sf-multicolumn-column').length > 0){ 2530 // Look through each column. 2531 let $column = $ul.find('div.sf-multicolumn-column > ol'); 2532 // Overall width. 2533 let mwWidth = 0; 2534 for (let d = 0; d < $column.length; d++){ 2535 resize($column.eq(d)); 2536 // New column width, in pixels. 2537 let colWidth = Math.ceil($column.width()); 2538 // Just a trick to convert em unit to px. 2539 $column.css({width:colWidth}) 2540 // Making column parents the same size. 2541 .parents('.sf-multicolumn-column').css({width:colWidth}); 2542 // Overall width. 2543 mwWidth += colWidth; 2544 } 2545 // Resizing the columns' container too. 2546 $ul.add($ul.find('li.sf-multicolumn-wrapper, li.sf-multicolumn-wrapper > ol')).css({width:mwWidth}); 2547 } 2548 else { 2549 resize($ul); 2550 } 2551 } 2552 } 2553 } 2554 function resize($ul){ 2555 // get all (li) children of this ul 2556 const $LIs = $ul.children(); 2557 // get all anchor grand-children 2558 const $As = $LIs.children('a'); 2559 // force content to one line and save current float property 2560 $LIs.css('white-space','nowrap'); 2561 // remove width restrictions and floats so elements remain vertically stacked 2562 $ul.add($LIs).add($As).css({float:'none',width:'auto'}); 2563 // this ul will now be shrink-wrapped to the longest li due to position:absolute 2564 // so save its width as ems. 2565 let emWidth = $ul.get(0).clientWidth / size; 2566 // add more width to ensure lines don't turn over at certain sizes in various browsers 2567 emWidth += o.extraWidth; 2568 // restrict to at least minWidth and at most maxWidth 2569 if (emWidth > o.maxWidth) { 2570 emWidth = o.maxWidth; 2571 } 2572 else if (emWidth < o.minWidth) { 2573 emWidth = o.minWidth; 2574 } 2575 emWidth += 'em'; 2576 // set ul to width in ems 2577 $ul.css({width:emWidth}); 2578 // restore li floats to avoid IE bugs 2579 // set li width to full width of this ul 2580 // revert white-space to normal 2581 $LIs.add($As).css({float:'',width:'',whiteSpace:''}); 2582 // update offset position of descendant ul to reflect new width of parent. 2583 // set it to 100% in case it isn't already set to this in the CSS 2584 for (let c = 0; c < $LIs.length; c++) { 2585 let $childUl = $LIs.eq(c).children('ul'); 2586 let offsetDirection = $childUl.css('left') !== undefined ? 'left' : 'right'; 2587 $childUl.css(offsetDirection,'100%'); 2588 } 2589 } 2590 return this; 2591 }; 2592 2593 // expose defaults 2594 $.fn.supersubs.defaults = { 2595 multicolumn: true, // define width for multi-column sub-menus and their columns. 2596 minWidth: 12, // requires em unit. 2597 maxWidth: 27, // requires em unit. 2598 extraWidth: 1 // extra width can ensure lines don't sometimes turn over due to slight browser differences in how they round-off values 2599 }; 2600})(jQuery); // plugin code ends 2601; 2602(function ($, Drupal, once) { 2603 Drupal.behaviors.superfish = { 2604 attach(context, drupalSettings) { 2605 // Take a look at each menu to apply Superfish to. 2606 $.each(drupalSettings.superfish || {}, function (index, options) { 2607 $(once('superfish', `ul#${options.id}`, context)).each(function () { 2608 const $menu = $(this); 2609 2610 // Check if we are to apply the Supersubs plug-in to it. 2611 if (options.plugins) { 2612 if (options.plugins.supersubs) { 2613 $menu.supersubs(options.plugins.supersubs); 2614 } 2615 } 2616 2617 // Apply Superfish to the menu. 2618 $menu.superfish(options.sf); 2619 // Check if we are to apply any other plug-in to it. 2620 if (options.plugins) { 2621 if (options.plugins.touchscreen) { 2622 $menu.sftouchscreen(options.plugins.touchscreen); 2623 } 2624 if (options.plugins.smallscreen) { 2625 $menu.sfsmallscreen(options.plugins.smallscreen); 2626 } 2627 if (options.plugins.supposition) { 2628 $menu.supposition(); 2629 } 2630 } 2631 }); 2632 }); 2633 }, 2634 }; 2635})(jQuery, Drupal, once); 2636; 2637/** 2638* DO NOT EDIT THIS FILE. 2639* See the following change record for more information, 2640* https://www.drupal.org/node/2815083 2641* @preserve 2642**/ 2643(function ($, Drupal, drupalSettings) { 2644 Drupal.Views = {}; 2645 Drupal.Views.parseQueryString = function (query) { 2646 var args = {}; 2647 var pos = query.indexOf('?'); 2648 if (pos !== -1) { 2649 query = query.substring(pos + 1); 2650 } 2651 var pair; 2652 var pairs = query.split('&'); 2653 for (var i = 0; i < pairs.length; i++) { 2654 pair = pairs[i].split('='); 2655 if (pair[0] !== 'q' && pair[1]) { 2656 args[decodeURIComponent(pair[0].replace(/\+/g, ' '))] = decodeURIComponent(pair[1].replace(/\+/g, ' ')); 2657 } 2658 } 2659 return args; 2660 }; 2661 Drupal.Views.parseViewArgs = function (href, viewPath) { 2662 var returnObj = {}; 2663 var path = Drupal.Views.getPath(href); 2664 var viewHref = Drupal.url(viewPath).substring(drupalSettings.path.baseUrl.length); 2665 if (viewHref && path.substring(0, viewHref.length + 1) === "".concat(viewHref, "/")) { 2666 returnObj.view_args = decodeURIComponent(path.substring(viewHref.length + 1, path.length)); 2667 returnObj.view_path = path; 2668 } 2669 return returnObj; 2670 }; 2671 Drupal.Views.pathPortion = function (href) { 2672 var protocol = window.location.protocol; 2673 if (href.substring(0, protocol.length) === protocol) { 2674 href = href.substring(href.indexOf('/', protocol.length + 2)); 2675 } 2676 return href; 2677 }; 2678 Drupal.Views.getPath = function (href) { 2679 href = Drupal.Views.pathPortion(href); 2680 href = href.substring(drupalSettings.path.baseUrl.length, href.length); 2681 if (href.substring(0, 3) === '?q=') { 2682 href = href.substring(3, href.length); 2683 } 2684 var chars = ['#', '?', '&']; 2685 for (var i = 0; i < chars.length; i++) { 2686 if (href.indexOf(chars[i]) > -1) { 2687 href = href.substr(0, href.indexOf(chars[i])); 2688 } 2689 } 2690 return href; 2691 }; 2692})(jQuery, Drupal, drupalSettings);;
2693/** 2694* DO NOT EDIT THIS FILE. 2695* See the following change record for more information, 2696* https://www.drupal.org/node/2815083 2697* @preserve 2698**/ 2699(function ($, Drupal, drupalSettings) { 2700 Drupal.behaviors.ViewsAjaxView = {}; 2701 Drupal.behaviors.ViewsAjaxView.attach = function (context, settings) { 2702 if (settings && settings.views && settings.views.ajaxViews) { 2703 var ajaxViews = settings.views.ajaxViews; 2704 Object.keys(ajaxViews || {}).forEach(function (i) { 2705 Drupal.views.instances[i] = new Drupal.views.ajaxView(ajaxViews[i]); 2706 }); 2707 } 2708 }; 2709 Drupal.behaviors.ViewsAjaxView.detach = function (context, settings, trigger) { 2710 if (trigger === 'unload') { 2711 if (settings && settings.views && settings.views.ajaxViews) { 2712 var ajaxViews = settings.views.ajaxViews; 2713 Object.keys(ajaxViews || {}).forEach(function (i) { 2714 var selector = ".js-view-dom-id-".concat(ajaxViews[i].view_dom_id); 2715 if ($(selector, context).length) { 2716 delete Drupal.views.instances[i]; 2717 delete settings.views.ajaxViews[i]; 2718 } 2719 }); 2720 } 2721 } 2722 }; 2723 Drupal.views = {}; 2724 Drupal.views.instances = {}; 2725 Drupal.views.ajaxView = function (settings) { 2726 var selector = ".js-view-dom-id-".concat(settings.view_dom_id); 2727 this.$view = $(selector); 2728 var ajaxPath = drupalSettings.views.ajax_path; 2729 if (ajaxPath.constructor.toString().indexOf('Array') !== -1) { 2730 ajaxPath = ajaxPath[0]; 2731 } 2732 var queryString = window.location.search || ''; 2733 if (queryString !== '') { 2734 queryString = queryString.slice(1).replace(/q=[^&]+&?|&?render=[^&]+/, ''); 2735 if (queryString !== '') { 2736 queryString = (/\?/.test(ajaxPath) ? '&' : '?') + queryString; 2737 } 2738 } 2739 this.element_settings = { 2740 url: ajaxPath + queryString, 2741 submit: settings, 2742 setClick: true, 2743 event: 'click', 2744 selector: selector, 2745 progress: { 2746 type: 'fullscreen' 2747 } 2748 }; 2749 this.settings = settings; 2750 this.$exposed_form = $("form#views-exposed-form-".concat(settings.view_name.replace(/_/g, '-'), "-").concat(settings.view_display_id.replace(/_/g, '-'))); 2751 once('exposed-form', this.$exposed_form).forEach($.proxy(this.attachExposedFormAjax, this)); 2752 once('ajax-pager', this.$view.filter($.proxy(this.filterNestedViews, this))).forEach($.proxy(this.attachPagerAjax, this)); 2753 var selfSettings = $.extend({}, this.element_settings, { 2754 event: 'RefreshView', 2755 base: this.selector, 2756 element: this.$view.get(0) 2757 }); 2758 this.refreshViewAjax = Drupal.ajax(selfSettings); 2759 }; 2760 Drupal.views.ajaxView.prototype.attachExposedFormAjax = function () { 2761 var that = this; 2762 this.exposedFormAjax = []; 2763 $('input[type=submit], button[type=submit], input[type=image]', this.$exposed_form).not('[data-drupal-selector=edit-reset]').each(function (index) { 2764 var selfSettings = $.extend({}, that.element_settings, { 2765 base: $(this).attr('id'), 2766 element: this 2767 }); 2768 that.exposedFormAjax[index] = Drupal.ajax(selfSettings); 2769 }); 2770 }; 2771 Drupal.views.ajaxView.prototype.filterNestedViews = function () { 2772 return !this.$view.parents('.view').length; 2773 }; 2774 Drupal.views.ajaxView.prototype.attachPagerAjax = function () { 2775 this.$view.find('ul.js-pager__items > li > a, th.views-field a, .attachment .views-summary a').each($.proxy(this.attachPagerLinkAjax, this)); 2776 }; 2777 Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function (id, link) { 2778 var $link = $(link); 2779 var viewData = {}; 2780 var href = $link.attr('href'); 2781 $.extend(viewData, this.settings, Drupal.Views.parseQueryString(href), Drupal.Views.parseViewArgs(href, this.settings.view_base_path)); 2782 var selfSettings = $.extend({}, this.element_settings, {
2783 submit: viewData, 2784 base: false, 2785 element: link 2786 }); 2787 this.pagerAjax = Drupal.ajax(selfSettings); 2788 }; 2789 Drupal.AjaxCommands.prototype.viewsScrollTop = function (ajax, response) { 2790 var offset = $(response.selector).offset(); 2791 var scrollTarget = response.selector; 2792 while ($(scrollTarget).scrollTop() === 0 && $(scrollTarget).parent()) { 2793 scrollTarget = $(scrollTarget).parent(); 2794 } 2795 if (offset.top - 10 < $(scrollTarget).scrollTop()) { 2796 $(scrollTarget).animate({ 2797 scrollTop: offset.top - 10 2798 }, 500); 2799 } 2800 }; 2801})(jQuery, Drupal, drupalSettings);; 2802/** 2803 * @file 2804 * better_exposed_filters.js 2805 * 2806 * Provides some client-side functionality for the Better Exposed Filters module. 2807 */ 2808 2809(function ($, Drupal, drupalSettings) { 2810 Drupal.behaviors.betterExposedFilters = { 2811 attach: function (context, settings) { 2812 // Add highlight class to checked checkboxes for better theming. 2813 $('.bef-tree input[type=checkbox], .bef-checkboxes input[type=checkbox]') 2814 // Highlight newly selected checkboxes. 2815 .change(function () { 2816 _bef_highlight(this, context); 2817 }) 2818 .filter(':checked').closest('.form-item', context).addClass('highlight'); 2819 } 2820 }; 2821 2822 /* 2823 * Helper functions 2824 */ 2825 2826 /** 2827 * Adds/Removes the highlight class from the form-item div as appropriate. 2828 */ 2829 function _bef_highlight(elem, context) { 2830 $elem = $(elem, context); 2831 $elem.attr('checked') 2832 ? $elem.closest('.form-item', context).addClass('highlight') 2833 : $elem.closest('.form-item', context).removeClass('highlight'); 2834 } 2835 2836})(jQuery, Drupal, drupalSettings); 2837;
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.