1/** 2* DO NOT EDIT THIS FILE. 3* See the following change record for more information, 4* https://www.drupal.org/node/2815083 5* @preserve 6**/ 7(function ($, Drupal) { 8 Drupal.theme.progressBar = function (id) { 9 return "<div id=\"".concat(id, "\" class=\"progress\" aria-live=\"polite\">") + '<div class="progress__label"> </div>' + '<div class="progress__track"><div class="progress__bar"></div></div>' + '<div class="progress__percentage"></div>' + '<div class="progress__description"> </div>' + '</div>'; 10 }; 11 Drupal.ProgressBar = function (id, updateCallback, method, errorCallback) { 12 this.id = id; 13 this.method = method || 'GET'; 14 this.updateCallback = updateCallback; 15 this.errorCallback = errorCallback; 16 this.element = $(Drupal.theme('progressBar', id)); 17 }; 18 $.extend(Drupal.ProgressBar.prototype, { 19 setProgress: function setProgress(percentage, message, label) { 20 if (percentage >= 0 && percentage <= 100) { 21 $(this.element).find('div.progress__bar').css('width', "".concat(percentage, "%")); 22 $(this.element).find('div.progress__percentage').html("".concat(percentage, "%")); 23 } 24 $('div.progress__description', this.element).html(message); 25 $('div.progress__label', this.element).html(label); 26 if (this.updateCallback) { 27 this.updateCallback(percentage, message, this); 28 } 29 }, 30 startMonitoring: function startMonitoring(uri, delay) { 31 this.delay = delay; 32 this.uri = uri; 33 this.sendPing(); 34 }, 35 stopMonitoring: function stopMonitoring() { 36 clearTimeout(this.timer); 37 this.uri = null; 38 }, 39 sendPing: function sendPing() { 40 if (this.timer) { 41 clearTimeout(this.timer); 42 } 43 if (this.uri) { 44 var pb = this; 45 var uri = this.uri; 46 if (uri.indexOf('?') === -1) { 47 uri += '?'; 48 } else { 49 uri += '&'; 50 } 51 uri += '_format=json'; 52 $.ajax({ 53 type: this.method, 54 url: uri, 55 data: '', 56 dataType: 'json', 57 success: function success(progress) { 58 if (progress.status === 0) { 59 pb.displayError(progress.data); 60 return; 61 } 62 pb.setProgress(progress.percentage, progress.message, progress.label); 63 pb.timer = setTimeout(function () { 64 pb.sendPing(); 65 }, pb.delay); 66 }, 67 error: function error(xmlhttp) { 68 var e = new Drupal.AjaxError(xmlhttp, pb.uri); 69 pb.displayError("<pre>".concat(e.message, "</pre>")); 70 } 71 }); 72 } 73 }, 74 displayError: function displayError(string) { 75 var error = $('<div class="messages messages--error"></div>').html(string); 76 $(this.element).before(error).hide(); 77 if (this.errorCallback) { 78 this.errorCallback(this); 79 } 80 } 81 }); 82})(jQuery, Drupal);; 83loadjs=function(){var h=function(){},c={},u={},f={};function o(e,n){if(e){var r=f[e];if(u[e]=n,r)for(;r.length;)r[0](e,n),r.splice(0,1)}}function l(e,n){e.call&&(e={success:e}),n.length?(e.error||h)(n):(e.success||h)(e)}function d(r,t,s,i){var c,o,e=document,n=s.async,u=(s.numRetries||0)+1,f=s.before||h,l=r.replace(/[\?|#].*$/,""),a=r.replace(/^(css|img)!/,"");i=i||0,/(^css!|\.css$)/.test(l)?((o=e.createElement("link")).rel="stylesheet",o.href=a,(c="hideFocus"in o)&&o.relList&&(c=0,o.rel="preload",o.as="style")):/(^img!|\.(png|gif|jpg|svg|webp)$)/.test(l)?(o=e.createElement("img")).src=a:((o=e.createElement("script")).src=r,o.async=void 0===n||n),!(o.onload=o.onerror=o.onbeforeload=function(e){var n=e.type[0];if(c)try{o.sheet.cssText.length||(n="e")}catch(e){18!=e.code&&(n="e")}if("e"==n){if((i+=1)<u)return d(r,t,s,i)}else if("preload"==o.rel&&"style"==o.as)return o.rel="stylesheet";t(r,n,e.defaultPrevented)})!==f(r,o)&&e.head.appendChild(o)}function r(e,n,r){var t,s;if(n&&n.trim&&(t=n),s=(t?r:n)||{},t){if(t in c)throw"LoadJS";c[t]=!0}function i(n,r){!function(e,t,n){var r,s,i=(e=e.push?e:[e]).length,c=i,o=[];for(r=function(e,n,r){if("e"==n&&o.push(e),"b"==n){if(!r)return;o.push(e)}--i||t(o)},s=0;s<c;s++)d(e[s],r,n)}(e,function(e){l(s,e),n&&l({success:n,error:r},e),o(t,e)},s)}if(s.returnPromise)return new Promise(i);i()}return r.ready=function(e,n){return function(e,r){e=e.push?e:[e];var n,t,s,i=[],c=e.length,o=c;
83for(n=function(e,n){n.length&&i.push(e),--o||r(i)};c--;)t=e[c],(s=u[t])?n(t,s):(f[t]=f[t]||[]).push(n)}(e,function(e){l(n,e)}),r},r.done=function(e){o(e,[])},r.reset=function(){c={},u={},f={}},r.isDefined=function(e){return e in c},r}();; 84/** 85* DO NOT EDIT THIS FILE. 86* See the following change record for more information, 87* https://www.drupal.org/node/2815083 88* @preserve 89**/ 90function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } 91function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } 92function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } 93function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } 94function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } 95function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } 96(function ($, window, Drupal, drupalSettings, loadjs, _ref) { 97 var isFocusable = _ref.isFocusable, 98 tabbable = _ref.tabbable; 99 Drupal.behaviors.AJAX = { 100 attach: function attach(context, settings) { 101 function loadAjaxBehavior(base) { 102 var elementSettings = settings.ajax[base]; 103 if (typeof elementSettings.selector === 'undefined') { 104 elementSettings.selector = "#".concat(base); 105 } 106 once('drupal-ajax', $(elementSettings.selector)).forEach(function (el) { 107 elementSettings.element = el; 108 elementSettings.base = base; 109 Drupal.ajax(elementSettings); 110 }); 111 } 112 Object.keys(settings.ajax || {}).forEach(function (base) { 113 return loadAjaxBehavior(base); 114 }); 115 Drupal.ajax.bindAjaxLinks(document.body); 116 once('ajax', '.use-ajax-submit').forEach(function (el) { 117 var elementSettings = {}; 118 elementSettings.url = $(el.form).attr('action'); 119 elementSettings.setClick = true; 120 elementSettings.event = 'click'; 121 elementSettings.progress = { 122 type: 'throbber' 123 }; 124 elementSettings.base = el.id; 125 elementSettings.element = el; 126 Drupal.ajax(elementSettings); 127 }); 128 }, 129 detach: function detach(context, settings, trigger) { 130 if (trigger === 'unload') { 131 Drupal.ajax.expired().forEach(function (instance) { 132 Drupal.ajax.instances[instance.instanceIndex] = null; 133 }); 134 } 135 } 136 }; 137 Drupal.AjaxError = function (xmlhttp, uri, customMessage) { 138 var statusCode; 139 var statusText; 140 var responseText; 141 if (xmlhttp.status) { 142 statusCode = "\n".concat(Drupal.t('An AJAX HTTP error occurred.'), "\n").concat(Drupal.t('HTTP Result Code: !status', { 143 '!status': xmlhttp.status 144 })); 145 } else { 146 statusCode = "\n".concat(Drupal.t('An AJAX HTTP request terminated abnormally.')); 147 } 148 statusCode += "\n".concat(Drupal.t('Debugging information follows.')); 149 var pathText = "\n".concat(Drupal.t('Path: !uri', { 150 '!uri': uri 151 })); 152 statusText = ''; 153 try { 154 statusText = "\n".concat(Drupal.t('StatusText: !statusText', { 155 '!statusText': xmlhttp.statusText.trim() 156 })); 157 } catch (e) {} 158 responseText = ''; 159 try { 160 responseText = "\n".concat(Drupal.t('ResponseText: !responseText', { 161 '!responseText': xmlhttp.responseText.trim() 162 })); 163 } catch (e) {} 164 responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi, ''); 165 responseText = responseText.replace(/[\n]+\s+/g, '\n'); 166 var readyStateText = xmlhttp.status === 0 ? "\n".concat(Drupal.t('ReadyState: !readyState', { 167 '!readyState': xmlhttp.readyState 168 })) : ''; 169 customMessage = customMessage ? "\n".concat(Drupal.t('CustomMessage: !customMessage', { 170 '!customMessage': customMessage 171 })) : ''; 172 this.message = statusCode + pathText + statusText + customMessage + responseText + readyStateText; 173 this.name = 'AjaxError'; 174 }; 175 Drupal.AjaxError.prototype = new Error(); 176 Drupal.AjaxError.prototype.constructor = Drupal.AjaxError; 177 Drupal.ajax = function (settings) { 178 if (arguments.length !== 1) { 179 throw new Error('Drupal.ajax() function must be called with one configuration object only'); 180 } 181 var base = settings.base || false; 182 var element = settings.element || false; 183 delete settings.base; 184 delete settings.element; 185 if (!settings.progress && !element) { 186 settings.progress = false;
187 } 188 var ajax = new Drupal.Ajax(base, element, settings); 189 ajax.instanceIndex = Drupal.ajax.instances.length; 190 Drupal.ajax.instances.push(ajax); 191 return ajax; 192 }; 193 Drupal.ajax.instances = []; 194 Drupal.ajax.expired = function () { 195 return Drupal.ajax.instances.filter(function (instance) { 196 return instance && instance.element !== false && !document.body.contains(instance.element); 197 }); 198 }; 199 Drupal.ajax.bindAjaxLinks = function (element) { 200 once('ajax', '.use-ajax', element).forEach(function (ajaxLink) { 201 var $linkElement = $(ajaxLink); 202 var elementSettings = { 203 progress: { 204 type: 'throbber' 205 }, 206 dialogType: $linkElement.data('dialog-type'), 207 dialog: $linkElement.data('dialog-options'), 208 dialogRenderer: $linkElement.data('dialog-renderer'), 209 base: $linkElement.attr('id'), 210 element: ajaxLink 211 }; 212 var href = $linkElement.attr('href'); 213 if (href) { 214 elementSettings.url = href; 215 elementSettings.event = 'click'; 216 } 217 Drupal.ajax(elementSettings); 218 }); 219 }; 220 Drupal.Ajax = function (base, element, elementSettings) { 221 var defaults = { 222 event: element ? 'mousedown' : null, 223 keypress: true, 224 selector: base ? "#".concat(base) : null, 225 effect: 'none', 226 speed: 'none', 227 method: 'replaceWith', 228 progress: { 229 type: 'throbber', 230 message: Drupal.t('Please wait...') 231 }, 232 submit: { 233 js: true 234 } 235 }; 236 $.extend(this, defaults, elementSettings); 237 this.commands = new Drupal.AjaxCommands(); 238 this.instanceIndex = false; 239 if (this.wrapper) { 240 this.wrapper = "#".concat(this.wrapper); 241 } 242 this.element = element; 243 this.element_settings = elementSettings; 244 this.elementSettings = elementSettings; 245 if (this.element && this.element.form) { 246 this.$form = $(this.element.form); 247 } 248 if (!this.url) { 249 var $element = $(this.element); 250 if ($element.is('a')) { 251 this.url = $element.attr('href'); 252 } else if (this.element && element.form) { 253 this.url = this.$form.attr('action'); 254 } 255 } 256 var originalUrl = this.url; 257 this.url = this.url.replace(/\/nojs(\/|$|\?|#)/, '/ajax$1'); 258 if (drupalSettings.ajaxTrustedUrl[originalUrl]) { 259 drupalSettings.ajaxTrustedUrl[this.url] = true; 260 } 261 var ajax = this; 262 ajax.options = { 263 url: ajax.url, 264 data: ajax.submit, 265 isInProgress: function isInProgress() { 266 return ajax.ajaxing; 267 }, 268 beforeSerialize: function beforeSerialize(elementSettings, options) { 269 return ajax.beforeSerialize(elementSettings, options); 270 }, 271 beforeSubmit: function beforeSubmit(formValues, elementSettings, options) { 272 ajax.ajaxing = true; 273 return ajax.beforeSubmit(formValues, elementSettings, options); 274 }, 275 beforeSend: function beforeSend(xmlhttprequest, options) { 276 ajax.ajaxing = true; 277 return ajax.beforeSend(xmlhttprequest, options); 278 }, 279 success: function success(response, status, xmlhttprequest) { 280 var _this = this; 281 if (typeof response === 'string') { 282 response = $.parseJSON(response); 283 } 284 if (response !== null && !drupalSettings.ajaxTrustedUrl[ajax.url]) { 285 if (xmlhttprequest.getResponseHeader('X-Drupal-Ajax-Token') !== '1') { 286 var customMessage = Drupal.t('The response failed verification so will not be processed.'); 287 return ajax.error(xmlhttprequest, ajax.url, customMessage); 288 } 289 } 290 return Promise.resolve(ajax.success(response, status)).then(function () { 291 ajax.ajaxing = false; 292 $(document).trigger('ajaxSuccess', [xmlhttprequest, _this]); 293 $(document).trigger('ajaxComplete', [xmlhttprequest, _this]); 294 if (--$.active === 0) { 295 $(document).trigger('ajaxStop'); 296 } 297 }); 298 }, 299 error: function error(xmlhttprequest, status, _error) { 300 ajax.ajaxing = false; 301 }, 302 complete: function complete(xmlhttprequest, status) { 303 if (status === 'error' || status === 'parsererror') { 304 return ajax.error(xmlhttprequest, ajax.url); 305 } 306 }, 307 dataType: 'json', 308 jsonp: false, 309 type: 'POST' 310 }; 311 if (elementSettings.dialog) { 312 ajax.options.data.dialogOptions = elementSettings.dialog; 313 } 314 if (ajax.options.url.indexOf('?') === -1) { 315 ajax.options.url += '?'; 316 } else { 317 ajax.options.url += '&'; 318 } 319 var wrapper = "drupal_".concat(elementSettings.dialogType || 'ajax'); 320 if (elementSettings.dialogRenderer) { 321 wrapper += ".".concat(elementSettings.dialogRenderer); 322 } 323 ajax.options.url += "".concat(Drupal.ajax.WRAPPER_FORMAT, "=").concat(wrapper); 324 $(ajax.element).on(elementSettings.event, function (event) { 325 if (!drupalSettings.ajaxTrustedUrl[ajax.url] && !Drupal.url.isLocal(ajax.url)) { 326 throw new Error(Drupal.t('The callback URL is not local and n
326ot trusted: !url', { 327 '!url': ajax.url 328 })); 329 } 330 return ajax.eventResponse(this, event); 331 }); 332 if (elementSettings.keypress) { 333 $(ajax.element).on('keypress', function (event) { 334 return ajax.keypressResponse(this, event); 335 }); 336 } 337 if (elementSettings.prevent) { 338 $(ajax.element).on(elementSettings.prevent, false); 339 } 340 }; 341 Drupal.ajax.WRAPPER_FORMAT = '_wrapper_format'; 342 Drupal.Ajax.AJAX_REQUEST_PARAMETER = '_drupal_ajax'; 343 Drupal.Ajax.prototype.execute = function () { 344 if (this.ajaxing) { 345 return; 346 } 347 try { 348 this.beforeSerialize(this.element, this.options); 349 return $.ajax(this.options); 350 } catch (e) { 351 this.ajaxing = false; 352 window.alert("An error occurred while attempting to process ".concat(this.options.url, ": ").concat(e.message)); 353 return $.Deferred().reject(); 354 } 355 }; 356 Drupal.Ajax.prototype.keypressResponse = function (element, event) { 357 var ajax = this; 358 if (event.which === 13 || event.which === 32 && element.type !== 'text' && element.type !== 'textarea' && element.type !== 'tel' && element.type !== 'number') { 359 event.preventDefault(); 360 event.stopPropagation(); 361 $(element).trigger(ajax.elementSettings.event); 362 } 363 }; 364 Drupal.Ajax.prototype.eventResponse = function (element, event) { 365 event.preventDefault(); 366 event.stopPropagation(); 367 var ajax = this; 368 if (ajax.ajaxing) { 369 return; 370 } 371 try { 372 if (ajax.$form) { 373 if (ajax.setClick) { 374 element.form.clk = element; 375 } 376 ajax.$form.ajaxSubmit(ajax.options); 377 } else { 378 ajax.beforeSerialize(ajax.element, ajax.options); 379 $.ajax(ajax.options); 380 } 381 } catch (e) { 382 ajax.ajaxing = false; 383 window.alert("An error occurred while attempting to process ".concat(ajax.options.url, ": ").concat(e.message)); 384 } 385 }; 386 Drupal.Ajax.prototype.beforeSerialize = function (element, options) { 387 if (this.$form && document.body.contains(this.$form.get(0))) { 388 var settings = this.settings || drupalSettings; 389 Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize'); 390 } 391 options.data[Drupal.Ajax.AJAX_REQUEST_PARAMETER] = 1; 392 var pageState = drupalSettings.ajaxPageState; 393 options.data['ajax_page_state[theme]'] = pageState.theme; 394 options.data['ajax_page_state[theme_token]'] = pageState.theme_token; 395 options.data['ajax_page_state[libraries]'] = pageState.libraries; 396 }; 397 Drupal.Ajax.prototype.beforeSubmit = function (formValues, element, options) {}; 398 Drupal.Ajax.prototype.beforeSend = function (xmlhttprequest, options) { 399 if (this.$form) { 400 options.extraData = options.extraData || {}; 401 options.extraData.ajax_iframe_upload = '1'; 402 var v = $.fieldValue(this.element); 403 if (v !== null) { 404 options.extraData[this.element.name] = v; 405 } 406 } 407 $(this.element).prop('disabled', true); 408 if (!this.progress || !this.progress.type) { 409 return; 410 } 411 var progressIndicatorMethod = "setProgressIndicator".concat(this.progress.type.slice(0, 1).toUpperCase()).concat(this.progress.type.slice(1).toLowerCase()); 412 if (progressIndicatorMethod in this && typeof this[progressIndicatorMethod] === 'function') { 413 this[progressIndicatorMethod].call(this); 414 } 415 }; 416 Drupal.theme.ajaxProgressThrobber = function (message) { 417 var messageMarkup = typeof message === 'string' ? Drupal.theme('ajaxProgressMessage', message) : ''; 418 var throbber = '<div class="throbber"> </div>'; 419 return "<div class=\"ajax-progress ajax-progress-throbber\">".concat(throbber).concat(messageMarkup, "</div>"); 420 }; 421 Drupal.theme.ajaxProgressIndicatorFullscreen = function () { 422 return '<div class="ajax-progress ajax-progress-fullscreen"> </div>'; 423 }; 424 Drupal.theme.ajaxProgressMessage = function (message) { 425 return "<div class=\"message\">".concat(message, "</div>"); 426 }; 427 Drupal.theme.ajaxProgressBar = function ($element) { 428 return $('<div class="ajax-progress ajax-progress-bar"></div>').append($element); 429 }; 430 Drupal.Ajax.prototype.setProgressIndicatorBar = function () { 431 var progressBar = new Drupal.ProgressBar("ajax-progress-".concat(this.element.i
431d), $.noop, this.progress.method, $.noop); 432 if (this.progress.message) { 433 progressBar.setProgress(-1, this.progress.message); 434 } 435 if (this.progress.url) { 436 progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500); 437 } 438 this.progress.element = $(Drupal.theme('ajaxProgressBar', progressBar.element)); 439 this.progress.object = progressBar; 440 $(this.element).after(this.progress.element); 441 }; 442 Drupal.Ajax.prototype.setProgressIndicatorThrobber = function () { 443 this.progress.element = $(Drupal.theme('ajaxProgressThrobber', this.progress.message)); 444 $(this.element).after(this.progress.element); 445 }; 446 Drupal.Ajax.prototype.setProgressIndicatorFullscreen = function () { 447 this.progress.element = $(Drupal.theme('ajaxProgressIndicatorFullscreen')); 448 $('body').append(this.progress.element); 449 }; 450 Drupal.Ajax.prototype.commandExecutionQueue = function (response, status) { 451 var _this2 = this; 452 var ajaxCommands = this.commands; 453 return Object.keys(response || {}).reduce(function (executionQueue, key) { 454 return executionQueue.then(function () { 455 var command = response[key].command; 456 if (command && ajaxCommands[command]) { 457 return ajaxCommands[command](_this2, response[key], status); 458 } 459 }); 460 }, Promise.resolve()); 461 }; 462 Drupal.Ajax.prototype.success = function (response, status) { 463 var _this3 = this; 464 if (this.progress.element) { 465 $(this.progress.element).remove(); 466 } 467 if (this.progress.object) { 468 this.progress.object.stopMonitoring(); 469 } 470 $(this.element).prop('disabled', false); 471 var elementParents = $(this.element).parents('[data-drupal-selector]').addBack().toArray(); 472 var focusChanged = Object.keys(response || {}).some(function (key) { 473 var _response$key = response[key], 474 command = _response$key.command, 475 method = _response$key.method; 476 return command === 'focusFirst' || command === 'invoke' && method === 'focus'; 477 }); 478 return this.commandExecutionQueue(response, status).then(function () { 479 if (!focusChanged && _this3.element && !$(_this3.element).data('disable-refocus')) { 480 var target = false;
481 for (var n = elementParents.length - 1; !target && n >= 0; n--) { 482 target = document.querySelector("[data-drupal-selector=\"".concat(elementParents[n].getAttribute('data-drupal-selector'), "\"]")); 483 } 484 if (target) { 485 $(target).trigger('focus'); 486 } 487 } 488 if (_this3.$form && document.body.contains(_this3.$form.get(0))) { 489 var settings = _this3.settings || drupalSettings; 490 Drupal.attachBehaviors(_this3.$form.get(0), settings); 491 } 492 _this3.settings = null; 493 }).catch(function (error) { 494 return console.error(Drupal.t('An error occurred during the execution of the Ajax response: !error', { 495 '!error': error 496 })); 497 }); 498 }; 499 Drupal.Ajax.prototype.getEffect = function (response) { 500 var type = response.effect || this.effect; 501 var speed = response.speed || this.speed; 502 var effect = {}; 503 if (type === 'none') { 504 effect.showEffect = 'show'; 505 effect.hideEffect = 'hide'; 506 effect.showSpeed = ''; 507 } else if (type === 'fade') { 508 effect.showEffect = 'fadeIn'; 509 effect.hideEffect = 'fadeOut'; 510 effect.showSpeed = speed; 511 } else { 512 effect.showEffect = "".concat(type, "Toggle"); 513 effect.hideEffect = "".concat(type, "Toggle"); 514 effect.showSpeed = speed; 515 } 516 return effect; 517 }; 518 Drupal.Ajax.prototype.error = function (xmlhttprequest, uri, customMessage) { 519 if (this.progress.element) { 520 $(this.progress.element).remove(); 521 } 522 if (this.progress.object) { 523 this.progress.object.stopMonitoring(); 524 } 525 $(this.wrapper).show(); 526 $(this.element).prop('disabled', false); 527 if (this.$form && document.body.contains(this.$form.get(0))) { 528 var settings = this.settings || drupalSettings; 529 Drupal.attachBehaviors(this.$form.get(0), settings); 530 } 531 throw new Drupal.AjaxError(xmlhttprequest, uri, customMessage); 532 }; 533 Drupal.theme.ajaxWrapperNewContent = function ($newContent, ajax, response) { 534 return (response.effect || ajax.effect) !== 'none' && $newContent.filter(function (i) { 535 return !($newContent[i].nodeName === '#comment' || $newContent[i].nodeName === '#text' && /^(\s|\n|\r)*$/.test($newContent[i].textContent)); 536 }).length > 1 ? Drupal.theme('ajaxWrapperMultipleRootElements', $newContent) : $newContent; 537 }; 538 Drupal.theme.ajaxWrapperMultipleRootElements = function ($elements) { 539 return $('<div></div>').append($elements); 540 }; 541 Drupal.AjaxCommands = function () {}; 542 Drupal.AjaxCommands.prototype = { 543 insert: function insert(ajax, response) { 544 var $wrapper = response.selector ? $(response.selector) : $(ajax.wrapper); 545 var method = response.method || ajax.method; 546 var effect = ajax.getEffect(response); 547 var settings = response.settings || ajax.settings || drupalSettings; 548 var $newContent = $($.parseHTML(response.data, document, true)); 549 $newContent = Drupal.theme('ajaxWrapperNewContent', $newContent, ajax, response); 550 switch (method) { 551 case 'html': 552 case 'replaceWith': 553 case 'replaceAll': 554 case 'empty': 555 case 'remove': 556 Drupal.detachBehaviors($wrapper.get(0), settings); 557 break; 558 default: 559 break; 560 } 561 $wrapper[method]($newContent); 562 if (effect.showEffect !== 'show') { 563 $newContent.hide(); 564 } 565 var $ajaxNewContent = $newContent.find('.ajax-new-content'); 566 if ($ajaxNewContent.length) { 567 $ajaxNewContent.hide(); 568 $newContent.show(); 569 $ajaxNewContent[effect.showEffect](effect.showSpeed); 570 } else if (effect.showEffect !== 'show') { 571 $newContent[effect.showEffect](effect.showSpeed); 572 } 573 if ($newContent.parents('html').length) { 574 $newContent.each(function (index, element) { 575 if (element.nodeType === Node.ELEMENT_NODE) { 576 Drupal.attachBehaviors(element, settings); 577 } 578 }); 579 } 580 }, 581 remove: function remove(ajax, response, status) { 582 var settings = response.settings || ajax.settings || drupalSettings; 583 $(response.selector).each(function () { 584 Drupal.detachBehaviors(this, settings); 585 }).remove(); 586 }, 587 changed: function changed(ajax, response, status) { 588 var $element = $(response.selector); 589 if (!$element.hasClass('ajax-changed')) { 590 $element.addClass('ajax-changed'); 591 if (response.asterisk) { 592 $element.find(response.asterisk).append(" <abbr class=\"ajax-changed\" title=\"".concat(Drupal.t('Changed'), "\">*</abbr> ")); 593 } 594 } 595 }, 596 alert: function alert(ajax, response, status) { 597 window.alert(response.text); 598 }, 599 announce: function announce(ajax, response) { 600 if (response.priority) { 601 Drupal.announce(response.text, response.priority); 602 } else { 603 Drupal.announce(response.text); 604 } 605 }, 606 redirect: function redirect(ajax, response, status) { 607 window.location = response.url; 608 }, 609 css: function css(ajax, response, status) { 610 $(response.selector).css(response.argument); 611 }, 612 settings: function settings(ajax, response, status) { 613 var ajaxSettings = drupalSettings.ajax; 614 if (ajaxSettings) {
615 Drupal.ajax.expired().forEach(function (instance) { 616 if (instance.selector) { 617 var selector = instance.selector.replace('#', ''); 618 if (selector in ajaxSettings) { 619 delete ajaxSettings[selector]; 620 } 621 } 622 }); 623 } 624 if (response.merge) { 625 $.extend(true, drupalSettings, response.settings); 626 } else { 627 ajax.settings = response.settings; 628 } 629 }, 630 data: function data(ajax, response, status) { 631 $(response.selector).data(response.name, response.value); 632 }, 633 focusFirst: function focusFirst(ajax, response, status) { 634 var focusChanged = false; 635 var container = document.querySelector(response.selector); 636 if (container) { 637 var tabbableElements = tabbable(container); 638 if (tabbableElements.length) { 639 tabbableElements[0].focus(); 640 focusChanged = true; 641 } else if (isFocusable(container)) { 642 container.focus(); 643 focusChanged = true; 644 } 645 } 646 if (ajax.hasOwnProperty('element') && !focusChanged) { 647 ajax.element.focus(); 648 } 649 }, 650 invoke: function invoke(ajax, response, status) { 651 var $element = $(response.selector); 652 $element[response.method].apply($element, _toConsumableArray(response.args)); 653 }, 654 restripe: function restripe(ajax, response, status) { 655 $(response.selector).find('> tbody > tr:visible, > tr:visible').removeClass('odd even').filter(':even').addClass('odd').end().filter(':odd').addClass('even'); 656 }, 657 update_build_id: function update_build_id(ajax, response, status) { 658 document.querySelectorAll("input[name=\"form_build_id\"][value=\"".concat(response.old, "\"]")).forEach(function (item) { 659 item.value = response.new; 660 }); 661 }, 662 add_css: function add_css(ajax, response, status) { 663 $('head').prepend(response.data); 664 }, 665 message: function message(ajax, response) { 666 var messages = new Drupal.Message(document.querySelector(response.messageWrapperQuerySelector)); 667 if (response.clearPrevious) { 668 messages.clear(); 669 } 670 messages.add(response.message, response.messageOptions); 671 }, 672 add_js: function add_js(ajax, response, status) { 673 var parentEl = document.querySelector(response.selector || 'body'); 674 var settings = ajax.settings || drupalSettings; 675 var allUniqueBundleIds = response.data.map(function (script) { 676 var uniqueBundleId = script.src + ajax.instanceIndex; 677 loadjs(script.src, uniqueBundleId, { 678 async: false, 679 before: function before(path, scriptEl) { 680 Object.keys(script).forEach(function (attributeKey) { 681 scriptEl.setAttribute(attributeKey, script[attributeKey]); 682 }); 683 parentEl.appendChild(scriptEl); 684 return false; 685 } 686 }); 687 return uniqueBundleId; 688 }); 689 return new Promise(function (resolve, reject) { 690 loadjs.ready(allUniqueBundleIds, { 691 success: function success() { 692 Drupal.attachBehaviors(parentEl, settings); 693 resolve(); 694 }, 695 error: function error(depsNotFound) { 696 var message = Drupal.t("The following files could not be loaded: @dependencies", { 697 '@dependencies': depsNotFound.join(', ') 698 }); 699 reject(message); 700 } 701 }); 702 }); 703 } 704 }; 705 var stopEvent = function stopEvent(xhr, settings) { 706 return xhr.getResponseHeader('X-Drupal-Ajax-Token') === '1' && settings.isInProgress && settings.isInProgress(); 707 }; 708 $.extend(true, $.event.special, { 709 ajaxSuccess: { 710 trigger: function trigger(event, xhr, settings) { 711 if (stopEvent(xhr, settings)) { 712 return false; 713 } 714 } 715 }, 716 ajaxComplete: { 717 trigger: function trigger(event, xhr, settings) { 718 if (stopEvent(xhr, settings)) { 719 $.active++; 720 return false; 721 } 722 } 723 } 724 }); 725})(jQuery, window, Drupal, drupalSettings, loadjs, window.tabbable);; 726/** 727* DO NOT EDIT THIS FILE. 728* See the following change record for more information, 729* https://www.drupal.org/node/2815083 730* @preserve 731**/ 732(function (Drupal) { 733 Drupal.theme.ajaxProgressBar = function ($element) { 734 return $element.addClass('ajax-progress ajax-progress-bar'); 735 }; 736})(Drupal);; 737(function (Drupal) { 738 739 /** 740 * Command to attach data using jQuery's data API. 741 * 742 * @param {Drupal.Ajax} [ajax] 743 * {@link Drupal.Ajax} object created by {@link Drupal.ajax}. 744 * @param {object} response 745 * The response from the Ajax request. 746 * @param {string} response.event_name 747 * The event name 748 * @param {object} response.data 749 * The value of the event. 750 */ 751 Drupal.AjaxCommands.prototype.gtagEvent = function (ajax, response) { 752 gtag('event', response.event_name, response.data) 753 } 754})(Drupal); 755; 756function ctSetCookie(cookies) 757{ 758 759 let useCookies, useAltCookies 760 761 if ('undefined' !== typeof ct_use_cookies) { 762 useCookies = ct_use_cookies; 763 } else { 764 useCookies = false;
765 } 766 767 if ('undefined' !== typeof ct_use_alt_cookies) { 768 useAltCookies = ct_use_alt_cookies; 769 } else { 770 useAltCookies = false 771 } 772 773 if (useCookies) { 774 if (useAltCookies && useAltCookies === 1) { 775 let xhr = new XMLHttpRequest(); 776 777 let json = JSON.stringify(cookies); 778 779 xhr.open("POST", '/admin/config/cleantalk/set_alt_cookies') 780 xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8'); 781 782 xhr.send(json); 783 } else { 784 cookies.forEach( 785 function (e) { 786 let ctSecure = location.protocol === "https:" ? "; secure" : ""; 787 document.cookie = e.name + "=" + encodeURIComponent(e.value) + "; path=/; expires=0; samesite=lax" + ctSecure; 788 } 789 ) 790 } 791 } 792} 793; 794var d = new Date(), 795 ctTimeMs = new Date().getTime(), 796 ctMouseEventTimerFlag = true, //Reading interval flag 797 ctMouseData = "[", 798 ctMouseDataCounter = 0, 799 ctScrollCollected = false, 800 ctEventTokenInterval = null; 801 802ctSetCookie( 803 [ 804 { 805 'name' : 'ct_check_js', 806 'value' : ct_check_js_val 807 }, 808 { 809 'name' : 'ct_ps_timestamp', 810 'value' : Math.floor(new Date().getTime()/1000) 811 }, 812 { 813 'name' : 'ct_fkp_timestamp', 814 'value' : '0' 815 }, 816 { 817 'name' : 'ct_pointer_data', 818 'value' : '0' 819 }, 820 { 821 'name' : 'ct_timezone', 822 'value' : d.getTimezoneOffset()/60*(-1) 823 }, 824 { 825 'name' : 'apbct_antibot', 826 'value' : drupal_ac_antibot_cookie_value 827 }, 828 { 829 'name' : 'ct_has_scrolled', 830 'value' : false 831 } 832 ] 833); 834 835//Reading interval 836 837var ctMouseReadInterval = setInterval( 838 function () { 839 ctMouseEventTimerFlag = true; 840 }, 150 841); 842 843//Writting interval 844 845var ctMouseWriteDataInterval = setInterval( 846 function () { 847 if(typeof ct_use_alt_cookies !== "undefined" && ct_use_alt_cookies === 1) { 848 return; 849 } 850 var ctMouseDataToSend = ctMouseData.slice(0,-1).concat("]"); 851 ctSetCookie( 852 [ 853 { 854 'name' : 'ct_pointer_data', 855 'value' : ctMouseDataToSend 856 } 857 ] 858 ); 859 }, 1200 860); 861 862//Stop observing function 863 864function ctMouseStopData() 865{ 866 if(typeof window.addEventListener == "function") { 867 window.removeEventListener("mousemove", ctFunctionMouseMove); 868 } else { 869 window.detachEvent("onmousemove", ctFunctionMouseMove); 870 } 871 clearInterval(ctMouseReadInterval); 872 clearInterval(ctMouseWriteDataInterval); 873} 874 875//Logging mouse position each 300 ms 876 877var ctFunctionMouseMove = function output(event) 878{ 879 if (ctMouseEventTimerFlag == true) { 880 var mouseDate = new Date(); 881 ctMouseData += "[" + Math.round(event.pageY) + "," + Math.round(event.pageX) + "," + Math.round(mouseDate.getTime() - ctTimeMs) + "],"; 882 ctMouseDataCounter++; 883 ctMouseEventTimerFlag = false; 884 if(ctMouseDataCounter >= 100) { 885 ctMouseStopData(); 886 } 887 } 888}; 889 890/** 891 * Set scrolling cookie 892 */ 893function ctSetHasScrolled() 894{ 895 if(! ctScrollCollected ) { 896 ctSetCookie( 897 [ 898 { 899 'name' : 'ct_has_scrolled', 900 'value' : true 901 } 902 ] 903 ); 904 ctScrollCollected = true; 905 } 906} 907 908//Stop key listening function 909 910function ctKeyStopStopListening() 911{ 912 if (typeof window.addEventListener == "function") { 913 window.removeEventListener("mousedown", ctFunctionFirstKey); 914 window.removeEventListener("keydown", ctFunctionFirstKey); 915 } 916 else { 917 window.detachEvent("mousedown", ctFunctionFirstKey); 918 window.detachEvent("keydown", ctFunctionFirstKey); 919 } 920} 921 922//Writing first key press timestamp 923 924var ctFunctionFirstKey = function output(event) 925{ 926 var KeyTimestamp = Math.floor(new Date().getTime()/1000); 927 ctSetCookie( 928 [ 929 { 930 'name' : 'ct_fkp_timestamp', 931 'value' : KeyTimestamp 932 } 933 ] 934 ); 935 ctKeyStopStopListening(); 936}; 937 938if (typeof window.addEventListener == "function") { 939 window.addEventListener("mousemove", ctFunctionMouseMove); 940 window.addEventListener("mousedown", ctFunctionFirstKey); 941 window.addEventListener("keydown", ctFunctionFirstKey); 942 window.addEventListener("scroll", ctSetHasScrolled); 943} 944else { 945 window.attachEvent("onmousemove", ctFunctionMouseMove); 946 window.attachEvent("mousedown", ctFunctionFirstKey); 947 window.attachEvent("keydown", ctFunctionFirstKey); 948 window.attachEvent("scroll", ctSetHasScrolled); 949} 950 951function apbct_collect_visible_fields( form ) 952{ 953 954 // Get only fields 955 var inputs = [], 956 inputs_visible = '', 957 inputs_visible_count = 0, 958 inputs_invisible = '', 959 inputs_invisible_count = 0, 960 inputs_with_duplicate_names = []; 961 962 for(var key in form.elements){ 963 if(!isNaN(+key)) { 964 inputs[key] = form.elements[key]; 965 } 966 } 967 968 // Filter fields
969 inputs = inputs.filter( 970 function (elem) { 971 972 // Filter already added fields 973 if(inputs_with_duplicate_names.indexOf(elem.getAttribute('name')) !== -1 ) { 974 return false; 975 } 976 // Filter inputs with same names for type == radio 977 if(-1 !== ['radio', 'checkbox'].indexOf(elem.getAttribute("type"))) { 978 inputs_with_duplicate_names.push(elem.getAttribute('name')); 979 return false; 980 } 981 return true; 982 } 983 ); 984 985 // Visible fields 986 inputs.forEach( 987 function (elem, i, elements) { 988 // Unnecessary fields 989 if(elem.getAttribute("type") === "submit" // type == submit 990 || elem.getAttribute('name') === null 991 || elem.getAttribute('name') === 'ct_checkjs' 992 ) { 993 return; 994 } 995 // Invisible fields 996 if(getComputedStyle(elem).display === "none" // hidden 997 || getComputedStyle(elem).visibility === "hidden" // hidden 998 || getComputedStyle(elem).opacity === "0" // hidden 999 || elem.getAttribute("type") === "hidden" // type == hidden 1000 ) { 1001 if(elem.classList.contains("wp-editor-area") ) { 1002 inputs_visible += " " + elem.getAttribute("name"); 1003 inputs_visible_count++; 1004 } else { 1005 inputs_invisible += " " + elem.getAttribute("name"); 1006 inputs_invisible_count++; 1007 } 1008 } 1009 // Visible fields 1010 else { 1011 inputs_visible += " " + elem.getAttribute("name"); 1012 inputs_visible_count++; 1013 } 1014 1015 } 1016 ); 1017 1018 inputs_invisible = inputs_invisible.trim(); 1019 inputs_visible = inputs_visible.trim(); 1020 1021 return { 1022 visible_fields : inputs_visible, 1023 visible_fields_count : inputs_visible_count, 1024 invisible_fields : inputs_invisible, 1025 invisible_fields_count : inputs_invisible_count, 1026 } 1027 1028} 1029 1030function apbct_visible_fields_set_cookie( visible_fields_collection ) 1031{ 1032 var collection = typeof visible_fields_collection === 'object' && visible_fields_collection !== null ? visible_fields_collection : {}; 1033 1034 ctSetCookie( 1035 [ 1036 { 1037 'name' : 'apbct_visible_fields', 1038 'value' : JSON.stringify(collection) 1039 } 1040 ] 1041 ) 1042} 1043 1044// Event token handler class. Get token and save it to the alternative sessions. 1045 1046class EventTokenHandler { 1047 1048 constructor(use_alt_cookies_option) { 1049 this.token = null; 1050 this.lsSavedFlagName = 'event_token_saved_to_alt_sessions'; 1051 this.lsEVentTokenName = 'bot_detector_event_token'; 1052 this.intervalValue = 1500; 1053 this.init(use_alt_cookies_option); 1054 } 1055 1056 init(use_alt_cookies_option){ 1057 if ('undefined' !== typeof use_alt_cookies_option && use_alt_cookies_option) { 1058 this.setNotSavedFlag(); 1059 this.startListenTokenLS(); 1060 } 1061 } 1062 1063 1064 setSavedFlag() 1065 { 1066 localStorage.setItem(this.lsSavedFlagName, '1'); 1067 } 1068 1069 setNotSavedFlag() 1070 { 1071 localStorage.setItem(this.lsSavedFlagName, '0'); 1072 } 1073 1074 isSaved() 1075 { 1076 let event_token_saved = localStorage.getItem(this.lsSavedFlagName); 1077 return event_token_saved !== null && event_token_saved !== undefined && event_token_saved === '1'; 1078 } 1079 1080 getEventToken() 1081 { 1082 let event_token = localStorage.getItem(this.lsEVentTokenName); 1083 try { 1084 event_token = event_token !== null ? JSON.parse(event_token) : false; 1085 } catch (e) { 1086 return false; 1087 } 1088 event_token = event_token.hasOwnProperty('value') ? event_token.value : false; 1089 if (typeof event_token === 'string' && event_token.length === 64) { 1090 return event_token; 1091 } 1092 return false; 1093 } 1094 1095 setEventTokenCookie() 1096 { 1097 if (typeof this.token === 'string' && this.token.length === 64) { 1098 ctSetCookie( 1099 [ 1100 { 1101 'name': 'apbct_event_token', 1102 'value': this.token 1103 } 1104 ] 1105 ) 1106 } 1107 } 1108 1109 stopListenTokenLS() 1110 { 1111 clearInterval(this.intervalID); 1112 } 1113 1114 startListenTokenLS() 1115 { 1116 this.intervalID = setInterval( this.intervalRun, this.intervalValue, this) 1117 } 1118 1119 intervalRun(handler) 1120 { 1121 if ( !handler.isSaved() ) { 1122 handler.token = handler.getEventToken(); 1123 if ( handler.token ) { 1124 handler.setEventTokenCookie(); 1125 handler.setSavedFlag(); 1126 handler.stopListenTokenLS(); 1127 } 1128 } 1129 } 1130} 1131 1132//Collect event token 1133new EventTokenHandler(ct_use_alt_cookies); 1134; 1135(function ($, undefined) { 1136 1137 'use strict'; 1138 1139 /** 1140   * Provides enhanced functionality for Pay Portal Paragraphs admin. 1141   * 1142   * @type {Drupal~behavior} 1143   * 1144   * @prop {Drupal~behaviorAttach} attach 1145   *  Adds administrative effects and enhancements for the various 1146 * Paragraphs components that act as the base for this module. 1147   */ 1148 Drupal.behaviors.payportal_admin = { 1149 attach: function (context, settings) { 1150 1151 var 1152 $settings = settings.payportal_admin, 1153 $keys = Object.keys($settings) 1154 ; 1155 1156 // The top level object literal is keyed by the deltas for 1157 // each Pay Portal paragraph instance. 1158 for (var i = 0, c = $keys.length; i < c; i++) { 1159 var $delta = $keys[i]; 1160 1161 // If an Add More set of elements is present for this delta... 1162 if ($settings[$delta]['payprovider_add_more'] !== undefined) { 1163 1164 // Update Add More button text based on the value 1165 // selected in the Add More select. 1166 $($settings[$delta]['payprovider_add_more']['select']).each(function () { 1167 var $this = this; 1168 1169 // Add event handler only once per element per behaviors attachment. 1170 $($this).once('payportal_admin_' + $delta).each(function () { 1171 1172 // Update button text when pay provider select option changes. 1173 $($this).on('change', function () { 1174 var $pattern = $settings[$delta]['payprovider_add_more']['pattern']; 1175 var $text = Drupal.t($pattern, {'@pp': this[this.selectedIndex].innerHTML}); 1176 $($settings[$delta]['payprovider_add_more']['button'], context) 1177 .prop('value', $text) 1178 .text($text); 1179 }); 1180 }); 1181 }); 1182 } 1183 } 1184 } 1185 }; 1186})(jQuery);; 1187/** 1188* DO NOT EDIT THIS FILE. 1189* See the following change record for more information, 1190* https://www.drupal.org/node/2815083 1191* @preserve 1192**/ 1193Drupal.debounce = function (func, wait, immediate) { 1194 var timeout; 1195 var result; 1196 return function () { 1197 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 1198 args[_key] = arguments[_key]; 1199 } 1200 var context = this; 1201 var later = function later() { 1202 timeout = null; 1203 if (!immediate) {
1204 result = func.apply(context, args); 1205 } 1206 }; 1207 var callNow = immediate && !timeout; 1208 clearTimeout(timeout); 1209 timeout = setTimeout(later, wait); 1210 if (callNow) { 1211 result = func.apply(context, args); 1212 } 1213 return result; 1214 }; 1215};; 1216/** 1217* DO NOT EDIT THIS FILE. 1218* See the following change record for more information, 1219* https://www.drupal.org/node/2815083 1220* @preserve 1221**/ 1222(function ($, Drupal, debounce) { 1223 $.fn.drupalGetSummary = function () { 1224 var callback = this.data('summaryCallback'); 1225 return this[0] && callback ? callback(this[0]).trim() : ''; 1226 }; 1227 $.fn.drupalSetSummary = function (callback) { 1228 var self = this; 1229 if (typeof callback !== 'function') { 1230 var val = callback; 1231 callback = function callback() { 1232 return val; 1233 }; 1234 } 1235 return this.data('summaryCallback', callback).off('formUpdated.summary').on('formUpdated.summary', function () { 1236 self.trigger('summaryUpdated'); 1237 }).trigger('summaryUpdated'); 1238 }; 1239 Drupal.behaviors.formSingleSubmit = { 1240 attach: function attach() { 1241 function onFormSubmit(e) { 1242 var $form = $(e.currentTarget); 1243 var formValues = $form.serialize(); 1244 var previousValues = $form.attr('data-drupal-form-submit-last'); 1245 if (previousValues === formValues) { 1246 e.preventDefault(); 1247 } else { 1248 $form.attr('data-drupal-form-submit-last', formValues); 1249 } 1250 } 1251 $(once('form-single-submit', 'body')).on('submit.singleSubmit', 'form:not([method~="GET"])', onFormSubmit); 1252 } 1253 }; 1254 function triggerFormUpdated(element) { 1255 $(element).trigger('formUpdated'); 1256 } 1257 function fieldsList(form) { 1258 return [].map.call(form.querySelectorAll('[name][id]'), function (el) { 1259 return el.id; 1260 }); 1261 } 1262 Drupal.behaviors.formUpdated = { 1263 attach: function attach(context) { 1264 var $context = $(context); 1265 var contextIsForm = $context.is('form'); 1266 var $forms = $(once('form-updated', contextIsForm ? $context : $context.find('form'))); 1267 var formFields; 1268 if ($forms.length) { 1269 $.makeArray($forms).forEach(function (form) { 1270 var events = 'change.formUpdated input.formUpdated '; 1271 var eventHandler = debounce(function (event) { 1272 triggerFormUpdated(event.target); 1273 }, 300); 1274 formFields = fieldsList(form).join(','); 1275 form.setAttribute('data-drupal-form-fields', formFields); 1276 $(form).on(events, eventHandler); 1277 }); 1278 } 1279 if (contextIsForm) { 1280 formFields = fieldsList(context).join(','); 1281 var currentFields = $(context).attr('data-drupal-form-fields'); 1282 if (formFields !== currentFields) { 1283 triggerFormUpdated(context); 1284 } 1285 } 1286 }, 1287 detach: function detach(context, settings, trigger) { 1288 var $context = $(context); 1289 var contextIsForm = $context.is('form'); 1290 if (trigger === 'unload') { 1291 once.remove('form-updated', contextIsForm ? $context : $context.find('form')).forEac
1291h(function (form) { 1292 form.removeAttribute('data-drupal-form-fields'); 1293 $(form).off('.formUpdated'); 1294 }); 1295 } 1296 } 1297 }; 1298 Drupal.behaviors.fillUserInfoFromBrowser = { 1299 attach: function attach(context, settings) { 1300 var userInfo = ['name', 'mail', 'homepage']; 1301 var $forms = $(once('user-info-from-browser', '[data-user-info-from-browser]')); 1302 if ($forms.length) { 1303 userInfo.forEach(function (info) { 1304 var $element = $forms.find("[name=".concat(info, "]")); 1305 var browserData = localStorage.getItem("Drupal.visitor.".concat(info)); 1306 if (!$element.length) { 1307 return; 1308 } 1309 var emptyValue = $element[0].value === ''; 1310 var defaultValue = $element.attr('data-drupal-default-value') === $element[0].value; 1311 if (browserData && (emptyValue || defaultValue)) { 1312 $element.each(function (index, item) { 1313 item.value = browserData; 1314 }); 1315 } 1316 }); 1317 } 1318 $forms.on('submit', function () { 1319 userInfo.forEach(function (info) { 1320 var $element = $forms.find("[name=".concat(info, "]")); 1321 if ($element.length) { 1322 localStorage.setItem("Drupal.visitor.".concat(info), $element[0].value); 1323 } 1324 }); 1325 }); 1326 } 1327 }; 1328 var handleFragmentLinkClickOrHashChange = function handleFragmentLinkClickOrHashChange(e) { 1329 var url; 1330 if (e.type === 'click') { 1331 url = e.currentTarget.location ? e.currentTarget.location : e.currentTarget; 1332 } else { 1333 url = window.location; 1334 } 1335 var hash = url.hash.substr(1); 1336 if (hash) { 1337 var $target = $("#".concat(hash)); 1338 $('body').trigger('formFragmentLinkClickOrHashChange', [$target]); 1339 setTimeout(function () { 1340 return $target.trigger('focus'); 1341 }, 300); 1342 } 1343 }; 1344 var debouncedHandleFragmentLinkClickOrHashChange = debounce(handleFragmentLinkClickOrHashChange, 300, true); 1345 $(window).on('hashchange.form-fragment', debouncedHandleFragmentLinkClickOrHashChange); 1346 $(document).on('click.form-fragment', 'a[href*="#"]', debouncedHandleFragmentLinkClickOrHashChange); 1347})(jQuery, Drupal, Drupal.debounce);; 1348/** 1349 * @file 1350 * Webform behaviors. 1351 */ 1352 1353(function ($, Drupal) { 1354 1355 'use strict'; 1356 1357 // Trigger Drupal's attaching of behaviors after the page is 1358 // completely loaded. 1359 // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button 1360 // @see https://stackoverflow.com/questions/20899274/how-to-refresh-page-on-back-button-click/20899422#20899422 1361 var isChrome = (/chrom(e|ium)/.test(window.navigator.userAgent.toLowerCase())); 1362 if (isChrome) { 1363 // Track back button in navigation. 1364 // @see https://stackoverflow.com/questions/37838430/detect-if-page-is-load-from-back-button 1365 var backButton = false; 1366 if (window.performance) { 1367 var navEntries = window.performance.getEntriesByType('navigation'); 1368 if (navEntries.length > 0 && navEntries[0].type === 'back_forward') { 1369 backButton = true; 1370 } 1371 else if (window.performance.navigation 1372 && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) { 1373 backButton = true; 1374 } 1375 } 1376 1377 // If the back button is pressed, delay Drupal's attaching of behaviors. 1378 if (backButton) { 1379 var attachBehaviors = Drupal.attachBehaviors; 1380 Drupal.attachBehaviors = function (context, settings) { 1381 setTimeout(function (context, settings) { 1382 attachBehaviors(context, settings); 1383 }, 300); 1384 }; 1385 } 1386 } 1387 1388})(jQuery, Drupal); 1389; 1390/** 1391* DO NOT EDIT THIS FILE. 1392* See the following change record for more information, 1393* https://www.drupal.org/node/2815083 1394* @preserve 1395**/ 1396(function ($, Drupal) { 1397 var states = { 1398 postponed: [] 1399 }; 1400 Drupal.states = states; 1401 function invert(a, invertState) { 1402 return invertState && typeof a !== 'undefined' ? !a : a; 1403 } 1404 function _compare2(a, b) { 1405 if (a === b) { 1406 return typeof a === 'undefined' ? a : true; 1407 } 1408 return typeof a === 'undefined' || typeof b === 'undefined'; 1409 } 1410 function ternary(a, b) { 1411 if (typeof a === 'undefined') { 1412 return b; 1413 } 1414 if (typeof b === 'undefined') { 1415 return a; 1416 } 1417 return a && b; 1418 } 1419 Drupal.behaviors.states = { 1420 attach: function attach(context, settings) { 1421 var $states = $(context).find('[data-drupal-states]'); 1422 var il = $states.length; 1423 var _loop = function _loop(i) { 1424 var config = JSON.parse($states[i].getAttribute('data-drupal-states')); 1425 Object.keys(config || {}
1425).forEach(function (state) { 1426 new states.Dependent({ 1427 element: $($states[i]), 1428 state: states.State.sanitize(state), 1429 constraints: config[state] 1430 }); 1431 }); 1432 }; 1433 for (var i = 0; i < il; i++) { 1434 _loop(i); 1435 } 1436 while (states.postponed.length) { 1437 states.postponed.shift()(); 1438 } 1439 } 1440 }; 1441 states.Dependent = function (args) { 1442 var _this = this; 1443 $.extend(this, { 1444 values: {}, 1445 oldValue: null 1446 }, args); 1447 this.dependees = this.getDependees(); 1448 Object.keys(this.dependees || {}).forEach(function (selector) { 1449 _this.initializeDependee(selector, _this.dependees[selector]); 1450 }); 1451 }; 1452 states.Dependent.comparisons = { 1453 RegExp: function RegExp(reference, value) { 1454 return reference.test(value); 1455 }, 1456 Function: function Function(reference, value) { 1457 return reference(value); 1458 }, 1459 Number: function Number(reference, value) { 1460 return typeof value === 'string' ? _compare2(reference.toString(), value) : _compare2(reference, value); 1461 } 1462 }; 1463 states.Dependent.prototype = { 1464 initializeDependee: function initializeDependee(selector, dependeeStates) { 1465 var _this2 = this; 1466 this.values[selector] = {}; 1467 Object.keys(dependeeStates).forEach(function (i) { 1468 var state = dependeeStates[i]; 1469 if ($.inArray(state, dependeeStates) === -1) { 1470 return; 1471 } 1472 state = states.State.sanitize(state); 1473 _this2.values[selector][state.name] = null; 1474 $(selector).on("state:".concat(state), { 1475 selector: selector, 1476 state: state 1477 }, function (e) { 1478 _this2.update(e.data.selector, e.data.state, e.value); 1479 }); 1480 new states.Trigger({ 1481 selector: selector, 1482 state: state 1483 }); 1484 }); 1485 }, 1486 compare: function compare(reference, selector, state) { 1487 var value = this.values[selector][state.name]; 1488 if (reference.constructor.name in states.Dependent.comparisons) { 1489 return states.Dependent.comparisons[reference.constructor.name](reference, value); 1490 } 1491 return _compare2(reference, value); 1492 }, 1493 update: function update(selector, state, value) { 1494 if (value !== this.values[selector][state.name]) { 1495 this.values[selector][state.name] = value; 1496 this.reevaluate(); 1497 } 1498 }, 1499 reevaluate: function reevaluate() { 1500 var value = this.verifyConstraints(this.constraints); 1501 if (value !== this.oldValue) { 1502 this.oldValue = value; 1503 value = invert(value, this.state.invert); 1504 this.element.trigger({ 1505 type: "state:".concat(this.state), 1506 value: value, 1507 trigger: true 1508 }); 1509 } 1510 }, 1511 verifyConstraints: function verifyConstraints(constraints, selector) { 1512 var result; 1513 if ($.isArray(constraints)) { 1514 var hasXor = $.inArray('xor', constraints) === -1; 1515 var len = constraints.length; 1516 for (var i = 0; i < len; i++) { 1517 if (constraints[i] !== 'xor') { 1518 var constraint = this.checkConstraints(constraints[i], selector, i); 1519 if (constraint && (hasXor || result)) { 1520 return hasXor; 1521 } 1522 result = result || constraint; 1523 } 1524 } 1525 } else if ($.isPlainObject(constraints)) { 1526 for (var n in constraints) { 1527 if (constraints.hasOwnProperty(n)) { 1528 result = ternary(result, this.checkConstraints(constraints[n], selector, n)); 1529 if (result === false) { 1530 return false; 1531 } 1532 } 1533 } 1534 } 1535 return result; 1536 }, 1537 checkConstraints: function checkConstraints(value, selector, state) { 1538 if (typeof state !== 'string' || /[0-9]/.test(state[0])) { 1539 state = null; 1540 } else if (typeof selector === 'undefined') { 1541 selector = state; 1542 state = null; 1543 } 1544 if (state !== null) { 1545 state = states.State.sanitize(state); 1546 return invert(this.compare(value, selector, state), state.invert); 1547 } 1548 return this.verifyConstraints(value, selector); 1549 }, 1550 getDependees: function getDependees() { 1551 var cache = {}; 1552 var _compare = this.compare; 1553 this.compare = function (reference, selector, state) { 1554 (cache[selector] || (cache[selector] = [])).push(state.name); 1555 }; 1556 this.verifyConstraints(this.constraints); 1557 this.compare = _compare; 1558 return cache; 1559 } 1560 }; 1561 states.Trigger = function (args) { 1562 $.extend(this, args); 1563 if (this.state in states.Trigger.states) { 1564 this.element = $(this.selector); 1565 if (!this.element.data("trigger:".concat(this.state))) { 1566 this.initialize(); 1567 } 1568 } 1569 }; 1570 states.Trigger.prototype = { 1571 initialize: function initialize() { 1572 var _this3 = this; 1573 var trigger = states.Trigger.states[this.state]; 1574 if (typeof trigger === 'function') { 1575 trigger.call(window, this.element); 1576 } else { 1577 Object.keys(trigger || {}
1577).forEach(function (event) { 1578 _this3.defaultTrigger(event, trigger[event]); 1579 }); 1580 } 1581 this.element.data("trigger:".concat(this.state), true); 1582 }, 1583 defaultTrigger: function defaultTrigger(event, valueFn) { 1584 var oldValue = valueFn.call(this.element); 1585 this.element.on(event, $.proxy(function (e) { 1586 var value = valueFn.call(this.element, e); 1587 if (oldValue !== value) { 1588 this.element.trigger({ 1589 type: "state:".concat(this.state), 1590 value: value, 1591 oldValue: oldValue 1592 }); 1593 oldValue = value; 1594 } 1595 }, this)); 1596 states.postponed.push($.proxy(function () { 1597 this.element.trigger({ 1598 type: "state:".concat(this.state), 1599 value: oldValue, 1600 oldValue: null 1601 }); 1602 }, this)); 1603 } 1604 }; 1605 states.Trigger.states = { 1606 empty: { 1607 keyup: function keyup() { 1608 return this.val() === ''; 1609 }, 1610 change: function change() { 1611 return this.val() === ''; 1612 } 1613 }, 1614 checked: { 1615 change: function change() { 1616 var checked = false; 1617 this.each(function () { 1618 checked = $(this).prop('checked'); 1619 return !checked; 1620 }); 1621 return checked; 1622 } 1623 }, 1624 value: { 1625 keyup: function keyup() { 1626 if (this.length > 1) { 1627 return this.filter(':checked').val() || false; 1628 } 1629 return this.val(); 1630 }, 1631 change: function change() { 1632 if (this.length > 1) { 1633 return this.filter(':checked').val() || false; 1634 } 1635 return this.val(); 1636 } 1637 }, 1638 collapsed: { 1639 collapsed: function collapsed(e) { 1640 return typeof e !== 'undefined' && 'value' in e ? e.value : !this.is('[open]'); 1641 } 1642 } 1643 }; 1644 states.State = function (state) { 1645 this.pristine = state; 1646 this.name = state; 1647 var process = true; 1648 do { 1649 while (this.name.charAt(0) === '!') { 1650 this.name = this.name.substring(1); 1651 this.invert = !this.invert; 1652 } 1653 if (this.name in states.State.aliases) { 1654 this.name = states.State.aliases[this.name]; 1655 } else { 1656 process = false; 1657 } 1658 } while (process); 1659 }; 1660 states.State.sanitize = function (state) { 1661 if (state instanceof states.State) { 1662 return state; 1663 } 1664 return new states.State(state); 1665 }; 1666 states.State.aliases = { 1667 enabled: '!disabled', 1668 invisible: '!visible', 1669 invalid: '!valid', 1670 untouched: '!touched', 1671 optional: '!required', 1672 filled: '!empty', 1673 unchecked: '!checked', 1674 irrelevant: '!relevant', 1675 expanded: '!collapsed', 1676 open: '!collapsed', 1677 closed: 'collapsed', 1678 readwrite: '!readonly' 1679 }; 1680 states.State.prototype = { 1681 invert: false, 1682 toString: function toString() { 1683 return this.name; 1684 } 1685 }; 1686 var $document = $(document); 1687 $document.on('state:disabled', function (e) { 1688 if (e.trigger) { 1689 $(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); 1690 } 1691 }); 1692 $document.on('state:required', function (e) { 1693 if (e.trigger) { 1694 if (e.value) { 1695 var label = "label".concat(e.target.id ? "[for=".concat(e.target.id, "]") : ''); 1696 var $label = $(e.target).attr({ 1697 required: 'required', 1698 'aria-required': 'true' 1699 }).closest('.js-form-item, .js-form-wrapper').find(label); 1700 if (!$label.hasClass('js-form-required').length) { 1701 $label.addClass('js-form-required form-required'); 1702 } 1703 } else { 1704 $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required'); 1705 } 1706 } 1707 }); 1708 $document.on('state:visible', function (e) { 1709 if (e.trigger) { 1710 $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggle(e.value); 1711 } 1712 }); 1713 $document.on('state:checked', function (e) { 1714 if (e.trigger) { 1715 $(e.target).closest('.js-form-item, .js-form-wrapper').find('input').prop('checked', e.value).trigger('change'); 1716 } 1717 }); 1718 $document.on('state:collapsed', function (e) { 1719 if (e.trigger) { 1720 if ($(e.target).is('[open]') === e.value) { 1721 $(e.target).find('> summary').trigger('click'); 1722 } 1723 } 1724 }); 1725})(jQuery, Drupal);; 1726/** 1727 * @file 1728 * JavaScript behaviors for custom webform #states. 1729 */ 1730 1731(function ($, Drupal, once) { 1732 1733 'use strict'; 1734 1735 Drupal.webform = Drupal.webform || {}; 1736 Drupal.webform.states = Drupal.webform.states || {}; 1737 Drupal.webform.states.slideDown = Drupal.webform.states.slideDown || {}; 1738 Drupal.webform.states.slideDown.duration = 'slow'; 1739 Drupal.webform.states.slideUp = Drupal.webform.states.slideUp || {}; 1740 Drupal.webform.states.slideUp.duration = 'fast'; 1741 1742 /* ************************************************************************ */ 1743 // jQuery functions. 1744 /* ************************************************************************ */ 1745 1746 /** 1747 * Check if an element has a specified data attribute. 1748 * 1749 * @param {string} data 1750 * The data attribute name. 1751 * 1752 * @return {boolean} 1753 * TRUE if an element has a specified data attribute. 1754 */ 1755 $.fn.hasData = function (data) { 1756 return (typeof this.data(data) !== 'undefined'); 1757 }; 1758 1759 /**
1760 * Check if element is within the webform or not. 1761 * 1762 * @return {boolean} 1763 * TRUE if element is within the webform. 1764 */ 1765 $.fn.isWebform = function () { 1766 return $(this).closest('form.webform-submission-form, form[id^="webform"], form[data-is-webform]').length ? true : false; 1767 }; 1768 1769 /** 1770 * Check if element is to be treated as a webform element. 1771 * 1772 * @return {boolean} 1773 * TRUE if element is to be treated as a webform element. 1774 */ 1775 $.fn.isWebformElement = function () { 1776 return ($(this).isWebform() || $(this).closest('[data-is-webform-element]').length) ? true : false; 1777 }; 1778 1779 /* ************************************************************************ */ 1780 // Trigger. 1781 /* ************************************************************************ */ 1782 1783 // The change event is triggered by cut-n-paste and select menus. 1784 // Issue #2445271: #states element empty check not triggered on mouse 1785 // based paste. 1786 // @see https://www.drupal.org/node/2445271 1787 Drupal.states.Trigger.states.empty.change = function change() { 1788 return this.val() === ''; 1789 }; 1790 1791 /* ************************************************************************ */ 1792 // Dependents. 1793 /* ************************************************************************ */ 1794 1795 // Apply solution included in #1962800 patch. 1796 // Issue #1962800: Form #states not working with literal integers as 1797 // values in IE11. 1798 // @see https://www.drupal.org/project/drupal/issues/1962800 1799 // @see https://www.drupal.org/files/issues/core-states-not-working-with-integers-ie11_1962800_46.patch 1800 // 1801 // This issue causes pattern, less than, and greater than support to break. 1802 // @see https://www.drupal.org/project/webform/issues/2981724 1803 var states = Drupal.states; 1804 Drupal.states.Dependent.prototype.compare = function compare(reference, selector, state) { 1805 var value = this.values[selector][state.name]; 1806 1807 var name = reference.constructor.name; 1808 if (!name) { 1809 name = $.type(reference); 1810 1811 name = name.charAt(0).toUpperCase() + name.slice(1); 1812 } 1813 if (name in states.Dependent.comparisons) { 1814 return states.Dependent.comparisons[name](reference, value); 1815 } 1816 1817 if (reference.constructor.name in states.Dependent.comparisons) { 1818 return states.Dependent.comparisons[reference.constructor.name](reference, value); 1819 } 1820 1821 return _compare2(reference, value); 1822 }; 1823 function _compare2(a, b) { 1824 if (a === b) { 1825 return typeof a === 'undefined' ? a : true; 1826 } 1827 1828 return typeof a === 'undefined' || typeof b === 'undefined'; 1829 } 1830 1831 // Adds pattern, less than, and greater than support to #state API. 1832 // @see http://drupalsun.com/julia-evans/2012/03/09/extending-form-api-states-regular-expressions 1833 Drupal.states.Dependent.comparisons.Object = function (reference, value) { 1834 if ('pattern' in reference) { 1835 return (new RegExp(reference['pattern'])).test(value); 1836 } 1837 else if ('!pattern' in reference) { 1838 return !((new RegExp(reference['!pattern'])).test(value)); 1839 } 1840 else if ('less' in reference) { 1841 return (value !== '' && parseFloat(reference['less']) > parseFloat(value)); 1842 } 1843 else if ('less_equal' in reference) { 1844 return (value !== '' && parseFloat(reference['less_equal']) >= parseFloat(value)); 1845 } 1846 else if ('greater' in reference) { 1847 return (value !== '' && parseFloat(reference['greater']) < parseFloat(value)); 1848 } 1849 else if ('greater_equal' in reference) { 1850 return (value !== '' && parseFloat(reference['greater_equal']) <= parseFloat(value)); 1851 } 1852 else if ('between' in reference || '!between' in reference) { 1853 if (value === '') { 1854 return false; 1855 } 1856 1857 var between = reference['between'] || reference['!between']; 1858 var betweenParts = between.split(':'); 1859 var greater = betweenParts[0]; 1860 var less = (typeof betweenParts[1] !== 'undefined') ? betweenParts[1] : null; 1861 var isGreaterThan = (greater === null || greater === '' || parseFloat(value) >= parseFloat(greater)); 1862 var isLessThan = (less === null || less === '' || parseFloat(value) <= parseFloat(less)); 1863 var result = (isGreaterThan && isLessThan); 1864 return (reference['!between']) ? !result : result; 1865 } 1866 else { 1867 return reference.indexOf(value) !== false; 1868 } 1869 }; 1870 1871 /* ************************************************************************ */ 1872 // States events. 1873 /* ************************************************************************ */ 1874 1875 var $document = $(document); 1876 1877 $document.on('state:required', function (e) { 1878 if (e.trigger && $(e.target).isWebformElement()) { 1879 var $target = $(e.target); 1880 // Fix #required file upload. 1881 // @see Issue #2860529: Conditional required File upload field don't work. 1882 toggleRequired($target.find('input[type="file"]'), e.value); 1883 1884 // Fix #required for radios and likert. 1885 // @see Issue #2856795: If radio buttons are required but not filled form is nevertheless submitted. 1886 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')) { 1887 $target.toggleClass('required', e.value); 1888 toggleRequired($target.find('input[type="radio"]'), e.value); 1889 } 1890 1891 // Fix #required for checkboxes. 1892 // @see Issue #2938414: Checkboxes don't support #states required. 1893 // @see checkboxRequiredhandler 1894 if ($target.is('.js-form-type-checkboxes, .js-form-type-webform-checkboxes-other, .js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other')) { 1895 $target.toggleClass('required', e.value); 1896 var $checkboxes = $target.find('input[type="checkbox"]'); 1897 if (e.value) { 1898 // Add event handler. 1899 $checkboxes.on('click', statesCheckboxesRequiredEventHandler); 1900 // Initialize and add required attribute. 1901 checkboxesRequired($target); 1902 } 1903 else { 1904 // Remove event handler. 1905 $checkboxes.off('click', statesCheckboxesRequiredEventHandler); 1906 // Remove required attribute. 1907 toggleRequired($checkboxes, false); 1908 } 1909 } 1910 1911 // Fix #required for tableselect. 1912 // @see Issue #3212581: Table select does not trigger client side validation 1913 if ($target.is('.js-webform-tableselect')) { 1914 $target.toggleClass('required', e.value); 1915 var isMultiple = $target.is('[multiple]'); 1916 if (isMultiple) { 1917 // Checkboxes. 1918 var $tbody = $target.find('tbody'); 1919 var $checkboxes = $tbody.find('input[type="checkbox"]'); 1920 copyRequireMessage($target, $checkboxes); 1921 if (e.value) { 1922 $checkboxes.on('click change', statesCheckboxesRequiredEventHandler); 1923 checkboxesRequired($tbody); 1924 } 1925 else { 1926 $checkboxes.off('click change ', statesCheckboxesRequiredEventHandler); 1927 toggleRequired($tbody, false); 1928 } 1929 } 1930 else { 1931 // Radios. 1932 var $radios = $target.find('input[type="radio"]'); 1933 copyRequireMessage($target, $radios); 1934 toggleRequired($radios, e.value); 1935 } 1936 } 1937 1938 // Fix required label for elements without the for attribute. 1939 // @see Issue #3145300: Conditional Visible Select Other not working. 1940 if ($target.is('.js-form-type-webform-select-other, .js-webform-type-webform-select-other')) { 1941 var $select = $target.find('select'); 1942 toggleRequired($select, e.value); 1943 copyRequireMessage($target, $select); 1944 } 1945 if ($target.find('> label:not([for])').length) { 1946 $target.find('> label').toggleClass('js-form-required form-required', e.value); 1947 } 1948 1949 // Fix required label for checkboxes and radios. 1950 // @see Issue #2938414: Checkboxes don't support #states required 1951 // @see Issue #2731991: Setting required on radios marks all options required. 1952 // @see Issue #2856315: Conditional Logic - Requiring Radios in a Fieldset. 1953 // Fix #required for fieldsets. 1954 // @see Issue #2977569: Hidden fieldsets that become visible with conditional logic cannot be made required. 1955 if ($target.is('.js-webform-type-radios, .js-webform-type-checkboxes, fieldset')) { 1956 $target.find('legend span.fieldset-legend:not(.visually-hidden),legend span.fieldset__label:not(.visually-hidden)').toggleClass('js-form-required form-required', e.value); 1957 } 1958 1959 // Issue #2986017: Fieldsets shouldn't have required attribute. 1960 if ($target.is('fieldset')) { 1961 $target.removeAttr('required aria-required'); 1962 } 1963 } 1964 }); 1965 1966 $document.on('state:checked', function (e) { 1967 if (e.trigger) { 1968 $(e.target).trigger('change'); 1969 } 1970 }); 1971 1972 $document.on('state:readonly', function (e) { 1973 if (e.trigger && $(e.target).isWebformElement()) { 1974 $(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); 1975 1976 // Trigger webform:readonly. 1977 $(e.target).trigger('webform:readonly') 1978 .find('select, input, textarea, button').trigger('webform:readonly'); 1979 } 1980 }); 1981 1982 $document.on('state:visible state:visible-slide', function (e) { 1983 if (e.trigger && $(e.target).isWebformElement()) { 1984 if (e.value) { 1985 $(':input', e.target).addBack().each(function () { 1986 restoreValueAndRequired(this); 1987 triggerEventHandlers(this); 1988 }); 1989 } 1990 else { 1991 // @see https://www.sitepoint.com/jquery-function-clear-form-data/ 1992 $(':input', e.target).addBack().each(function () { 1993 backupValueAndRequired(this); 1994 clearValueAndRequired(this); 1995 triggerEventHandlers(this); 1996 }); 1997 } 1998 } 1999 }); 2000 2001 $document.on('state:visible-slide', function (e) { 2002 if (e.trigger && $(e.target).isWebformElement()) { 2003 var effect = e.value ? 'slideDown' : 'slideUp'; 2004 var duration = Drupal.webform.states[effect].duration; 2005 $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper')[effect](duration); 2006 } 2007 }); 2008 Drupal.states.State.aliases['invisible-slide'] = '!visible-slide'; 2009 2010 $document.on('state:disabled', function (e) { 2011 if (e.trigger && $(e.target).isWebformElement()) { 2012 // Make sure disabled property is set before triggering webform:disabled. 2013 // Copied from: core/misc/states.js 2014 $(e.target) 2015 .prop('disabled', e.value) 2016 .closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value) 2017 .find('select, input, textarea, button').prop('disabled', e.value); 2018 2019 // Never disable hidden file[fids] because the existing values will 2020 // be completely lost when the webform is submitted. 2021 var fileElements = $(e.target) 2022 .find(':input[type="hidden"][name$="[fids]"]'); 2023 if (fileElements.length) { 2024 // Remove 'disabled' attribute from fieldset which will block 2025 // all disabled elements from being submitted. 2026 if ($(e.target).is('fieldset')) { 2027 $(e.target).prop('disabled', false); 2028 } 2029 fileElements.removeAttr('disabled'); 2030 } 2031 2032 // Trigger webform:disabled. 2033 $(e.target).trigger('webform:disabled') 2034 .find('select, input, textarea, button').trigger('webform:disabled'); 2035 } 2036 }); 2037 2038 /* ************************************************************************ */ 2039 // Behaviors. 2040 /* ************************************************************************ */ 2041 2042 /** 2043 * Adds HTML5 validation to required checkboxes. 2044 * 2045 * @type {Drupal~behavior} 2046 * 2047 * @see https://www.drupal.org/project/webform/issues/3068998 2048 */ 2049 Drupal.behaviors.webformCheckboxesRequired = { 2050 attach: function (context) { 2051 $(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)) 2052 .each(function () { 2053 var $element = $(this); 2054 $element.find('input[type="checkbox"]').on('click', statesCheckboxesRequiredEventHandler); 2055 setTimeout(function () {checkboxesRequired($element);}); 2056 }); 2057 } 2058 }; 2059 2060 /** 2061 * Adds HTML5 validation to required radios. 2062 * 2063 * @type {Drupal~behavior} 2064 * 2065 * @see https://www.drupal.org/project/webform/issues/2856795 2066 */ 2067 Drupal.behaviors.webformRadiosRequired = { 2068 attach: function (context) { 2069 $(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)) 2070 .each(function () { 2071 var $element = $(this); 2072 setTimeout(function () {radiosRequired($element);}); 2073 }); 2074 } 2075 }; 2076 2077 /** 2078 * Adds HTML5 validation to required table select. 2079 * 2080 * @type {Drupal~behavior} 2081 * 2082 * @see https://www.drupal.org/project/webform/issues/2856795 2083 */ 2084 Drupal.behaviors.webformTableSelectRequired = { 2085 attach: function (context) { 2086 $(once('webform-tableselect-required','.js-webform-tableselect.required', context)) 2087 .each(function () { 2088 var $element = $(this); 2089 var $tbody = $element.find('tbody'); 2090 var isMultiple = $element.is('[multiple]'); 2091 2092 if (isMultiple) { 2093 // Check all checkbox triggers checkbox 'change' event on 2094 // select and deselect all. 2095 // @see Drupal.tableSelect 2096 $tbody.find('input[type="checkbox"]').on('click change', function () { 2097 checkboxesRequired($tbody); 2098 }); 2099 } 2100 2101 setTimeout(function () { 2102 isMultiple ? checkboxesRequired($tbody) : radiosRequired($element); 2103 }); 2104 }); 2105 } 2106 }; 2107 2108 /** 2109 * Add HTML5 multiple checkboxes required validation. 2110 * 2111 * @param {jQuery} $element
2112 * An jQuery object containing HTML5 radios. 2113 * 2114 * @see https://stackoverflow.com/a/37825072/145846 2115 */ 2116 function checkboxesRequired($element) { 2117 var $firstCheckbox = $element.find('input[type="checkbox"]').first(); 2118 var isChecked = $element.find('input[type="checkbox"]').is(':checked'); 2119 toggleRequired($firstCheckbox, !isChecked); 2120 copyRequireMessage($element, $firstCheckbox); 2121 } 2122 2123 /** 2124 * Add HTML5 radios required validation. 2125 * 2126 * @param {jQuery} $element 2127 * An jQuery object containing HTML5 radios. 2128 * 2129 * @see https://www.drupal.org/project/webform/issues/2856795 2130 */ 2131 function radiosRequired($element) { 2132 var $radios = $element.find('input[type="radio"]'); 2133 var isRequired = $element.hasClass('required'); 2134 toggleRequired($radios, isRequired); 2135 copyRequireMessage($element, $radios); 2136 } 2137 2138 /* ************************************************************************ */ 2139 // Event handlers. 2140 /* ************************************************************************ */ 2141 2142 /** 2143 * Trigger #states API HTML5 multiple checkboxes required validation. 2144 * 2145 * @see https://stackoverflow.com/a/37825072/145846 2146 */ 2147 function statesCheckboxesRequiredEventHandler() { 2148 var $element = $(this).closest('.js-webform-type-checkboxes, .js-webform-type-webform-checkboxes-other'); 2149 checkboxesRequired($element); 2150 } 2151 2152 /** 2153 * Trigger an input's event handlers. 2154 * 2155 * @param {element} input 2156 * An input. 2157 */ 2158 function triggerEventHandlers(input) { 2159 var $input = $(input); 2160 var type = input.type; 2161 var tag = input.tagName.toLowerCase(); 2162 // Add 'webform.states' as extra parameter to event handlers. 2163 // @see Drupal.behaviors.webformUnsaved 2164 var extraParameters = ['webform.states']; 2165 if (type === 'checkbox' || type === 'radio') { 2166 $input 2167 .trigger('change', extraParameters) 2168 .trigger('blur', extraParameters); 2169 } 2170 else if (tag === 'select') { 2171 // Do not trigger the onchange event for Address element's country code 2172 // when it is initialized. 2173 // @see \Drupal\address\Element\Country 2174 if ($input.closest('.webform-type-address').length) { 2175 if (!$input.data('webform-states-address-initialized') 2176 && $input.attr('autocomplete') === 'country' 2177 && $input.val() === $input.find("option[selected]").attr('value')) { 2178 return; 2179 } 2180 $input.data('webform-states-address-initialized', true); 2181 } 2182 2183 $input 2184 .trigger('change', extraParameters) 2185 .trigger('blur', extraParameters); 2186 } 2187 else if (type !== 'submit' && type !== 'button' && type !== 'file') { 2188 // Make sure input mask is removed and then reset when value is restored. 2189 // @see https://www.drupal.org/project/webform/issues/3124155 2190 // @see https://www.drupal.org/project/webform/issues/3202795 2191 var hasInputMask = ($.fn.inputmask && $input.hasClass('js-webform-input-mask')); 2192 hasInputMask && $input.inputmask('remove'); 2193 2194 $input 2195 .trigger('input', extraParameters) 2196 .trigger('change', extraParameters) 2197 .trigger('keydown', extraParameters) 2198 .trigger('keyup', extraParameters) 2199 .trigger('blur', extraParameters); 2200 2201 hasInputMask && $input.inputmask(); 2202 } 2203 } 2204 2205 /* ************************************************************************ */ 2206 // Backup and restore value functions. 2207 /* ************************************************************************ */ 2208 2209 /** 2210 * Backup an input's current value and required attribute 2211 * 2212 * @param {element} input 2213 * An input. 2214 */ 2215 function backupValueAndRequired(input) { 2216 var $input = $(input); 2217 var type = input.type; 2218 var tag = input.tagName.toLowerCase(); // Normalize case. 2219 2220 // Backup required. 2221 if ($input.prop('required') && !$input.hasData('webform-required')) { 2222 $input.data('webform-required', true); 2223 } 2224 2225 // Backup value. 2226 if (!$input.hasData('webform-value')) { 2227 if (type === 'checkbox' || type === 'radio') { 2228 $input.data('webform-value', $input.prop('checked')); 2229 } 2230 else if (tag === 'select') { 2231 var values = []; 2232 $input.find('option:selected').each(function (i, option) { 2233 values[i] = option.value; 2234 }); 2235 $input.data('webform-value', values); 2236 } 2237 else if (type !== 'submit' && type !== 'button') { 2238 $input.data('webform-value', input.value); 2239 } 2240 } 2241 } 2242 2243 /** 2244 * Restore an input's value and required attribute. 2245 * 2246 * @param {element} input 2247 * An input. 2248 */ 2249 function restoreValueAndRequired(input) { 2250 var $input = $(input); 2251 2252 // Restore value. 2253 var value = $input.data('webform-value'); 2254 if (typeof value !== 'undefined') { 2255 var type = input.type; 2256 var tag = input.tagName.toLowerCase(); // Normalize case. 2257 2258 if (type === 'checkbox' || type === 'radio') { 2259 $input.prop('checked', value); 2260 } 2261 else if (tag === 'select') { 2262 $.each(value, function (i, option_value) { 2263 // Prevent "Syntax error, unrecognized expression" error by 2264 // escaping single quotes. 2265 // @see https://forum.jquery.com/topic/escape-characters-prior-to-using-selector 2266 option_value = option_value.replace(/'/g, "\\\'"); 2267 $input.find("option[value='" + option_value + "']").prop('selected', true); 2268 }); 2269 } 2270 else if (type !== 'submit' && type !== 'button') { 2271 input.value = value; 2272 } 2273 $input.removeData('webform-value'); 2274 } 2275 2276 // Restore required. 2277 var required = $input.data('webform-required'); 2278 if (typeof required !== 'undefined') { 2279 if (required) { 2280 $input.prop('required', true); 2281 } 2282 $input.removeData('webform-required'); 2283 } 2284 } 2285 2286 /** 2287 * Clear an input's value and required attributes. 2288 * 2289 * @param {element} input 2290 * An input. 2291 */ 2292 function clearValueAndRequired(input) { 2293 var $input = $(input); 2294 2295 // Check for #states no clear attribute.
2296 // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/ 2297 if ($input.closest('[data-webform-states-no-clear]').length) { 2298 return; 2299 } 2300 2301 // Clear value. 2302 var type = input.type; 2303 var tag = input.tagName.toLowerCase(); // Normalize case. 2304 if (type === 'checkbox' || type === 'radio') { 2305 $input.prop('checked', false); 2306 } 2307 else if (tag === 'select') { 2308 if ($input.find('option[value=""]').length) { 2309 $input.val(''); 2310 } 2311 else { 2312 input.selectedIndex = -1; 2313 } 2314 } 2315 else if (type !== 'submit' && type !== 'button') { 2316 input.value = (type === 'color') ? '#000000' : ''; 2317 } 2318 2319 // Clear required. 2320 $input.prop('required', false); 2321 } 2322 2323 /* ************************************************************************ */ 2324 // Helper functions. 2325 /* ************************************************************************ */ 2326 2327 /** 2328 * Toggle an input's required attributes. 2329 * 2330 * @param {element} $input 2331 * An input. 2332 * @param {boolean} required 2333 * Is input required. 2334 */ 2335 function toggleRequired($input, required) { 2336 var isCheckboxOrRadio = ($input.attr('type') === 'radio' || $input.attr('type') === 'checkbox'); 2337 if (required) { 2338 if (isCheckboxOrRadio) { 2339 $input.attr({'required': 'required'}); 2340 } 2341 else { 2342 $input.attr({'required': 'required', 'aria-required': 'true'}); 2343 } 2344 } 2345 else { 2346 if (isCheckboxOrRadio) { 2347 $input.removeAttr('required'); 2348 } 2349 else { 2350 $input.removeAttr('required aria-required'); 2351 } 2352 } 2353 } 2354 2355 /** 2356 * Copy the clientside_validation.module's message. 2357 * 2358 * @param {jQuery} $source 2359 * The source element. 2360 * @param {jQuery} $destination 2361 * The destination element. 2362 */ 2363 function copyRequireMessage($source, $destination) { 2364 if ($source.attr('data-msg-required')) { 2365 $destination.attr('data-msg-required', $source.attr('data-msg-required')); 2366 } 2367 } 2368 2369})(jQuery, Drupal, once); 2370; 2371/** 2372 * @file 2373 * JavaScript behaviors for webforms. 2374 */ 2375 2376(function ($, Drupal, once) { 2377 2378 'use strict'; 2379 2380 /** 2381 * Remove single submit event listener. 2382 * 2383 * @type {Drupal~behavior} 2384 * 2385 * @prop {Drupal~behaviorAttach} attach 2386 * Attaches the behavior for removing single submit event listener. 2387 * 2388 * @see Drupal.behaviors.formSingleSubmit 2389 */ 2390 Drupal.behaviors.webformRemoveFormSingleSubmit = { 2391 attach: function attach() { 2392 function onFormSubmit(e) { 2393 var $form = $(e.currentTarget); 2394 $form.removeAttr('data-drupal-form-submit-last'); 2395 } 2396 $(once('webform-single-submit', 'body')) 2397 .on('submit.singleSubmit', 'form.webform-remove-single-submit', onFormSubmit); 2398 } 2399 }; 2400 2401 /** 2402 * Prevent webform autosubmit on wizard pages. 2403 * 2404 * @type {Drupal~behavior} 2405 * 2406 * @prop {Drupal~behaviorAttach} attach 2407 * Attaches the behavior for disabling webform autosubmit. 2408 * Wizard pages need to be progressed with the Previous or Next buttons, 2409 * not by pressing Enter. 2410 */ 2411 Drupal.behaviors.webformDisableAutoSubmit = { 2412 attach: function (context) { 2413 // Not using context so that inputs loaded via Ajax will have autosubmit 2414 // disabled. 2415 // @see http://stackoverflow.com/questions/11235622/jquery-disable-form-submit-on-enter 2416 $(once('webform-disable-autosubmit', $('.js-webform-disable-autosubmit input').not(':button, :submit, :reset, :image, :file'))) 2417 .on('keyup keypress', function (e) { 2418 if (e.which === 13) { 2419 e.preventDefault(); 2420 return false; 2421 } 2422 }); 2423 } 2424 }; 2425 2426 /** 2427 * Custom required and pattern validation error messages. 2428 * 2429 * @type {Drupal~behavior} 2430 * 2431 * @prop {Drupal~behaviorAttach} attach 2432 * Attaches the behavior for the webform custom required and pattern 2433 * validation error messages. 2434 * 2435 * @see http://stackoverflow.com/questions/5272433/html5-form-required-attribute-set-custom-validation-message 2436 **/ 2437 Drupal.behaviors.webformRequiredError = { 2438 attach: function (context) { 2439 $(once('webform-required-error', $(context).find(':input[data-webform-required-error], :input[data-webform-pattern-error]'))) 2440 .on('invalid', function () { 2441 this.setCustomValidity(''); 2442 if (this.valid) { 2443 return; 2444 } 2445 2446 if (this.validity.patternMismatch && $(this).attr('data-webform-pattern-error')) { 2447 this.setCustomValidity($(this).attr('data-webform-pattern-error')); 2448 } 2449 else if (this.validity.valueMissing && $(this).attr('data-webform-required-error')) { 2450 this.setCustomValidity($(this).attr('data-webform-required-error')); 2451 } 2452 }) 2453 .on('input change', function () { 2454 // Find all related elements by name and reset custom validity. 2455 // This specifically applies to required radios and checkboxes. 2456 var name = $(this).attr('name'); 2457 $(this.form).find(':input[name="' + name + '"]').each(function () { 2458 this.setCustomValidity(''); 2459 }); 2460 }); 2461 } 2462 }; 2463 2464 // When #state:required is triggered we need to reset the target elements 2465 // custom validity. 2466 $(document).on('state:required', function (e) { 2467 $(e.target).filter(':input[data-webform-required-error]') 2468 .each(function () {this.setCustomValidity('');}); 2469 }); 2470 2471})(jQuery, Drupal, once); 2472; 2473/** 2474 * @file 2475 * JavaScript behaviors for details element. 2476 */ 2477 2478(function ($, Drupal, once) { 2479 2480 'use strict'; 2481 2482 // Determine if local storage exists and is enabled. 2483 // This approach is copied from Modernizr. 2484 // @see https://github.com/Modernizr/Modernizr/blob/c56fb8b09515f629806ca44742932902ac145302/modernizr.js#L696-731 2485 var hasLocalStorage = (function () { 2486 try { 2487 localStorage.setItem('webform', 'webform'); 2488 localStorage.removeItem('webform'); 2489 return true; 2490 } 2491 catch (e) { 2492 return false;
2493 } 2494 }()); 2495 2496 /** 2497 * Attach handler to save details open/close state. 2498 * 2499 * @type {Drupal~behavior} 2500 */ 2501 Drupal.behaviors.webformDetailsSave = { 2502 attach: function (context) { 2503 if (!hasLocalStorage) { 2504 return; 2505 } 2506 2507 // Summary click event handler. 2508 $(once('webform-details-summary-save', 'details > summary', context)).on('click', function () { 2509 var $details = $(this).parent(); 2510 2511 // @see https://css-tricks.com/snippets/jquery/make-an-jquery-hasattr/ 2512 if ($details[0].hasAttribute('data-webform-details-nosave')) { 2513 return; 2514 } 2515 2516 var name = Drupal.webformDetailsSaveGetName($details); 2517 if (!name) { 2518 return; 2519 } 2520 2521 var open = ($details.attr('open') !== 'open') ? '1' : '0'; 2522 localStorage.setItem(name, open); 2523 }); 2524 2525 // Initialize details open state via local storage. 2526 $(once('webform-details-save', 'details', context)).each(function () { 2527 var $details = $(this); 2528 2529 var name = Drupal.webformDetailsSaveGetName($details); 2530 if (!name) { 2531 return; 2532 } 2533 2534 var open = localStorage.getItem(name); 2535 if (open === null) { 2536 return; 2537 } 2538 2539 if (open === '1') { 2540 $details.attr('open', 'open'); 2541 } 2542 else { 2543 $details.removeAttr('open'); 2544 } 2545 }); 2546 } 2547 2548 }; 2549 2550 /** 2551 * Get the name used to store the state of details element. 2552 * 2553 * @param {jQuery} $details 2554 * A details element. 2555 * 2556 * @return {string} 2557 * The name used to store the state of details element. 2558 */ 2559 Drupal.webformDetailsSaveGetName = function ($details) { 2560 if (!hasLocalStorage) { 2561 return ''; 2562 } 2563 2564 // Ignore details that are vertical tabs pane. 2565 if ($details.hasClass('vertical-tabs__pane')) { 2566 return ''; 2567 } 2568 2569 // Any details element not included a webform must have define its own id. 2570 var webformId = $details.attr('data-webform-element-id'); 2571 if (webformId) { 2572 return 'Drupal.webform.' + webformId.replace('--', '.'); 2573 } 2574 2575 var detailsId = $details.attr('id'); 2576 if (!detailsId) { 2577 return ''; 2578 } 2579 2580 var $form = $details.parents('form'); 2581 if (!$form.length || !$form.attr('id')) { 2582 return ''; 2583 } 2584 2585 var formId = $form.attr('id'); 2586 if (!formId) { 2587 return ''; 2588 } 2589 2590 // ISSUE: When Drupal renders a webform in a modal dialog it appends a unique 2591 // identifier to webform ids and details ids. (i.e. my-form--FeSFISegTUI) 2592 // WORKAROUND: Remove the unique id that delimited using double dashes. 2593 formId = formId.replace(/--.+?$/, '').replace(/-/g, '_'); 2594 detailsId = detailsId.replace(/--.+?$/, '').replace(/-/g, '_'); 2595 return 'Drupal.webform.' + formId + '.' + detailsId; 2596 }; 2597 2598})(jQuery, Drupal, once); 2599; 2600/** 2601* DO NOT EDIT THIS FILE. 2602* See the following change record for more information, 2603* https://www.drupal.org/node/2815083 2604* @preserve 2605**/ 2606(function (Drupal, debounce) { 2607 var liveElement; 2608 var announcements = []; 2609 Drupal.behaviors.drupalAnnounce = { 2610 attach: function attach(context) { 2611 if (!liveElement) { 2612 liveElement = document.createElement('div'); 2613 liveElement.id = 'drupal-live-announce'; 2614 liveElement.className = 'visually-hidden'; 2615 liveElement.setAttribute('aria-live', 'polite'); 2616 liveElement.setAttribute('aria-busy', 'false'); 2617 document.body.appendChild(liveElement); 2618 } 2619 } 2620 }; 2621 function announce() { 2622 var text = []; 2623 var priority = 'polite'; 2624 var announcement; 2625 var il = announcements.length; 2626 for (var i = 0; i < il; i++) { 2627 announcement = announcements.pop(); 2628 text.unshift(announcement.text); 2629 if (announcement.priority === 'assertive') { 2630 priority = 'assertive'; 2631 } 2632 } 2633 if (text.length) { 2634 liveElement.innerHTML = ''; 2635 liveElement.setAttribute('aria-busy', 'true'); 2636 liveElement.setAttribute('aria-live', priority); 2637 liveElement.innerHTML = text.join('\n'); 2638 liveElement.setAttribute('aria-busy', 'false'); 2639 } 2640 } 2641 Drupal.announce = function (text, priority) { 2642 announcements.push({ 2643 text: text, 2644 priority: priority 2645 }); 2646 return debounce(announce, 200)(); 2647 }; 2648})(Drupal, Drupal.debounce);; 2649/** 2650 * @file 2651 * JavaScript behaviors for details element. 2652 */ 2653 2654(function ($, Drupal, once) { 2655 2656 'use strict'; 2657 2658 Drupal.webform = Drupal.webform || {}; 2659 Drupal.webform.detailsToggle = Drupal.webform.detailsToggle || {}; 2660 Drupal.webform.detailsToggle.options = Drupal.webform.detailsToggle.options || {}; 2661 2662 /** 2663 * Attach handler to toggle details open/close state. 2664 * 2665 * @type {Drupal~behavior} 2666 */ 2667 Drupal.behaviors.webformDetailsToggle = { 2668 attach: function (context) { 2669 $(once('webform-details-toggle', '.js-webform-details-toggle', context)).each(function () { 2670 var $form = $(this); 2671 var $tabs = $form.find('.webform-tabs'); 2672 2673 // Get only the main details elements and ignore all nested details. 2674 var selector = ($tabs.length) ? '.webform-tab' : '.js-webform-details-toggle, .webform-elements'; 2675 var $details = $form.find('details').filter(function () { 2676 var $parents = $(this).parentsUntil(selector); 2677 return ($parents.find('details').length === 0); 2678 }); 2679 2680 // Toggle is only useful when there are two or more details elements. 2681 if ($details.length < 2) { 2682 return; 2683 } 2684 2685 var options = $.extend({ 2686 button: '<button type="button" class="webform-details-toggle-state"></button>' 2687 }, Drupal.webform.detailsToggle.options); 2688 2689 // Create toggle buttons. 2690 var $toggle = $(options.button) 2691 .attr('title', Drupal.t('Toggle details widget state.')) 2692 .on('click', function (e) { 2693 // Get details that are not vertical tabs pane. 2694 var $details = $form.find('details:not(.vertical-tabs__pane)'); 2695 var open; 2696 if (Drupal.webform.detailsToggle.isFormDetailsOpen($form)) { 2697 $details.removeAttr('open'); 2698 open = 0; 2699 } 2700 else { 2701 $details.attr('open', 'open'); 2702 open = 1; 2703 } 2704 Drupal.webform.detailsToggle.setDetailsToggleLabel($form); 2705 2706 // Set the saved states for all the details elements. 2707 // @see webform.element.details.save.js 2708 if (Drupal.webformDetailsSaveGetName) { 2709 $details.each(function () { 2710 // Note: Drupal.webformDetailsSaveGetName checks if localStorage 2711 // exists and is enabled. 2712 // @see webform.element.details.save.js 2713 var name = Drupal.webformDetailsSaveGetName($(this)); 2714 if (name) {
2715 localStorage.setItem(name, open); 2716 } 2717 }); 2718 } 2719 }) 2720 .wrap('<div class="webform-details-toggle-state-wrapper"></div>') 2721 .parent(); 2722 2723 if ($tabs.length) { 2724 // Add toggle state before the tabs. 2725 $tabs.find('.item-list:first-child').eq(0).before($toggle); 2726 } 2727 else { 2728 // Add toggle state link to first details element. 2729 $details.eq(0).before($toggle); 2730 } 2731 2732 Drupal.webform.detailsToggle.setDetailsToggleLabel($form); 2733 }); 2734 } 2735 }; 2736 2737 /** 2738 * Determine if a webform's details are all opened. 2739 * 2740 * @param {jQuery} $form 2741 * A webform. 2742 * 2743 * @return {boolean} 2744 * TRUE if a webform's details are all opened. 2745 */ 2746 Drupal.webform.detailsToggle.isFormDetailsOpen = function ($form) { 2747 return ($form.find('details[open]').length === $form.find('details').length); 2748 }; 2749 2750 /** 2751 * Set a webform's details toggle state widget label. 2752 * 2753 * @param {jQuery} $form 2754 * A webform. 2755 */ 2756 Drupal.webform.detailsToggle.setDetailsToggleLabel = function ($form) { 2757 var isOpen = Drupal.webform.detailsToggle.isFormDetailsOpen($form); 2758 2759 var label = (isOpen) ? Drupal.t('Collapse all') : Drupal.t('Expand all'); 2760 $form.find('.webform-details-toggle-state').html(label); 2761 2762 var text = (isOpen) ? Drupal.t('All details have been expanded.') : Drupal.t('All details have been collapsed.'); 2763 Drupal.announce(text); 2764 }; 2765 2766})(jQuery, Drupal, once); 2767; 2768/** 2769 * @file 2770 * JavaScript behaviors for message element integration. 2771 */ 2772 2773(function ($, Drupal, once) { 2774 2775 'use strict'; 2776 2777 // Determine if local storage exists and is enabled. 2778 // This approach is copied from Modernizr. 2779 // @see https://github.com/Modernizr/Modernizr/blob/c56fb8b09515f629806ca44742932902ac145302/modernizr.js#L696-731 2780 var hasLocalStorage = (function () { 2781 try { 2782 localStorage.setItem('webform', 'webform'); 2783 localStorage.removeItem('webform'); 2784 return true; 2785 } 2786 catch (e) { 2787 return false; 2788 } 2789 }()); 2790 2791 // Determine if session storage exists and is enabled. 2792 // This approach is copied from Modernizr. 2793 // @see https://github.com/Modernizr/Modernizr/blob/c56fb8b09515f629806ca44742932902ac145302/modernizr.js#L696-731 2794 var hasSessionStorage = (function () { 2795 try { 2796 sessionStorage.setItem('webform', 'webform'); 2797 sessionStorage.removeItem('webform'); 2798 return true; 2799 } 2800 catch (e) { 2801 return false; 2802 } 2803 }()); 2804 2805 /** 2806 * Behavior for handler message close. 2807 * 2808 * @type {Drupal~behavior} 2809 */ 2810 Drupal.behaviors.webformMessageClose = { 2811 attach: function (context) { 2812 $(once('webform-message--close', '.js-webform-message--close', context)).each(function () { 2813 var $element = $(this); 2814 2815 var id = $element.attr('data-message-id'); 2816 var storage = $element.attr('data-message-storage'); 2817 var effect = $element.attr('data-message-close-effect') || 'hide'; 2818 switch (effect) { 2819 case 'slide': effect = 'slideUp'; break; 2820 2821 case 'fade': effect = 'fadeOut'; break; 2822 } 2823 2824 // Check storage status. 2825 if (isClosed($element, storage, id)) { 2826 return; 2827 } 2828 2829 // Only show element if it's style is not set to 'display: none' 2830 // and it is not hidden via .js-webform-states-hidden. 2831 if ($element.attr('style') !== 'display: none;' && !$element.hasClass('js-webform-states-hidden')) { 2832 $element.show(); 2833 } 2834 2835 $element.find('.js-webform-message__link').on('click', function (event) { 2836 $element[effect](); 2837 setClosed($element, storage, id); 2838 $element.trigger('close'); 2839 event.preventDefault(); 2840 }); 2841 }); 2842 } 2843 }; 2844 2845 function isClosed($element, storage, id) { 2846 if (!id || !storage) { 2847 return false; 2848 } 2849 2850 switch (storage) { 2851 case 'local': 2852 if (hasLocalStorage) { 2853 return localStorage.getItem('Drupal.webform.message.' + id) || false; 2854 } 2855 return false; 2856 2857 case 'session': 2858 if (hasSessionStorage) { 2859 return sessionStorage.getItem('Drupal.webform.message.' + id) || false; 2860 } 2861 return false;
2862 2863 default: 2864 return false; 2865 } 2866 } 2867 2868 function setClosed($element, storage, id) { 2869 if (!id || !storage) { 2870 return; 2871 } 2872 2873 switch (storage) { 2874 case 'local': 2875 if (hasLocalStorage) { 2876 localStorage.setItem('Drupal.webform.message.' + id, true); 2877 } 2878 break; 2879 2880 case 'session': 2881 if (hasSessionStorage) { 2882 sessionStorage.setItem('Drupal.webform.message.' + id, true); 2883 } 2884 break; 2885 2886 case 'user': 2887 case 'state': 2888 case 'custom': 2889 $.get($element.find('.js-webform-message__link').attr('href')); 2890 return true; 2891 } 2892 } 2893 2894})(jQuery, Drupal, once); 2895; 2896/** 2897 * @file 2898 * JavaScript behaviors for details element. 2899 */ 2900 2901(function ($, Drupal) { 2902 2903 'use strict'; 2904 2905 /** 2906 * Attach handler to details with invalid inputs. 2907 * 2908 * @type {Drupal~behavior} 2909 */ 2910 Drupal.behaviors.webformDetailsInvalid = { 2911 attach: function (context) { 2912 $('details :input', context).on('invalid', function () { 2913 $(this).parents('details:not([open])').children('summary').trigger('click'); 2914 2915 // Synd details toggle label. 2916 if (Drupal.webform && Drupal.webform.detailsToggle) { 2917 Drupal.webform.detailsToggle.setDetailsToggleLabel($(this.form)); 2918 } 2919 }); 2920 } 2921 }; 2922 2923})(jQuery, Drupal); 2924; 2925/** 2926* DO NOT EDIT THIS FILE. 2927* See the following change record for more information, 2928* https://www.drupal.org/node/2815083 2929* @preserve 2930**/ 2931(function ($, Drupal) { 2932 function DetailsSummarizedContent(node) { 2933 this.$node = $(node); 2934 this.setupSummary(); 2935 } 2936 $.extend(DetailsSummarizedContent, { 2937 instances: [] 2938 }); 2939 $.extend(DetailsSummarizedContent.prototype, { 2940 setupSummary: function setupSummary() { 2941 this.$detailsSummarizedContentWrapper = $(Drupal.theme('detailsSummarizedContentWrapper')); 2942 this.$node.on('summaryUpdated', $.proxy(this.onSummaryUpdated, this)).trigger('summaryUpdated').find('> summary').append(this.$detailsSummarizedContentWrapper); 2943 }, 2944 onSummaryUpdated: function onSummaryUpdated() { 2945 var text = this.$node.drupalGetSummary(); 2946 this.$detailsSummarizedContentWrapper.html(Drupal.theme('detailsSummarizedContentText', text)); 2947 } 2948 }); 2949 Drupal.behaviors.detailsSummary = { 2950 attach: function attach(context) { 2951 DetailsSummarizedContent.instances = DetailsSummarizedContent.instances.concat(once('details', 'details', context).map(function (details) { 2952 return new DetailsSummarizedContent(details); 2953 })); 2954 } 2955 }; 2956 Drupal.DetailsSummarizedContent = DetailsSummarizedContent; 2957 Drupal.theme.detailsSummarizedContentWrapper = function () { 2958 return "<span class=\"summary\"></span>"; 2959 }; 2960 Drupal.theme.detailsSummarizedContentText = function (text) { 2961 return text ? " (".concat(text, ")") : ''; 2962 }; 2963})(jQuery, Drupal);; 2964/** 2965* DO NOT EDIT THIS FILE. 2966* See the following change record for more information, 2967* https://www.drupal.org/node/2815083 2968* @preserve 2969**/ 2970(function ($, Drupal) { 2971 Drupal.behaviors.detailsAria = { 2972 attach: function attach() { 2973 $(once('detailsAria', 'body')).on('click.detailsAria', 'summary', function (event) { 2974 var $summary = $(event.currentTarget); 2975 var open = $(event.currentTarget.parentNode).attr('open') === 'open' ? 'false' : 'true'; 2976 $summary.attr({ 2977 'aria-expanded': open, 2978 'aria-pressed': open 2979 }); 2980 }); 2981 } 2982 }; 2983})(jQuery, Drupal);; 2984/** 2985 * @file 2986 * Polyfill for HTML5 details elements. 2987 */ 2988 2989(function ($, Modernizr, Drupal) { 2990 2991 'use strict'; 2992 2993 /** 2994 * The collapsible details object represents a single details element. 2995 * 2996 * @constructor Drupal.CollapsibleDetails 2997 * 2998 * @param {HTMLElement} node 2999 * The details element. 3000 */ 3001 function CollapsibleDetails(node) { 3002 this.$node = $(node);
3003 this.$node.data('.js-details', this); 3004 // Expand details if there are errors inside, or if it contains an 3005 // element that is targeted by the URI fragment identifier. 3006 var anchor = location.hash && location.hash !== '#' ? ', ' + location.hash : ''; 3007 if (this.$node.find('.error' + anchor).length) { 3008 this.$node.attr('open', true); 3009 } 3010 // Initialize and setup the summary, 3011 this.setupSummary(); 3012 // Initialize and setup the legend. 3013 this.setupLegend(); 3014 } 3015 3016 $.extend(CollapsibleDetails, /** @lends Drupal.CollapsibleDetails */{ 3017 3018 /** 3019 * Holds references to instantiated CollapsibleDetails objects. 3020 * 3021 * @type {Array.<Drupal.CollapsibleDetails>} 3022 */ 3023 instances: [] 3024 }); 3025 3026 $.extend(CollapsibleDetails.prototype, /** @lends Drupal.CollapsibleDetails# */{ 3027 3028 /** 3029 * Initialize and setup summary events and markup. 3030 * 3031 * @fires event:summaryUpdated 3032 * 3033 * @listens event:summaryUpdated 3034 */ 3035 setupSummary: function () { 3036 this.$summary = $('<span class="summary"></span>'); 3037 this.$node 3038 .on('summaryUpdated', $.proxy(this.onSummaryUpdated, this)) 3039 .trigger('summaryUpdated'); 3040 }, 3041 3042 /** 3043 * Initialize and setup legend markup. 3044 */ 3045 setupLegend: function () { 3046 // Turn the summary into a clickable link. 3047 var $legend = this.$node.find('> summary'); 3048 3049 $('<span class="js-details-fallback-text visually-hidden"></span>') 3050 .append(this.$node.attr('open') ? Drupal.t('Hide') : Drupal.t('Show')) 3051 .prependTo($legend) 3052 .after(document.createTextNode(' ')); 3053 3054 // .wrapInner() does not retain bound events. 3055 $('<a class="details__fallback-link"></a>') 3056 .attr('href', '#' + this.$node.attr('id')) 3057 .prepend($legend.contents()) 3058 .appendTo($legend); 3059 3060 $legend 3061 .append(this.$summary) 3062 .on('click', $.proxy(this.onLegendClick, this)); 3063 }, 3064 3065 /** 3066 * Handle legend clicks. 3067 * 3068 * @param {jQuery.Event} e 3069 * The event triggered. 3070 */ 3071 onLegendClick: function (e) { 3072 this.toggle(); 3073 e.preventDefault(); 3074 }, 3075 3076 /** 3077 * Update summary. 3078 */ 3079 onSummaryUpdated: function () { 3080 var text = $.trim(this.$node.drupalGetSummary()); 3081 this.$summary.html(text ? ' (' + text + ')' : ''); 3082 }, 3083 3084 /** 3085 * Toggle the visibility of a details element using smooth animations. 3086 */ 3087 toggle: function () { 3088 var isOpen = !!this.$node.attr('open'); 3089 var $summaryPrefix = this.$node.find('> summary .js-details-fallback-text'); 3090 if (isOpen) { 3091 $summaryPrefix.html(Drupal.t('Show')); 3092 } 3093 else { 3094 $summaryPrefix.html(Drupal.t('Hide')); 3095 } 3096 // Delay setting the attribute to emulate chrome behavior and make 3097 // details-aria.js work as expected with this polyfill. 3098 setTimeout(function () { 3099 this.$node.attr('open', !isOpen); 3100 }.bind(this), 0); 3101 } 3102 }); 3103 3104 /** 3105 * Polyfill HTML5 details element. 3106 * 3107 * @type {Drupal~behavior} 3108 * 3109 * @prop {Drupal~behaviorAttach} attach 3110 * Attaches behavior for the details element. 3111 */ 3112 Drupal.behaviors.collapse = { 3113 attach: function (context) { 3114 if (Modernizr.details) { 3115 return; 3116 } 3117 var $collapsibleDetails = $(context).find('details').once('collapse').addClass('collapse-processed'); 3118 if ($collapsibleDetails.length) { 3119 for (var i = 0; i < $collapsibleDetails.length; i++) { 3120 CollapsibleDetails.instances.push(new CollapsibleDetails($collapsibleDetails[i])); 3121 } 3122 } 3123 } 3124 }; 3125 3126 // Expose constructor in the public space. 3127 Drupal.CollapsibleDetails = CollapsibleDetails; 3128 3129})(jQuery, Modernizr, Drupal); 3130; 3131/** 3132 * @file 3133 * JavaScript behaviors for options elements. 3134 */ 3135 3136(function ($, Drupal) { 3137 3138 'use strict'; 3139 3140 /** 3141 * Attach handlers to options buttons element. 3142 * 3143 * @type {Drupal~behavior} 3144 */ 3145 Drupal.behaviors.webformOptionsButtons = { 3146 attach: function (context) { 3147 // Place <input> inside of <label> before the label. 3148 $(context).find('label.webform-options-display-buttons-label > input[type="checkbox"], label.webform-options-display-buttons-label > input[type="radio"]').each(function () { 3149 var $input = $(this); 3150 var $label = $input.parent(); 3151 $input.detach().insertBefore($label); 3152 }); 3153 } 3154 }; 3155 3156})(jQuery, Drupal); 3157; 3158/** 3159 * @file 3160 * JavaScript behaviors for select menu. 3161 */ 3162 3163(function ($, Drupal, once) { 3164 3165 'use strict'; 3166 3167 /** 3168 * Disable select menu options using JavaScript. 3169 * 3170 * @type {Drupal~behavior} 3171 */ 3172 Drupal.behaviors.webformSelectOptionsDisabled = { 3173 attach: function (context) { 3174 $(once('webform-select-options-disabled', 'select[data-webform-select-options-disabled]', context)).each(function () { 3175 var $select = $(this); 3176 var disabled = $select.attr('data-webform-select-options-disabled').split(/\s*,\s*/); 3177 $select.find('option').filter(function isDisabled() { 3178 return ($.inArray(this.value, disabled) !== -1); 3179 }).attr('disabled', 'disabled'); 3180 }); 3181 } 3182 }; 3183 3184})(jQuery, Drupal, once); 3185; 3186/** 3187 * @file 3188 * JavaScript behaviors for checkboxes. 3189 */ 3190 3191(function ($, Drupal, once) { 3192 3193 'use strict'; 3194 3195 /** 3196 * Adds check all or none checkboxes support. 3197 * 3198 * @type {Drupal~behavior} 3199 * 3200 * @see https://www.drupal.org/project/webform/issues/3068998 3201 */ 3202 Drupal.behaviors.webformCheckboxesAllorNone = { 3203 attach: function (context) { 3204 $(once('webform-checkboxes-all-or-none', '[data-options-all], [data-options-none]', context)) 3205 .each(function () { 3206 var $element = $(this); 3207 3208 var options_all_value = $element.data('options-all'); 3209 var options_none_value = $element.data('options-none'); 3210 3211 // Get all checkboxes. 3212 var $checkboxes = $element.find('input[type="checkbox"]'); 3213 3214 // Get all options/checkboxes. 3215 var $options = $checkboxes 3216 .not('[value="' + options_all_value + '"]') 3217 .not('[value="' + options_none_value + '"]'); 3218 3219 // Get options all and none checkboxes. 3220 var $options_all = $element 3221 .find(':checkbox[value="' + options_all_value + '"]'); 3222 var $options_none = $element 3223 .find(':checkbox[value="' + options_none_value + '"]'); 3224 3225 // All of the above. 3226 if ($options_all.length) { 3227 $options_all.on('click', toggleCheckAllEventHandler); 3228 if ($options_all.prop('checked')) { 3229 toggleCheckAllEventHandler(); 3230 } 3231 } 3232 3233 // None of the above. 3234 if ($options_none.length) { 3235 $options_none.on('click', toggleCheckNoneEventHandler); 3236 toggleCheckNoneEventHandler(); 3237 } 3238 3239 $options.on('click', toggleCheckboxesEventHandler); 3240 toggleCheckboxesEventHandler(); 3241 3242 /** 3243 * Toggle check all checkbox checked state. 3244 */ 3245 function toggleCheckAllEventHandler() { 3246 if ($options_all.prop('checked')) { 3247 // Uncheck options none. 3248 if ($options_none.is(':checked')) { 3249 $options_none 3250 .prop('checked', false) 3251 .trigger('change', ['webform.states']); 3252 } 3253 // Check check all unchecked options. 3254 $options.not(':checked') 3255 .prop('checked', true) 3256 .trigger('change', ['webform.states']); 3257 } 3258 else { 3259 // Check uncheck all checked options. 3260 $options.filter(':checked') 3261 .prop('checked', false) 3262 .trigger('change', ['webform.states']); 3263 } 3264 } 3265 3266 /** 3267 * Toggle check none checkbox checked state. 3268 */ 3269 function toggleCheckNoneEventHandler() { 3270 if ($options_none.prop('checked')) { 3271 $checkboxes 3272 .not('[value="' + options_none_value + '"]') 3273 .filter(':checked') 3274 .prop('checked', false) 3275 .trigger('change', ['webform.states']); 3276 } 3277 } 3278 3279 /** 3280 * Toggle check all checkbox checked state. 3281 */ 3282 function toggleCheckboxesEventHandler() { 3283 var isAllChecked = ($options.filter(':checked').length === $options.length); 3284 if ($options_all.length 3285 && $options_all.prop('checked') !== isAllChecked) { 3286 $options_all 3287 .prop('checked', isAllChecked) 3288 .trigger('change', ['webform.states']); 3289 } 3290 var isOneChecked = $options.is(':checked'); 3291 if ($options_none.length 3292 && isOneChecked) { 3293 $options_none 3294 .prop('checked', false) 3295 .trigger('change', ['webform.states']); 3296 } 3297 } 3298 }); 3299 } 3300 }; 3301 3302})(jQuery, Drupal, once); 3303;
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.