1(function (Drupal) { 2 3 /** 4 * Command to attach data using jQuery's data API. 5 * 6 * @param {Drupal.Ajax} [ajax] 7 * {@link Drupal.Ajax} object created by {@link Drupal.ajax}. 8 * @param {object} response 9 * The response from the Ajax request. 10 * @param {string} response.event_name 11 * The event name 12 * @param {object} response.data 13 * The value of the event. 14 */ 15 Drupal.AjaxCommands.prototype.gtagEvent = function (ajax, response) { 16 gtag('event', response.event_name, response.data) 17 } 18})(Drupal); 19; 20function ctSetCookie(cookies) 21{ 22 23 let useCookies, useAltCookies 24 25 if ('undefined' !== typeof ct_use_cookies) { 26 useCookies = ct_use_cookies; 27 } else { 28 useCookies = false; 29 } 30 31 if ('undefined' !== typeof ct_use_alt_cookies) { 32 useAltCookies = ct_use_alt_cookies; 33 } else { 34 useAltCookies = false 35 } 36 37 if (useCookies) { 38 if (useAltCookies && useAltCookies === 1) { 39 let xhr = new XMLHttpRequest(); 40 41 let json = JSON.stringify(cookies); 42 43 xhr.open("POST", '/admin/config/cleantalk/set_alt_cookies') 44 xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8'); 45 46 xhr.send(json); 47 } else { 48 cookies.forEach( 49 function (e) { 50 let ctSecure = location.protocol === "https:" ? "; secure" : ""; 51 document.cookie = e.name + "=" + encodeURIComponent(e.value) + "; path=/; expires=0; samesite=lax" + ctSecure; 52 } 53 ) 54 } 55 } 56} 57; 58var d = new Date(), 59 ctTimeMs = new Date().getTime(), 60 ctMouseEventTimerFlag = true, //Reading interval flag 61 ctMouseData = "[", 62 ctMouseDataCounter = 0, 63 ctScrollCollected = false, 64 ctEventTokenInterval = null; 65 66ctSetCookie( 67 [ 68 { 69 'name' : 'ct_check_js', 70 'value' : ct_check_js_val 71 }, 72 { 73 'name' : 'ct_ps_timestamp', 74 'value' : Math.floor(new Date().getTime()/1000) 75 }, 76 { 77 'name' : 'ct_fkp_timestamp', 78 'value' : '0' 79 }, 80 { 81 'name' : 'ct_pointer_data', 82 'value' : '0' 83 }, 84 { 85 'name' : 'ct_timezone', 86 'value' : d.getTimezoneOffset()/60*(-1) 87 }, 88 { 89 'name' : 'apbct_antibot', 90 'value' : drupal_ac_antibot_cookie_value 91 }, 92 { 93 'name' : 'ct_has_scrolled', 94 'value' : false 95 } 96 ] 97); 98 99//Reading interval 100 101var ctMouseReadInterval = setInterval( 102 function () { 103 ctMouseEventTimerFlag = true; 104 }, 150 105); 106 107//Writting interval 108 109var ctMouseWriteDataInterval = setInterval( 110 function () { 111 if(typeof ct_use_alt_cookies !== "undefined" && ct_use_alt_cookies === 1) { 112 return; 113 } 114 var ctMouseDataToSend = ctMouseData.slice(0,-1).concat("]"); 115 ctSetCookie( 116 [ 117 { 118 'name' : 'ct_pointer_data', 119 'value' : ctMouseDataToSend 120 } 121 ] 122 ); 123 }, 1200 124); 125 126//Stop observing function 127 128function ctMouseStopData() 129{ 130 if(typeof window.addEventListener == "function") { 131 window.removeEventListener("mousemove", ctFunctionMouseMove); 132 } else { 133 window.detachEvent("onmousemove", ctFunctionMouseMove); 134 } 135 clearInterval(ctMouseReadInterval); 136 clearInterval(ctMouseWriteDataInterval); 137} 138 139//Logging mouse position each 300 ms 140 141var ctFunctionMouseMove = function output(event) 142{ 143 if (ctMouseEventTimerFlag == true) { 144 var mouseDate = new Date(); 145 ctMouseData += "[" + Math.round(event.pageY) + "," + Math.round(event.pageX) + "," + Math.round(mouseDate.getTime() - ctTimeMs) + "],"; 146 ctMouseDataCounter++; 147 ctMouseEventTimerFlag = false; 148 if(ctMouseDataCounter >= 100) { 149 ctMouseStopData(); 150 } 151 } 152}; 153 154/** 155 * Set scrolling cookie 156 */ 157function ctSetHasScrolled() 158{ 159 if(! ctScrollCollected ) { 160 ctSetCookie( 161 [ 162 { 163 'name' : 'ct_has_scrolled', 164 'value' : true 165 } 166 ] 167 ); 168 ctScrollCollected = true; 169 } 170} 171 172//Stop key listening function 173 174function ctKeyStopStopListening() 175{ 176 if (typeof window.addEventListener == "function") { 177 window.removeEventListener("mousedown", ctFunctionFirstKey); 178 window.removeEventListener("keydown", ctFunctionFirstKey); 179 } 180 else { 181 window.detachEvent("mousedown", ctFunctionFirstKey); 182 window.detachEvent("keydown", ctFunctionFirstKey); 183 } 184} 185 186//Writing first key press timestamp 187 188var ctFunctionFirstKey = function output(event) 189{ 190 var KeyTimestamp = Math.floor(new Date().getTime()/1000);
191 ctSetCookie( 192 [ 193 { 194 'name' : 'ct_fkp_timestamp', 195 'value' : KeyTimestamp 196 } 197 ] 198 ); 199 ctKeyStopStopListening(); 200}; 201 202if (typeof window.addEventListener == "function") { 203 window.addEventListener("mousemove", ctFunctionMouseMove); 204 window.addEventListener("mousedown", ctFunctionFirstKey); 205 window.addEventListener("keydown", ctFunctionFirstKey); 206 window.addEventListener("scroll", ctSetHasScrolled); 207} 208else { 209 window.attachEvent("onmousemove", ctFunctionMouseMove); 210 window.attachEvent("mousedown", ctFunctionFirstKey); 211 window.attachEvent("keydown", ctFunctionFirstKey); 212 window.attachEvent("scroll", ctSetHasScrolled); 213} 214 215function apbct_collect_visible_fields( form ) 216{ 217 218 // Get only fields 219 var inputs = [], 220 inputs_visible = '', 221 inputs_visible_count = 0, 222 inputs_invisible = '', 223 inputs_invisible_count = 0, 224 inputs_with_duplicate_names = []; 225 226 for(var key in form.elements){ 227 if(!isNaN(+key)) { 228 inputs[key] = form.elements[key]; 229 } 230 } 231 232 // Filter fields 233 inputs = inputs.filter( 234 function (elem) { 235 236 // Filter already added fields 237 if(inputs_with_duplicate_names.indexOf(elem.getAttribute('name')) !== -1 ) { 238 return false; 239 } 240 // Filter inputs with same names for type == radio 241 if(-1 !== ['radio', 'checkbox'].indexOf(elem.getAttribute("type"))) { 242 inputs_with_duplicate_names.push(elem.getAttribute('name')); 243 return false; 244 } 245 return true; 246 } 247 ); 248 249 // Visible fields 250 inputs.forEach( 251 function (elem, i, elements) { 252 // Unnecessary fields 253 if(elem.getAttribute("type") === "submit" // type == submit 254 || elem.getAttribute('name') === null 255 || elem.getAttribute('name') === 'ct_checkjs' 256 ) { 257 return; 258 } 259 // Invisible fields 260 if(getComputedStyle(elem).display === "none" // hidden 261 || getComputedStyle(elem).visibility === "hidden" // hidden 262 || getComputedStyle(elem).opacity === "0" // hidden 263 || elem.getAttribute("type") === "hidden" // type == hidden 264 ) { 265 if(elem.classList.contains("wp-editor-area") ) { 266 inputs_visible += " " + elem.getAttribute("name"); 267 inputs_visible_count++; 268 } else { 269 inputs_invisible += " " + elem.getAttribute("name"); 270 inputs_invisible_count++; 271 } 272 } 273 // Visible fields 274 else { 275 inputs_visible += " " + elem.getAttribute("name"); 276 inputs_visible_count++; 277 } 278 279 } 280 ); 281 282 inputs_invisible = inputs_invisible.trim(); 283 inputs_visible = inputs_visible.trim(); 284 285 return { 286 visible_fields : inputs_visible, 287 visible_fields_count : inputs_visible_count, 288 invisible_fields : inputs_invisible, 289 invisible_fields_count : inputs_invisible_count, 290 } 291 292} 293 294function apbct_visible_fields_set_cookie( visible_fields_collection ) 295{ 296 var collection = typeof visible_fields_collection === 'object' && visible_fields_collection !== null ? visible_fields_collection : {}; 297 298 ctSetCookie( 299 [ 300 { 301 'name' : 'apbct_visible_fields', 302 'value' : JSON.stringify(collection) 303 } 304 ] 305 ) 306} 307 308// Event token handler class. Get token and save it to the alternative sessions. 309 310class EventTokenHandler { 311 312 constructor(use_alt_cookies_option) { 313 this.token = null; 314 this.lsSavedFlagName = 'event_token_saved_to_alt_sessions'; 315 this.lsEVentTokenName = 'bot_detector_event_token'; 316 this.intervalValue = 1500; 317 this.init(use_alt_cookies_option); 318 } 319 320 init(use_alt_cookies_option){ 321 if ('undefined' !== typeof use_alt_cookies_option && use_alt_cookies_option) { 322 this.setNotSavedFlag(); 323 this.startListenTokenLS(); 324 } 325 } 326 327 328 setSavedFlag() 329 { 330 localStorage.setItem(this.lsSavedFlagName, '1'); 331 } 332 333 setNotSavedFlag() 334 { 335 localStorage.setItem(this.lsSavedFlagName, '0'); 336 } 337 338 isSaved() 339 { 340 let event_token_saved = localStorage.getItem(this.lsSavedFlagName); 341 return event_token_saved !== null && event_token_saved !== undefined && event_token_saved === '1'; 342 } 343 344 getEventToken() 345 { 346 let event_token = localStorage.getItem(this.lsEVentTokenName); 347 try { 348 event_token = event_token !== null ? JSON.parse(event_token) : false;
349 } catch (e) { 350 return false; 351 } 352 event_token = event_token.hasOwnProperty('value') ? event_token.value : false; 353 if (typeof event_token === 'string' && event_token.length === 64) { 354 return event_token; 355 } 356 return false; 357 } 358 359 setEventTokenCookie() 360 { 361 if (typeof this.token === 'string' && this.token.length === 64) { 362 ctSetCookie( 363 [ 364 { 365 'name': 'apbct_event_token', 366 'value': this.token 367 } 368 ] 369 ) 370 } 371 } 372 373 stopListenTokenLS() 374 { 375 clearInterval(this.intervalID); 376 } 377 378 startListenTokenLS() 379 { 380 this.intervalID = setInterval( this.intervalRun, this.intervalValue, this) 381 } 382 383 intervalRun(handler) 384 { 385 if ( !handler.isSaved() ) { 386 handler.token = handler.getEventToken(); 387 if ( handler.token ) { 388 handler.setEventTokenCookie(); 389 handler.setSavedFlag(); 390 handler.stopListenTokenLS(); 391 } 392 } 393 } 394} 395 396//Collect event token 397new EventTokenHandler(ct_use_alt_cookies); 398; 399/** 400 * @file 401 * Bootstrap Popovers. 402 */ 403 404var Drupal = Drupal || {}; 405 406(function ($, Drupal, Bootstrap) { 407 "use strict"; 408 409 var $document = $(document); 410 411 /** 412 * Extend the Bootstrap Popover plugin constructor class. 413 */ 414 Bootstrap.extendPlugin('popover', function (settings) { 415 return { 416 DEFAULTS: { 417 animation: !!settings.popover_animation, 418 autoClose: !!settings.popover_auto_close, 419 enabled: settings.popover_enabled, 420 html: !!settings.popover_html, 421 placement: settings.popover_placement, 422 selector: settings.popover_selector, 423 trigger: settings.popover_trigger, 424 title: settings.popover_title, 425 content: settings.popover_content, 426 delay: parseInt(settings.popover_delay, 10), 427 container: settings.popover_container 428 } 429 }; 430 }); 431 432 /** 433 * Bootstrap Popovers. 434 * 435 * @todo This should really be properly delegated if selector option is set. 436 */ 437 Drupal.behaviors.bootstrapPopovers = { 438 $activePopover: null, 439 attach: function (context) { 440 // Immediately return if popovers are not available. 441 if (!$.fn.popover || !$.fn.popover.Constructor.DEFAULTS.enabled) { 442 return; 443 } 444 445 var _this = this; 446 447 $document 448 .on('show.bs.popover', '[data-toggle=popover]', function () { 449 var $trigger = $(this); 450 var popover = $trigger.data('bs.popover'); 451 452 // Only keep track of clicked triggers that we're manually handling. 453 if (popover.options.originalTrigger === 'click') { 454 if (_this.$activePopover && _this.getOption('autoClose') && !_this.$activePopover.is($trigger)) { 455 _this.$activePopover.popover('hide'); 456 } 457 _this.$activePopover = $trigger; 458 } 459 }) 460 // Unfortunately, :focusable is only made available when using jQuery 461 // UI. While this would be the most semantic pseudo selector to use 462 // here, jQuery UI may not always be loaded. Instead, just use :visible 463 // here as this just needs some sort of selector here. This activates 464 // delegate binding to elements in jQuery so it can work it's bubbling 465 // focus magic since elements don't really propagate their focus events. 466 // @see https://www.drupal.org/project/bootstrap/issues/3013236 467 .on('focus.bs.popover', ':visible', function (e) { 468 var $target = $(e.target); 469 if (_this.$activePopover && _this.getOption('autoClose') && !_this.$activePopover.is($target) && !$target.closest('.popover.in')[0]) { 470 _this.$activePopover.popover('hide'); 471 _this.$activePopover = null; 472 } 473 }) 474 .on('click.bs.popover', function (e) { 475 var $target = $(e.target); 476 if (_this.$activePopover && _this.getOption('autoClose') && !$target.is('[data-toggle=popover]') && !$target.closest('.popover.in')[0]) { 477 _this.$activePopover.popover('hide'); 478 _this.$activePopover = null; 479 } 480 }) 481 .on('keyup.bs.popover', function (e) { 482 if (_this.$activePopover && _this.getOption('autoClose') && e.which === 27) { 483 _this.$activePopover.popover('hide'); 484 _this.$activePopover = null; 485 } 486 }) 487 ; 488 489 var elements = $(context).find('[data-toggle=popover]').toArray(); 490 for (var i = 0; i < elements.length; i++) { 491 var $element = $(elements[i]); 492 var options = $.extend({}, $.fn.popover.Constructor.DEFAULTS, $element.data()); 493 494 // Store the original trigger. 495 options.originalTrigger = options.trigger; 496 497 // If the trigger is "click", then we'll handle it manually here. 498 if (options.trigger === 'click') { 499 options.trigger = 'manual'; 500 } 501 502 // Retrieve content from a target element. 503 var target = options.target || $element.is('a[href^="#"]') && $element.attr('href'); 504 var $target = $document.find(target).clone(); 505 if (!options.content && $target[0]) { 506 $target.removeClass('visually-hidden hidden').removeAttr('aria-hidden'); 507 options.content = $target.wrap('<div/>').parent()[options.html ? 'html' : 'text']() || ''; 508 } 509 510 // Initialize the popover. 511 $element.popover(options); 512 513 // Handle clicks manually. 514 if (options.originalTrigger === 'click') { 515 // To ensure the element is bound multiple times, remove any 516 // previously set event handler before adding another one. 517 $element 518 .off('click.drupal.bootstrap.popover') 519 .on('click.drupal.bootstrap.popover', function (e) { 520 $(this).popover('toggle'); 521 e.preventDefault(); 522 e.stopPropagation(); 523 }) 524 ; 525 } 526 } 527 }, 528 detach: function (context) { 529 // Immediately return if popovers are not available. 530 if (!$.fn.popover || !$.fn.popover.Constructor.DEFAULTS.enabled) { 531 return; 532 } 533 534 // Destroy all popovers. 535 $(context).find('[data-toggle="popover"]') 536 .off('click.drupal.bootstrap.popover') 537 .popover('destroy') 538 ; 539 }, 540 getOption: function(name, defaultValue, element) { 541 var $element = element ? $(element) : this.$activePopover; 542 var options = $.extend(true, {}, $.fn.popover.Constructor.DEFAULTS, ($element && $element.data('bs.popover') || {}).options); 543 if (options[name] !== void 0) { 544 return options[name]; 545 } 546 return defaultValue !== void 0 ? defaultValue : void 0; 547 } 548 }; 549 550})(window.jQuery, window.Drupal, window.Drupal.bootstrap); 551; 552/** 553 * @file 554 * Bootstrap Tooltips. 555 */ 556 557var Drupal = Drupal || {}; 558 559(function ($, Drupal, Bootstrap) { 560 "use strict"; 561 562 /** 563 * Extend the Bootstrap Tooltip plugin constructor class. 564 */ 565 Bootstrap.extendPlugin('tooltip', function (settings) { 566 return { 567 DEFAULTS: { 568 animation: !!settings.tooltip_animation, 569 enabled: settings.tooltip_enabled, 570 html: !!settings.tooltip_html, 571 placement: settings.tooltip_placement, 572 selector: settings.tooltip_selector, 573 trigger: settings.tooltip_trigger, 574 delay: parseInt(settings.tooltip_delay, 10), 575 container: settings.tooltip_container 576 } 577 }; 578 }); 579 580 /** 581 * Bootstrap Tooltips. 582 * 583 * @todo This should really be properly delegated if selector option is set. 584 */ 585 Drupal.behaviors.bootstrapTooltips = { 586 attach: function (context) { 587 // Immediately return if tooltips are not available. 588 if (!$.fn.tooltip || !$.fn.tooltip.Constructor.DEFAULTS.enabled) { 589 return; 590 } 591 592 var elements = $(context).find('[data-toggle="tooltip"]').toArray(); 593 for (var i = 0; i < elements.length; i++) { 594 var $element = $(elements[i]); 595 var options = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, $element.data()); 596 $element.tooltip(options); 597 } 598 }, 599 detach: function (context) { 600 // Immediately return if tooltips are not available. 601 if (!$.fn.tooltip || !$.fn.tooltip.Constructor.DEFAULTS.enabled) { 602 return; 603 } 604 605 // Destroy all tooltips. 606 $(context).find('[data-toggle="tooltip"]').tooltip('destroy'); 607 } 608 }; 609 610})(window.jQuery, window.Drupal, window.Drupal.bootstrap); 611; 612/*! 613 * jQuery Form Plugin 614 * version: 4.3.0 615 * Requires jQuery v1.7.2 or later 616 * Project repository: https://github.com/jquery-form/form 617 618 * Copyright 2017 Kevin Morris 619 * Copyright 2006 M. Alsup 620 621 * Dual licensed under the LGPL-2.1+ or MIT licenses 622 * https://github.com/jquery-form/form#license 623 624 * This library is free software; you can redistribute it and/or 625 * modify it under the terms of the GNU Lesser General Public
vendor: 16,397 bytes, lines 626-633
626 * License as published by the Free Software Foundation; either 627 * version 2.1 of the License, or (at your option) any later version. 628 * This library is distributed in the hope that it will be useful, 629 * but WITHOUT ANY WARRANTY; without even the implied warranty of 630 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 631 * Lesser General Public License for more details. 632 */ 633!function(r){"function"==typeof define&&define.amd?define(["jquery"],r):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),r(t),t}:r(jQuery)}(function(q){"use strict";var m=/\r?\n/g,S={};S.fileapi=void 0!==q('<input type="file">').get(0).files,S.formdata=void 0!==window.FormData;var _=!!q.fn.prop;function o(e){var t=e.data;e.isDefaultPrevented()||(e.preventDefault(),q(e.target).closest("form").ajaxSubmit(t))}function i(e){var t=e.target,r=q(t);if(!r.is("[type=submit],[type=image]")){var a=r.closest("[type=submit]");if(0===a.length)return;t=a[0]}var n,o=t.form;"image"===(o.clk=t).type&&(void 0!==e.offsetX?(o.clk_x=e.offsetX,o.clk_y=e.offsetY):"function"==typeof q.fn.offset?(n=r.offset(),o.clk_x=e.pageX-n.left,o.clk_y=e.pageY-n.top):(o.clk_x=e.pageX-t.offsetLeft,o.clk_y=e.pageY-t.offsetTop)),setTimeout(function(){o.clk=o.clk_x=o.clk_y=null},100)}function N(){var e;q.fn.ajaxSubmit.debug&&(e="[jquery.form] "+Array.prototype.join.call(arguments,""),window.console&&window.console.log?window.console.log(e):window.opera&&window.opera.postError&&window.opera.postError(e))}q.fn.attr2=function(){if(!_)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},q.fn.ajaxSubmit=function(M,e,t,r){if(!this.length)return N("ajaxSubmit: skipping submit process - no element selected"),this;var O,a,n,o,X=this;"function"==typeof M?M={success:M}:"string"==typeof M||!1===M&&0<arguments.length?(M={url:M,data:e,dataType:t},"function"==typeof r&&(M.success=r)):void 0===M&&(M={}),O=M.method||M.type||this.attr2("method"),n=(n=(n="string"==typeof(a=M.url||this.attr2("action"))?q.trim(a):"")||window.location.href||"")&&(n.match(/^([^#]+)/)||[])[1],o=/(MSIE|Trident)/.test(navigator.userAgent||"")&&/^https/i.test(window.location.href||"")?"javascript:false":"about:blank",M=q.extend(!0,{url:n,success:q.ajaxSettings.success,type:O||q.ajaxSettings.type,iframeSrc:o},M);var i={};if(this.trigger("form-pre-serialize",[this,M,i]),i.veto)return N("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(M.beforeSerialize&&!1===M.beforeSerialize(this,M))return N("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var s=M.traditional;void 0===s&&(s=q.ajaxSettings.traditional);var u,c,C=[],l=this.formToArray(M.semantic,C,M.filtering);if(M.data&&(c=q.isFunction(M.data)?M.data(l):M.data,M.extraData=c,u=q.param(c,s)),M.beforeSubmit&&!1===M.beforeSubmit(l,this,M))return N("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[l,this,M,i]),i.veto)return N("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var f=q.param(l,s);u&&(f=f?f+"&"+u:u),"GET"===M.type.toUpperCase()?(M.url+=(0<=M.url.indexOf("?")?"&":"?")+f,M.data=null):M.data=f;var d,m,p,h=[];M.resetForm&&h.push(function(){X.resetForm()}),M.clearForm&&h.push(function(){X.clearForm(M.includeHidden)}),!M.dataType&&M.target?(d=M.success||function(){},h.push(function(e,t,r){var a=arguments,n=M.replaceTarget?"replaceWith":"html";q(M.target)[n](e).each(function(){d.apply(this,a)})})):M.success&&(q.isArray(M.success)?q.merge(h,M.success):h.push(M.success)),M.success=function(e,t,r){for(var a=M.context||this,n=0,o=h.length;n<o;n++)h[n].apply(a,[e,t,r||X,X])},M.error&&(m=M.error,M.error=function(e,t,r){var a=M.context||this;m.apply(a,[e,t,r,X])}),M.complete&&(p=M.complete,M.complete=function(e,t){var r=M.context||this;p.apply(r,[e,t,X])});var v=0<q("input[type=file]:enabled",this).filter(function(){return""!==q(this).val()}).length,g="multipart/form-data",x=X.attr("enctype")===g||X.attr("encoding")===g,y=S.fileapi&&S.formdata;N("fileAPI :"+y);var b,T=(v||x)&&!y;!1!==M.iframe&&(M.iframe||T)?M.closeKeepAlive?q.get(M.closeKeepAlive,function(){b=w(l)}):b=w(l):b=(v||x)&&y?function(e){for(var r=new FormData,t=0;t<e.length;t++)r.append(e[t].name,e[t].value);if(M.extraData){var a=function(e){var t,r,a=q.param(e,M.traditional).split("&"),n=a.length,o=[];for(t=0;t<n;t++)a[t]=a[t].replace(/\+/g," "),r=a[t].split("="),o.push([decodeURIComponent(r[0]),decodeURIComponent(r[1])]);return o}(M.extraData);for(t=0;t<a.length;t++)a[t]&&r.append(a[t][0],a[t][1])}M.data=null;var n=q.extend(!0,{},q.ajaxSettings,M,{contentType:!1,processData:!1,cache:!1,type:O||"POST"});M.uploadProgress&&(n.xhr=function(){var e=q.ajaxSettings.xhr();return e.upload&&e.upload.addEventListener("progress",function(e){var t=0,r=e.loaded||e.position,a=e.total;e.lengthComputable&&(t=Math.ceil(r/a*100)),M.uploadProgress(e,r,a,t)},!1),e});n.data=null;var o=n.beforeSend;return n.beforeSend=function(e,t){M.formData?t.data=M.formData:t.data=r,o&&o.call(this,e,t)},q.ajax(n)}(l):q.ajax(M),X.removeData("jqxhr").data("jqxhr",b);for(var j=0;j<C.length;j++)C[j]=null;return this.trigger("form-submit-notify",[this,M]),this;function w(e){var t,r,l,f,o,d,m,p,a,n,h,v,i=X[0],g=q.Deferred();if(g.abort=function(e){p.abort(e)},e)for(r=0;r<C.length;r++)t=q(C[r]),_?t.prop("disabled",!1):t.removeAttr("disabled");(l=q.extend(!0,{},q.ajaxSettings,M)).context=l.context||l,o="jqFormIO"+(new Date).getTime();var s=i.ownerDocument,u=X.closest("body");if(l.iframeTarget?(n=(d=q(l.iframeTarget,s)).attr2("name"))?o=n:d.attr2("name",o):(d=q('<iframe name="'+o+'" src="'+l.iframeSrc+'" />',s)).css({position:"absolute",top:"-1000px",left:"-1000px"}),m=d[0],p={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(e){var t="timeout"===e?"timeout":"aborted";N("aborting upload... "+t),this.aborted=1;try{m.contentWindow.document.execCommand&&m.contentWindow.document.execCommand("Stop")}catch(e){}d.attr("src",l.iframeSrc),p.error=t,l.error&&l.error.call(l.context,p,t,e),f&&q.event.trigger("ajaxError",[p,l,t]),l.complete&&l.complete.call(l.context,p,t)}},(f=l.global)&&0==q.active++&&q.event.trigger("ajaxStart"),f&&q.event.trigger("ajaxSend",[p,l]),l.beforeSend&&!1===l.beforeSend.call(l.context,p,l))return l.global&&q.active--,g.reject(),g;if(p.aborted)return g.reject(),g;(a=i.clk)&&(n=a.name)&&!a.disabled&&(l.extraData=l.extraData||{},l.extraData[n]=a.value,"image"===a.type&&(l.extraData[n+".x"]=i.clk_x,l.extraData[n+".y"]=i.clk_y));var x=1,y=2;function b(t){var r=null;try{t.contentWindow&&(r=t.contentWindow.document)}catch(e){N("cannot get iframe.contentWindow document: "+e)}if(r)return r;try{r=t.contentDocument?t.contentDocument:t.document}catch(e){N("cannot get iframe.contentDocument: "+e),r=t.document}return r}var c=q("meta[name=csrf-token]").attr("content"),T=q("meta[name=csrf-param]").attr("content");function j(){var e=X.attr2("target"),t=X.attr2("action"),r=X.attr("enctype")||X.attr("encoding")||"multipart/form-data";i.setAttribute("target",o),O&&!/post/i.test(O)||i.setAttribute("method","POST"),t!==l.url&&i.setAttribute("action",l.url),l.skipEncodingOverride||O&&!/post/i.test(O)||X.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),l.timeout&&(v=setTimeout(function(){h=!0,A(x)},l.timeout));var a=[];try{if(l.extraData)for(var n in l.extraData)l.extraData.hasOwnProperty(n)&&(q.isPlainObject(l.extraData[n])&&l.extraData[n].hasOwnProperty("name")&&l.extraData[n].hasOwnProperty("value")?a.push(q('<input type="hidden" name="'+l.extraData[n].name+'">',s).val(l.extraData[n].value).appendTo(i)[0]):a.push(q('<input type="hidden" name="'+n+'">',s).val(l.extraData[n]).appendTo(i)[0]));l.iframeTarget||d.appendTo(u),m.attachEvent?m.attachEvent("onload",A):m.addEventListener("load",A,!1),setTimeout(function e(){try{var t=b(m).readyState;N("state = "+t),t&&"uninitialized"===t.toLowerCase()&&setTimeout(e,50)}catch(e){N("Server abort: ",e," (",e.name,")"),A(y),v&&clearTimeout(v),v=void 0}},15);try{i.submit()}catch(e){document.createElement("form").submit.apply(i)}}finally{i.setAttribute("action",t),i.setAttribute("enctype",r),e?i.setAttribute("target",e):X.removeAttr("target"),q(a).remove()}}T&&c&&(l.extraData=l.extraData||{},l.extraData[T]=c),l.forceSync?j():setTimeout(j,10);var w,S,k,D=50;function A(e){if(!p.aborted&&!k){if((S=b(m))||(N("cannot access response document"),e=y),e===x&&p)return p.abort("timeout"),void g.reject(p,"timeout");if(e===y&&p)return p.abort("server abort"),void g.reject(p,"error","server abort");if(S&&S.location.href!==l.iframeSrc||h){m.detachEvent?m.detachEvent("onload",A):m.removeEventListener("load",A,!1);var t,r="success";try{if(h)throw"timeout";var a="xml"===l.dataType||S.XMLDocument||q.isXMLDoc(S);if(N("isXml="+a),!a&&window.opera&&(null===S.body||!S.body.innerHTML)&&--D)return N("requeing onLoad callback, DOM not available"),void setTimeout(A,250);var n=S.body?S.body:S.documentElement;p.responseText=n?n.innerHTML:null,p.responseXML=S.XMLDocument?S.XMLDocument:S,a&&(l.dataType="xml"),p.getResponseHeader=function(e){return{"content-type":l.dataType}[e.toLowerCase()]},n&&(p.status=Number(n.getAttribute("status"))||p.status,p.statusText=n.getAttribute("statusText")||p.statusText);var o,i,s,u=(l.dataType||"").toLowerCase(),c=/(json|script|text)/.test(u);c||l.textarea?(o=S.getElementsByTagName("textarea")[0])?(p.responseText=o.value,p.status=Number(o.getAttribute("status"))||p.status,p.statusText=o.getAttribute("statusText")||p.statusText):c&&(i=S.getElementsByTagName("pre")[0],s=S.getElementsByTagName("body")[0],i?p.responseText=i.textContent?i.textContent:i.innerText:s&&(p.responseText=s.textContent?s.textContent:s.innerText)):"xml"===u&&!p.responseXML&&p.responseText&&(p.responseXML=F(p.responseText));try{w=E(p,u,l)}catch(e){r="parsererror",p.error=t=e||r}}catch(e){N("error caught: ",e),r="error",p.error=t=e||r}p.aborted&&(N("upload aborted"),r=null),p.status&&(r=200<=p.status&&p.status<300||304===p.status?"success":"error"),"success"===r?(l.success&&l.success.call(l.context,w,"success",p),g.resolve(p.responseText,"success",p),f&&q.event.trigger("ajaxSuccess",[p,l])):r&&(void 0===t&&(t=p.statusText),l.error&&l.error.call(l.context,p,r,t),g.reject(p,"error",t),f&&q.event.trigger("ajaxError",[p,l,t])),f&&q.event.trigger("ajaxComplete",[p,l]),f&&!--q.active&&q.event.trigger("ajaxStop"),l.complete&&l.complete.call(l.context,p,r),k=!0,l.timeout&&clearTimeout(v),setTimeout(function(){l.iframeTarget?d.attr("src",l.iframeSrc):d.remove(),p.responseXML=null},100)}}}var F=q.parseXML||function(e,t){return window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!==t.documentElement.nodeName?t:null},L=q.parseJSON||function(e){return window.eval("("+e+")")},E=function(e,t,r){var a=e.getResponseHeader("content-type")||"",n=("xml"===t||!t)&&0<=a.indexOf("xml"),o=n?e.responseXML:e.responseText;return n&&"parsererror"===o.documentElement.nodeName&&q.error&&q.error("parsererror"),r&&r.dataFilter&&(o=r.dataFilter(o,t)),"string"==typeof o&&(("json"===t||!t)&&0<=a.indexOf("json")?o=L(o):("script"===t||!t)&&0<=a.indexOf("javascript")&&q.globalEval(o)),o};return g}},q.fn.ajaxForm=function(e,t,r,a){if(("string"==typeof e||!1===e&&0<arguments.length)&&(e={url:e,data:t,dataType:r},"function"==typeof a&&(e.success=a)),(e=e||{}).delegation=e.delegation&&q.isFunction(q.fn.on),e.delegation||0!==this.length)return e.delegation?(q(document).off("submit.form-plugin",this.selector,o).off("click.form-plugin",this.selector,i).on("submit.form-plugin",this.selector,e,o).on("click.form-plugin",this.selector,e,i),this):(e.beforeFormUnbind&&e.beforeFormUnbind(this,e),this.ajaxFormUnbind().on("submit.form-plugin",e,o).on("click.form-plugin",e,i));var n={s:this.selector,c:this.context};return!q.isReady&&n.s?(N("DOM not ready, queuing ajaxForm"),q(function(){q(n.s,n.c).ajaxForm(e)})):N("terminating; zero elements found by selector"+(q.isReady?"":" (DOM not ready)")),this},q.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},q.fn.formToArray=function(e,t,r){var a=[];if(0===this.length)return a;var n,o,i,s,u,c,l,f,d,m,p=this[0],h=this.attr("id"),v=(v=e||void 0===p.elements?p.getElementsByTagName("*"):p.elements)&&q.makeArray(v);if(h&&(e||/(Edge|Trident)\//.test(navigator.userAgent))&&(n=q(':input[form="'+h+'"]').get()).length&&(v=(v||[]).concat(n)),!v||!v.length)return a;for(q.isFunction(r)&&(v=q.map(v,r)),o=0,c=v.length;o<c;o++)if((m=(u=v[o]).name)&&!u.disabled)if(e&&p.clk&&"image"===u.type)p.clk===u&&(a.push({name:m,value:q(u).val(),type:u.type}),a.push({name:m+".x",value:p.clk_x},{name:m+".y",value:p.clk_y}));else if((s=q.fieldValue(u,!0))&&s.constructor===Array)for(t&&t.push(u),i=0,l=s.length;i<l;i++)a.push({name:m,value:s[i]});else if(S.fileapi&&"file"===u.type){t&&t.push(u);var g=u.files;if(g.length)for(i=0;i<g.length;i++)a.push({name:m,value:g[i],type:u.type});else a.push({name:m,value:"",type:u.type})}else null!=s&&(t&&t.push(u),a.push({name:m,value:s,type:u.type,required:u.required}));return e||!p.clk||(m=(d=(f=q(p.clk))[0]).name)&&!d.disabled&&"image"===d.type&&(a.push({name:m,value:f.val()}),a.push({name:m+".x",value:p.clk_x},{name:m+".y",value:p.clk_y})),a},q.fn.formSerialize=function(e){return q.param(this.formToArray(e))},q.fn.fieldSerialize=function(n){var o=[];return this.each(function(){var e=this.name;if(e){var t=q.fieldValue(this,n);if(t&&t.constructor===Array)for(var r=0,a=t.length;r<a;r++)o.push({name:e,value:t[r]});else null!=t&&o.push({name:this.name,value:t})}}),q.param(o)},q.fn.fieldValue=function(e){for(var t=[],r=0,a=this.length;r<a;r++){var n=this[r],o=q.fieldValue(n,e);null==o||o.constructor===Array&&!o.length||(o.constructor===Array?q.merge(t,o):t.push(o))}return t},q.fieldValue=function(e,t){var r=e.name,a=e.type,n=e.tagName.toLowerCase();if(void 0===t&&(t=!0),t&&(!r||e.disabled||"reset"===a||"button"===a||("checkbox"===a||"radio"===a)&&!e.checked||("submit"===a||"image"===a)&&e.form&&e.form.clk!==e||"select"===n&&-1===e.selectedIndex))return null;if("select"!==n)return q(e).val().replace(m,"\r\n");var o=e.selectedIndex;if(o<0)return null;for(var i=[],s=e.options,u="select-one"===a,c=u?o+1:s.length,l=u?o:0;l<c;l++){var f=s[l];if(f.selected&&!f.disabled){var d=(d=f.value)||(f.attributes&&f.attributes.value&&!f.attributes.value.specified?f.text:f.value);if(u)return d;i.push(d)}}return i},q.fn.clearForm=function(e){return this.each(function(){q("input,select,textarea",this).clearFields(e)})},q.fn.clearFields=q.fn.clearInputs=function(r){var a=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var e=this.type,t=this.tagName.toLowerCase();a.test(e)||"textarea"===t?this.value="":"checkbox"===e||"radio"===e?this.checked=!1:"select"===t?this.selectedIndex=-1:"file"===e?/MSIE/.test(navigator.userAgent)?q(this).replaceWith(q(this).clone(!0)):q(this).val(""):r&&(!0===r&&/hidden/.test(e)||"string"==typeof r&&q(this).is(r))&&(this.value="")})},q.fn.resetForm=function(){return this.each(function(){var t=q(this),e=this.tagName.toLowerCase();switch(e){case"input":this.checked=this.defaultChecked;case"textarea":return this.value=this.defaultValue,!0;case"option":case"optgroup":var r=t.parents("select");return r.length&&r[0].multiple?"option"===e?this.selected=this.defaultSelected:t.find("option").resetForm():r.resetForm(),!0;case"select":return t.find("option").each(function(e){if(this.selected=this.defaultSelected,this.defaultSelected&&!t[0].multiple)return t[0].selectedIndex=e,!1}),!0;case"label":var a=q(t.attr("for")),n=t.find("input,select,textarea");return a[0]&&n.unshift(a[0]),n.resetForm(),!0;case"form":return"function"!=typeof this.reset&&("object"!=typeof this.reset||this.reset.nodeType)||this.reset(),!0;default:return t.find("form,input,label,select,textarea").resetForm(),!0}})},q.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},q.fn.selected=function(r){return void 0===r&&(r=!0),this.each(function(){var e,t=this.t
633ype;"checkbox"===t||"radio"===t?this.checked=r:"option"===this.tagName.toLowerCase()&&(e=q(this).parent("select"),r&&e[0]&&"select-one"===e[0].type&&e.find("option").selected(!1),this.selected=r)})},q.fn.ajaxSubmit.debug=!1}); 634 635; 636/** 637* DO NOT EDIT THIS FILE. 638* See the following change record for more information, 639* https://www.drupal.org/node/2815083 640* @preserve 641**/ 642(function ($, Drupal, drupalSettings) { 643 Drupal.Views = {}; 644 Drupal.Views.parseQueryString = function (query) { 645 var args = {}; 646 var pos = query.indexOf('?'); 647 if (pos !== -1) { 648 query = query.substring(pos + 1); 649 } 650 var pair; 651 var pairs = query.split('&'); 652 for (var i = 0; i < pairs.length; i++) { 653 pair = pairs[i].split('='); 654 if (pair[0] !== 'q' && pair[1]) { 655 args[decodeURIComponent(pair[0].replace(/\+/g, ' '))] = decodeURIComponent(pair[1].replace(/\+/g, ' ')); 656 } 657 } 658 return args; 659 }; 660 Drupal.Views.parseViewArgs = function (href, viewPath) { 661 var returnObj = {}; 662 var path = Drupal.Views.getPath(href); 663 var viewHref = Drupal.url(viewPath).substring(drupalSettings.path.baseUrl.length); 664 if (viewHref && path.substring(0, viewHref.length + 1) === "".concat(viewHref, "/")) { 665 returnObj.view_args = decodeURIComponent(path.substring(viewHref.length + 1, path.length)); 666 returnObj.view_path = path; 667 } 668 return returnObj; 669 }; 670 Drupal.Views.pathPortion = function (href) { 671 var protocol = window.location.protocol; 672 if (href.substring(0, protocol.length) === protocol) { 673 href = href.substring(href.indexOf('/', protocol.length + 2)); 674 } 675 return href; 676 }; 677 Drupal.Views.getPath = function (href) { 678 href = Drupal.Views.pathPortion(href); 679 href = href.substring(drupalSettings.path.baseUrl.length, href.length); 680 if (href.substring(0, 3) === '?q=') { 681 href = href.substring(3, href.length); 682 } 683 var chars = ['#', '?', '&']; 684 for (var i = 0; i < chars.length; i++) { 685 if (href.indexOf(chars[i]) > -1) { 686 href = href.substr(0, href.indexOf(chars[i])); 687 } 688 } 689 return href; 690 }; 691})(jQuery, Drupal, drupalSettings);; 692/** 693* DO NOT EDIT THIS FILE. 694* See the following change record for more information, 695* https://www.drupal.org/node/2815083 696* @preserve 697**/ 698(function ($, Drupal, drupalSettings) { 699 Drupal.behaviors.ViewsAjaxView = {}; 700 Drupal.behaviors.ViewsAjaxView.attach = function (context, settings) { 701 if (settings && settings.views && settings.views.ajaxViews) { 702 var ajaxViews = settings.views.ajaxViews; 703 Object.keys(ajaxViews || {}).forEach(function (i) { 704 Drupal.views.instances[i] = new Drupal.views.ajaxView(ajaxViews[i]); 705 }); 706 } 707 }; 708 Drupal.behaviors.ViewsAjaxView.detach = function (context, settings, trigger) { 709 if (trigger === 'unload') { 710 if (settings && settings.views && settings.views.ajaxViews) { 711 var ajaxViews = settings.views.ajaxViews; 712 Object.keys(ajaxViews || {}).forEach(function (i) { 713 var selector = ".js-view-dom-id-".concat(ajaxViews[i].view_dom_id); 714 if ($(selector, context).length) { 715 delete Drupal.views.instances[i]; 716 delete settings.views.ajaxViews[i]; 717 } 718 }); 719 } 720 } 721 }; 722 Drupal.views = {}; 723 Drupal.views.instances = {}; 724 Drupal.views.ajaxView = function (settings) { 725 var selector = ".js-view-dom-id-".concat(settings.view_dom_id); 726 this.$view = $(selector); 727 var ajaxPath = drupalSettings.views.ajax_path; 728 if (ajaxPath.constructor.toString().indexOf('Array') !== -1) { 729 ajaxPath = ajaxPath[0]; 730 } 731 var queryString = window.location.search || ''; 732 if (queryString !== '') { 733 queryString = queryString.slice(1).replace(/q=[^&]+&?|&?render=[^&]+/, ''); 734 if (queryString !== '') { 735 queryString = (/\?/.test(ajaxPath) ? '&' : '?') + queryString; 736 } 737 } 738 this.element_settings = { 739 url: ajaxPath + queryString, 740 submit: settings, 741 setClick: true, 742 event: 'click', 743 selector: selector, 744 progress: { 745 type: 'fullscreen' 746 } 747 }; 748 this.settings = settings; 749 this.$exposed_form = $("form#views-exposed-form-".concat(settings.view_name.replace(/_/g, '-'), "-").concat(settings.view_display_id.replace(/_/g, '-'))); 750 once('exposed-form', this.$exposed_form).forEach($.proxy(this.attachExposedFormAjax, this));
751 once('ajax-pager', this.$view.filter($.proxy(this.filterNestedViews, this))).forEach($.proxy(this.attachPagerAjax, this)); 752 var selfSettings = $.extend({}, this.element_settings, { 753 event: 'RefreshView', 754 base: this.selector, 755 element: this.$view.get(0) 756 }); 757 this.refreshViewAjax = Drupal.ajax(selfSettings); 758 }; 759 Drupal.views.ajaxView.prototype.attachExposedFormAjax = function () { 760 var that = this; 761 this.exposedFormAjax = []; 762 $('input[type=submit], button[type=submit], input[type=image]', this.$exposed_form).not('[data-drupal-selector=edit-reset]').each(function (index) { 763 var selfSettings = $.extend({}, that.element_settings, { 764 base: $(this).attr('id'), 765 element: this 766 }); 767 that.exposedFormAjax[index] = Drupal.ajax(selfSettings); 768 }); 769 }; 770 Drupal.views.ajaxView.prototype.filterNestedViews = function () { 771 return !this.$view.parents('.view').length; 772 }; 773 Drupal.views.ajaxView.prototype.attachPagerAjax = function () { 774 this.$view.find('ul.js-pager__items > li > a, th.views-field a, .attachment .views-summary a').each($.proxy(this.attachPagerLinkAjax, this)); 775 }; 776 Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function (id, link) { 777 var $link = $(link); 778 var viewData = {}; 779 var href = $link.attr('href'); 780 $.extend(viewData, this.settings, Drupal.Views.parseQueryString(href), Drupal.Views.parseViewArgs(href, this.settings.view_base_path)); 781 var selfSettings = $.extend({}, this.element_settings, {
782 submit: viewData, 783 base: false, 784 element: link 785 }); 786 this.pagerAjax = Drupal.ajax(selfSettings); 787 }; 788 Drupal.AjaxCommands.prototype.viewsScrollTop = function (ajax, response) { 789 var offset = $(response.selector).offset(); 790 var scrollTarget = response.selector; 791 while ($(scrollTarget).scrollTop() === 0 && $(scrollTarget).parent()) { 792 scrollTarget = $(scrollTarget).parent(); 793 } 794 if (offset.top - 10 < $(scrollTarget).scrollTop()) { 795 $(scrollTarget).animate({ 796 scrollTop: offset.top - 10 797 }, 500); 798 } 799 }; 800})(jQuery, Drupal, drupalSettings);; 801/** 802 * @file 803 * Extends core ajax_view.js. 804 */ 805 806(function ($, Drupal) { 807 'use strict'; 808 809 /** 810 * @method 811 */ 812 Drupal.views.ajaxView.prototype.attachExposedFormAjax = function () { 813 var that = this; 814 this.exposedFormAjax = []; 815 $('button[type=submit], input[type=submit], input[type=image]', this.$exposed_form).not('[data-drupal-selector=edit-reset]').each(function (index) { 816 var self_settings = $.extend({}, that.element_settings, { 817 base: $(this).attr('id'), 818 element: this 819 }); 820 that.exposedFormAjax[index] = Drupal.ajax(self_settings); 821 }); 822 }; 823 824})(jQuery, Drupal); 825; 826((Drupal) => { 827 'use strict'; 828 829 /** 830 * Factory for generating alert classes for different callback styles. 831 * 832 * Each alert style's ticker class is responsible for registering its type 833 * with this factory. 834 * 835 * @type {{get(*): *, register(*, *): this}} 836 */ 837 Drupal.alertFactory = (function () { 838 839 /** 840 * Object of factory callbacks for each alert type, keyed by their 841 * respective alert style names. 842 * 843 * @type {{}} 844 */ 845 let callbacks = {}; 846 847 /** 848 * Return a factory object for registering and retrieving ticker classes. 849 */ 850 return { 851 852 /** 853 * Register's an alert style's factory callback. 854 * 855 * @param {string} type 856 * The name of the alert style for which to register a factory callback. 857 * @param {function} callback 858 * The callback to invoke for generating an alert display class for this 859 * alert style. 860 * @returns {Drupal.alertFactory} 861 * Reference to self. 862 */ 863 register(type, callback) { 864 if (typeof callback === 'function') { 865 callbacks[type] = callback; 866 } 867 return this; 868 }, 869 870 /** 871 * Returns the factory callback for the specified alert style. 872 * 873 * @param {string} type 874 * The name of the alert style for which to return a factory callback. 875 * @returns {function} 876 * The factory callback that will return the ticker class for the 877 * specified ticker style. 878 */ 879 get(type) { 880 return callbacks[type]; 881 } 882 } 883 })(); 884})(Drupal); 885; 886((Drupal, undefined) => { 887 'use strict'; 888 889 /** 890 * Represents a single, ticker-style alerts display. 891 */ 892 class AlertsTicker { 893 894 /** 895 * If TRUE, the current ticker is actively running. 896 * 897 * @type {boolean} 898 */ 899 #running = false; 900 901 /** 902 * Index of the alert that is currently displayed or will be displayed when 903 * the ticker starts. 904 * 905 * @type {number} 906 */ 907 #current = 0; 908 909 /** 910 * The ID of the currently running setTimeout() invocation. 911 * 912 * @type {int} 913 */ 914 #timeoutId; 915 916 /** 917 * Reference to the promise chain that controls the ticker animations. 918 * 919 * @type {Promise} 920 */ 921 animationChain; 922 923 /** 924 * True if the next/prev pagers should do nothing (e.g. if the ticker is 925 * currently advancing to the next alert item). 926 * 927 * @type {boolean} 928 */ 929 pagerLocked = false; 930 931 /** 932 * Constructs a new AlertsTicker object. 933 * 934 * @param {HTMLElement} ticker 935 * Reference to the outermost element that represents this ticker display. 936 * @param {{}} selectors 937 * Object of selectors for identifying: 938 * - The element that acts as the direct container for the individual 939 * alert items. 940 * - The counter element. 941 * - The clickable element to display the previous alert. 942 * - The clickable element to display the next alert. 943 * @param {{}} alerts 944 * An object whose keys are HTML IDs that identify individual alert items, 945 * and whose values are each objects containing the following configuration 946 * data per alert item: 947 * - delay: The number of milliseconds that a given alert item should be 948 * displayed before advancing to the next alert item. 949 */ 950 constructor(ticker, selectors, alerts, ) { 951 this.ticker = ticker; 952 this.container = document.querySelector(selectors.container); 953 this.counter = document.querySelector(selectors.counter); 954 this.pager = { 955 'prev': document.querySelector(selectors.prev), 956 'next': document.querySelector(selectors.next) 957 }; 958 959 /** 960 * Set up AlertItem objects, each with doubly-linked references. 961 */ 962 this.alerts = [];
963 Object.keys(alerts).forEach(id => { 964 const 965 alert = new AlertItem(id, alerts[id], this), 966 sequence = this.alerts.push(alert) 967 ; 968 alert.sequence = sequence; 969 if (sequence > 1) { 970 // Create linked references between immediate siblings. 971 const prev = this.alerts[sequence - 2]; 972 alert.prev = prev; 973 prev.next = alert; 974 } 975 }); 976 // Make the associations circular. 977 this.alerts[ this.#lastIndex() ].next = this.alerts[0]; 978 this.alerts[0].prev = this.alerts[ this.#lastIndex() ]; 979 980 /** 981 * Set up prev/next event handlers. 982 */ 983 this.pager.next.onclick = e => { 984 if (this.pagerLocked) { 985 return; 986 } 987 this.animationChain = this.animationChain 988 .then(() => this.cancel()) 989 .then(() => this.#doAdvance()); 990 } 991 this.pager.prev.onclick = e => { 992 if (this.pagerLocked) { 993 return; 994 } 995 this.animationChain = this.animationChain 996 .then(() => this.cancel()) 997 .then(() => this.#doAdvance(true)); 998 } 999 } 1000 1001 /** 1002 * Returns a reference to the current alert item. 1003 * 1004 * @returns {AlertItem} 1005 */ 1006 current () { 1007 return this.alerts[this.#current]; 1008 } 1009 1010 /** 1011 * Advances the current marker to the next alert item in sequence and 1012 * returns a reference to that alert item. 1013 * 1014 * @returns {AlertItem} 1015 */ 1016 next () { 1017 this.#current = (this.#current < this.#lastIndex()) 1018 ? this.#current + 1 1019 : 0; 1020 return this.current(); 1021 } 1022 1023 /** 1024 * Advances the current marker to the previous alert item in sequence and 1025 * returns a reference to that alert item. 1026 * 1027 * @returns {AlertItem} 1028 */ 1029 prev () { 1030 this.#current = (this.#current > 0) 1031 ? this.#current - 1 1032 : this.#lastIndex(); 1033 return this.current(); 1034 } 1035 1036 /** 1037 * Calls .next() or .prev(), based on the value of reverse, and returns the 1038 * resultant value. 1039 * 1040 * @param reverse 1041 * TRUE if .prev() should be returned. Otherwise, .next() will be returned. 1042 * @returns {AlertItem} 1043 * Reference to the newly queued AlertItem. 1044 */ 1045 #page (reverse = false) { 1046 return reverse ? this.prev() : this.next(); 1047 } 1048 1049 /** 1050 * Begin the ticker animation sequence. 1051 * 1052 * @returns {AlertsTicker} 1053 * Reference to self. 1054 */ 1055 start () { 1056 if (this.#running) { 1057 return this; 1058 } 1059 this.animationChain = new Promise((resolve, reject) => { 1060 this.current().display() 1061 resolve(this); 1062 }).then(() => this.advance()); 1063 this.#running = true; 1064 return this; 1065 } 1066 1067 /** 1068 * Sets an animation timer for the next ticker transition and returns the 1069 * promise that will resolve when the timer expires. 1070 * 1071 * @returns {Promise<unknown>} 1072 * A promise that resolves when the timer expires. 1073 */ 1074 advance () { 1075 return new Promise((resolve, reject) => { 1076 this.#timeoutId = setTimeout(() => { 1077 this.#doAdvance(); 1078 return resolve(this.current()); 1079 }, this.current().settings.delay) 1080 }); 1081 } 1082 1083 /** 1084 * Returns a promise that resolves by hiding the current alert and advancing 1085 * the next alert into the display. 1086 * 1087 * @param reverse 1088 * True if the previous alert should be advanced. Otherwise, the next alert 1089 * will advance. 1090 * @returns {Promise<unknown>} 1091 * A promise that resolves once the transition sequence has been inited. 1092 */ 1093 #doAdvance (reverse = false) { 1094 return new Promise((resolve, reject) => { 1095 this.current().hide(reverse) 1096 .then(() => this.#page(reverse).display(reverse)) 1097 .then(() => this.advance()); 1098 resolve(this.current()); 1099 }); 1100 } 1101 1102 /** 1103 * Clears the current setTimeout() invocation and returns an immediately 1104 * resolved promise. 1105 * 1106 * @returns {Promise<unknown>} 1107 */ 1108 cancel () { 1109 clearTimeout(this.#timeoutId); 1110 return new Promise((resolve, reject) => { 1111 resolve(this.current()); 1112 }); 1113 } 1114 1115 /** 1116 * Returns an immediately resolved promise that sets the current pager 1117 * sequence value in the ticker's pager. 1118 * 1119 * @returns {AlertsTicker} 1120 * Reference to self. 1121 */ 1122 setSequence () { 1123 this.counter.textContent = this.current().sequence 1124 return this; 1125 } 1126 1127 /** 1128 * Returns the ordinal index number that represents the last alert in the 1129 * alerts[] property array. 1130 * 1131 * @returns {number} 1132 */ 1133 #lastIndex () { 1134 return this.alerts.length - 1; 1135 } 1136 1137 } 1138 1139 /** 1140 * Represents a single alert display item. 1141 */ 1142 class AlertItem { 1143 1144 /** 1145 * The render classes to apply to the alert item's element on every class 1146 * name change. 1147 * 1148 * @type {[]} 1149 */ 1150 #baseClasses = []; 1151 1152 /** 1153 * The sequence number of this alert item. 1154 * 1155 * @type {number} 1156 */ 1157 sequence; 1158 1159 /** 1160 * Reference to the AlertItem that precedes this AlertItem in the sequence. 1161 * 1162 * @type {AlertItem} 1163 */ 1164 prev; 1165 1166 /** 1167 * Reference to the AlertItem that follows this AlertItem in the sequence. 1168 * 1169 * @type {AlertItem} 1170 */ 1171 next; 1172 1173 /** 1174 * Constructs a new AlertItem object. 1175 * 1176 * @param {string} id 1177 * The HTML ID of the element that this alert item represents. 1178 * @param {[]} settings 1179 * An object of settings, with the following key/value pairs: 1180 * - delay: The number of milliseconds to display this Alert before 1181 * cycling to the next alert in sequence. 1182 * @param {AlertsTicker} parent 1183 * Reference to the parent ticker object. 1184 */ 1185 constructor(id, settings, parent) { 1186 this.parent = parent; 1187 this.id = id; 1188 this.element = document.getElementById(id); 1189 this.settings = settings; 1190 this.oscillator = new Oscillator( 1191 this.parent.container, 1192 this.element.querySelector('.alert-message'), 1193 this.settings.delay 1194 ); 1195 this.#baseClasses = this 1196 .element.className 1197 .replace('hidden', '') 1198 .split(' '); 1199 this.#baseClasses.push('animate__animated'); 1200 } 1201 1202 /** 1203 * Animates this alert item entering the display container from the left. 1204 * 1205 * @param reverse
1206 * If true, the animation enters from the right. 1207 * @returns {Promise} 1208 * Reference to self. 1209 */ 1210 display (reverse = false) { 1211 return new Promise((resolve, reject) => { 1212 this.element.addEventListener('animationend', () => { 1213 this.reset(); 1214 this.parent.pagerLocked = false; 1215 return resolve(this); 1216 }, {once: true}); 1217 this.parent.pagerLocked = true; 1218 this.element.className = this.#concatClasses(Animation.getShow(reverse)); 1219 this.parent.setSequence(); 1220 this.oscillator 1221 .animate() 1222 .monitorResize(); 1223 }); 1224 } 1225 1226 /** 1227 * Animates this alert item exiting the display container to the right. 1228 * 1229 * @param reverse 1230 * If true, the animation exits to the left. 1231 * @returns {Promise} 1232 * Reference to self. 1233 */ 1234 hide (reverse = false) { 1235 return new Promise((resolve, reject) => { 1236 this.element.addEventListener('animationend', () => { 1237 this.parent.pagerLocked = false; 1238 return resolve(this); 1239 }, {once: true}); 1240 this.parent.pagerLocked = true; 1241 this.element.className = this 1242 .#concatClasses(Animation.getHide(reverse)).concat(' animate__fast'); 1243 this.oscillator.clear(); 1244 }); 1245 } 1246 1247 /** 1248 * Resets this AlertItem's element's class string to this alert's base 1249 * classes. 1250 * 1251 * @returns {AlertItem} 1252 * Reference to self. 1253 */ 1254 reset () { 1255 this.element.className = this.#baseClasses.join(' '); 1256 return this; 1257 } 1258 1259 /** 1260 * Returns the classes to apply based on the specified operation. 1261 * 1262 * @param {string} op_class 1263 * The operation class to concatenate with the base classes. 1264 * @returns {string} 1265 * Returns the space-delimited list of classes to apply. 1266 */ 1267 #concatClasses (op_class) { 1268 return this.#baseClasses.concat(op_class).join(' '); 1269 } 1270 1271 } 1272 1273 /** 1274 * Static class that acts as a canonical enum for animation classes. 1275 * 1276 * @see library.animate.css in cwb_alerts.libraries.yml 1277 */ 1278 class Animation { 1279 static ShowNext = new Animation('animate__fadeInLeftBig'); 1280 static ShowPrev = new Animation('animate__fadeInRightBig'); 1281 static HideNext = new Animation('animate__fadeOutRightBig'); 1282 static HidePrev = new Animation('animate__fadeOutLeftBig'); 1283 1284 constructor (name) { 1285 this.name = name; 1286 } 1287 1288 /** 1289 * Returns the class to animate an alert item into the ticker display from 1290 * the left. 1291 * 1292 * @param reverse 1293 * True if the ticker should animate in from the right. 1294 * @returns {string} 1295 */ 1296 static getShow (reverse = false) { 1297 return reverse ? Animation.ShowPrev.name : Animation.ShowNext.name 1298 } 1299 1300 /** 1301 * Returns the class to animate an alert item out of the ticker display to 1302 * the right. 1303 * 1304 * @param reverse 1305 * True if the ticker should animate out to the left. 1306 * @returns {string} 1307 */ 1308 static getHide (reverse = false) { 1309 return reverse ? Animation.HidePrev.name : Animation.HideNext.name; 1310 } 1311 1312 } 1313 1314 /** 1315 * An object for managing alert messages that are longer than their container. 1316 * When an alert message is detected to be longer than its enclosing element, 1317 * it will be horizontally oscillated back and forth. 1318 */ 1319 class Oscillator { 1320 1321 /** 1322 * Amount of overflow, in pixels, that needs to be oscillated. 1323 * 1324 * @type {number} 1325 */ 1326 #overflow; 1327 1328 /** 1329 * The transition time for each oscillation. 1330 * 1331 * @type {number} 1332 */ 1333 #animationSpeed; 1334 1335 /** 1336 * The original CSS transition value for this oscillator's element. 1337 * 1338 * @type {string} 1339 */ 1340 #originalTransition; 1341 1342 /** 1343 * The original CSS margin-left value for this oscillator's element. 1344 * 1345 * @type {string} 1346 */ 1347 #originalMarginLeft; 1348 1349 /** 1350 * A canvas object that provides a computational manifold that does not 1351 * result in DOM reflow. 1352 * 1353 * @type {HTMLCanvasElement} 1354 */ 1355 #canvas = document.createElement("canvas"); 1356 1357 /** 1358 * Constructs a new oscillator object. 1359 * 1360 * @param {HTMLElement} textContainer 1361 * Reference to the element that acts as the enclosing container for all 1362 * alerts. 1363 * @param {HTMLElement} textElement 1364 * Reference to a specific element whose content should be oscillated 1365 * within the enclosing container. 1366 * @param {number} delay 1367 * The number of seconds that this alert will be displayed. 1368 */ 1369 constructor (textContainer, textElement, delay) { 1370 this.container = textContainer; 1371 this.element = textElement; 1372 this.delay = delay; 1373 this.#originalTransition = this.element.style.transition; 1374 this.#originalMarginLeft = this.element.style.marginLeft; 1375 } 1376 1377 /**
1378 * Returns the CSS computed value for a specific CSS style. 1379 * 1380 * @param {string} property 1381 * The name of the CSS property whose computed value should be returned. 1382 * @returns {string} 1383 * The computed CSS value. 1384 */ 1385 #getComputedStyle (property) { 1386 return window.getComputedStyle(this.element, null) 1387 .getPropertyValue(property); 1388 } 1389 1390 /** 1391 * Returns a canvas context whose font has been set to the same as the 1392 * current text element. 1393 * 1394 * @returns {CanvasRenderingContext2D} 1395 * Canvas rendering context. 1396 */ 1397 #getFontContext () { 1398 const context = this.#canvas.getContext("2d"); 1399 context.font = this.#getComputedStyle('font'); 1400 return context; 1401 } 1402 1403 /** 1404 * Returns the width, in pixels, of the container element. 1405 * 1406 * @returns {number} 1407 * The pixel width of the container element. 1408 */ 1409 getContainerWidth () { 1410 return this.container.offsetWidth; 1411 } 1412 1413 /** 1414 * Returns the width, in pixels, of the text element's text content. 1415 * 1416 * @returns {number} 1417 * The pixel width of the text element's text content. 1418 */ 1419 getTextWidth () { 1420 const context = this.#getFontContext(); 1421 const metrics = context.measureText(this.element.textContent); 1422 return metrics.width; 1423 } 1424 1425 /** 1426 * Returns the number of pixels difference between the container element and 1427 * the text element. Positive values indicate surplus space in the 1428 * container; negative values indicate overflowing text. 1429 * 1430 * @returns {number} 1431 * The number of pixels difference between container and text element 1432 * width. 1433 */ 1434 overflow () { 1435 return this.getContainerWidth() - this.getTextWidth(); 1436 } 1437 1438 /** 1439 * Detects any text overflow and animates an oscillation of necessary. 1440 * 1441 * @returns {Oscillator} 1442 * Reference to self. 1443 */ 1444 animate () { 1445 this.#calculate(); 1446 if (this.#overflow >= 0) { 1447 return this; 1448 } 1449 const delay = '0.5'; //Math.min(2, this.#animationSpeed); 1450 this.element.style.transition = this 1451 .#originalTransition 1452 .concat(` margin-left ${this.#animationSpeed}s ease-in-out 2s`); 1453 this.element.style.marginLeft = this.#getMarginLeft(this.element.direction); 1454 this.toggleOscillation = e => { 1455 e.target.direction *= -1; 1456 e.target.style.marginLeft = this.#getMarginLeft(e.target.direction); 1457 }; 1458 this.element.addEventListener('transitionend', this.toggleOscillation); 1459 return this; 1460 } 1461 1462 /** 1463 * Invokes a window resize event listener in order that will respond to 1464 * resize events be re-calculating the overflow and transition time. 1465 * 1466 * @returns {Oscillator} 1467 * Reference to self. 1468 */ 1469 monitorResize () { 1470 this.listenResize = Drupal.debounce(() => { 1471 this.element.removeEventListener('transitionend', this.toggleOscillation); 1472 this.animate(); 1473 }, 300); 1474 window.addEventListener('resize', this.listenResize); 1475 return this; 1476 } 1477 1478 /** 1479 * Clears all oscillation animations for this container/text element pair. 1480 * 1481 * @returns {Oscillator} 1482 * Reference to self. 1483 */ 1484 clear () { 1485 this.element.style.transition = this.#originalTransition; 1486 this.element.style.marginLeft = this.#originalMarginLeft; 1487 this.element.direction = 1; 1488 this.element.removeEventListener('transitionend', this.toggleOscillation); 1489 window.removeEventListener('resize', this.listenResize) 1490 return this; 1491 } 1492 1493 /** 1494 * Calculates the overflow and animation speed and stores those values in 1495 * private local properties. 1496 * 1497 * @returns {Oscillator} 1498 * Reference ot self. 1499 */ 1500 #calculate () { 1501 this.#overflow = Math.min(this.overflow() - this.#totalPadding(), 0); 1502 if (this.#overflow >= 0) { 1503 return this; 1504 } 1505 this.#animationSpeed = Math.min(Math.max( 1506 (this.delay / 1000) - 3, 1507 1), 10); 1508 return this; 1509 } 1510 1511 /** 1512 * Returns an appropriate margin left values based on the direction of 1513 * oscillation. 1514 * 1515 * @param {number} direction 1516 * A value of 1 for the initial oscillation direction (left to right), or 1517 * -1 for the reverse oscillation (right to left). 1518 * @returns {string} 1519 * A valid CSS value for the margin-left property. 1520 */ 1521 #getMarginLeft (direction = 1) { 1522 return direction > 0 ? `${this.#overflow}px` : '0'; 1523 } 1524 1525 /** 1526 * Returns the total width of the text element's left and right padding. 1527 * 1528 * @returns {number} 1529 * Number of total pixels of left and right padding. 1530 */ 1531 #totalPadding () { 1532 return parseInt(this.#getComputedStyle('padding-left')) 1533 + parseInt(this.#getComputedStyle('padding-right')); 1534 } 1535 1536 /** 1537 * Returns the current font size for the text element. 1538 * 1539 * @returns {number} 1540 * The pixel size of the text element's font. 1541 */ 1542 #fontSize () { 1543 return parseInt(this.#getComputedStyle('font-size')); 1544 } 1545 1546 } 1547 1548 // Register the AlertsTicker class with the alertFactory. 1549 Drupal.alertFactory 1550 .register('ticker', (ticker, selectors, alerts) => { 1551 return new AlertsTicker(ticker, selectors, alerts); 1552 }); 1553})(Drupal); 1554; 1555(function ($, undefined) { 1556 'use strict'; 1557 1558 /** 1559 * Attach ticker alerts behavior. 1560 * 1561 * @type {Drupal~behavior} 1562 * 1563 * @prop {Drupal~behaviorAttach} attach 1564 * Initializes the ticker's operation for each instance on page. 1565 * 1566 */ 1567 Drupal.behaviors.cwb_alerts_ticker = { 1568 attach: function (context, settings) { 1569 $('body').once('cwb-alerts-ticker').each(function () { 1570 const 1571 _settings = settings.cwb_alerts_ticker, 1572 selectors = _settings.selectors, 1573 alerts = _settings.data.alerts 1574 ; 1575 $(selectors.ticker, context).each(function () { 1576 const alerts_ticker = Drupal.alertFactory 1577 .get('ticker')(this, selectors, alerts); 1578 alerts_ticker.start(); 1579 }); 1580 }); 1581 } 1582 } 1583})(jQuery); 1584;
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.