1/******************************************************************************* 2 * Copyright 2019 Adobe 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17/** 18 * Element.matches() 19 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill 20 */ 21if (!Element.prototype.matches) { 22 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 23} 24 25// eslint-disable-next-line valid-jsdoc 26/** 27 * Element.closest() 28 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill 29 */ 30if (!Element.prototype.closest) { 31 Element.prototype.closest = function(s) { 32 "use strict"; 33 var el = this; 34 if (!document.documentElement.contains(el)) { 35 return null; 36 } 37 do { 38 if (el.matches(s)) { 39 return el; 40 } 41 el = el.parentElement || el.parentNode; 42 } while (el !== null && el.nodeType === 1); 43 return null; 44 }; 45} 46 47/******************************************************************************* 48 * Copyright 2019 Adobe 49 * 50 * Licensed under the Apache License, Version 2.0 (the "License"); 51 * you may not use this file except in compliance with the License. 52 * You may obtain a copy of the License at 53 * 54 * http://www.apache.org/licenses/LICENSE-2.0 55 * 56 * Unless required by applicable law or agreed to in writing, software 57 * distributed under the License is distributed on an "AS IS" BASIS, 58 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 59 * See the License for the specific language governing permissions and 60 * limitations under the License. 61 ******************************************************************************/ 62(function() { 63 "use strict"; 64 65 var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined; 66 if (!containerUtils) { 67 // eslint-disable-next-line no-console 68 console.warn("Accordion: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page."); 69 } 70 var dataLayerEnabled; 71 var dataLayer; 72 var dataLayerName; 73 var delay = 100; 74 75 var NS = "cmp"; 76 var IS = "accordion"; 77 78 var keyCodes = { 79 ENTER: 13, 80 SPACE: 32, 81 END: 35, 82 HOME: 36, 83 ARROW_LEFT: 37, 84 ARROW_UP: 38, 85 ARROW_RIGHT: 39, 86 ARROW_DOWN: 40 87 }; 88 89 var selectors = { 90 self: "[data-" + NS + '-is="' + IS + '"]' 91 }; 92
93 var cssClasses = { 94 button: { 95 disabled: "cmp-accordion__button--disabled", 96 expanded: "cmp-accordion__button--expanded" 97 }, 98 panel: { 99 hidden: "cmp-accordion__panel--hidden", 100 expanded: "cmp-accordion__panel--expanded" 101 } 102 }; 103 104 var dataAttributes = { 105 item: { 106 expanded: "data-cmp-expanded" 107 } 108 }; 109 110 var properties = { 111 /** 112 * Determines whether a single accordion item is forced to be expanded at a time. 113 * Expanding one item will collapse all others. 114 * 115 * @memberof Accordion 116 * @type {Boolean} 117 * @default false 118 */ 119 "singleExpansion": { 120 "default": false, 121 "transform": function(value) { 122 return !(value === null || typeof value === "undefined"); 123 } 124 } 125 }; 126 127 /** 128 * Accordion Configuration. 129 * 130 * @typedef {Object} AccordionConfig Represents an Accordion configuration 131 * @property {HTMLElement} element The HTMLElement representing the Accordion 132 * @property {Object} options The Accordion options 133 */ 134 135 /** 136 * Accordion. 137 * 138 * @class Accordion 139 * @classdesc An interactive Accordion component for toggling panels of related content 140 * @param {AccordionConfig} config The Accordion configuration 141 */ 142 function Accordion(config) { 143 var that = this; 144 145 if (config && config.element) { 146 init(config); 147 } 148 149 /** 150 * Initializes the Accordion. 151 * 152 * @private 153 * @param {AccordionConfig} config The Accordion configuration 154 */ 155 function init(config) { 156 that._config = config; 157 158 // prevents multiple initialization 159 config.element.removeAttribute("data-" + NS + "-is"); 160 161 setupProperties(config.options); 162 cacheElements(config.element); 163 164 if (that._elements["item"]) { 165 // ensures multiple element types are arrays. 166 that._elements["item"] = Array.isArray(that._elements["item"]) ? that._elements["item"] : [that._elements["item"]]; 167 that._elements["button"] = Array.isArray(that._elements["button"]) ? that._elements["button"] : [that._elements["button"]]; 168 that._elements["panel"] = Array.isArray(that._elements["panel"]) ? that._elements["panel"] : [that._elements["panel"]]; 169 170 if (that._properties.singleExpansion) { 171 var expandedItems = getExpandedItems(); 172 // multiple expanded items annotated, display the last item open. 173 if (expandedItems.length > 1) { 174 toggle(expandedItems.length - 1); 175 } 176 } 177 178 refreshItems(); 179 bindEvents(); 180 scrollToDeepLinkIdInAccordion(); 181 } 182 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 183 /* 184 * Editor message handling: 185 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame 186 * - check that the message data panel container type is correct and that the id (path) matches this specific Accordion component 187 * - if so, route the "navigate" operation to enact a navigation of the Accordion based on index data 188 */ 189 window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 190 window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 191 if (message.data && message.data.type === "cmp-accordion" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 192 if (message.data.operation === "navigate") { 193 // switch to single expansion mode when navigating in edit mode. 194 var singleExpansion = that._properties.singleExpansion; 195 that._properties.singleExpansion = true; 196 toggle(message.data.index); 197 198 // revert to the configured state. 199 that._properties.singleExpansion = singleExpansion; 200 } 201 } 202 }); 203 } 204 } 205 206 /**
207 * Displays the panel containing the element that corresponds to the deep link in the URI fragment 208 * and scrolls the browser to this element. 209 */ 210 function scrollToDeepLinkIdInAccordion() { 211 if (containerUtils) { 212 var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "item", "item"); 213 if (deepLinkItemIdx > -1) { 214 var deepLinkItem = that._elements["item"][deepLinkItemIdx]; 215 if (deepLinkItem && !deepLinkItem.hasAttribute(dataAttributes.item.expanded)) { 216 // if single expansion: close all accordion items 217 if (that._properties.singleExpansion) { 218 for (var j = 0; j < that._elements["item"].length; j++) { 219 if (that._elements["item"][j].hasAttribute(dataAttributes.item.expanded)) { 220 setItemExpanded(that._elements["item"][j], false, true); 221 } 222 } 223 } 224 // expand the accordion item containing the deep link 225 setItemExpanded(deepLinkItem, true, true); 226 } 227 var hashId = window.location.hash.substring(1); 228 if (hashId) { 229 var hashItem = document.querySelector("[id='" + hashId + "']"); 230 if (hashItem) { 231 hashItem.scrollIntoView(); 232 } 233 } 234 } 235 } 236 } 237 238 /** 239 * Caches the Accordion elements as defined via the {@code data-accordion-hook="ELEMENT_NAME"} markup API. 240 * 241 * @private 242 * @param {HTMLElement} wrapper The Accordion wrapper element 243 */ 244 function cacheElements(wrapper) { 245 that._elements = {}; 246 that._elements.self = wrapper; 247 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 248 249 for (var i = 0; i < hooks.length; i++) { 250 var hook = hooks[i]; 251 if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own accordion elements 252 var capitalized = IS; 253 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 254 var key = hook.dataset[NS + "Hook" + capitalized]; 255 if (that._elements[key]) { 256 if (!Array.isArray(that._elements[key])) { 257 var tmp = that._elements[key]; 258 that._elements[key] = [tmp]; 259 } 260 that._elements[key].push(hook); 261 } else { 262 that._elements[key] = hook; 263 } 264 } 265 } 266 } 267 268 /** 269 * Sets up properties for the Accordion based on the passed options. 270 * 271 * @private 272 * @param {Object} options The Accordion options 273 */ 274 function setupProperties(options) { 275 that._properties = {}; 276 277 for (var key in properties) { 278 if (Object.prototype.hasOwnProperty.call(properties, key)) { 279 var property = properties[key]; 280 var value = null; 281 282 if (options && options[key] != null) { 283 value = options[key]; 284 285 // transform the provided option 286 if (property && typeof property.transform === "function") { 287 value = property.transform(value); 288 } 289 } 290 291 if (value === null) { 292 // value still null, take the property default 293 value = properties[key]["default"]; 294 } 295 296 that._properties[key] = value; 297 } 298 } 299 } 300 301 /** 302 * Binds Accordion event handling. 303 * 304 * @private 305 */ 306 function bindEvents() { 307 window.addEventListener("hashchange", scrollToDeepLinkIdInAccordion, false); 308 var buttons = that._elements["button"]; 309 if (buttons) { 310 for (var i = 0; i < buttons.length; i++) { 311 (function(index) { 312 buttons[i].addEventListener("click", function(event) { 313 toggle(index); 314 focusButton(index); 315 }); 316 buttons[i].addEventListener("keydown", function(event) { 317 onButtonKeyDown(event, index); 318 }); 319 })(i); 320 } 321 } 322 } 323 324 /** 325 * Handles button keydown events. 326 * 327 * @private 328 * @param {Object} event The keydown event 329 * @param {Number} index The index of the button triggering the event 330 */ 331 function onButtonKeyDown(event, index) { 332 var lastIndex = that._elements["button"].length - 1; 333 334 switch (event.keyCode) { 335 case keyCodes.ARROW_LEFT: 336 case keyCodes.ARROW_UP: 337 event.preventDefault(); 338 if (index > 0) { 339 focusButton(index - 1); 340 } 341 break; 342 case keyCodes.ARROW_RIGHT: 343 case keyCodes.ARROW_DOWN: 344 event.preventDefault(); 345 if (index < lastIndex) { 346 focusButton(index + 1); 347 } 348 break; 349 case keyCodes.HOME: 350 event.preventDefault(); 351 focusButton(0); 352 break; 353 case keyCodes.END: 354 event.preventDefault(); 355 focusButton(lastIndex); 356 break;
357 case keyCodes.ENTER: 358 case keyCodes.SPACE: 359 event.preventDefault(); 360 toggle(index); 361 focusButton(index); 362 break; 363 default: 364 return; 365 } 366 } 367 368 /** 369 * General handler for toggle of an item. 370 * 371 * @private 372 * @param {Number} index The index of the item to toggle 373 */ 374 function toggle(index) { 375 var item = that._elements["item"][index]; 376 if (item) { 377 if (that._properties.singleExpansion) { 378 // ensure only a single item is expanded if single expansion is enabled. 379 for (var i = 0; i < that._elements["item"].length; i++) { 380 if (that._elements["item"][i] !== item) { 381 var expanded = getItemExpanded(that._elements["item"][i]); 382 if (expanded) { 383 setItemExpanded(that._elements["item"][i], false); 384 } 385 } 386 } 387 } 388 setItemExpanded(item, !getItemExpanded(item)); 389 390 if (dataLayerEnabled) { 391 var accordionId = that._elements.self.id; 392 var expandedItems = getExpandedItems() 393 .map(function(item) { 394 return getDataLayerId(item); 395 }); 396 397 var uploadPayload = { component: {} }; 398 uploadPayload.component[accordionId] = { shownItems: expandedItems }; 399 400 var removePayload = { component: {} }; 401 removePayload.component[accordionId] = { shownItems: undefined }; 402 403 dataLayer.push(removePayload); 404 dataLayer.push(uploadPayload); 405 } 406 } 407 } 408 409 /** 410 * Sets an item's expanded state based on the provided flag and refreshes its internals. 411 * 412 * @private 413 * @param {HTMLElement} item The item to mark as expanded, or not expanded 414 * @param {Boolean} expanded true to mark the item expanded, false otherwise 415 * @param {Boolean} keepHash true to keep the hash in the URL, false to update it 416 */ 417 function setItemExpanded(item, expanded, keepHash) { 418 if (expanded) { 419 item.setAttribute(dataAttributes.item.expanded, ""); 420 var index = that._elements["item"].indexOf(item); 421 if (!keepHash && containerUtils) { 422 containerUtils.updateUrlHash(that, "item", index); 423 } 424 if (dataLayerEnabled) { 425 dataLayer.push({ 426 event: "cmp:show", 427 eventInfo: { 428 path: "component." + getDataLayerId(item) 429 } 430 }); 431 } 432 433 } else { 434 item.removeAttribute(dataAttributes.item.expanded); 435 if (!keepHash && containerUtils) { 436 containerUtils.removeUrlHash(); 437 } 438 if (dataLayerEnabled) { 439 dataLayer.push({ 440 event: "cmp:hide", 441 eventInfo: { 442 path: "component." + getDataLayerId(item) 443 } 444 }); 445 } 446 } 447 refreshItem(item); 448 } 449 450 /** 451 * Gets an item's expanded state. 452 * 453 * @private 454 * @param {HTMLElement} item The item for checking its expanded state 455 * @returns {Boolean} true if the item is expanded, false otherwise 456 */ 457 function getItemExpanded(item) { 458 return item && item.dataset && item.dataset["cmpExpanded"] !== undefined; 459 } 460 461 /** 462 * Refreshes an item based on its expanded state. 463 * 464 * @private 465 * @param {HTMLElement} item The item to refresh 466 */ 467 function refreshItem(item) { 468 var expanded = getItemExpanded(item); 469 if (expanded) { 470 expandItem(item); 471 } else { 472 collapseItem(item); 473 } 474 } 475 476 /** 477 * Refreshes all items based on their expanded state. 478 * 479 * @private 480 */ 481 function refreshItems() { 482 for (var i = 0; i < that._elements["item"].length; i++) { 483 refreshItem(that._elements["item"][i]); 484 } 485 } 486 487 /** 488 * Returns all expanded items. 489 * 490 * @private 491 * @returns {HTMLElement[]} The expanded items 492 */ 493 function getExpandedItems() { 494 var expandedItems = []; 495 496 for (var i = 0; i < that._elements["item"].length; i++) { 497 var item = that._elements["item"][i]; 498 var expanded = getItemExpanded(item); 499 if (expanded) { 500 expandedItems.push(item); 501 } 502 } 503 504 return expandedItems; 505 } 506 507 /** 508 * Annotates the item and its internals with 509 * the necessary style and accessibility attributes to indicate it is expanded. 510 * 511 * @private 512 * @param {HTMLElement} item The item to annotate as expanded 513 */ 514 function expandItem(item) { 515 var index = that._elements["item"].indexOf(item); 516 if (index > -1) { 517 var button = that._elements["button"][index]; 518 var panel = that._elements["panel"][index];
519 button.classList.add(cssClasses.button.expanded); 520 // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute 521 // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934 522 setTimeout(function() { 523 button.setAttribute("aria-expanded", true); 524 }, delay); 525 panel.classList.add(cssClasses.panel.expanded); 526 panel.classList.remove(cssClasses.panel.hidden); 527 panel.setAttribute("aria-hidden", false); 528 } 529 } 530 531 /** 532 * Annotates the item and its internals with 533 * the necessary style and accessibility attributes to indicate it is not expanded. 534 * 535 * @private 536 * @param {HTMLElement} item The item to annotate as not expanded 537 */ 538 function collapseItem(item) { 539 var index = that._elements["item"].indexOf(item); 540 if (index > -1) { 541 var button = that._elements["button"][index]; 542 var panel = that._elements["panel"][index]; 543 button.classList.remove(cssClasses.button.expanded); 544 // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute 545 // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934 546 setTimeout(function() { 547 button.setAttribute("aria-expanded", false); 548 }, delay); 549 panel.classList.add(cssClasses.panel.hidden); 550 panel.classList.remove(cssClasses.panel.expanded); 551 panel.setAttribute("aria-hidden", true); 552 } 553 } 554 555 /** 556 * Focuses the button at the provided index. 557 * 558 * @private 559 * @param {Number} index The index of the button to focus 560 */ 561 function focusButton(index) { 562 var button = that._elements["button"][index]; 563 button.focus(); 564 } 565 } 566 567 /** 568 * Reads options data from the Accordion wrapper element, defined via {@code data-cmp-*} data attributes. 569 * 570 * @private 571 * @param {HTMLElement} element The Accordion element to read options data from 572 * @returns {Object} The options read from the component data attributes 573 */ 574 function readData(element) { 575 var data = element.dataset; 576 var options = []; 577 var capitalized = IS; 578 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 579 var reserved = ["is", "hook" + capitalized]; 580 581 for (var key in data) { 582 if (Object.prototype.hasOwnProperty.call(data, key)) { 583 var value = data[key]; 584 585 if (key.indexOf(NS) === 0) { 586 key = key.slice(NS.length); 587 key = key.charAt(0).toLowerCase() + key.substring(1); 588 589 if (reserved.indexOf(key) === -1) { 590 options[key] = value; 591 } 592 } 593 } 594 } 595 596 return options; 597 } 598 599 /** 600 * Parses the dataLayer string and returns the ID 601 * 602 * @private 603 * @param {HTMLElement} item the accordion item 604 * @returns {String} dataLayerId or undefined 605 */ 606 function getDataLayerId(item) { 607 if (item) { 608 if (item.dataset.cmpDataLayer) { 609 return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0]; 610 } else { 611 return item.id; 612 } 613 } 614 return null; 615 } 616 617 /** 618 * Document ready handler and DOM mutation observers. Initializes Accordion components as necessary. 619 * 620 * @private 621 */ 622 function onDocumentReady() { 623 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 624 if (dataLayerEnabled) { 625 dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer"; 626 dataLayer = window[dataLayerName] = window[dataLayerName] || []; 627 } 628 629 var elements = document.querySelectorAll(selectors.self); 630 for (var i = 0; i < elements.length; i++) { 631 new Accordion({ element: elements[i], options: readData(elements[i]) }); 632 } 633 634 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 635 var body = document.querySelector("body"); 636 var observer = new MutationObserver(function(mutations) { 637 mutations.forEach(function(mutation) { 638 // needed for IE 639 var nodesArray = [].slice.call(mutation.addedNodes); 640 if (nodesArray.length > 0) { 641 nodesArray.forEach(function(addedNode) { 642 if (addedNode.querySelectorAll) { 643 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 644 elementsArray.forEach(function(element) { 645 new Accordion({ element: element, options: readData(element) }); 646 }); 647 } 648 }); 649 } 650 }); 651 }); 652 653 observer.observe(body, { 654 subtree: true, 655 childList: true, 656 characterData: true 657 }); 658 } 659 660 if (document.readyState !== "loading") { 661 onDocumentReady(); 662 } else { 663 document.addEventListener("DOMContentLoaded", onDocumentReady); 664 } 665 666 if (containerUtils) { 667 window.addEventListener("load", containerUtils.scrollToAnchor, false); 668 } 669 670}()); 671 672 673/******************************************************************************* 674 * Copyright 2018 Adobe 675 * 676 * Licensed under the Apache License, Version 2.0 (the "License");
677 * you may not use this file except in compliance with the License. 678 * You may obtain a copy of the License at 679 * 680 * http://www.apache.org/licenses/LICENSE2.0 681 * 682 * Unless required by applicable law or agreed to in writing, software 683 * distributed under the License is distributed on an "AS IS" BASIS, 684 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 685 * See the License for the specific language governing permissions and 686 * limitations under the License. 687 ******************************************************************************/ 688 689/** 690 * Element.matches() 691 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill 692 */ 693if (!Element.prototype.matches) { 694 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 695} 696 697// eslint-disable-next-line valid-jsdoc 698/** 699 * Element.closest() 700 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill 701 */ 702if (!Element.prototype.closest) { 703 Element.prototype.closest = function(s) { 704 "use strict"; 705 var el = this; 706 if (!document.documentElement.contains(el)) { 707 return null; 708 } 709 do { 710 if (el.matches(s)) { 711 return el; 712 } 713 el = el.parentElement || el.parentNode; 714 } while (el !== null && el.nodeType === 1); 715 return null; 716 }; 717} 718 719/******************************************************************************* 720 * Copyright 2018 Adobe 721 * 722 * Licensed under the Apache License, Version 2.0 (the "License"); 723 * you may not use this file except in compliance with the License. 724 * You may obtain a copy of the License at 725 * 726 * http://www.apache.org/licenses/LICENSE-2.0 727 * 728 * Unless required by applicable law or agreed to in writing, software 729 * distributed under the License is distributed on an "AS IS" BASIS, 730 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 731 * See the License for the specific language governing permissions and 732 * limitations under the License. 733 ******************************************************************************/ 734/* global 735 CQ 736 */ 737(function() { 738 "use strict"; 739 740 var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined; 741 if (!containerUtils) { 742 // eslint-disable-next-line no-console 743 console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page."); 744 } 745 var dataLayerEnabled; 746 var dataLayer; 747 var dataLayerName; 748 749 var NS = "cmp"; 750 var IS = "tabs"; 751 752 var keyCodes = { 753 END: 35, 754 HOME: 36, 755 ARROW_LEFT: 37, 756 ARROW_UP: 38, 757 ARROW_RIGHT: 39, 758 ARROW_DOWN: 40 759 }; 760 761 var selectors = { 762 self: "[data-" + NS + '-is="' + IS + '"]', 763 active: { 764 tab: "cmp-tabs__tab--active", 765 tabpanel: "cmp-tabs__tabpanel--active" 766 } 767 }; 768 769 /** 770 * Tabs Configuration 771 * 772 * @typedef {Object} TabsConfig Represents a Tabs configuration 773 * @property {HTMLElement} element The HTMLElement representing the Tabs 774 * @property {Object} options The Tabs options 775 */ 776 777 /** 778 * Tabs 779 * 780 * @class Tabs 781 * @classdesc An interactive Tabs component for navigating a list of tabs 782 * @param {TabsConfig} config The Tabs configuration 783 */ 784 function Tabs(config) { 785 var that = this; 786 787 if (config && config.element) { 788 init(config); 789 } 790 791 /** 792 * Initializes the Tabs 793 * 794 * @private 795 * @param {TabsConfig} config The Tabs configuration 796 */ 797 function init(config) { 798 that._config = config; 799 800 // prevents multiple initialization 801 config.element.removeAttribute("data-" + NS + "-is"); 802 803 cacheElements(config.element); 804 that._active = getActiveIndex(that._elements["tab"]); 805 806 if (that._elements.tabpanel) { 807 refreshActive(); 808 bindEvents(); 809 scrollToDeepLinkIdInTabs(); 810 } 811 812 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 813 /* 814 * Editor message handling: 815 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
816 * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component 817 * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data 818 */ 819 CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 820 CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 821 if (message.data && message.data.type === "cmp-tabs" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 822 if (message.data.operation === "navigate") { 823 navigate(message.data.index); 824 } 825 } 826 }); 827 } 828 } 829 830 /** 831 * Displays the panel containing the element that corresponds to the deep link in the URI fragment 832 * and scrolls the browser to this element. 833 */ 834 function scrollToDeepLinkIdInTabs() { 835 if (containerUtils) { 836 var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "tab", "tabpanel"); 837 if (deepLinkItemIdx > -1) { 838 var deepLinkItem = that._elements["tab"][deepLinkItemIdx]; 839 if (deepLinkItem && that._elements["tab"][that._active].id !== deepLinkItem.id) { 840 navigateAndFocusTab(deepLinkItemIdx, true); 841 } 842 var hashId = window.location.hash.substring(1); 843 if (hashId) { 844 var hashItem = document.querySelector("[id='" + hashId + "']"); 845 if (hashItem) { 846 hashItem.scrollIntoView(); 847 } 848 } 849 } 850 } 851 } 852 853 /** 854 * Returns the index of the active tab, if no tab is active returns 0 855 * 856 * @param {Array} tabs Tab elements 857 * @returns {Number} Index of the active tab, 0 if none is active 858 */ 859 function getActiveIndex(tabs) { 860 if (tabs) { 861 for (var i = 0; i < tabs.length; i++) { 862 if (tabs[i].classList.contains(selectors.active.tab)) { 863 return i; 864 } 865 } 866 } 867 return 0; 868 } 869 870 /** 871 * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API 872 * 873 * @private 874 * @param {HTMLElement} wrapper The Tabs wrapper element 875 */ 876 function cacheElements(wrapper) { 877 that._elements = {}; 878 that._elements.self = wrapper; 879 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 880 881 for (var i = 0; i < hooks.length; i++) { 882 var hook = hooks[i]; 883 if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own tab elements 884 var capitalized = IS; 885 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 886 var key = hook.dataset[NS + "Hook" + capitalized]; 887 if (that._elements[key]) { 888 if (!Array.isArray(that._elements[key])) { 889 var tmp = that._elements[key]; 890 that._elements[key] = [tmp]; 891 } 892 that._elements[key].push(hook); 893 } else { 894 that._elements[key] = hook; 895 } 896 } 897 } 898 } 899 900 /** 901 * Binds Tabs event handling 902 * 903 * @private 904 */ 905 function bindEvents() { 906 window.addEventListener("hashchange", scrollToDeepLinkIdInTabs, false); 907 var tabs = that._elements["tab"]; 908 if (tabs) { 909 for (var i = 0; i < tabs.length; i++) { 910 (function(index) { 911 tabs[i].addEventListener("click", function(event) { 912 navigateAndFocusTab(index); 913 }); 914 tabs[i].addEventListener("keydown", function(event) { 915 onKeyDown(event); 916 }); 917 })(i); 918 } 919 } 920 } 921 922 /** 923 * Handles tab keydown events 924 * 925 * @private 926 * @param {Object} event The keydown event 927 */ 928 function onKeyDown(event) { 929 var index = that._active; 930 var lastIndex = that._elements["tab"].length - 1; 931 932 switch (event.keyCode) { 933 case keyCodes.ARROW_LEFT: 934 case keyCodes.ARROW_UP: 935 event.preventDefault(); 936 if (index > 0) { 937 navigateAndFocusTab(index - 1); 938 } 939 break; 940 case keyCodes.ARROW_RIGHT: 941 case keyCodes.ARROW_DOWN: 942 event.preventDefault(); 943 if (index < lastIndex) { 944 navigateAndFocusTab(index + 1); 945 } 946 break; 947 case keyCodes.HOME: 948 event.preventDefault(); 949 navigateAndFocusTab(0); 950 break; 951 case keyCodes.END: 952 event.preventDefault(); 953 navigateAndFocusTab(lastIndex); 954 break; 955 default: 956 return; 957 } 958 } 959 960 /** 961 * Refreshes the tab markup based on the current {@code Tabs#_active} index 962 * 963 * @private 964 */ 965 function refreshActive() { 966 var tabpanels = that._elements["tabpanel"]; 967 var tabs = that._elements["tab"]; 968 969 if (tabpanels) { 970 if (Array.isArray(tabpanels)) { 971 for (var i = 0; i < tabpanels.length; i++) { 972 if (i === parseInt(that._active)) { 973 tabpanels[i].classList.add(selectors.active.tabpanel); 974 tabpanels[i].removeAttribute("aria-hidden"); 975 tabs[i].classList.add(selectors.active.tab); 976 tabs[i].setAttribute("aria-selected", true); 977 tabs[i].setAttribute("tabindex", "0"); 978 } else { 979 tabpanels[i].classList.remove(selectors.active.tabpanel); 980 tabpanels[i].setAttribute("aria-hidden", true); 981 tabs[i].classList.remove(selectors.active.tab); 982 tabs[i].setAttribute("aria-selected", false); 983 tabs[i].setAttribute("tabindex", "-1"); 984 } 985 } 986 } else { 987 // only one tab 988 tabpanels.classList.add(selectors.active.tabpanel); 989 tabs.classList.add(selectors.active.tab); 990 } 991 } 992 } 993 994 /** 995 * Focuses the element and prevents scrolling the element into view 996 * 997 * @param {HTMLElement} element Element to focus 998 */ 999 function focusWithoutScroll(element) { 1000 var x = window.scrollX || window.pageXOffset; 1001 var y = window.scrollY || window.pageYOffset; 1002 element.focus(); 1003 window.scrollTo(x, y); 1004 } 1005 1006 /** 1007 * Navigates to the tab at the provided index 1008 * 1009 * @private 1010 * @param {Number} index The index of the tab to navigate to 1011 */ 1012 function navigate(index) { 1013 that._active = index; 1014 refreshActive(); 1015 } 1016 1017 /** 1018 * Navigates to the item at the provided index and ensures the active tab gains focus 1019 * 1020 * @private 1021 * @param {Number} index The index of the item to navigate to 1022 * @param {Boolean} keepHash true to keep the hash in the URL, false to update it 1023 */ 1024 function navigateAndFocusTab(index, keepHash) { 1025 var exActive = that._active; 1026 if (!keepHash && containerUtils) { 1027 containerUtils.updateUrlHash(that, "tab", index); 1028 } 1029 navigate(index); 1030 focusWithoutScroll(that._elements["tab"][index]); 1031 1032 if (dataLayerEnabled) { 1033 1034 var activeItem = getDataLayerId(that._elements.tabpanel[index]); 1035 var exActiveItem = getDataLayerId(that._elements.tabpanel[exActive]); 1036 1037 dataLayer.push({ 1038 event: "cmp:show", 1039 eventInfo: { 1040 path: "component." + activeItem 1041 } 1042 }); 1043 1044 dataLayer.push({ 1045 event: "cmp:hide", 1046 eventInfo: { 1047 path: "component." + exActiveItem 1048 } 1049 }); 1050 1051 var tabsId = that._elements.self.id; 1052 var uploadPayload = { component: {} }; 1053 uploadPayload.component[tabsId] = { shownItems: [activeItem] }; 1054 1055 var removePayload = { component: {} }; 1056 removePayload.component[tabsId] = { shownItems: undefined }; 1057 1058 dataLayer.push(removePayload); 1059 dataLayer.push(uploadPayload); 1060 } 1061 } 1062 } 1063 1064 /**
1065 * Reads options data from the Tabs wrapper element, defined via {@code data-cmp-*} data attributes 1066 * 1067 * @private 1068 * @param {HTMLElement} element The Tabs element to read options data from 1069 * @returns {Object} The options read from the component data attributes 1070 */ 1071 function readData(element) { 1072 var data = element.dataset; 1073 var options = []; 1074 var capitalized = IS; 1075 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1076 var reserved = ["is", "hook" + capitalized]; 1077 1078 for (var key in data) { 1079 if (Object.prototype.hasOwnProperty.call(data, key)) { 1080 var value = data[key]; 1081 1082 if (key.indexOf(NS) === 0) { 1083 key = key.slice(NS.length); 1084 key = key.charAt(0).toLowerCase() + key.substring(1); 1085 1086 if (reserved.indexOf(key) === -1) { 1087 options[key] = value; 1088 } 1089 } 1090 } 1091 } 1092 1093 return options; 1094 } 1095 1096 /** 1097 * Parses the dataLayer string and returns the ID 1098 * 1099 * @private 1100 * @param {HTMLElement} item the accordion item 1101 * @returns {String} dataLayerId or undefined 1102 */ 1103 function getDataLayerId(item) { 1104 if (item) { 1105 if (item.dataset.cmpDataLayer) { 1106 return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0]; 1107 } else { 1108 return item.id; 1109 } 1110 } 1111 return null; 1112 } 1113 1114 /** 1115 * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary. 1116 * 1117 * @private 1118 */ 1119 function onDocumentReady() { 1120 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 1121 if (dataLayerEnabled) { 1122 dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer"; 1123 dataLayer = window[dataLayerName] = window[dataLayerName] || []; 1124 } 1125 1126 var elements = document.querySelectorAll(selectors.self); 1127 for (var i = 0; i < elements.length; i++) { 1128 new Tabs({ element: elements[i], options: readData(elements[i]) }); 1129 } 1130 1131 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 1132 var body = document.querySelector("body"); 1133 var observer = new MutationObserver(function(mutations) { 1134 mutations.forEach(function(mutation) { 1135 // needed for IE 1136 var nodesArray = [].slice.call(mutation.addedNodes); 1137 if (nodesArray.length > 0) { 1138 nodesArray.forEach(function(addedNode) { 1139 if (addedNode.querySelectorAll) { 1140 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 1141 elementsArray.forEach(function(element) { 1142 new Tabs({ element: element, options: readData(element) }); 1143 }); 1144 } 1145 }); 1146 } 1147 }); 1148 }); 1149 1150 observer.observe(body, { 1151 subtree: true, 1152 childList: true, 1153 characterData: true 1154 }); 1155 } 1156 1157 if (document.readyState !== "loading") { 1158 onDocumentReady(); 1159 } else { 1160 document.addEventListener("DOMContentLoaded", onDocumentReady); 1161 } 1162 1163 if (containerUtils) { 1164 window.addEventListener("load", containerUtils.scrollToAnchor, false); 1165 } 1166 1167}()); 1168 1169 1170/******************************************************************************* 1171 * Copyright 2018 Adobe 1172 * 1173 * Licensed under the Apache License, Version 2.0 (the "License"); 1174 * you may not use this file except in compliance with the License. 1175 * You may obtain a copy of the License at 1176 * 1177 * http://www.apache.org/licenses/LICENSE2.0 1178 * 1179 * Unless required by applicable law or agreed to in writing, software 1180 * distributed under the License is distributed on an "AS IS" BASIS, 1181 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1182 * See the License for the specific language governing permissions and 1183 * limitations under the License. 1184 ******************************************************************************/ 1185 1186/** 1187 * Element.matches() 1188 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill 1189 */ 1190if (!Element.prototype.matches) { 1191 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 1192} 1193 1194// eslint-disable-next-line valid-jsdoc 1195/** 1196 * Element.closest() 1197 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill 1198 */ 1199if (!Element.prototype.closest) { 1200 Element.prototype.closest = function(s) { 1201 "use strict"; 1202 var el = this; 1203 if (!document.documentElement.contains(el)) { 1204 return null; 1205 } 1206 do { 1207 if (el.matches(s)) { 1208 return el; 1209 } 1210 el = el.parentElement || el.parentNode; 1211 } while (el !== null && el.nodeType === 1); 1212 return null; 1213 }; 1214} 1215 1216/******************************************************************************* 1217 * Copyright 2018 Adobe 1218 * 1219 * Licensed under the Apache License, Version 2.0 (the "License");
1220 * you may not use this file except in compliance with the License. 1221 * You may obtain a copy of the License at 1222 * 1223 * http://www.apache.org/licenses/LICENSE-2.0 1224 * 1225 * Unless required by applicable law or agreed to in writing, software 1226 * distributed under the License is distributed on an "AS IS" BASIS, 1227 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1228 * See the License for the specific language governing permissions and 1229 * limitations under the License. 1230 ******************************************************************************/ 1231/* global 1232 CQ 1233 */ 1234(function() { 1235 "use strict"; 1236 1237 var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined; 1238 if (!containerUtils) { 1239 // eslint-disable-next-line no-console 1240 console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page."); 1241 } 1242 var dataLayerEnabled; 1243 var dataLayer; 1244 1245 var NS = "cmp"; 1246 var IS = "tabs"; 1247 1248 var keyCodes = { 1249 END: 35, 1250 HOME: 36, 1251 ARROW_LEFT: 37, 1252 ARROW_UP: 38, 1253 ARROW_RIGHT: 39, 1254 ARROW_DOWN: 40 1255 }; 1256 1257 var selectors = { 1258 self: "[data-" + NS + '-is="' + IS + '"]', 1259 active: { 1260 tab: "cmp-tabs__tab--active", 1261 tabpanel: "cmp-tabs__tabpanel--active" 1262 } 1263 }; 1264 1265 /** 1266 * Tabs Configuration 1267 * 1268 * @typedef {Object} TabsConfig Represents a Tabs configuration 1269 * @property {HTMLElement} element The HTMLElement representing the Tabs 1270 * @property {Object} options The Tabs options 1271 */ 1272 1273 /** 1274 * Tabs 1275 * 1276 * @class Tabs 1277 * @classdesc An interactive Tabs component for navigating a list of tabs 1278 * @param {TabsConfig} config The Tabs configuration 1279 */ 1280 function Tabs(config) { 1281 var that = this; 1282 1283 if (config && config.element) { 1284 init(config); 1285 } 1286 1287 /** 1288 * Initializes the Tabs 1289 * 1290 * @private 1291 * @param {TabsConfig} config The Tabs configuration 1292 */ 1293 function init(config) { 1294 // debugger; 1295 that._config = config; 1296 1297 // prevents multiple initialization 1298 config.element.removeAttribute("data-" + NS + "-is"); 1299 1300 cacheElements(config.element); 1301 that._active = getActiveIndex(that._elements["tab"]); 1302 1303 if (that._elements.tabpanel) { 1304 // debugger; 1305 refreshActive(); 1306 bindEvents(); 1307 scrollToDeepLinkIdInTabs(); 1308 } 1309 1310 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 1311 /* 1312 * Editor message handling: 1313 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame 1314 * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component 1315 * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data 1316 */ 1317 CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 1318 CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 1319 if (message.data && message.data.type === "cmp-tabs" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 1320 if (message.data.operation === "navigate") { 1321 navigate(message.data.index); 1322 } 1323 } 1324 }); 1325 } 1326 } 1327 1328 /** 1329 * Displays the panel containing the element that corresponds to the deep link in the URI fragment 1330 * and scrolls the browser to this element. 1331 */ 1332 function scrollToDeepLinkIdInTabs() { 1333 // debugger; 1334 if (containerUtils) { 1335 var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "tab", "tabpanel"); 1336 if (deepLinkItemIdx > -1) { 1337 var deepLinkItem = that._elements["tab"][deepLinkItemIdx]; 1338 if (deepLinkItem && that._elements["tab"][that._active].id !== deepLinkItem.id) { 1339 navigateAndFocusTab(deepLinkItemIdx, true); 1340 } 1341 var hashId = window.location.hash.substring(1); 1342 if (hashId) { 1343 var hashItem = document.querySelector("[id='" + hashId + "']"); 1344 if (hashItem) { 1345 hashItem.scrollIntoView(); 1346 } 1347 } 1348 } 1349 } 1350 } 1351 1352 /** 1353 * Returns the index of the active tab, if no tab is active returns 0 1354 * 1355 * @param {Array} tabs Tab elements 1356 * @returns {Number} Index of the active tab, 0 if none is active 1357 */ 1358 function getActiveIndex(tabs) { 1359 if (tabs) { 1360 for (var i = 0; i < tabs.length; i++) { 1361 if (tabs[i].classList.contains(selectors.active.tab) && tabs[i].classList.contains("nav-link h-100 active")) { 1362 return i; 1363 } 1364 } 1365 } 1366 return 0; 1367 } 1368 1369 /** 1370 * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API 1371 * 1372 * @private 1373 * @param {HTMLElement} wrapper The Tabs wrapper element 1374 */ 1375 function cacheElements(wrapper) { 1376 that._elements = {}; 1377 that._elements.self = wrapper; 1378 // var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 1379 var all = that._elements.self.getElementsByTagName("*"); 1380 var hooks = []; 1381 1382 for (var i = 0; i < all.length; i++) { 1383 var el = all[i]; 1384 if (el.hasAttribute("data-" + NS + "-hook-" + IS)) { 1385 hooks.push(el); 1386 } 1387 } 1388 1389 for (var i = 0; i < hooks.length; i++) { 1390 var hook = hooks[i]; 1391 if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own tab elements 1392 var capitalized = IS; 1393 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1394 var key = hook.dataset[NS + "Hook" + capitalized]; 1395 if (that._elements[key]) { 1396 if (!Array.isArray(that._elements[key])) { 1397 var tmp = that._elements[key]; 1398 that._elements[key] = [tmp]; 1399 } 1400 that._elements[key].push(hook); 1401 } else { 1402 that._elements[key] = hook; 1403 } 1404 } 1405 } 1406 } 1407 1408 /** 1409 * Binds Tabs event handling 1410 * 1411 * @private 1412 */ 1413 function bindEvents() { 1414 window.addEventListener("hashchange", scrollToDeepLinkIdInTabs, false); 1415 var tabs = that._elements["tab"]; 1416 if (tabs) { 1417 for (var i = 0; i < tabs.length; i++) { 1418 (function(index) { 1419 tabs[i].addEventListener("click", function(event) { 1420 navigateAndFocusTab(index); 1421 }); 1422 tabs[i].addEventListener("keydown", function(event) { 1423 onKeyDown(event); 1424 }); 1425 })(i); 1426 } 1427 } 1428 } 1429 1430 /** 1431 * Handles tab keydown events 1432 * 1433 * @private 1434 * @param {Object} event The keydown event 1435 */ 1436 function onKeyDown(event) { 1437 var index = that._active; 1438 var lastIndex = that._elements["tab"].length - 1; 1439 1440 switch (event.keyCode) { 1441 case keyCodes.ARROW_LEFT: 1442 case keyCodes.ARROW_UP: 1443 event.preventDefault(); 1444 if (index > 0) { 1445 navigateAndFocusTab(index - 1); 1446 } 1447 break; 1448 case keyCodes.ARROW_RIGHT: 1449 case keyCodes.ARROW_DOWN: 1450 event.preventDefault(); 1451 if (index < lastIndex) { 1452 navigateAndFocusTab(index + 1); 1453 } 1454 break; 1455 case keyCodes.HOME: 1456 event.preventDefault(); 1457 navigateAndFocusTab(0); 1458 break; 1459 case keyCodes.END: 1460 event.preventDefault(); 1461 navigateAndFocusTab(lastIndex); 1462 break; 1463 default: 1464 return; 1465 } 1466 } 1467 1468 /** 1469 * Refreshes the tab markup based on the current {@code Tabs#_active} index 1470 * 1471 * @private 1472 */ 1473 function refreshActive() { 1474 var tabpanels = that._elements["tabpanel"]; 1475 var tabs = that._elements["tab"]; 1476 1477 if (tabpanels) { 1478 if (Array.isArray(tabpanels)) { 1479 for (var i = 0; i < tabpanels.length; i++) { 1480 if (i === parseInt(that._active)) { 1481 tabpanels[i].classList.add(selectors.active.tabpanel); 1482 tabpanels[i].removeAttribute("aria-hidden"); 1483 tabs[i].classList.add(selectors.active.tab); 1484 tabs[i].classList.add("active"); 1485 tabs[i].setAttribute("aria-selected", true); 1486 tabs[i].setAttribute("tabindex", "0"); 1487 } else { 1488 tabpanels[i].classList.remove(selectors.active.tabpanel); 1489 tabpanels[i].setAttribute("aria-hidden", true); 1490 tabs[i].classList.remove(selectors.active.tab); 1491 tabs[i].classList.remove("active"); 1492 tabs[i].setAttribute("aria-selected", false); 1493 tabs[i].setAttribute("tabindex", "-1"); 1494 } 1495 } 1496 } else { 1497 // only one tab 1498 tabpanels.classList.add(selectors.active.tabpanel); 1499 tabs.classList.add(selectors.active.tab); 1500 } 1501 } 1502 } 1503 1504 /** 1505 * Focuses the element and prevents scrolling the element into view 1506 * 1507 * @param {HTMLElement} element Element to focus 1508 */ 1509 function focusWithoutScroll(element) { 1510 var x = window.scrollX || window.pageXOffset; 1511 var y = window.scrollY || window.pageYOffset; 1512 element.focus(); 1513 window.scrollTo(x, y); 1514 } 1515 1516 /** 1517 * Navigates to the tab at the provided index 1518 * 1519 * @private 1520 * @param {Number} index The index of the tab to navigate to 1521 */ 1522 function navigate(index) { 1523 that._active = index; 1524 refreshActive(); 1525 } 1526 1527 /** 1528 * Navigates to the item at the provided index and ensures the active tab gains focus 1529 * 1530 * @private 1531 * @param {Number} index The index of the item to navigate to 1532 * @param {Boolean} keepHash true to keep the hash in the URL, false to update it 1533 */ 1534 function navigateAndFocusTab(index, keepHash) { 1535 //debugger; 1536 var exActive = that._active; 1537 if (!keepHash && containerUtils) { 1538 containerUtils.updateUrlHash(that, "tab", index); 1539 } 1540 navigate(index); 1541 focusWithoutScroll(that._elements["tab"][index]); 1542 1543 if (dataLayerEnabled) { 1544 1545 var activeItem = getDataLayerId(that._elements.tabpanel[index]); 1546 var exActiveItem = getDataLayerId(that._elements.tabpanel[exActive]); 1547 1548 dataLayer.push({ 1549 event: "cmp:show", 1550 eventInfo: { 1551 path: "component." + activeItem 1552 } 1553 }); 1554 1555 dataLayer.push({ 1556 event: "cmp:hide", 1557 eventInfo: { 1558 path: "component." + exActiveItem 1559 } 1560 }); 1561 1562 var tabsId = that._elements.self.id; 1563 var uploadPayload = { component: {} }; 1564 uploadPayload.component[tabsId] = { shownItems: [activeItem] }; 1565 1566 var removePayload = { component: {} }; 1567 removePayload.component[tabsId] = { shownItems: undefined }; 1568 1569 dataLayer.push(removePayload); 1570 dataLayer.push(uploadPayload); 1571 } 1572 } 1573 } 1574 1575 /**
1576 * Reads options data from the Tabs wrapper element, defined via {@code data-cmp-*} data attributes 1577 * 1578 * @private 1579 * @param {HTMLElement} element The Tabs element to read options data from 1580 * @returns {Object} The options read from the component data attributes 1581 */ 1582 function readData(element) { 1583 var data = element.dataset; 1584 var options = []; 1585 var capitalized = IS; 1586 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1587 var reserved = ["is", "hook" + capitalized]; 1588 1589 for (var key in data) { 1590 if (Object.prototype.hasOwnProperty.call(data, key)) { 1591 var value = data[key]; 1592 1593 if (key.indexOf(NS) === 0) { 1594 key = key.slice(NS.length); 1595 key = key.charAt(0).toLowerCase() + key.substring(1); 1596 1597 if (reserved.indexOf(key) === -1) { 1598 options[key] = value; 1599 } 1600 } 1601 } 1602 } 1603 1604 return options; 1605 } 1606 1607 /** 1608 * Parses the dataLayer string and returns the ID 1609 * 1610 * @private 1611 * @param {HTMLElement} item the accordion item 1612 * @returns {String} dataLayerId or undefined 1613 */ 1614 function getDataLayerId(item) { 1615 if (item) { 1616 if (item.dataset.cmpDataLayer) { 1617 try { 1618 return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0]; 1619 } catch (e) { 1620 console.error("Errore nel parsing di cmpDataLayer:", e); 1621 return null; 1622 } 1623 } else { 1624 return item.id; 1625 } 1626 } 1627 return null; 1628 } 1629 1630 /** 1631 * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary. 1632 * 1633 * @private 1634 */ 1635 function onDocumentReady() { 1636 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 1637 dataLayer = (dataLayerEnabled) ? window.adobeDataLayer = window.adobeDataLayer || [] : undefined; 1638 1639 // var elements = document.querySelectorAll(selectors.self); 1640 var all = document.getElementsByTagName("*"); 1641 var elements = []; 1642 1643 for (var i = 0; i < all.length; i++) { 1644 var el = all[i]; 1645 if (el.hasAttribute("data-" + NS + "-hook-" + IS)) { 1646 elements.push(el); 1647 } 1648 } 1649 for (var i = 0; i < elements.length; i++) { 1650 new Tabs({ element: elements[i], options: readData(elements[i]) }); 1651 } 1652 1653 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 1654 // var body = document.querySelector("body"); 1655 var body = document.getElementsByTagName("body")[0]; 1656 var observer = new MutationObserver(function(mutations) { 1657 mutations.forEach(function(mutation) { 1658 // needed for IE 1659 var nodesArray = [].slice.call(mutation.addedNodes); 1660 if (nodesArray.length > 0) { 1661 nodesArray.forEach(function(addedNode) { 1662 if (addedNode instanceof Element) { 1663 var all = addedNode.getElementsByTagName("*"); 1664 var elements = []; 1665 1666 for (var i = 0; i < all.length; i++) { 1667 var el = all[i]; 1668 if (el.hasAttribute("data-" + NS + "-hook-" + IS)) { 1669 elements.push(el); 1670 } 1671 } 1672 var elementsArray = [].slice.call(elements); 1673 elementsArray.forEach(function(element) { 1674 new Tabs({ element: element, options: readData(element) }); 1675 }); 1676 } 1677 }); 1678 } 1679 }); 1680 }); 1681 1682 observer.observe(body, { 1683 subtree: true, 1684 childList: true, 1685 characterData: true 1686 }); 1687 1688 // debugger; 1689 let tabAnchorWithHash = window.location.hash; 1690 let tabAnchor = tabAnchorWithHash.replace('#', ""); 1691 let tabDivAnchor = tabAnchor.replace("-tab", "") 1692 let li = $('[role=tablist]').children() 1693 let anchorDivs = $('div[id*=tabsCustom][id*=item]') 1694 1695 1696 1697 if (tabAnchorWithHash) { 1698 $(li).each(function (i, li) { 1699 $(anchorDivs, li).each(function (ii, divs) { 1700 if ($(li).attr('id') == tabAnchor && $(divs).attr('id') == tabDivAnchor) { 1701 $(li).children().attr('class', 'nav-link h-100 cmp-tabs__tab cmp-tabs__tab--active') 1702 $(divs).attr('class', 'cmp-tabs__tabpanel cmp-tabs__tabpanel--active') 1703 } else { 1704 $(li).children().attr('class', 'nav-link h-100 cmp-tabs__tab') 1705 $(divs).attr('class', 'cmp-tabs__tabpanel') 1706 } 1707 }) 1708 }) 1709 } 1710 } 1711 1712 if (document.readyState !== "loading") { 1713 onDocumentReady(); 1714 } else { 1715 document.addEventListener("DOMContentLoaded", onDocumentReady); 1716 } 1717 1718 if (containerUtils) { 1719 window.addEventListener("load", containerUtils.scrollToAnchor, false); 1720 } 1721 1722}()); 1723 1724/******************************************************************************* 1725 * Copyright 2022 Adobe 1726 * 1727 * Licensed under the Apache License, Version 2.0 (the "License");
1728 * you may not use this file except in compliance with the License. 1729 * You may obtain a copy of the License at 1730 * 1731 * http://www.apache.org/licenses/LICENSE-2.0 1732 * 1733 * Unless required by applicable law or agreed to in writing, software 1734 * distributed under the License is distributed on an "AS IS" BASIS, 1735 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1736 * See the License for the specific language governing permissions and 1737 * limitations under the License. 1738 ******************************************************************************/ 1739(function(document) { 1740 "use strict"; 1741 1742 window.CMP = window.CMP || {}; 1743 window.CMP.utils = (function() { 1744 var NS = "cmp"; 1745 1746 /** 1747 * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes 1748 * 1749 * @param {HTMLElement} element The component element to read options data from 1750 * @param {String} is The component identifier 1751 * @returns {String[]} The options read from the component data attributes 1752 */ 1753 var readData = function(element, is) { 1754 var data = element.dataset; 1755 var options = []; 1756 var capitalized = is; 1757 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1758 var reserved = ["is", "hook" + capitalized]; 1759 1760 for (var key in data) { 1761 if (Object.prototype.hasOwnProperty.call(data, key)) { 1762 var value = data[key]; 1763 1764 if (key.indexOf(NS) === 0) { 1765 key = key.slice(NS.length); 1766 key = key.charAt(0).toLowerCase() + key.substring(1); 1767 1768 if (reserved.indexOf(key) === -1) { 1769 options[key] = value; 1770 } 1771 } 1772 } 1773 } 1774 return options; 1775 }; 1776 1777 /** 1778 * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand 1779 * @param {String[]} options the options to transform 1780 * @param {Object} properties object of properties of property functions 1781 * @returns {Object} transformed properties 1782 */ 1783 var setupProperties = function(options, properties) { 1784 var transformedProperties = {}; 1785 1786 for (var key in properties) { 1787 if (Object.prototype.hasOwnProperty.call(properties, key)) { 1788 var property = properties[key]; 1789 if (options && options[key] != null) { 1790 if (property && typeof property.transform === "function") { 1791 transformedProperties[key] = property.transform(options[key]); 1792 } else { 1793 transformedProperties[key] = options[key]; 1794 } 1795 } else { 1796 transformedProperties[key] = properties[key]["default"]; 1797 } 1798 } 1799 } 1800 return transformedProperties; 1801 }; 1802 1803 1804 return { 1805 readData: readData, 1806 setupProperties: setupProperties 1807 }; 1808 }()); 1809}(window.document)); 1810 1811/******************************************************************************* 1812 * Copyright 2018 Adobe 1813 * 1814 * Licensed under the Apache License, Version 2.0 (the "License"); 1815 * you may not use this file except in compliance with the License. 1816 * You may obtain a copy of the License at 1817 * 1818 * http://www.apache.org/licenses/LICENSE-2.0 1819 * 1820 * Unless required by applicable law or agreed to in writing, software 1821 * distributed under the License is distributed on an "AS IS" BASIS, 1822 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1823 * See the License for the specific language governing permissions and 1824 * limitations under the License. 1825 ******************************************************************************/ 1826(function() { 1827 "use strict"; 1828 1829 var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.c
1829ontainer && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined; 1830 if (!containerUtils) { 1831 // eslint-disable-next-line no-console 1832 console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page."); 1833 } 1834 var dataLayerEnabled; 1835 var dataLayer; 1836 var dataLayerName; 1837 1838 var NS = "cmp"; 1839 var IS = "carousel"; 1840 1841 var keyCodes = { 1842 SPACE: 32, 1843 END: 35, 1844 HOME: 36, 1845 ARROW_LEFT: 37, 1846 ARROW_UP: 38, 1847 ARROW_RIGHT: 39, 1848 ARROW_DOWN: 40 1849 }; 1850 1851 var selectors = { 1852 self: "[data-" + NS + '-is="' + IS + '"]' 1853 }; 1854 1855 var properties = { 1856 /** 1857 * Determines whether the Carousel will automatically transition between slides 1858 * 1859 * @memberof Carousel 1860 * @type {Boolean} 1861 * @default false 1862 */ 1863 "autoplay": { 1864 "default": false, 1865 "transform": function(value) { 1866 return !(value === null || typeof value === "undefined"); 1867 } 1868 }, 1869 /** 1870 * Duration (in milliseconds) before automatically transitioning to the next slide 1871 * 1872 * @memberof Carousel 1873 * @type {Number} 1874 * @default 5000 1875 */ 1876 "delay": { 1877 "default": 5000, 1878 "transform": function(value) { 1879 value = parseFloat(value); 1880 return !isNaN(value) ? value : null; 1881 } 1882 }, 1883 /** 1884 * Determines whether automatic pause on hovering the carousel is disabled 1885 * 1886 * @memberof Carousel 1887 * @type {Boolean} 1888 * @default false 1889 */ 1890 "autopauseDisabled": { 1891 "default": false, 1892 "transform": function(value) { 1893 return !(value === null || typeof value === "undefined"); 1894 } 1895 } 1896 }; 1897 1898 /** 1899 * Carousel Configuration 1900 * 1901 * @typedef {Object} CarouselConfig Represents a Carousel configuration 1902 * @property {HTMLElement} element The HTMLElement representing the Carousel 1903 * @property {*[]} options The Carousel options 1904 */ 1905 1906 /** 1907 * Carousel 1908 * 1909 * @class Carousel 1910 * @classdesc An interactive Carousel component for navigating a list of generic items 1911 * @param {CarouselConfig} config The Carousel configuration 1912 */ 1913 function Carousel(config) { 1914 var that = this; 1915 1916 if (config && config.element) { 1917 init(config); 1918 } 1919 1920 /** 1921 * Initializes the Carousel 1922 * 1923 * @private 1924 * @param {CarouselConfig} config The Carousel configuration 1925 */ 1926 function init(config) { 1927 that._config = config; 1928 1929 // prevents multiple initialization 1930 config.element.removeAttribute("data-" + NS + "-is"); 1931 1932 setupProperties(config.options); 1933 cacheElements(config.element); 1934 1935 that._active = 0; 1936 that._paused = false; 1937 1938 if (that._elements.item) { 1939 initializeActive(); 1940 bindEvents(); 1941 resetAutoplayInterval(); 1942 refreshPlayPauseActions(); 1943 scrollToDeepLinkIdInCarousel(); 1944 } 1945 1946 // TODO: This section is only relevant in edit mode and should move to the editor clientLib 1947 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 1948 /* 1949 * Editor message handling: 1950 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame 1951 * - check that the message data panel container type is correct and that the id (path) matches this specific Carousel component 1952 * - if so, route the "navigate" operation to enact a navigation of the Carousel based on index data 1953 */ 1954 window.CQ = window.CQ || {}; 1955 window.CQ.CoreComponents = window.CQ.CoreComponents || {}; 1956 window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 1957 window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 1958 if (message.data && message.data.type === "cmp-carousel" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 1959 if (message.data.operation === "navigate") { 1960 navigate(message.data.index); 1961 } 1962 } 1963 }); 1964 } 1965 } 1966 1967 /**
1968 * Displays the slide containing the element that corresponds to the deep link in the URI fragment 1969 * and scrolls the browser to this element. 1970 */ 1971 function scrollToDeepLinkIdInCarousel() { 1972 if (containerUtils) { 1973 var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "item", "item"); 1974 if (deepLinkItemIdx > -1) { 1975 var deepLinkItem = that._elements["item"][deepLinkItemIdx]; 1976 if (deepLinkItem && that._elements["item"][that._active].id !== deepLinkItem.id) { 1977 navigateAndFocusIndicator(deepLinkItemIdx, true); 1978 // pause the carousel auto-rotation 1979 pause(); 1980 } 1981 var hashId = window.location.hash.substring(1); 1982 if (hashId) { 1983 var hashItem = document.querySelector("[id='" + hashId + "']"); 1984 if (hashItem) { 1985 hashItem.scrollIntoView(); 1986 } 1987 } 1988 } 1989 } 1990 } 1991 1992 /** 1993 * Caches the Carousel elements as defined via the {@code data-carousel-hook="ELEMENT_NAME"} markup API 1994 * 1995 * @private 1996 * @param {HTMLElement} wrapper The Carousel wrapper element 1997 */ 1998 function cacheElements(wrapper) { 1999 that._elements = {}; 2000 that._elements.self = wrapper; 2001 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 2002 2003 for (var i = 0; i < hooks.length; i++) { 2004 var hook = hooks[i]; 2005 var capitalized = IS; 2006 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2007 var key = hook.dataset[NS + "Hook" + capitalized]; 2008 if (that._elements[key]) { 2009 if (!Array.isArray(that._elements[key])) { 2010 var tmp = that._elements[key]; 2011 that._elements[key] = [tmp]; 2012 } 2013 that._elements[key].push(hook); 2014 } else { 2015 that._elements[key] = hook; 2016 } 2017 } 2018 } 2019 2020 /** 2021 * Sets up properties for the Carousel based on the passed options. 2022 * 2023 * @private 2024 * @param {Object} options The Carousel options 2025 */ 2026 function setupProperties(options) { 2027 that._properties = {}; 2028 2029 for (var key in properties) { 2030 if (Object.prototype.hasOwnProperty.call(properties, key)) { 2031 var property = properties[key]; 2032 var value = null; 2033 2034 if (options && options[key] != null) { 2035 value = options[key]; 2036 2037 // transform the provided option 2038 if (property && typeof property.transform === "function") { 2039 value = property.transform(value); 2040 } 2041 } 2042 2043 if (value === null) { 2044 // value still null, take the property default 2045 value = properties[key]["default"]; 2046 } 2047 2048 that._properties[key] = value; 2049 } 2050 } 2051 } 2052 2053 /** 2054 * Binds Carousel event handling 2055 * 2056 * @private 2057 */ 2058 function bindEvents() { 2059 window.addEventListener("hashchange", scrollToDeepLinkIdInCarousel, false); 2060 if (that._elements["previous"]) { 2061 that._elements["previous"].addEventListener("click", function() { 2062 var index = getPreviousIndex(); 2063 navigate(index); 2064 if (dataLayerEnabled) { 2065 dataLayer.push({ 2066 event: "cmp:show", 2067 eventInfo: { 2068 path: "component." + getDataLayerId(that._elements.item[index]) 2069 } 2070 }); 2071 } 2072 }); 2073 } 2074 2075 if (that._elements["next"]) { 2076 that._elements["next"].addEventListener("click", function() { 2077 var index = getNextIndex(); 2078 navigate(index); 2079 if (dataLayerEnabled) { 2080 dataLayer.push({ 2081 event: "cmp:show", 2082 eventInfo: { 2083 path: "component." + getDataLayerId(that._elements.item[index]) 2084 } 2085 }); 2086 } 2087 }); 2088 } 2089 2090 var indicators = that._elements["indicator"]; 2091 if (indicators) { 2092 for (var i = 0; i < indicators.length; i++) { 2093 (function(index) { 2094 indicators[i].addEventListener("click", function(event) { 2095 navigateAndFocusIndicator(index); 2096 // pause the carousel auto-rotation 2097 pause(); 2098 }); 2099 })(i); 2100 } 2101 } 2102 2103 if (that._elements["pause"]) { 2104 if (that._properties.autoplay) { 2105 that._elements["pause"].addEventListener("click", onPauseClick); 2106 } 2107 } 2108 2109 if (that._elements["play"]) { 2110 if (that._properties.autoplay) { 2111 that._elements["play"].addEventListener("click", onPlayClick); 2112 } 2113 } 2114 2115 that._elements.self.addEventListener("keydown", onKeyDown); 2116 2117 if (!that._properties.autopauseDisabled) { 2118 that._elements.self.addEventListener("mouseenter", onMouseEnter); 2119 that._elements.self.addEventListener("mouseleave", onMouseLeave); 2120 } 2121 2122 // for accessibility we pause animation when a element get focused 2123 var items = that._elements["item"]; 2124 if (items) { 2125 for (var j = 0; j < items.length; j++) { 2126 items[j].addEventListener("focusin", onMouseEnter); 2127 items[j].addEventListener("focusout", onMouseLeave); 2128 } 2129 } 2130 } 2131 2132 /**
2133 * Handles carousel keydown events 2134 * 2135 * @private 2136 * @param {Object} event The keydown event 2137 */ 2138 function onKeyDown(event) { 2139 var index = that._active; 2140 var lastIndex = that._elements["indicator"].length - 1; 2141 2142 switch (event.keyCode) { 2143 case keyCodes.ARROW_LEFT: 2144 case keyCodes.ARROW_UP: 2145 event.preventDefault(); 2146 if (index > 0) { 2147 navigateAndFocusIndicator(index - 1); 2148 } 2149 break; 2150 case keyCodes.ARROW_RIGHT: 2151 case keyCodes.ARROW_DOWN: 2152 event.preventDefault(); 2153 if (index < lastIndex) { 2154 navigateAndFocusIndicator(index + 1); 2155 } 2156 break; 2157 case keyCodes.HOME: 2158 event.preventDefault(); 2159 navigateAndFocusIndicator(0); 2160 break; 2161 case keyCodes.END: 2162 event.preventDefault(); 2163 navigateAndFocusIndicator(lastIndex); 2164 break; 2165 case keyCodes.SPACE: 2166 if (that._properties.autoplay && (event.target !== that._elements["previous"] && event.target !== that._elements["next"])) { 2167 event.preventDefault(); 2168 if (!that._paused) { 2169 pause(); 2170 } else { 2171 play(); 2172 } 2173 } 2174 if (event.target === that._elements["pause"]) { 2175 that._elements["play"].focus(); 2176 } 2177 if (event.target === that._elements["play"]) { 2178 that._elements["pause"].focus(); 2179 } 2180 break; 2181 default: 2182 return; 2183 } 2184 } 2185 2186 /** 2187 * Handles carousel mouseenter events 2188 * 2189 * @private 2190 * @param {Object} event The mouseenter event 2191 */ 2192 function onMouseEnter(event) { 2193 clearAutoplayInterval(); 2194 } 2195 2196 /** 2197 * Handles carousel mouseleave events 2198 * 2199 * @private 2200 * @param {Object} event The mouseleave event 2201 */ 2202 function onMouseLeave(event) { 2203 resetAutoplayInterval(); 2204 } 2205 2206 /** 2207 * Handles pause element click events 2208 * 2209 * @private 2210 * @param {Object} event The click event 2211 */ 2212 function onPauseClick(event) { 2213 pause(); 2214 that._elements["play"].focus(); 2215 } 2216 2217 /** 2218 * Handles play element click events 2219 * 2220 * @private 2221 * @param {Object} event The click event 2222 */ 2223 function onPlayClick() { 2224 play(); 2225 that._elements["pause"].focus(); 2226 } 2227 2228 /** 2229 * Pauses the playing of the Carousel. Sets {@code Carousel#_paused} marker. 2230 * Only relevant when autoplay is enabled 2231 * 2232 * @private 2233 */ 2234 function pause() { 2235 that._paused = true; 2236 clearAutoplayInterval(); 2237 refreshPlayPauseActions(); 2238 } 2239 2240 /** 2241 * Enables the playing of the Carousel. Sets {@code Carousel#_paused} marker. 2242 * Only relevant when autoplay is enabled 2243 * 2244 * @private 2245 */ 2246 function play() { 2247 that._paused = false; 2248 2249 // If the Carousel is hovered, don't begin auto transitioning until the next mouse leave event 2250 var hovered = false; 2251 if (that._elements.self.parentElement) { 2252 hovered = that._elements.self.parentElement.querySelector(":hover") === that._elements.self; 2253 } 2254 if (that._properties.autopauseDisabled || !hovered) { 2255 resetAutoplayInterval(); 2256 } 2257 2258 refreshPlayPauseActions(); 2259 } 2260 2261 /** 2262 * Refreshes the play/pause action markup based on the {@code Carousel#_paused} state 2263 * 2264 * @private 2265 */ 2266 function refreshPlayPauseActions() {
2267 setActionDisabled(that._elements["pause"], that._paused); 2268 setActionDisabled(that._elements["play"], !that._paused); 2269 } 2270 2271 /** 2272 * Initialize {@code Carousel#_active} based on the active item of the carousel. 2273 */ 2274 function initializeActive() { 2275 var items = that._elements["item"]; 2276 if (items && Array.isArray(items)) { 2277 for (var i = 0; i < items.length; i++) { 2278 if (items[i].classList.contains("cmp-carousel__item--active")) { 2279 that._active = i; 2280 break; 2281 } 2282 } 2283 } 2284 } 2285 2286 /** 2287 * Refreshes the item markup based on the current {@code Carousel#_active} index 2288 * 2289 * @private 2290 */ 2291 function refreshActive() { 2292 var items = that._elements["item"]; 2293 var indicators = that._elements["indicator"]; 2294 2295 if (items) { 2296 if (Array.isArray(items)) { 2297 for (var i = 0; i < items.length; i++) { 2298 if (i === parseInt(that._active)) { 2299 items[i].classList.add("cmp-carousel__item--active"); 2300 items[i].removeAttribute("aria-hidden"); 2301 indicators[i].classList.add("cmp-carousel__indicator--active"); 2302 indicators[i].setAttribute("aria-selected", true); 2303 indicators[i].setAttribute("tabindex", "0"); 2304 } else { 2305 items[i].classList.remove("cmp-carousel__item--active"); 2306 items[i].setAttribute("aria-hidden", true); 2307 indicators[i].classList.remove("cmp-carousel__indicator--active"); 2308 indicators[i].setAttribute("aria-selected", false); 2309 indicators[i].setAttribute("tabindex", "-1"); 2310 } 2311 } 2312 } else { 2313 // only one item 2314 items.classList.add("cmp-carousel__item--active"); 2315 indicators.classList.add("cmp-carousel__indicator--active"); 2316 } 2317 } 2318 } 2319 2320 /** 2321 * Focuses the element and prevents scrolling the element into view 2322 * 2323 * @param {HTMLElement} element Element to focus 2324 */ 2325 function focusWithoutScroll(element) { 2326 var x = window.scrollX || window.pageXOffset; 2327 var y = window.scrollY || window.pageYOffset; 2328 element.focus(); 2329 window.scrollTo(x, y); 2330 } 2331 2332 /** 2333 * Retrieves the next active index, with looping 2334 * 2335 * @private 2336 * @returns {Number} Index of the next carousel item 2337 */ 2338 function getNextIndex() { 2339 return that._active === (that._elements["item"].length - 1) ? 0 : that._active + 1; 2340 } 2341 2342 /** 2343 * Retrieves the previous active index, with looping 2344 * 2345 * @private 2346 * @returns {Number} Index of the previous carousel item 2347 */ 2348 function getPreviousIndex() { 2349 return that._active === 0 ? (that._elements["item"].length - 1) : that._active - 1; 2350 } 2351 2352 /** 2353 * Navigates to the item at the provided index 2354 * 2355 * @private 2356 * @param {Number} index The index of the item to navigate to 2357 * @param {Boolean} keepHash true to keep the hash in the URL, false to update it 2358 */ 2359 function navigate(index, keepHash) { 2360 if (index < 0 || index > (that._elements["item"].length - 1)) { 2361 return; 2362 } 2363 2364 that._active = index; 2365 refreshActive(); 2366 2367 if (!keepHash && containerUtils) { 2368 containerUtils.updateUrlHash(that, "item", index); 2369 } 2370 2371 if (dataLayerEnabled) { 2372 var carouselId = that._elements.self.id; 2373 var activeItem = getDataLayerId(that._elements.item[index]); 2374 var updatePayload = { component: {} }; 2375 updatePayload.component[carouselId] = { shownItems: [activeItem] }; 2376 2377 var removePayload = { component: {} }; 2378 removePayload.component[carouselId] = { shownItems: undefined }; 2379 2380 dataLayer.push(removePayload); 2381 dataLayer.push(updatePayload); 2382 } 2383 2384 // reset the autoplay transition interval following navigation, if not already hovering the carousel
2385 if (that._elements.self.parentElement) { 2386 if (that._elements.self.parentElement.querySelector(":hover") !== that._elements.self) { 2387 resetAutoplayInterval(); 2388 } 2389 } 2390 } 2391 2392 /** 2393 * Navigates to the item at the provided index and ensures the active indicator gains focus 2394 * 2395 * @private 2396 * @param {Number} index The index of the item to navigate to 2397 * @param {Boolean} keepHash true to keep the hash in the URL, false to update it 2398 */ 2399 function navigateAndFocusIndicator(index, keepHash) { 2400 navigate(index, keepHash); 2401 focusWithoutScroll(that._elements["indicator"][index]); 2402 2403 if (dataLayerEnabled) { 2404 dataLayer.push({ 2405 event: "cmp:show", 2406 eventInfo: { 2407 path: "component." + getDataLayerId(that._elements.item[index]) 2408 } 2409 }); 2410 } 2411 } 2412 2413 /** 2414 * Starts/resets automatic slide transition interval 2415 * 2416 * @private 2417 */ 2418 function resetAutoplayInterval() { 2419 if (that._paused || !that._properties.autoplay) { 2420 return; 2421 } 2422 clearAutoplayInterval(); 2423 that._autoplayIntervalId = window.setInterval(function() { 2424 if (document.visibilityState && document.hidden) { 2425 return; 2426 } 2427 var indicators = that._elements["indicators"]; 2428 if (indicators !== document.activeElement && indicators.contains(document.activeElement)) { 2429 // if an indicator has focus, ensure we switch focus following navigation 2430 navigateAndFocusIndicator(getNextIndex(), true); 2431 } else { 2432 navigate(getNextIndex(), true); 2433 } 2434 }, that._properties.delay); 2435 } 2436 2437 /** 2438 * Clears/pauses automatic slide transition interval 2439 * 2440 * @private 2441 */ 2442 function clearAutoplayInterval() { 2443 window.clearInterval(that._autoplayIntervalId); 2444 that._autoplayIntervalId = null; 2445 } 2446 2447 /** 2448 * Sets the disabled state for an action and toggles the appropriate CSS classes 2449 * 2450 * @private 2451 * @param {HTMLElement} action Action to disable 2452 * @param {Boolean} [disable] {@code true} to disable, {@code false} to enable 2453 */ 2454 function setActionDisabled(action, disable) { 2455 if (!action) { 2456 return; 2457 } 2458 if (disable !== false) { 2459 action.disabled = true; 2460 action.classList.add("cmp-carousel__action--disabled"); 2461 } else { 2462 action.disabled = false; 2463 action.classList.remove("cmp-carousel__action--disabled"); 2464 } 2465 } 2466 } 2467 2468 /** 2469 * Parses the dataLayer string and returns the ID 2470 * 2471 * @private 2472 * @param {HTMLElement} item the accordion item 2473 * @returns {String} dataLayerId or undefined 2474 */ 2475 function getDataLayerId(item) { 2476 if (item) { 2477 if (item.dataset.cmpDataLayer) { 2478 return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0]; 2479 } else { 2480 return item.id; 2481 } 2482 } 2483 return null; 2484 } 2485 2486 /** 2487 * Document ready handler and DOM mutation observers. Initializes Carousel components as necessary. 2488 * 2489 * @private 2490 */ 2491 function onDocumentReady() { 2492 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 2493 if (dataLayerEnabled) { 2494 dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer"; 2495 dataLayer = window[dataLayerName] = window[dataLayerName] || []; 2496 } 2497 2498 var elements = document.querySelectorAll(selectors.self); 2499 for (var i = 0; i < elements.length; i++) { 2500 new Carousel({ element: elements[i], options: CMP.utils.readData(elements[i], IS) }); 2501 } 2502 2503 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 2504 var body = document.querySelector("body"); 2505 var observer = new MutationObserver(function(mutations) { 2506 mutations.forEach(function(mutation) { 2507 // needed for IE 2508 var nodesArray = [].slice.call(mutation.addedNodes); 2509 if (nodesArray.length > 0) { 2510 nodesArray.forEach(function(addedNode) { 2511 if (addedNode.querySelectorAll) { 2512 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 2513 elementsArray.forEach(function(element) { 2514 new Carousel({ element: element, options: CMP.utils.readData(element, IS) }); 2515 }); 2516 } 2517 }); 2518 } 2519 }); 2520 }); 2521 2522 observer.observe(body, { 2523 subtree: true, 2524 childList: true, 2525 characterData: true 2526 }); 2527 } 2528 2529 var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) { 2530 document.addEventListener("DOMContentLoaded", resolve); 2531 }); 2532 Promise.all([documentReady]).then(onDocumentReady); 2533 2534 if (containerUtils) { 2535 window.addEventListener("load", containerUtils.scrollToAnchor, false); 2536 } 2537 2538}()); 2539 2540 2541/******************************************************************************* 2542 * Copyright 2017 Adobe 2543 * 2544 * Licensed under the Apache License, Version 2.0 (the "License");
2545 * you may not use this file except in compliance with the License. 2546 * You may obtain a copy of the License at 2547 * 2548 * http://www.apache.org/licenses/LICENSE-2.0 2549 * 2550 * Unless required by applicable law or agreed to in writing, software 2551 * distributed under the License is distributed on an "AS IS" BASIS, 2552 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2553 * See the License for the specific language governing permissions and 2554 * limitations under the License. 2555 ******************************************************************************/ 2556if (window.Element && !Element.prototype.closest) { 2557 // eslint valid-jsdoc: "off" 2558 Element.prototype.closest = 2559 function(s) { 2560 "use strict"; 2561 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 2562 var el = this; 2563 var i; 2564 do { 2565 i = matches.length; 2566 while (--i >= 0 && matches.item(i) !== el) { 2567 // continue 2568 } 2569 } while ((i < 0) && (el = el.parentElement)); 2570 return el; 2571 }; 2572} 2573 2574if (window.Element && !Element.prototype.matches) { 2575 Element.prototype.matches = 2576 Element.prototype.matchesSelector || 2577 Element.prototype.mozMatchesSelector || 2578 Element.prototype.msMatchesSelector || 2579 Element.prototype.oMatchesSelector || 2580 Element.prototype.webkitMatchesSelector || 2581 function(s) { 2582 "use strict"; 2583 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 2584 var i = matches.length; 2585 while (--i >= 0 && matches.item(i) !== this) { 2586 // continue 2587 } 2588 return i > -1; 2589 }; 2590} 2591 2592if (!Object.assign) { 2593 Object.assign = function(target, varArgs) { // .length of function is 2 2594 "use strict"; 2595 if (target === null) { 2596 throw new TypeError("Cannot convert undefined or null to object"); 2597 } 2598 2599 var to = Object(target); 2600 2601 for (var index = 1; index < arguments.length; index++) { 2602 var nextSource = arguments[index]; 2603 2604 if (nextSource !== null) { 2605 for (var nextKey in nextSource) { 2606 if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 2607 to[nextKey] = nextSource[nextKey]; 2608 } 2609 } 2610 } 2611 } 2612 return to; 2613 }; 2614} 2615 2616(function(arr) { 2617 "use strict"; 2618 arr.forEach(function(item) { 2619 if (Object.prototype.hasOwnProperty.call(item, "remove")) { 2620 return; 2621 } 2622 Object.defineProperty(item, "remove", { 2623 configurable: true, 2624 enumerable: true, 2625 writable: true, 2626 value: function remove() { 2627 this.parentNode.removeChild(this); 2628 } 2629 }); 2630 }); 2631})([Element.prototype, CharacterData.prototype, DocumentType.prototype]); 2632 2633/******************************************************************************* 2634 * Copyright 2022 Adobe 2635 * 2636 * Licensed under the Apache License, Version 2.0 (the "License"); 2637 * you may not use this file except in compliance with the License. 2638 * You may obtain a copy of the License at 2639 * 2640 * http://www.apache.org/licenses/LICENSE-2.0 2641 * 2642 * Unless required by applicable law or agreed to in writing, software 2643 * distributed under the License is distributed on an "AS IS" BASIS, 2644 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2645 * See the License for the specific language governing permissions and 2646 * limitations under the License. 2647 ******************************************************************************/ 2648(function(document) { 2649 "use strict"; 2650 2651 window.CMP = window.CMP || {}; 2652 window.CMP.utils = (function() { 2653 var NS = "cmp"; 2654 2655 /** 2656 * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes 2657 * 2658 * @param {HTMLElement} element The component element to read options data from 2659 * @param {String} is The component identifier 2660 * @returns {String[]} The options read from the component data attributes 2661 */ 2662 var readData = function(element, is) { 2663 var data = element.dataset; 2664 var options = []; 2665 var capitalized = is; 2666 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2667 var reserved = ["is", "hook" + capitalized]; 2668 2669 for (var key in data) { 2670 if (Object.prototype.hasOwnProperty.call(data, key)) { 2671 var value = data[key]; 2672 2673 if (key.indexOf(NS) === 0) { 2674 key = key.slice(NS.length); 2675 key = key.charAt(0).toLowerCase() + key.substring(1); 2676 2677 if (reserved.indexOf(key) === -1) { 2678 options[key] = value; 2679 } 2680 } 2681 } 2682 } 2683 return options; 2684 }; 2685 2686 /** 2687 * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand 2688 * @param {String[]} options the options to transform 2689 * @param {Object} properties object of properties of property functions 2690 * @returns {Object} transformed properties 2691 */ 2692 var setupProperties = function(options, properties) { 2693 var transformedProperties = {}; 2694 2695 for (var key in properties) { 2696 if (Object.prototype.hasOwnProperty.call(properties, key)) { 2697 var property = properties[key]; 2698 if (options && options[key] != null) { 2699 if (property && typeof property.transform === "function") { 2700 transformedProperties[key] = property.transform(options[key]); 2701 } else { 2702 transformedProperties[key] = options[key]; 2703 } 2704 } else { 2705 transformedProperties[key] = properties[key]["default"]; 2706 } 2707 } 2708 } 2709 return transformedProperties; 2710 }; 2711 2712 2713 return { 2714 readData: readData, 2715 setupProperties: setupProperties 2716 }; 2717 }()); 2718}(window.document)); 2719 2720/******************************************************************************* 2721 * Copyright 2022 Adobe 2722 * 2723 * Licensed under the Apache License, Version 2.0 (the "License");
2724 * you may not use this file except in compliance with the License. 2725 * You may obtain a copy of the License at 2726 * 2727 * http://www.apache.org/licenses/LICENSE-2.0 2728 * 2729 * Unless required by applicable law or agreed to in writing, software 2730 * distributed under the License is distributed on an "AS IS" BASIS, 2731 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2732 * See the License for the specific language governing permissions and 2733 * limitations under the License. 2734 ******************************************************************************/ 2735(function(document) { 2736 "use strict"; 2737 2738 window.CMP = window.CMP || {}; 2739 window.CMP.image = window.CMP.image || {}; 2740 window.CMP.image.dynamicMedia = (function() { 2741 var autoSmartCrops = {}; 2742 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 2743 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}"; 2744 var SRC_URI_DPR_OFF = "dpr=off"; 2745 var SRC_URI_DPR_ON = "dpr=on,{dpr}"; 2746 var dpr = window.devicePixelRatio || 1; 2747 var config = { 2748 minWidth: 20 2749 }; 2750 2751 /** 2752 * get auto smart crops from dm 2753 * @param {String} src the src uri 2754 * @returns {{}} the smart crop json object 2755 */ 2756 var getAutoSmartCrops = function(src) { 2757 var request = new XMLHttpRequest(); 2758 var url = src.split(SRC_URI_TEMPLATE_WIDTH_VAR)[0] + "?req=set,json"; 2759 request.open("GET", url, false); 2760 request.onload = function() { 2761 if (request.status >= 200 && request.status < 400) { 2762 // success status 2763 var responseText = request.responseText; 2764 var rePayload = new RegExp(/^(?:\/\*jsonp\*\/)?\s*([^()]+)\(([\s\S]+),\s*"[0-9]*"\);?$/gmi); 2765 var rePayloadJSON = new RegExp(/^{[\s\S]*}$/gmi); 2766 var resPayload = rePayload.exec(responseText); 2767 var payload; 2768 if (resPayload) { 2769 var payloadStr = resPayload[2]; 2770 if (rePayloadJSON.test(payloadStr)) { 2771 payload = JSON.parse(payloadStr); 2772 } 2773 2774 } 2775 // check "relation" - only in case of smartcrop preset 2776 if (payload && payload.set.relation && payload.set.relation.length > 0) { 2777 for (var i = 0; i < payload.set.relation.length; i++) { 2778 autoSmartCrops[parseInt(payload.set.relation[i].userdata.SmartCropWidth)] = 2779 ":" + payload.set.relation[i].userdata.SmartCropDef; 2780 } 2781 } 2782 } else { 2783 // error status 2784 } 2785 }; 2786 request.send(); 2787 return autoSmartCrops; 2788 }; 2789 2790 /** 2791 * Build and return the srcset value based on the available auto smart crops 2792 * @param {String} src the src uri 2793 * @param {Object} smartCrops the smart crops object 2794 * @returns {String} the srcset 2795 */ 2796 var getSrcSet = function(src, smartCrops) { 2797 var srcset; 2798 var keys = Object.keys(smartCrops); 2799 if (keys.length > 0) { 2800 srcset = []; 2801 for (var key in autoSmartCrops) { 2802 srcset.push(src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, smartCrops[key]) + " " + key + "w"); 2803 } 2804 } 2805 return srcset.join(","); 2806 }; 2807 2808 /** 2809 * Get the optimal width based on the available sizes 2810 * @param {[Number]} sizes the available sizes 2811 * @param {Number} width the element width 2812 * @returns {String} the optimal width 2813 */ 2814 function getOptimalWidth(sizes, width) { 2815 var len = sizes.length; 2816 var key = 0; 2817 2818 while ((key < len - 1) && (sizes[key] < width)) { 2819 key++; 2820 } 2821 2822 return sizes[key] !== undefined ? sizes[key].toString() : width; 2823 } 2824 2825 /** 2826 * Get the width of an element or parent element if the width is smaller than the minimum width 2827 * @param {HTMLElement} component the image component 2828 * @param {HTMLElement | Node} parent the parent element 2829 * @returns {Number} the width of the element 2830 */ 2831 var getWidth = function(component, parent) { 2832 var width = component.offsetWidth; 2833 while (width < config.minWidth && parent && !component._autoWidth) { 2834 width = parent.offsetWidth; 2835 parent = parent.parentNode; 2836 } 2837 return width; 2838 }; 2839 2840 /** 2841 * Set the src and srcset attribute for a Dynamic Media Image which auto smart crops enabled. 2842 * @param {HTMLElement} component the image component 2843 * @param {{}} properties the component properties 2844 */ 2845 var setDMAttributes = function(component, properties) { 2846 // for v3 we first have to turn the dpr on
2847 var src = properties.src.replace(SRC_URI_DPR_OFF, SRC_URI_DPR_ON); 2848 src = src.replace(SRC_URI_TEMPLATE_DPR_VAR, dpr); 2849 var smartCrops = {}; 2850 var width; 2851 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 2852 smartCrops = getAutoSmartCrops(src); 2853 } 2854 var hasWidths = (properties.widths && properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 2855 if (hasWidths) { 2856 var image = component.querySelector("img"); 2857 var elemWidth = getWidth(component, component.parentNode); 2858 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 2859 image.setAttribute("srcset", CMP.image.dynamicMedia.getSrcSet(src, smartCrops)); 2860 width = getOptimalWidth(Object.keys(smartCrops, elemWidth)); 2861 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, smartCrops[width])); 2862 } else { 2863 width = getOptimalWidth(properties.widths, elemWidth); 2864 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, width)); 2865 } 2866 } 2867 }; 2868 2869 /** 2870 * Get the src attribute based on the optimal width 2871 * @param {String} src the src uri 2872 * @param {String} width the element width 2873 * @returns {String} the final src attribute 2874 */ 2875 var getSrc = function(src, width) { 2876 if (src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR) > -1) { 2877 src = src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, width); 2878 } 2879 return src; 2880 }; 2881 2882 2883 return { 2884 getAutoSmartCrops: getAutoSmartCrops, 2885 getSrcSet: getSrcSet, 2886 getSrc: getSrc, 2887 setDMAttributes: setDMAttributes, 2888 getWidth: getWidth 2889 }; 2890 }()); 2891 document.dispatchEvent(new CustomEvent("core.wcm.components.commons.site.image.dynamic-media.loaded")); 2892}(window.document)); 2893 2894/******************************************************************************* 2895 * Copyright 2016 Adobe 2896 * 2897 * Licensed under the Apache License, Version 2.0 (the "License"); 2898 * you may not use this file except in compliance with the License. 2899 * You may obtain a copy of the License at 2900 * 2901 * http://www.apache.org/licenses/LICENSE-2.0 2902 * 2903 * Unless required by applicable law or agreed to in writing, software 2904 * distributed under the License is distributed on an "AS IS" BASIS, 2905 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2906 * See the License for the specific language governing permissions and 2907 * limitations under the License. 2908 ******************************************************************************/ 2909(function() { 2910 "use strict"; 2911 2912 var NS = "cmp"; 2913 var IS = "image"; 2914 2915 var EMPTY_PIXEL = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; 2916 var LAZY_THRESHOLD_DEFAULT = 0; 2917 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 2918 var SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY = "width={width}"; 2919 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}"; 2920 2921 var selectors = { 2922 self: "[data-" + NS + '-is="' + IS + '"]', 2923 image: '[data-cmp-hook-image="image"]', 2924 map: '[data-cmp-hook-image="map"]', 2925 area: '[data-cmp-hook-image="area"]' 2926 }; 2927 2928 var lazyLoader = { 2929 "cssClass": "cmp-image__image--is-loading", 2930 "style": { 2931 "height": 0, 2932 "padding-bottom": "" // will be replaced with % ratio 2933 } 2934 }; 2935 2936 var properties = { 2937 /** 2938 * An array of alternative image widths (in pixels). 2939 * Used to replace a {.width} variable in the src property with an optimal width if a URI template is provided. 2940 * 2941 * @memberof Image 2942 * @type {Number[]} 2943 * @default [] 2944 */ 2945 "widths": { 2946 "default": [], 2947 "transform": function(value) { 2948 var widths = []; 2949 value.split(",").forEach(function(item) { 2950 item = parseFloat(item); 2951 if (!isNaN(item)) { 2952 widths.push(item); 2953 } 2954 }); 2955 return widths; 2956 } 2957 }, 2958 /** 2959 * Indicates whether the image should be rendered lazily. 2960 * 2961 * @memberof Image 2962 * @type {Boolean} 2963 * @default false 2964 */ 2965 "lazy": { 2966 "default": false, 2967 "transform": function(value) { 2968 return !(value === null || typeof value === "undefined"); 2969 } 2970 }, 2971 /** 2972 * Indicates image is DynamicMedia image. 2973 * 2974 * @memberof Image 2975 * @type {Boolean} 2976 * @default false 2977 */ 2978 "dmimage": { 2979 "default": false, 2980 "transform": function(value) { 2981 return !(value === null || typeof value === "undefined"); 2982 } 2983 }, 2984 /** 2985 * The lazy threshold. 2986 * This is the number of pixels, in advance of becoming visible, when an lazy-loading image should begin 2987 * to load. 2988 * 2989 * @memberof Image 2990 * @type {Number} 2991 * @default 0 2992 */ 2993 "lazythreshold": { 2994 "default": 0, 2995 "transform": function(value) { 2996 var val = parseInt(value); 2997 if (isNaN(val)) { 2998 return LAZY_THRESHOLD_DEFAULT; 2999 } 3000 return val; 3001 } 3002 }, 3003 /** 3004 * The image source. 3005 * 3006 * Can be a simple image source, or a URI template representation that 3007 * can be variable expanded - useful for building an image configuration with an alternative width. 3008 * e.g. '/path/image.coreimg{.width}.jpeg/1506620954214.jpeg' 3009 * 3010 * @memberof Image 3011 * @type {String} 3012 */ 3013 "src": { 3014 "transform": function(value) { 3015 return decodeURIComponent(value); 3016 } 3017 } 3018 }; 3019 3020 var devicePixelRatio = window.devicePixelRatio || 1; 3021 3022 function Image(config) { 3023 var that = this; 3024 3025 var smartCrops = {}; 3026 3027 var useAssetDelivery = false;
3028 var srcUriTemplateWidthVar = SRC_URI_TEMPLATE_WIDTH_VAR; 3029 3030 function init(config) { 3031 // prevents multiple initialization 3032 config.element.removeAttribute("data-" + NS + "-is"); 3033 3034 // check if asset delivery is used 3035 if (config.options.src && config.options.src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY) >= 0) { 3036 useAssetDelivery = true; 3037 srcUriTemplateWidthVar = SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY; 3038 } 3039 3040 that._properties = CMP.utils.setupProperties(config.options, properties); 3041 cacheElements(config.element); 3042 // check image is DM asset; if true try to make req=set 3043 if (config.options.src && Object.prototype.hasOwnProperty.call(config.options, "dmimage") && (config.options["smartcroprendition"] === "SmartCrop:Auto")) { 3044 smartCrops = CMP.image.dynamicMedia.getAutoSmartCrops(config.options.src); 3045 } 3046 3047 if (!that._elements.noscript) { 3048 return; 3049 } 3050 3051 that._elements.container = that._elements.link ? that._elements.link : that._elements.self; 3052 3053 unwrapNoScript(); 3054 3055 if (that._properties.lazy) { 3056 addLazyLoader(); 3057 } 3058 3059 if (that._elements.map) { 3060 that._elements.image.addEventListener("load", onLoad); 3061 } 3062 3063 window.addEventListener("resize", onWindowResize); 3064 ["focus", "click", "load", "transitionend", "animationend", "scroll"].forEach(function(name) { 3065 document.addEventListener(name, that.update); 3066 }); 3067 3068 that._elements.image.addEventListener("cmp-image-redraw", that.update); 3069 3070 that._interSectionObserver = new IntersectionObserver(function(entries, interSectionObserver) { 3071 entries.forEach(function(entry) { 3072 if (entry.intersectionRatio > 0) { 3073 that.update(); 3074 } 3075 }); 3076 }); 3077 that._interSectionObserver.observe(that._elements.self); 3078 3079 that.update(); 3080 } 3081 3082 function loadImage() { 3083 var hasWidths = (that._properties.widths && that._properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 3084 var replacement; 3085 if (Object.keys(smartCrops).length > 0) { 3086 var optimalWidth = getOptimalWidth(Object.keys(smartCrops), false); 3087 replacement = smartCrops[optimalWidth]; 3088 } else { 3089 replacement = hasWidths ? (that._properties.dmimage ? "" : ".") + getOptimalWidth(that._properties.widths, true) : ""; 3090 } 3091 if (useAssetDelivery) { 3092 replacement = replacement !== "" ? ("width=" + replacement.substring(1)) : ""; 3093 } 3094 var url = that._properties.src.replace(srcUriTemplateWidthVar, replacement); 3095 url = url.replace(SRC_URI_TEMPLATE_DPR_VAR, devicePixelRatio); 3096 3097 var imgSrcAttribute = that._elements.image.getAttribute("src"); 3098 3099 if (url !== imgSrcAttribute) { 3100 if (imgSrcAttribute === null || imgSrcAttribute === EMPTY_PIXEL) { 3101 that._elements.image.setAttribute("src", url); 3102 } else { 3103 var urlTemplateParts = that._properties.src.split(srcUriTemplateWidthVar); 3104 // check if image src was dynamically swapped meanwhile (e.g. by Target) 3105 var isImageRefSame = imgSrcAttribute.startsWith(urlTemplateParts[0]); 3106 if (isImageRefSame && urlTemplateParts.length > 1) { 3107 isImageRefSame = imgSrcAttribute.endsWith(urlTemplateParts[urlTemplateParts.length - 1]); 3108 } 3109 if (isImageRefSame) { 3110 that._elements.image.setAttribute("src", url); 3111 if (!hasWidths) { 3112 window.removeEventListener("scroll", that.update); 3113 } 3114 } 3115 } 3116 } 3117 if (that._lazyLoaderShowing) { 3118 that._elements.image.addEventListener("load", removeLazyLoader); 3119 } 3120 that._interSectionObserver.unobserve(that._elements.self); 3121 } 3122 3123 function getOptimalWidth(widths, useDevicePixelRatio) { 3124 var container = that._elements.self; 3125 var containerWidth = container.clientWidth; 3126 while (containerWidth === 0 && container.parentNode) { 3127 container = container.parentNode; 3128 containerWidth = container.clientWidth; 3129 } 3130 3131 var dpr = useDevicePixelRatio ? devicePixelRatio : 1; 3132 var optimalWidth = containerWidth * dpr; 3133 var len = widths.length; 3134 var key = 0; 3135 3136 while ((key < len - 1) && (widths[key] < optimalWidth)) { 3137 key++; 3138 } 3139 3140 return widths[key].toString(); 3141 } 3142 3143 function addLazyLoader() { 3144 var width = that._elements.image.getAttribute("width"); 3145 var height = that._elements.image.getAttribute("height"); 3146 3147 if (width && height) { 3148 var ratio = (height / width) * 100; 3149 var styles = lazyLoader.style; 3150 3151 styles["padding-bottom"] = ratio + "%"; 3152 3153 for (var s in styles) { 3154 if (Object.prototype.hasOwnProperty.call(styles, s)) { 3155 that._elements.image.style[s] = styles[s]; 3156 } 3157 } 3158 } 3159 that._elements.image.setAttribute("src", EMPTY_PIXEL); 3160 that._elements.image.classList.add(lazyLoader.cssClass); 3161 that._lazyLoaderShowing = true; 3162 } 3163 3164 function unwrapNoScript() { 3165 var markup = decodeNoscript(that._elements.noscript.textContent.trim()); 3166 var parser = new DOMParser(); 3167 3168 // temporary document avoids requesting the image before removing its src 3169 var temporaryDocument = parser.parseFromString(markup, "text/html"); 3170 var imageElement = temporaryDocument.querySelector(selectors.image); 3171 imageElement.removeAttribute("src"); 3172 that._elements.container.insertBefore(imageElement, that._elements.noscript); 3173 3174 var mapElement = temporaryDocument.querySelector(selectors.map); 3175 if (mapElement) { 3176 that._elements.container.insertBefore(mapElement, that._elements.noscript); 3177 } 3178 3179 that._elements.noscript.parentNode.removeChild(that._elements.noscript); 3180 if (that._elements.container.matches(selectors.image)) { 3181 that._elements.image = that._elements.container; 3182 } else { 3183 that._elements.image = that._elements.container.querySelector(selectors.image); 3184 } 3185 3186 that._elements.map = that._elements.container.querySelector(selectors.map); 3187 that._elements.areas = that._elements.container.querySelectorAll(selectors.area); 3188 } 3189 3190 function removeLazyLoader() { 3191 that._elements.image.classList.remove(lazyLoader.cssClass); 3192 for (var property in lazyLoader.style) { 3193 if (Object.prototype.hasOwnProperty.call(lazyLoader.style, property)) { 3194 that._elements.image.style[property] = ""; 3195 } 3196 } 3197 that._elements.image.removeEventListener("load", removeLazyLoader); 3198 that._lazyLoaderShowing = false;
3199 } 3200 3201 function isLazyVisible() { 3202 if (that._elements.container.offsetParent === null) { 3203 return false; 3204 } 3205 3206 var wt = window.pageYOffset; 3207 var wb = wt + document.documentElement.clientHeight; 3208 var et = that._elements.container.getBoundingClientRect().top + wt; 3209 var eb = et + that._elements.container.clientHeight; 3210 3211 return eb >= wt - that._properties.lazythreshold && et <= wb + that._properties.lazythreshold; 3212 } 3213 3214 function resizeAreas() { 3215 if (that._elements.areas && that._elements.areas.length > 0) { 3216 for (var i = 0; i < that._elements.areas.length; i++) { 3217 var width = that._elements.image.width; 3218 var height = that._elements.image.height; 3219 3220 if (width && height) { 3221 var relcoords = that._elements.areas[i].dataset.cmpRelcoords; 3222 if (relcoords) { 3223 var relativeCoordinates = relcoords.split(","); 3224 var coordinates = new Array(relativeCoordinates.length); 3225 3226 for (var j = 0; j < coordinates.length; j++) { 3227 if (j % 2 === 0) { 3228 coordinates[j] = parseInt(relativeCoordinates[j] * width); 3229 } else { 3230 coordinates[j] = parseInt(relativeCoordinates[j] * height); 3231 } 3232 } 3233 3234 that._elements.areas[i].coords = coordinates; 3235 } 3236 } 3237 } 3238 } 3239 } 3240 3241 function cacheElements(wrapper) { 3242 that._elements = {}; 3243 that._elements.self = wrapper; 3244 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 3245 3246 for (var i = 0; i < hooks.length; i++) { 3247 var hook = hooks[i]; 3248 var capitalized = IS; 3249 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3250 var key = hook.dataset[NS + "Hook" + capitalized]; 3251 that._elements[key] = hook; 3252 } 3253 } 3254 3255 function onWindowResize() { 3256 that.update(); 3257 resizeAreas(); 3258 } 3259 3260 function onLoad() { 3261 resizeAreas(); 3262 } 3263 3264 that.update = function() { 3265 if (that._properties.lazy) { 3266 if (isLazyVisible()) { 3267 loadImage(); 3268 } 3269 } else { 3270 loadImage(); 3271 } 3272 }; 3273 3274 if (config && config.element) { 3275 init(config); 3276 } 3277 } 3278 3279 function onDocumentReady() { 3280 var elements = document.querySelectorAll(selectors.self); 3281 for (var i = 0; i < elements.length; i++) { 3282 new Image({ element: elements[i], options: CMP.utils.readData(elements[i], IS) }); 3283 } 3284 3285 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 3286 var body = document.querySelector("body"); 3287 var observer = new MutationObserver(function(mutations) { 3288 mutations.forEach(function(mutation) { 3289 // needed for IE 3290 var nodesArray = [].slice.call(mutation.addedNodes); 3291 if (nodesArray.length > 0) { 3292 nodesArray.forEach(function(addedNode) { 3293 if (addedNode.querySelectorAll) { 3294 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 3295 elementsArray.forEach(function(element) { 3296 new Image({ element: element, options: CMP.utils.readData(element, IS) }); 3297 }); 3298 } 3299 }); 3300 } 3301 }); 3302 }); 3303 3304 observer.observe(body, { 3305 subtree: true, 3306 childList: true, 3307 characterData: true 3308 }); 3309 } 3310 3311 var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) { 3312 document.addEventListener("DOMContentLoaded", resolve); 3313 }); 3314 3315 Promise.all([documentReady]).then(onDocumentReady); 3316 /* 3317 on drag & drop of the component into a parsys, noscript's content will be escaped multiple times by the editor which creates 3318 the DOM for editing; the HTML parser cannot be used here due to the multiple escaping 3319 */ 3320 function decodeNoscript(text) { 3321 text = text.replace(/&(amp;)*lt;/g, "<"); 3322 text = text.replace(/&(amp;)*gt;/g, ">"); 3323 return text; 3324 } 3325 3326})(); 3327 3328 3329/******************************************************************************* 3330 * Copyright 2017 Adobe 3331 * 3332 * Licensed under the Apache License, Version 2.0 (the "License");
3333 * you may not use this file except in compliance with the License. 3334 * You may obtain a copy of the License at 3335 * 3336 * http://www.apache.org/licenses/LICENSE-2.0 3337 * 3338 * Unless required by applicable law or agreed to in writing, software 3339 * distributed under the License is distributed on an "AS IS" BASIS, 3340 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3341 * See the License for the specific language governing permissions and 3342 * limitations under the License. 3343 ******************************************************************************/ 3344(function() { 3345 "use strict"; 3346 3347 var NS = "cmp"; 3348 var IS = "search"; 3349 3350 var DELAY = 300; // time before fetching new results when the user is typing a search string 3351 var LOADING_DISPLAY_DELAY = 300; // minimum time during which the loading indicator is displayed 3352 var PARAM_RESULTS_OFFSET = "resultsOffset"; 3353 3354 var keyCodes = { 3355 TAB: 9, 3356 ENTER: 13, 3357 ESCAPE: 27, 3358 ARROW_UP: 38, 3359 ARROW_DOWN: 40 3360 }; 3361 3362 var selectors = { 3363 self: "[data-" + NS + '-is="' + IS + '"]', 3364 item: { 3365 self: "[data-" + NS + "-hook-" + IS + '="item"]', 3366 title: "[data-" + NS + "-hook-" + IS + '="itemTitle"]', 3367 focused: "." + NS + "-search__item--is-focused" 3368 } 3369 }; 3370 3371 var properties = { 3372 /** 3373 * The minimum required length of the search term before results are fetched. 3374 * 3375 * @memberof Search 3376 * @type {Number} 3377 * @default 3 3378 */ 3379 minLength: { 3380 "default": 3, 3381 transform: function(value) { 3382 value = parseFloat(value); 3383 return isNaN(value) ? null : value; 3384 } 3385 }, 3386 /** 3387 * The maximal number of results fetched by a search request. 3388 * 3389 * @memberof Search 3390 * @type {Number} 3391 * @default 10 3392 */ 3393 resultsSize: { 3394 "default": 10, 3395 transform: function(value) { 3396 value = parseFloat(value); 3397 return isNaN(value) ? null : value; 3398 } 3399 } 3400 }; 3401 3402 var idCount = 0; 3403 3404 function readData(element) { 3405 var data = element.dataset; 3406 var options = []; 3407 var capitalized = IS; 3408 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3409 var reserved = ["is", "hook" + capitalized]; 3410 3411 for (var key in data) { 3412 if (Object.prototype.hasOwnProperty.call(data, key)) { 3413 var value = data[key]; 3414 3415 if (key.indexOf(NS) === 0) { 3416 key = key.slice(NS.length); 3417 key = key.charAt(0).toLowerCase() + key.substring(1); 3418 3419 if (reserved.indexOf(key) === -1) { 3420 options[key] = value; 3421 } 3422 } 3423 } 3424 } 3425 3426 return options; 3427 } 3428 3429 function toggleShow(element, show) { 3430 if (element) { 3431 if (show !== false) { 3432 element.style.display = "block"; 3433 element.setAttribute("aria-hidden", false); 3434 } else { 3435 element.style.display = "none"; 3436 element.setAttribute("aria-hidden", true); 3437 } 3438 } 3439 } 3440 3441 function serialize(form) { 3442 var query = []; 3443 if (form && form.elements) { 3444 for (var i = 0; i < form.elements.length; i++) { 3445 var node = form.elements[i]; 3446 if (!node.disabled && node.name) { 3447 var param = [node.name, encodeURIComponent(node.value)]; 3448 query.push(param.join("=")); 3449 } 3450 } 3451 } 3452 return query.join("&"); 3453 } 3454 3455 function mark(node, regex) { 3456 if (!node || !regex) { 3457 return; 3458 } 3459 3460 // text nodes 3461 if (node.nodeType === 3) { 3462 var nodeValue = node.nodeValue; 3463 var match = regex.exec(nodeValue); 3464 3465 if (nodeValue && match) { 3466 var element = document.createElement("mark"); 3467 element.className = NS + "-search__item-mark"; 3468 element.appendChild(document.createTextNode(match[0])); 3469 3470 var after = node.splitText(match.index); 3471 after.nodeValue = after.nodeValue.substring(match[0].length); 3472 node.parentNode.insertBefore(element, after); 3473 } 3474 } else if (node.hasChildNodes()) { 3475 for (var i = 0; i < node.childNodes.length; i++) { 3476 // recurse 3477 mark(node.childNodes[i], regex); 3478 } 3479 } 3480 } 3481 3482 function Search(config) { 3483 if (config.element) { 3484 // prevents multiple initialization 3485 config.element.removeAttribute("data-" + NS + "-is"); 3486 } 3487 3488 this._cacheElements(config.element); 3489 this._setupProperties(config.options); 3490 3491 this._action = this._elements.form.getAttribute("action"); 3492 this._resultsOffset = 0; 3493 this._hasMoreResults = true; 3494 3495 this._elements.input.addEventListener("input", this._onInput.bind(this)); 3496 this._elements.input.addEventListener("focus", this._onInput.bind(this)); 3497 this._elements.input.addEventListener("keydown", this._onKeydown.bind(this)); 3498 this._elements.clear.addEventListener("click", this._onClearClick.bind(this)); 3499 document.addEventListener("click", this._onDocumentClick.bind(this)); 3500 this._elements.results.addEventListener("scroll", this._onScroll.bind(this)); 3501 3502 this._makeAccessible(); 3503 } 3504 3505 Search.prototype._displayResults = function() { 3506 if (this._elements.input.value.length === 0) { 3507 toggleShow(this._elements.clear, false); 3508 this._cancelResults(); 3509 } else if (this._elements.input.value.length < this._properties.minLength) { 3510 toggleShow(this._elements.clear, true); 3511 } else { 3512 this._updateResults(); 3513 toggleShow(this._elements.clear, true); 3514 } 3515 }; 3516 3517 Search.prototype._onScroll = function(event) { 3518 // fetch new results when the results to be scrolled down are less than the visible results 3519 if (this._elements.results.scrollTop + 2 * this._elements.results.clientHeight >= this._elements.results.scrollHeight) { 3520 this._resultsOffset += this._properties.resultsSize; 3521 this._displayResults(); 3522 } 3523 }; 3524 3525 Search.prototype._onInput = function(event) { 3526 var self = this; 3527 self._cancelResults(); 3528 // start searching when the search term reaches the minimum length 3529 this._timeout = setTimeout(function() { 3530 self._displayResults(); 3531 }, DELAY); 3532 }; 3533 3534 Search.prototype._onKeydown = function(event) { 3535 var self = this; 3536 3537 switch (event.keyCode) { 3538 case keyCodes.TAB: 3539 if (self._resultsOpen()) { 3540 toggleShow(self._elements.results, false); 3541 self._elements.input.setAttribute("aria-expanded", "false"); 3542 } 3543 break;
3544 case keyCodes.ENTER: 3545 event.preventDefault(); 3546 if (self._resultsOpen()) { 3547 var focused = self._elements.results.querySelector(selectors.item.focused); 3548 if (focused) { 3549 focused.click(); 3550 } 3551 } 3552 break; 3553 case keyCodes.ESCAPE: 3554 self._cancelResults(); 3555 break; 3556 case keyCodes.ARROW_UP: 3557 if (self._resultsOpen()) { 3558 event.preventDefault(); 3559 self._stepResultFocus(true); 3560 } 3561 break; 3562 case keyCodes.ARROW_DOWN: 3563 if (self._resultsOpen()) { 3564 event.preventDefault(); 3565 self._stepResultFocus(); 3566 } else { 3567 // test the input and if necessary fetch and display the results 3568 self._onInput(); 3569 } 3570 break; 3571 default: 3572 return; 3573 } 3574 }; 3575 3576 Search.prototype._onClearClick = function(event) { 3577 event.preventDefault(); 3578 this._elements.input.value = ""; 3579 toggleShow(this._elements.clear, false); 3580 toggleShow(this._elements.results, false); 3581 this._elements.input.setAttribute("aria-expanded", "false"); 3582 }; 3583 3584 Search.prototype._onDocumentClick = function(event) { 3585 var inputContainsTarget = this._elements.input.contains(event.target); 3586 var resultsContainTarget = this._elements.results.contains(event.target); 3587 3588 if (!(inputContainsTarget || resultsContainTarget)) { 3589 toggleShow(this._elements.results, false); 3590 this._elements.input.setAttribute("aria-expanded", "false"); 3591 } 3592 }; 3593 3594 Search.prototype._resultsOpen = function() { 3595 return this._elements.results.style.display !== "none"; 3596 }; 3597 3598 Search.prototype._makeAccessible = function() { 3599 var id = NS + "-search-results-" + idCount; 3600 this._elements.input.setAttribute("aria-owns", id); 3601 this._elements.results.id = id; 3602 idCount++; 3603 }; 3604 3605 Search.prototype._generateItems = function(data, results) { 3606 var self = this; 3607 3608 data.forEach(function(item) { 3609 var el = document.createElement("span"); 3610 el.innerHTML = self._elements.itemTemplate.innerHTML; 3611 el.querySelectorAll(selectors.item.title)[0].appendChild(document.createTextNode(item.title)); 3612 el.querySelectorAll(selectors.item.self)[0].setAttribute("href", self._safeHref(item.url)); 3613 results.innerHTML += el.innerHTML; 3614 }); 3615 }; 3616 3617 Search.prototype._safeHref = function(href) { 3618 var a = document.createElement("a"); 3619 a.href = href; 3620 return a.pathname; 3621 }; 3622 3623 Search.prototype._markResults = function() { 3624 var nodeList = this._elements.results.querySelectorAll(selectors.item.self); 3625 var escapedTerm = this._elements.input.value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 3626 var regex = new RegExp("(" + escapedTerm + ")", "gi"); 3627 3628 for (var i = this._resultsOffset - 1; i < nodeList.length; ++i) { 3629 var result = nodeList[i]; 3630 mark(result, regex); 3631 } 3632 }; 3633 3634 Search.prototype._stepResultFocus = function(reverse) { 3635 var results = this._elements.results.querySelectorAll(selectors.item.self); 3636 var focused = this._elements.results.querySelector(selectors.item.focused); 3637 var newFocused; 3638 var index = Array.prototype.indexOf.call(results, focused); 3639 var focusedCssClass = NS + "-search__item--is-focused"; 3640 3641 if (results.length > 0) { 3642 3643 if (!reverse) { 3644 // highlight the next result 3645 if (index < 0) { 3646 results[0].classList.add(focusedCssClass); 3647 results[0].setAttribute("aria-selected", "true"); 3648 } else if (index + 1 < results.length) { 3649 results[index].classList.remove(focusedCssClass); 3650 results[index].setAttribute("aria-selected", "false"); 3651 results[index + 1].classList.add(focusedCssClass); 3652 results[index + 1].setAttribute("aria-selected", "true"); 3653 } 3654 3655 // if the last visible result is partially hidden, scroll up until it's completely visible 3656 newFocused = this._elements.results.querySelector(selectors.item.focused); 3657 if (newFocused) { 3658 var bottomHiddenHeight = newFocused.offsetTop + newFocused.offsetHeight - this._elements.results.scrollTop - this._elements.results.clientHeight; 3659 if (bottomHiddenHeight > 0) { 3660 this._elements.results.scrollTop += bottomHiddenHeight; 3661 } else { 3662 this._onScroll(); 3663 } 3664 } 3665 3666 } else { 3667 // highlight the previous result 3668 if (index >= 1) { 3669 results[index].classList.remove(focusedCssClass); 3670 results[index].setAttribute("aria-selected", "false"); 3671 results[index - 1].classList.add(focusedCssClass); 3672 results[index - 1].setAttribute("aria-selected", "true"); 3673 } 3674 3675 // if the first visible result is partially hidden, scroll down until it's completely visible 3676 newFocused = this._elements.results.querySelector(selectors.item.focused); 3677 if (newFocused) { 3678 var topHiddenHeight = this._elements.results.scrollTop - newFocused.offsetTop; 3679 if (topHiddenHeight > 0) { 3680 this._elements.results.scrollTop -= topHiddenHeight; 3681 } 3682 } 3683 } 3684 } 3685 }; 3686 3687 Search.prototype._updateResults = function() { 3688 var self = this; 3689 if (self._hasMoreResults) { 3690 var request = new XMLHttpRequest(); 3691 var url = self._action + "?" + serialize(self._elements.form) + "&" + PARAM_RESULTS_OFFSET + "=" + self._resultsOffset; 3692 3693 request.open("GET", url, true); 3694 request.onload = function() { 3695 // when the results are loaded: hide the loading indicator and display the search icon after a minimum period 3696 setTimeout(function() { 3697 toggleShow(self._elements.loadingIndicator, false); 3698 toggleShow(self._elements.icon, true); 3699 }, LOADING_DISPLAY_DELAY); 3700 if (request.status >= 200 && request.status < 400) { 3701 // success status 3702 var data = JSON.parse(request.responseText); 3703 if (data.length > 0) { 3704 self._generateItems(data, self._elements.results); 3705 self._markResults(); 3706 toggleShow(self._elements.results, true); 3707 self._elements.input.setAttribute("aria-expanded", "true"); 3708 } else { 3709 self._hasMoreResults = false;
3710 } 3711 // the total number of results is not a multiple of the fetched results: 3712 // -> we reached the end of the query 3713 if (self._elements.results.querySelectorAll(selectors.item.self).length % self._properties.resultsSize > 0) { 3714 self._hasMoreResults = false; 3715 } 3716 } else { 3717 // error status 3718 } 3719 }; 3720 // when the results are loading: display the loading indicator and hide the search icon 3721 toggleShow(self._elements.loadingIndicator, true); 3722 toggleShow(self._elements.icon, false); 3723 request.send(); 3724 } 3725 }; 3726 3727 Search.prototype._cancelResults = function() { 3728 clearTimeout(this._timeout); 3729 this._elements.results.scrollTop = 0; 3730 this._resultsOffset = 0; 3731 this._hasMoreResults = true; 3732 this._elements.results.innerHTML = ""; 3733 this._elements.input.setAttribute("aria-expanded", "false"); 3734 }; 3735 3736 Search.prototype._cacheElements = function(wrapper) { 3737 this._elements = {}; 3738 this._elements.self = wrapper; 3739 var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 3740 3741 for (var i = 0; i < hooks.length; i++) { 3742 var hook = hooks[i]; 3743 var capitalized = IS; 3744 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3745 var key = hook.dataset[NS + "Hook" + capitalized]; 3746 this._elements[key] = hook; 3747 } 3748 }; 3749 3750 Search.prototype._setupProperties = function(options) { 3751 this._properties = {}; 3752 3753 for (var key in properties) { 3754 if (Object.prototype.hasOwnProperty.call(properties, key)) { 3755 var property = properties[key]; 3756 if (options && options[key] != null) { 3757 if (property && typeof property.transform === "function") { 3758 this._properties[key] = property.transform(options[key]); 3759 } else { 3760 this._properties[key] = options[key]; 3761 } 3762 } else { 3763 this._properties[key] = properties[key]["default"]; 3764 } 3765 } 3766 } 3767 }; 3768 3769 function onDocumentReady() { 3770 var elements = document.querySelectorAll(selectors.self); 3771 for (var i = 0; i < elements.length; i++) { 3772 new Search({ element: elements[i], options: readData(elements[i]) }); 3773 } 3774 3775 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 3776 var body = document.querySelector("body"); 3777 var observer = new MutationObserver(function(mutations) { 3778 mutations.forEach(function(mutation) { 3779 // needed for IE 3780 var nodesArray = [].slice.call(mutation.addedNodes); 3781 if (nodesArray.length > 0) { 3782 nodesArray.forEach(function(addedNode) { 3783 if (addedNode.querySelectorAll) { 3784 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 3785 elementsArray.forEach(function(element) { 3786 new Search({ element: element, options: readData(element) }); 3787 }); 3788 } 3789 }); 3790 } 3791 }); 3792 }); 3793 3794 observer.observe(body, { 3795 subtree: true, 3796 childList: true, 3797 characterData: true 3798 }); 3799 } 3800 3801 if (document.readyState !== "loading") { 3802 onDocumentReady(); 3803 } else { 3804 document.addEventListener("DOMContentLoaded", onDocumentReady); 3805 } 3806 3807})(); 3808 3809 3810/******************************************************************************* 3811 * Copyright 2016 Adobe 3812 * 3813 * Licensed under the Apache License, Version 2.0 (the "License"); 3814 * you may not use this file except in compliance with the License. 3815 * You may obtain a copy of the License at 3816 * 3817 * http://www.apache.org/licenses/LICENSE-2.0 3818 * 3819 * Unless required by applicable law or agreed to in writing, softw
3819are 3820 * distributed under the License is distributed on an "AS IS" BASIS, 3821 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3822 * See the License for the specific language governing permissions and 3823 * limitations under the License. 3824 ******************************************************************************/ 3825(function() { 3826 "use strict"; 3827 3828 var NS = "cmp"; 3829 var IS = "formText"; 3830 var IS_DASH = "form-text"; 3831 var SELF_SELECTOR = "[data-" + NS + '-is="' + IS + '"]'; 3832 3833 var selectors = { 3834 self: SELF_SELECTOR, 3835 validationMessage: SELF_SELECTOR + " .cmp-form-text__validation-message" 3836 }; 3837 3838 var displayValidationMessage = false; 3839 3840 var properties = { 3841 /** 3842 * A validation message to display if there is a type mismatch between the user input and expected input. 3843 * 3844 * @type {String} 3845 */ 3846 constraintMessage: "", 3847 /** 3848 * A validation message to display if no input is supplied, but input is expected for the field. 3849 * 3850 * @type {String} 3851 */ 3852 requiredMessage: "" 3853 }; 3854 3855 function readData(element) { 3856 var data = element.dataset; 3857 var options = []; 3858 var capitalized = IS; 3859 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3860 var reserved = ["is", "hook" + capitalized]; 3861 3862 for (var key in data) { 3863 if (Object.prototype.hasOwnProperty.call(data, key)) { 3864 var value = data[key]; 3865 3866 if (key.indexOf(NS) === 0) { 3867 key = key.slice(NS.length); 3868 key = key.charAt(0).toLowerCase() + key.substring(1); 3869 3870 if (reserved.indexOf(key) === -1) { 3871 options[key] = value; 3872 } 3873 } 3874 } 3875 } 3876 3877 return options; 3878 } 3879 3880 function FormText(config) { 3881 if (config.element) { 3882 // prevents multiple initialization 3883 config.element.removeAttribute("data-" + NS + "-is"); 3884 } 3885 3886 this._cacheElements(config.element); 3887 this._setupProperties(config.options); 3888 3889 this._elements.input.addEventListener("invalid", this._onInvalid.bind(this)); 3890 this._elements.input.addEventListener("input", this._onInput.bind(this)); 3891 if (displayValidationMessage) { 3892 this._elements.input.checkValidity(); 3893 } 3894 } 3895 3896 FormText.prototype._onInvalid = function(event) { 3897 event.target.setCustomValidity(""); 3898 if (event.target.validity.typeMismatch) { 3899 if (this._properties.constraintMessage) { 3900 event.target.setCustomValidity(this._properties.constraintMessage); 3901 } 3902 } else if (event.target.validity.valueMissing) { 3903 if (this._properties.requiredMessage) { 3904 event.target.setCustomValidity(this._properties.requiredMessage); 3905 } 3906 } 3907 if (displayValidationMessage) { 3908 var validationMessage = event.target.parentElement.querySelector(".cmp-form-text__validation-message"); 3909 if (validationMessage) { 3910 validationMessage.innerText = event.target.validationMessage; 3911 } 3912 } 3913 }; 3914 3915 FormText.prototype._onInput = function(event) { 3916 event.target.setCustomValidity(""); 3917 if (displayValidationMessage) { 3918 event.target.checkValidity(); 3919 } 3920 }; 3921 3922 FormText.prototype._cacheElements = function(wrapper) { 3923 this._elements = {}; 3924 this._elements.self = wrapper; 3925 var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS_DASH + "]"); 3926 for (var i = 0; i < hooks.length; i++) { 3927 var hook = hooks[i]; 3928 var capitalized = IS; 3929 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3930 var key = hook.dataset[NS + "Hook" + capitalized]; 3931 this._elements[key] = hook; 3932 } 3933 }; 3934 3935 FormText.prototype._setupProperties = function(options) { 3936 this._properties = {}; 3937 3938 for (var key in properties) { 3939 if (Object.prototype.hasOwnProperty.call(properties, key)) { 3940 var property = properties[key]; 3941 if (options && options[key] != null) { 3942 if (property && typeof property.transform === "function") { 3943 this._properties[key] = property.transform(options[key]); 3944 } else { 3945 this._properties[key] = options[key]; 3946 } 3947 } else { 3948 this._properties[key] = properties[key]["default"]; 3949 } 3950 } 3951 } 3952 }; 3953 3954 function onDocumentReady() {
3955 var validationMessages = document.querySelectorAll(selectors.validationMessage); 3956 if (validationMessages && validationMessages.length > 0) { 3957 displayValidationMessage = true; 3958 } 3959 3960 var elements = document.querySelectorAll(selectors.self); 3961 for (var i = 0; i < elements.length; i++) { 3962 new FormText({ element: elements[i], options: readData(elements[i]) }); 3963 } 3964 3965 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 3966 var body = document.querySelector("body"); 3967 var observer = new MutationObserver(function(mutations) { 3968 mutations.forEach(function(mutation) { 3969 // needed for IE 3970 var nodesArray = [].slice.call(mutation.addedNodes); 3971 if (nodesArray.length > 0) { 3972 nodesArray.forEach(function(addedNode) { 3973 if (addedNode.querySelectorAll) { 3974 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 3975 elementsArray.forEach(function(element) { 3976 new FormText({ element: element, options: readData(element) }); 3977 }); 3978 } 3979 }); 3980 } 3981 }); 3982 }); 3983 3984 observer.observe(body, { 3985 subtree: true, 3986 childList: true, 3987 characterData: true 3988 }); 3989 } 3990 3991 if (document.readyState !== "loading") { 3992 onDocumentReady(); 3993 } else { 3994 document.addEventListener("DOMContentLoaded", onDocumentReady); 3995 } 3996 3997})(); 3998 3999 4000/******************************************************************************* 4001 * Copyright 2020 Adobe 4002 * 4003 * Licensed under the Apache License, Version 2.0 (the "License"); 4004 * you may not use this file except in compliance with the License. 4005 * You may obtain a copy of the License at 4006 * 4007 * http://www.apache.org/licenses/LICENSE-2.0 4008 * 4009 * Unless required by applicable law or agreed to in writing, software 4010 * distributed under the License is distributed on an "AS IS" BASIS, 4011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4012 * See the License for the specific language governing permissions and 4013 * limitations under the License. 4014 ******************************************************************************/ 4015(function () { 4016 "use strict"; 4017 4018 var NS = "cmp"; 4019 var IS = "pdfviewer"; 4020 var SDK_URL = "https://documentservices.adobe.com/view-sdk/viewer.js"; 4021 var SDK_READY_EVENT = "adobe_dc_view_sdk.ready"; 4022 4023 var selectors = { 4024 self: "[data-" + NS + '-is="' + IS + '"]', 4025 sdkScript: 'script[src="' + SDK_URL + '"]' 4026 }; 4027 4028 function initSDK() { 4029 var sdkIncluded = $(selectors.sdkScript).length > 0; 4030 if (!window.adobe_dc_view_sdk && !sdkIncluded) { 4031 var dcv = document.createElement("script"); 4032 dcv.type = "text/javascript"; 4033 dcv.src = SDK_URL; 4034 document.body.appendChild(dcv); 4035 } 4036 } 4037 4038 function previewPdf(component) { 4039 var $component = $(component); 4040 4041 // prevents multiple initialization 4042 $component.removeAttr("data-" + NS + "-is"); 4043 4044 // add the view sdk to the page 4045 initSDK(); 4046 4047 // manage the preview 4048 if ($component.data() && component.id) { 4049 if (window.AdobeDC && window.AdobeDC.View) { 4050 dcView(component); 4051 } else { 4052 document.addEventListener(SDK_READY_EVENT, function () { 4053 dcView(component); 4054 }); 4055 } 4056 } 4057 } 4058 4059 function dcView(component) { 4060 var adobeDCView = new window.AdobeDC.View({ 4061 clientId: component.dataset.cmpClientId, 4062 divId: component.id + "-content", 4063 locale: navigator.language, 4064 reportSuiteId: component.dataset.cmpReportSuiteId 4065 }); 4066 4067 let viewerConfig; 4068 try { 4069 viewerConfig = JSON.parse(component.dataset.cmpViewerConfigJson); 4070 } catch (e) { 4071 console.error("Errore nel parsing di cmpViewerConfigJson:", e); 4072 return; 4073 } 4074 adobeDCView.previewFile({ 4075 content: { location: { url: component.dataset.cmpDocumentPath } }, 4076 metaData: { fileName: component.dataset.cmpDocumentFileName } 4077 }, viewerConfig); 4078 } 4079 4080 function onDocumentReady() { 4081 // Inizializza i pdfviewer presenti al caricamento 4082 $(selectors.self).each(function () { 4083 previewPdf(this); 4084 }); 4085 4086 // Observer per elementi aggiunti dinamicamente 4087 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 4088 var observer = new MutationObserver(function (mutations) { 4089 mutations.forEach(function (mutation) { 4090 $(mutation.addedNodes).each(function () { 4091 var $node = $(this); 4092 if ($node.find) { 4093 $node.find(selectors.self).each(function () { 4094 previewPdf(this); 4095 }); 4096 } 4097 }); 4098 }); 4099 }); 4100 4101 observer.observe(document.body, { 4102 subtree: true, 4103 childList: true, 4104 characterData: true 4105 }); 4106 } 4107 4108 if (document.readyState !== "loading") { 4109 onDocumentReady(); 4110 } else { 4111 $(document).ready(onDocumentReady); 4112 } 4113})(); 4114 4115 4116/******************************************************************************* 4117 * Copyright 2020 Adobe 4118 * 4119 * Licensed under the Apache License, Version 2.0 (the "License");
4120 * you may not use this file except in compliance with the License. 4121 * You may obtain a copy of the License at 4122 * 4123 * http://www.apache.org/licenses/LICENSE2.0 4124 * 4125 * Unless required by applicable law or agreed to in writing, software 4126 * distributed under the License is distributed on an "AS IS" BASIS, 4127 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4128 * See the License for the specific language governing permissions and 4129 * limitations under the License. 4130 ******************************************************************************/ 4131 4132/** 4133 * Element.matches() 4134 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill 4135 */ 4136if (!Element.prototype.matches) { 4137 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 4138} 4139 4140// eslint-disable-next-line valid-jsdoc 4141/** 4142 * Element.closest() 4143 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill 4144 */ 4145if (!Element.prototype.closest) { 4146 Element.prototype.closest = function(s) { 4147 "use strict"; 4148 var el = this; 4149 if (!document.documentElement.contains(el)) { 4150 return null; 4151 } 4152 do { 4153 if (el.matches(s)) { 4154 return el; 4155 } 4156 el = el.parentElement || el.parentNode; 4157 } while (el !== null && el.nodeType === 1); 4158 return null; 4159 }; 4160} 4161 4162// https://tc39.github.io/ecma262/#sec-array.prototype.find 4163if (!Array.prototype.find) { 4164 Object.defineProperty(Array.prototype, "find", { 4165 value: function(predicate) { 4166 "use strict"; 4167 // 1. Let O be ? ToObject(this value). 4168 if (this == null) { 4169 throw TypeError('"this" is null or not defined'); 4170 } 4171 4172 var o = Object(this); 4173 4174 // 2. Let len be ? ToLength(? Get(O, "length")). 4175 var len = o.length >>> 0; 4176 4177 // 3. If IsCallable(predicate) is false, throw a TypeError exception. 4178 if (typeof predicate !== "function") { 4179 throw TypeError("predicate must be a function"); 4180 } 4181 4182 // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. 4183 var thisArg = arguments[1]; 4184 4185 // 5. Let k be 0. 4186 var k = 0; 4187 4188 // 6. Repeat, while k < len 4189 while (k < len) { 4190 // a. Let Pk be ! ToString(k). 4191 // b. Let kValue be ? Get(O, Pk). 4192 // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). 4193 // d. If testResult is true, return kValue. 4194 var kValue = o[k]; 4195 if (predicate.call(thisArg, kValue, k, o)) { 4196 return kValue; 4197 } 4198 // e. Increase k by 1. 4199 k++; 4200 } 4201 4202 // 7. Return undefined. 4203 return undefined; 4204 }, 4205 configurable: true, 4206 writable: true 4207 }); 4208} 4209 4210"use strict";function _slicedToArray(t,e){return _arrayWithHoles(t)||_iterableToArrayLimit(t,e)||_unsupportedIterableToArray(t,e)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _iterableToArrayLimit(t,e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(t)){var n=[],r=!0,o=!1,a=void 0;try{for(var i,u=t[Symbol.iterator]();!(r=(i=u.next()).done)&&(n.push(i.value),!e||n.length!==e);r=!0);}catch(t){o=!0,a=t}finally{try{r||null==u.return||u.return()}finally{if(o)throw a}}return n}}function _arrayWithHoles(t){if(Array.isArray(t))return t}function _createForOfIteratorHelper(t){if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(t=_unsupportedIterableToArray(t))){var e=0,n=function(){};return{s:n,n:function(){return e>=t.length?{done:!0}:{done:!1,value:t[e++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,o,a=!0,i=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){i=!0,o=t},f:function(){try{a||null==r.return||r.return()}finally{if(i)throw o}}}}function _unsupportedIterableToArray(t,e){if(t){if("string"==typeof t)return _arrayLikeToArray(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(n):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(t,e):void 0}}function _arrayLikeToArray(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function a(i,u,c){function f(e,t){if(!u[e]){if(!i[e]){var n="function"==typeof require&&require;if(!t&&n)return n(e,!0);if(s)return s(e,!0);var r=new Error("Cannot find module '"+e+"'");throw r.code="MODULE_NOT_FOUND",r}var o=u[e]={exports:{}};i[e][0].call(o.exports,function(t){return f(i[e][1][t]||t)},o,o.exports,a,i,u,c)}return u[e].exports}for(var s="function"==typeof require&&require,t=0;t<c.length;t++)f(c[t]);return f}({1:[function(t,wn,En){(function(On){(function(){function n(t,e){for(var n=-1,r=null==t?0:t.length,o=0,a=[];++n<r;){var i=t[n];e(i,n,t)&&(a[o++]=i)}return a}function a(t,e){for(var n=-1,r=null==t?0:t.length,o=Array(r);++n<r;)o[n]=e(t[n],n,t);return o}function f(t,e){for(var n=-1,r=e.length,o=t.length;++n<r;)t[o+n]=e[n];return t}function b(t,e){for(var n=-1,r=null==t?0:t.length;++n<r;)if(e(t[n],n,t))return!0;return!1}function o(t,e,n){var r=t.length;for(n+=-1;++n<r;)if(e(t[n],n,t))return n;return-1}function i(t){return t!=t}function t(e){return function(t){return e(t)}}function h(t){var n=-1,r=Array(t.size);return t.forEach(function(t,e){r[++n]=[e,t]}),r}function e(e){var n=Object;return function(t){return e(n(t))}}function v(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[++e]=t}),n}function r(){}function u(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}function s(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}function d(t){var e=-1,n=null==t?0:t.length;for(this.__data__=new s;++e<n;)this.add(t[e])}function g(t){this.size=(this.__data__=new c(t)).size}function l(t,e){var n=hn(t),r=!n&&bn(t),o=!n&&!r&&vn(t),a=!n&&!r&&!o&&_n(t);if(n=n||r||o||a){r=t.length;for(var i=String,u=-1,c=Array(r);++u<r;)c[u]=i(u);r=c}else r=[];var f;i=r.length;for(f in t)!e&&!be.call(t,f)||n&&("length"==f||o&&("offset"==f||"parent"==f)||a&&("buffer"==f||"byteLength"==f||"byteOffset"==f)||Q(f,i))||r.push(f);return r}function _(t,e,n){(n===Mt||ft(t[e],n))&&(n!==Mt||e in t)||j(t,e,n)}function y(t,e,n){var r=t[e];be.call(t,e)&&ft(r,n)&&(n!==Mt||e in t)||j(t,e,n)}function p(t,e){for(var n=t.length;n--;)if(ft(t[n][0],e))return n;return-1}function j(t,e,n){"__proto__"==e&&xe?xe(t,e,{configurable:!0,enumerable:!0,value:n,writable:!0}):t[e]=n}function m(n,r,o,t,e,a){var i,u=1&r,c=2&r,f=4&r;
4210if(o&&(i=e?o(n,t,e,a):o(n)),i!==Mt)return i;if(!bt(n))return n;if(t=hn(n)){if(i=function(t){var e=t.length,n=new t.constructor(e);return e&&"string"==typeof t[0]&&be.call(t,"index")&&(n.index=t.index,n.input=t.input),n}(n),!u)return U(n,i)}else{var s=nn(n),l="[object Function]"==s||"[object GeneratorFunction]"==s;if(vn(n))return M(n,u);if("[object Object]"==s||"[object Arguments]"==s||l&&!e){if(i=c||l?{}:Y(n),!u)return c?function(t,e){return P(t,en(t),e)}(n,function(t,e){return t&&P(e,St(e),t)}(i,n)):function(t,e){return P(t,tn(t),e)}(n,function(t,e){return t&&P(e,Lt(e),t)}(i,n))}else{if(!Kt[s])return e?n:{};i=function(t,e,n){var r=t.constructor;switch(e){case"[object ArrayBuffer]":return z(t);case"[object Boolean]":case"[object Date]":return new r(+t);case"[object DataView]":return e=n?z(t.buffer):t.buffer,new t.constructor(e,t.byteOffset,t.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]":return C(t,n);case"[object Map]":return new r;case"[object Number]":case"[object String]":return new r(t);case"[object RegExp]":return(e=new t.constructor(t.source,Ht.exec(t))).lastIndex=t.lastIndex,e;case"[object Set]":return new r;case"[object Symbol]":return qe?Object(qe.call(t)):{}}}(n,s,u)}}if(e=(a=a||new g).get(n))return e;if(a.set(n,i),gn(n))return n.forEach(function(t){i.add(m(t,r,o,t,n,a))}),i;if(dn(n))return n.forEach(function(t,e){i.set(e,m(t,r,o,e,n,a))}),i;c=f?c?B:H:c?St:Lt;var p=t?Mt:c(n);return function(t,e){for(var n=-1,r=null==t?0:t.length;++n<r&&!1!==e(t[n],n,t););}(p||n,function(t,e){p&&(t=n[e=t]),y(i,e,m(t,r,o,e,n,a))}),i}function A(t,e){for(var n=0,r=(e=F(e,t)).length;null!=t&&n<r;)t=t[nt(e[n++])];return n&&n==r?t:Mt}function O(t,e,n){return e=e(t),hn(t)?e:f(e,n(t))}function w(t){if(null==t)t=t===Mt?"[object Undefined]":"[object Null]";else if(Te&&Te in Object(t)){var e=be.call(t,Te),n=t[Te];try{t[Te]=Mt;var r=!0}catch(t){}var o=ve.call(t);r&&(e?t[Te]=n:delete t[Te]),t=o}else t=ve.call(t);return t}function E(t,e){return null!=t&&be.call(t,e)}function L(t,e){return null!=t&&e in Object(t)}function S(t){return ht(t)&&"[object Arguments]"==w(t)}function T(t,e,n,r,o){if(t===e)e=!0;else if(null==t||null==e||!ht(t)&&!ht(e))e=t!=t&&e!=e;else t:{var a,i,u=hn(t),c=hn(e),f="[object Object]"==(a="[object Arguments]"==(a=u?"[object Array]":nn(t))?"[object Object]":a);c="[object Object]"==(i="[object Arguments]"==(i=c?"[object Array]":nn(e))?"[object Object]":i);if((i=a==i)&&vn(t)){if(!vn(e)){e=!1;break t}f=!(u=!0)}if(i&&!f)o=o||new g,e=u||_n(t)?V(t,e,n,r,T,o):function(t,e,n,r,o,a,i){switch(n){case"[object DataView]":if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)break;t=t.buffer,e=e.buffer;case"[object ArrayBuffer]":if(t.byteLength!=e.byteLength||!a(new me(t),new me(e)))break;return!0;case"[object Boolean]":case"[object Date]":case"[object Number]":return ft(+t,+e);case"[object Error]":return t.name==e.name&&t.message==e.message;case"[object RegExp]":case"[object String]":return t==e+"";case"[object Map]":var u=h;case"[object Set]":if(u=u||v,t.size!=e.size&&!(1&r))break;return(n=i.get(t))?n==e:(r|=2,i.set(t,e),e=V(u(t),u(e),r,o,a,i),i.delete(t),e);case"[object Symbol]":if(qe)return qe.call(t)==qe.call(e)}return!1}(t,e,a,n,r,T,o);else{if(!(1&n)&&(u=f&&be.call(t,"__wrapped__"),a=c&&be.call(e,"__wrapped__"),u||a)){e=T(t=u?t.value():t,e=a?e.value():e,n,r,o=o||new g);break t}if(i)e:if(o=o||new g,u=1&n,a=H(t),c=a.length,i=H(e).length,c==i||u){for(f=c;f--;){var s=a[f];if(!(u?s in e:be.call(e,s))){e=!1;break e}}if((i=o.get(t))&&o.get(e))e=i==e;else{i=!0,o.set(t,e),o.set(e,t);for(var l=u;++f<c;){var p=t[s=a[f]],y=e[s];if(r)var b=u?r(y,p,s,e,t,o):r(p,y,s,t,e,o);if(b===Mt?p!==y&&!T(p,y,n,r,o):!b){i=!1;break}l=l||"constructor"==s}i&&!l&&((n=t.constructor)!=(r=e.constructor)&&"constructor"in t&&"constructor"in e&&!("function"==typeof n&&n instanceof n&&"function"==typeof r&&r instanceof r)&&(i=!1)),o.delete(t),o.delete(e),e=i}}else e=!1;else e=!1}}return e}function x(t){return"function"==typeof t?t:null==t?It:"object"==_typeof(t)?hn(t)?function(n,r){return X(n)&&r==r&&!bt(r)?tt(nt(n),r):function(t){var e=wt(t,n);return e===Mt&&e===r?Et(t,n):T(r,e,3)}}(t[0],t[1]):function(e){var n=function(t){for(var e=Lt(t),n=e.length;n--;){var r=e[n],o=t[r];e[n]=[r,o,o==o&&!bt(o)]}return e}(e);return 1==n.length&&n[0][2]?tt(n[0][0],n[0][1]):function(t){return t===e||function(t,e){var n=e.length,r=n;if(null==t)return!r;for(t=Object(t);n--;){if((o=e[n])[2]?o[1]!==t[o[0]]:!(o[0]in t))return!1}for(;++n<r;
4210){var o,a=(o=e[n])[0],i=t[a],u=o[1];if(o[2]){if(i===Mt&&!(a in t))return!1}else if(o=new g,void 0!==Mt||!T(u,i,3,void 0,o))return!1}return!0}(t,n)}}(t):Nt(t)}function I(t){if(!Z(t))return Ne(t);var e,n=[];for(e in Object(t))be.call(t,e)&&"constructor"!=e&&n.push(e);return n}function k(s,l,p,y,b){s!==l&&Xe(l,function(t,e){if(bt(t)){var n=b=b||new g,r="__proto__"==e?Mt:s[e],o="__proto__"==e?Mt:l[e];if(f=n.get(o))_(s,e,f);else{var a=(f=y?y(r,o,e+"",s,l,n):Mt)===Mt;if(a){var i=hn(o),u=!i&&vn(o),c=!i&&!u&&_n(o),f=o;i||u||c?f=hn(r)?r:lt(r)?U(r):u?M(o,!(a=!1)):c?C(o,!(a=!1)):[]:vt(o)||bn(o)?bn(f=r)?f=At(r):(!bt(r)||p&&pt(r))&&(f=Y(o)):a=!1}a&&(n.set(o,f),k(f,o,p,y,n),n.delete(o)),_(s,e,f)}}else(n=y?y("__proto__"==e?Mt:s[e],t,e+"",s,l,b):Mt)===Mt&&(n=t),_(s,e,n)},St)}function N(t){if("string"==typeof t)return t;if(hn(t))return a(t,N)+"";if(gt(t))return Je?Je.call(t):"";var e=t+"";return"0"==e&&1/t==-zt?"-0":e}function D(t,e){var n;if((e=F(e,t)).length<2)n=t;else{var r=0,o=-1,a=-1,i=(n=e).length;for(r<0&&(r=i<-r?0:i+r),(o=i<o?i:o)<0&&(o+=i),i=o<r?0:o-r>>>0,r>>>=0,o=Array(i);++a<i;)o[a]=n[a+r];n=A(t,o)}null==(t=n)||delete t[nt(it(e))]}function F(t,e){return hn(t)?t:X(t,e)?[t]:ln(Ot(t))}function M(t,e){if(e)return t.slice();var n=t.length;n=Ae?Ae(n):new t.constructor(n);return t.copy(n),n}function z(t){var e=new t.constructor(t.byteLength);return new me(e).set(new me(t)),e}function C(t,e){return new t.constructor(e?z(t.buffer):t.buffer,t.byteOffset,t.length)}function U(t,e){var n=-1,r=t.length;for(e=e||Array(r);++n<r;)e[n]=t[n];return e}function P(t,e,n){var r=!n;n=n||{};for(var o=-1,a=e.length;++o<a;){var i=e[o],u=Mt;u===Mt&&(u=t[i]),r?j(n,i,u):y(n,i,u)}return n}function R(f){return function(t){return sn(et(t,void 0,It),t+"")}(function(t,e){var n,r=-1,o=e.length,a=1<o?e[o-1]:Mt,i=2<o?e[2]:Mt;a=3<f.length&&"function"==typeof a?(o--,a):Mt;if(n=i){n=e[0];var u=e[1];if(bt(i)){var c=_typeof(u);n=!!("number"==c?st(i)&&Q(u,i.length):"string"==c&&u in i)&&ft(i[u],n)}else n=!1}for(n&&(a=o<3?Mt:a,o=1),t=Object(t);++r<o;)(i=e[r])&&f(t,i,r,a);return t})}function $(t){return vt(t)?Mt:t}function V(t,e,n,r,o,a){var i=1&n,u=t.length;if(u!=(c=e.length)&&!(i&&u<c))return!1;if((c=a.get(t))&&a.get(e))return c==e;var c=-1,f=!0,s=2&n?new d:Mt;for(a.set(t,e),a.set(e,t);++c<u;){var l=t[c],p=e[c];if(r)var y=i?r(p,l,c,e,t,a):r(l,p,c,t,e,a);if(y!==Mt){if(y)continue;f=!1;break}if(s){if(!b(e,function(t,e){if(!s.has(e)&&(l===t||o(l,t,n,r,a)))return s.push(e)})){f=!1;break}}else if(l!==p&&!o(l,p,n,r,a)){f=!1;break}}return a.delete(t),a.delete(e),f}function H(t){return O(t,Lt,tn)}function B(t){return O(t,St,en)}function W(t,e){var n=(n=r.iteratee||kt)===kt?x:n;return arguments.length?n(t,e):n}function G(t,e){var n=t.__data__,r=_typeof(e);return("string"==r||"number"==r||"symbol"==r||"boolean"==r?"__proto__"!==e:null===e)?n["string"==typeof e?"string":"hash"]:n.map}function q(t,e){var n=null==t?Mt:t[e];return!bt(n)||he&&he in n||!(pt(n)?ge:Gt).test(rt(n))?Mt:n}function J(t,e,n){for(var r=-1,o=(e=F(e,t)).length,a=!1;++r<o;){var i=nt(e[r]);if(!(a=null!=t&&n(t,i)))break;t=t[i]}return a||++r!=o?a:!!(o=null==t?0:t.length)&&yt(o)&&Q(i,o)&&(hn(t)||bn(t))}function Y(t){return"function"!=typeof t.constructor||Z(t)?{}:Ye(Oe(t))}function K(t){return hn(t)||bn(t)||!!(Se&&t&&t[Se])}function Q(t,e){var n=_typeof(t);return!!(e=null==e?9007199254740991:e)&&("number"==n||"symbol"!=n&&Jt.test(t))&&-1<t&&0==t%1&&t<e}function X(t,e){if(hn(t))return!1;var n=_typeof(t);return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!gt(t))||Pt.test(t)||!Ut.test(t)||null!=e&&t in Object(e)}function Z(t){var e=t&&t.constructor;return t===("function"==typeof e&&e.prototype||le)}function tt(e,n){return function(t){return null!=t&&t[e]===n&&(n!==Mt||e in Object(t))}}function et(o,a,i){return a=De(a===Mt?o.length-1:a,0),function(){for(var t=arguments,e=-1,n=De(t.length-a,0),r=Array(n);++e<n;)r[e]=t[a+e];for(e=-1,n=Array(a+1);++e<a;)n[e]=t[e];return n[a]=i(r),function(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}(o,this,n)}}function nt(t){if("string"==typeof t||gt(t))return t;var e=t+"";return"0"==e&&1/t==-zt?"-0":e}function rt(t){if(null==t)return"";try{return ye.call(t)}catch(t){}return t+""}function ot(t,e,n){var r=null==t?0:t.length;return r?((n=null==n?0:jt(n))<0&&(n=De(r+n,0)),o(t,W(e,3),n)):-1}function at(t){return null!=t&&t.length?function t(e,n,r,o,a){var i=-1,u=e.length;for(r=r||K,a=a||[];++i<u;){var c=e[i];0<n&&r(c)?1<n?t(c,n-1,r,o,a):f(a,c):o||(a[a.length]=c)}return a}(t,1):[]}function it(t){var e=null==t?0:t.length;return e?t[e-1]:Mt}function ut(r,o){function a(){var t=arguments,e=o?o.apply(this,t):t[0],n=a.cache;return n.has(e)?n.get(e):(t=r.apply(this,t),a.cache=n.set(e,t)||n,t)}if("function"!=typeof r||null!=o&&"function"!=typeof o)throw new TypeError("Expected a function");return a.cache=new(ut.Cache||s),a}function ct(e){if("function"!=typeof e)throw new TypeError("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!e.call(this);case 1:return!e.call(this,t[0]);case 2:return!e.call(this,t[0],t[1]);case 3:return!e.call(this,t[0],t[1],t[2])}return!e.apply(this,t)}}function ft(t,e){return t===e||t!=t&&e!=e}function st(t){return null!=t&&yt(t.length)&&!pt(t)}function lt(t){return ht(t)&&st(t)}function pt(t){return!!bt(t)&&("[object Function]"==(t=w(t))||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t)}function yt(t){return"number"==typeof t&&-1<t&&0==t%1&&t<=9007199254740991}function bt(t){var e=_typeof(t);return null!=t&&("object"==e||"function"==e)}function ht(t){return null!=t&&"object"==_typeof(t)}function vt(t){return!(!ht(t)||"[object Object]"!=w(t))&&(null===(t=Oe(t))||"function"==typeof(t=be.call(t,"constructor")&&t.constructor)&&t instanceof t&&ye.call(t)==de)}function dt(t){return"string"==typeof t||!hn(t)&&ht(t)&&"[object String]"==w(t)}function gt(t){return"symbol"==_typeof(t)||ht(t)&&"[object Symbol]"==w(t)}function _t(t){return t?(t=mt(t))===zt||t===-zt?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}function jt(t){var e=(t=_t(t))%1;return t==t?e?t-e:t:0}function mt(t){if("number"==typeof t)return t;if(gt(t))return Ct;if(bt(t)&&(t=bt(t="function"==typeof t.valueOf?t.valueOf():t)?t+"":t),"string"!=typeof t)return 0===t?t:+t;t=t.replace($t,"");var e=Wt.test(t);return e||qt.test(t)?Xt(t.slice(2),e?2:8):Bt.test(t)?Ct:+t}function At(t){return P(t,St(t))}function Ot(t){return null==t?"":N(t)}function wt(t,e,n){return(t=null==t?Mt:A(t,e))===Mt?n:t}function Et(t,e){return null!=t&&J(t,e,L)}function Lt(t){return st(t)?l(t):I(t)}function St(t){if(st(t))t=l(t,!0);else if(bt(t)){var e,n=Z(t),r=[];for(e in t)("constructor"!=e||!n&&be.call(t,e))&&r.push(e);t=r}else{if(e=[],null!=t)for(n in Object(t))e.push(n);t=e}return t}function Tt(t){return null==t?[]:function(e,t){return a(t,function(t){return e[t]})}(t,Lt(t))}function xt(t){return function(){return t}}function It(t){return t}function kt(t){return x("function"==typeof t?t:m(t,1))}function Nt(t){return X(t)?function(e){return function(t){return null==t?Mt:t[e]}}(nt(t)):function(e){return function(t){return A(t,e)}}(t)}function Dt(){return[]}function Ft(){return!1}var Mt,zt=1/0,Ct=NaN,Ut=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Pt=/^\w*$/,Rt=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,$t=/^\s+|\s+$/g,Vt=/\\(\\)?/g,Ht=/\w*$/,Bt=/^[-+]0x[0-9a-f]+$/i,Wt=/^0b[01]+$/i,Gt=/^\[object .+?Constructor\]$/,qt=/^0o[0-7]+$/i,Jt=/^(?:0|[1-9]\d*)$/,Yt={};
4210Yt["[object Float32Array]"]=Yt["[object Float64Array]"]=Yt["[object Int8Array]"]=Yt["[object Int16Array]"]=Yt["[object Int32Array]"]=Yt["[object Uint8Array]"]=Yt["[object Uint8ClampedArray]"]=Yt["[object Uint16Array]"]=Yt["[object Uint32Array]"]=!0,Yt["[object Arguments]"]=Yt["[object Array]"]=Yt["[object ArrayBuffer]"]=Yt["[object Boolean]"]=Yt["[object DataView]"]=Yt["[object Date]"]=Yt["[object Error]"]=Yt["[object Function]"]=Yt["[object Map]"]=Yt["[object Number]"]=Yt["[object Object]"]=Yt["[object RegExp]"]=Yt["[object Set]"]=Yt["[object String]"]=Yt["[object WeakMap]"]=!1;var Kt={};Kt["[object Arguments]"]=Kt["[object Array]"]=Kt["[object ArrayBuffer]"]=Kt["[object DataView]"]=Kt["[object Boolean]"]=Kt["[object Date]"]=Kt["[object Float32Array]"]=Kt["[object Float64Array]"]=Kt["[object Int8Array]"]=Kt["[object Int16Array]"]=Kt["[object Int32Array]"]=Kt["[object Map]"]=Kt["[object Number]"]=Kt["[object Object]"]=Kt["[object RegExp]"]=Kt["[object Set]"]=Kt["[object String]"]=Kt["[object Symbol]"]=Kt["[object Uint8Array]"]=Kt["[object Uint8ClampedArray]"]=Kt["[object Uint16Array]"]=Kt["[object Uint32Array]"]=!0,Kt["[object Error]"]=Kt["[object Function]"]=Kt["[object WeakMap]"]=!1;var Qt,Xt=parseInt,Zt="object"==_typeof(On)&&On&&On.Object===Object&&On,te="object"==("undefined"==typeof self?"undefined":_typeof(self))&&self&&self.Object===Object&&self,ee=Zt||te||Function("return this")(),ne="object"==_typeof(En)&&En&&!En.nodeType&&En,re=ne&&"object"==_typeof(wn)&&wn&&!wn.nodeType&&wn,oe=re&&re.exports===ne,ae=oe&&Zt.process;t:{try{Qt=ae&&ae.binding&&ae.binding("util");break t}catch(t){}Qt=void 0}var ie,ue=Qt&&Qt.isMap,ce=Qt&&Qt.isSet,fe=Qt&&Qt.isTypedArray,se=Array.prototype,le=Object.prototype,pe=ee["__core-js_shared__"],ye=Function.prototype.toString,be=le.hasOwnProperty,he=(ie=/[^.]+$/.exec(pe&&pe.keys&&pe.keys.IE_PROTO||""))?"Symbol(src)_1."+ie:"",ve=le.toString,de=ye.call(Object),ge=RegExp("^"+ye.call(be).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),_e=oe?ee.Buffer:Mt,je=ee.Symbol,me=ee.Uint8Array,Ae=_e?_e.a:Mt,Oe=e(Object.getPrototypeOf),we=Object.create,Ee=le.propertyIsEnumerable,Le=se.splice,Se=je?je.isConcatSpreadable:Mt,Te=je?je.toStringTag:Mt,xe=function(){try{var t=q(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),Ie=Object.getOwnPropertySymbols,ke=_e?_e.isBuffer:Mt,Ne=e(Object.keys),De=Math.max,Fe=Date.now,Me=q(ee,"DataView"),ze=q(ee,"Map"),Ce=q(ee,"Promise"),Ue=q(ee,"Set"),Pe=q(ee,"WeakMap"),Re=q(Object,"create"),$e=rt(Me),Ve=rt(ze),He=rt(Ce),Be=rt(Ue),We=rt(Pe),Ge=je?je.prototype:Mt,qe=Ge?Ge.valueOf:Mt,Je=Ge?Ge.toString:Mt,Ye=function(t){return bt(t)?we?we(t):(Ke.prototype=t,t=new Ke,Ke.prototype=Mt,t):{}};function Ke(){}u.prototype.clear=function(){this.__data__=Re?Re(null):{},this.size=0},u.prototype.delete=function(t){return t=this.has(t)&&delete this.__data__[t],this.size-=t?1:0,t},u.prototype.get=function(t){var e=this.__data__;return Re?"__lodash_hash_undefined__"===(t=e[t])?Mt:t:be.call(e,t)?e[t]:Mt},u.prototype.has=function(t){var e=this.__data__;return Re?e[t]!==Mt:be.call(e,t)},u.prototype.set=function(t,e){var n=this.__data__;return this.size+=this.has(t)?0:1,n[t]=Re&&e===Mt?"__lodash_hash_undefined__":e,this},c.prototype.clear=function(){this.__data__=[],this.size=0},c.prototype.delete=function(t){var e=this.__data__;return!((t=p(e,t))<0||(t==e.length-1?e.pop():Le.call(e,t,1),--this.size,0))},c.prototype.get=function(t){var e=this.__data__;return(t=p(e,t))<0?Mt:e[t][1]},c.prototype.has=function(t){return-1<p(this.__data__,t)},c.prototype.set=function(t,e){var n=this.__data__,r=p(n,t);return r<0?(++this.size,n.push([t,e])):n[r][1]=e,this},s.prototype.clear=function(){this.size=0,this.__data__={hash:new u,map:new(ze||c),string:new u}},s.prototype.delete=function(t){return t=G(this,t).delete(t),this.size-=t?1:0,t},s.prototype.get=function(t){return G(this,t).get(t)},s.prototype.has=function(t){return G(this,t).has(t)},s.prototype.set=function(t,e){var n=G(this,t),r=n.size;return n.set(t,e),this.size+=n.size==r?0:1,this},d.prototype.add=d.prototype.push=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this},d.prototype.has=function(t){return this.__data__.has(t)},g.prototype.clear=function(){this.__data__=new c,this.size=0},g.prototype.delete=function(t){var e=this.__data__;return t=e.delete(t),this.size=e.size,t},g.prototype.get=function(t){return this.__data__.get(t)},g.prototype.has=function(t){return this.__data__.has(t)},g.prototype.set=function(t,e){var n=this.__data__;if(n instanceof c){var r=n.__data__;if(!ze||r.length<199)return r.push([t,e]),this.size=++n.size,this;n=this.__data__=new s(r)}return n.set(t,e),this.size=n.size,this};var Qe=function(t,e){if(null==t)return t;if(!st(t))return function(t,e){return t&&Xe(t,e,Lt)}(t,e);for(var n=t.length,r=-1,o=Object(t);++r<n&&!1!==e(o[r],r,o););return t},Xe=function(t,e,n){for(var r=-1,o=Object(t),a=(n=n(t)).length;a--;){var i=n[++r];if(!1===e(o[i],i,o))break}return t},Ze=xe?function(t,e){return xe(t,"toString",{configurable:!0,enumerable:!1,value:xt(e),writable:!0})}:It,tn=Ie?function(e){return null==e?[]:(e=Object(e),n(Ie(e),function(t){return Ee.call(e,t)}))}:Dt,en=Ie?function(t){for(var e=[];t;)f(e,tn(t)),t=Oe(t);return e}:Dt,nn=w;(Me&&"[object DataView]"!=nn(new Me(new ArrayBuffer(1)))||ze&&"[object Map]"!=nn(new ze)||Ce&&"[object Promise]"!=nn(Ce.resolve())||Ue&&"[object Set]"!=nn(new Ue)||Pe&&"[object WeakMap]"!=nn(new Pe))&&(nn=function(t){var e=w(t);if(t=(t="[object Object]"==e?t.constructor:Mt)?rt(t):"")switch(t){case $e:return"[object DataView]";case Ve:return"[object Map]";case He:return"[object Promise]";case Be:return"[object Set]";case We:return"[object WeakMap]"}return e});var rn,on,an,un,cn,fn,sn=(un=Ze,fn=cn=0,function(){var t=Fe(),e=16-(t-fn);if(fn=t,0<e){if(800<=++cn)return arguments[0]}else cn=0;return un.apply(Mt,arguments)}),ln=(an=(on=ut(on=function(t){var o=[];return 46===t.charCodeAt(0)&&o.push(""),t.replace(Rt,function(t,e,n,r){o.push(n?r.replace(Vt,"$1"):e||t)}),o},function(t){return 500===an.size&&an.clear(),t})).cache,on),pn=(rn=ot,function(t,e,n){var r=Object(t);if(!st(t)){var o=W(e,3);t=Lt(t),e=function(t){return o(r[t],t,r)}}return-1<(e=rn(t,e,n))?r[o?t[e]:e]:Mt});ut.Cache=s;var yn,bn=S(function(){return arguments}())?S:function(t){return ht(t)&&be.call(t,"callee")&&!Ee.call(t,"callee")},hn=Array.isArray,vn=ke||Ft,dn=ue?t(ue):function(t){return ht(t)&&"[object Map]"==nn(t)},gn=ce?t(ce):function(t){return ht(t)&&"[object Set]"==nn(t)}
4210,_n=fe?t(fe):function(t){return ht(t)&&yt(t.length)&&!!Yt[w(t)]},jn=R(function(t,e,n){k(t,e,n)}),mn=R(function(t,e,n,r){k(t,e,n,r)}),An=sn(et(yn=function(e,t){var n={};if(null==e)return n;var r=!1;t=a(t,function(t){return t=F(t,e),r=r||1<t.length,t}),P(e,B(e),n),r&&(n=m(n,7,$));for(var o=t.length;o--;)D(n,t[o]);return n},Mt,at),yn+"");r.constant=xt,r.flatten=at,r.iteratee=kt,r.keys=Lt,r.keysIn=St,r.memoize=ut,r.merge=jn,r.mergeWith=mn,r.negate=ct,r.omit=An,r.property=Nt,r.reject=function(t,e){return(hn(t)?n:function(t,r){var o=[];return Qe(t,function(t,e,n){r(t,e,n)&&o.push(t)}),o})(t,ct(W(e,3)))},r.toPlainObject=At,r.values=Tt,r.cloneDeep=function(t){return m(t,5)},r.cloneDeepWith=function(t,e){return m(t,5,e="function"==typeof e?e:Mt)},r.eq=ft,r.find=pn,r.findIndex=ot,r.get=wt,r.has=function(t,e){return null!=t&&J(t,e,E)},r.hasIn=Et,r.identity=It,r.includes=function(t,e,n,r){if(t=st(t)?t:Tt(t),n=n&&!r?jt(n):0,r=t.length,n<0&&(n=De(r+n,0)),dt(t))t=n<=r&&-1<t.indexOf(e,n);else{if(r=!!r){if(e==e)t:{for(n-=1,r=t.length;++n<r;)if(t[n]===e){t=n;break t}t=-1}else t=o(t,i,n);r=-1<t}t=r}return t},r.isArguments=bn,r.isArray=hn,r.isArrayLike=st,r.isArrayLikeObject=lt,r.isBuffer=vn,r.isEmpty=function(t){if(null==t)return!0;if(st(t)&&(hn(t)||"string"==typeof t||"function"==typeof t.splice||vn(t)||_n(t)||bn(t)))return!t.length;var e=nn(t);if("[object Map]"==e||"[object Set]"==e)return!t.size;if(Z(t))return!I(t).length;for(var n in t)if(be.call(t,n))return!1;return!0},r.isEqual=function(t,e){return T(t,e)},r.isFunction=pt,r.isLength=yt,r.isMap=dn,r.isNull=function(t){return null===t},r.isObject=bt,r.isObjectLike=ht,r.isPlainObject=vt,r.isSet=gn,r.isString=dt,r.isSymbol=gt,r.isTypedArray=_n,r.last=it,r.stubArray=Dt,r.stubFalse=Ft,r.toFinite=_t,r.toInteger=jt,r.toNumber=mt,r.toString=Ot,r.VERSION="4.17.5",re&&((re.exports=r)._=r,ne._=r)}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],2:[function(t,e,n){e.exports={itemType:{DATA:"data",FCTN:"fctn",EVENT:"event",LISTENER_ON:"listenerOn",LISTENER_OFF:"listenerOff"},dataLayerEvent:{CHANGE:"adobeDataLayer:change",EVENT:"adobeDataLayer:event"},listenerScope:{PAST:"past",FUTURE:"future",ALL:"all"}}},{}],3:[function(t,e,n){var r=t("../custom-lodash"),c=t("../version.json").version,l=r.cloneDeep,p=r.get,y=t("./item"),b=t("./listener"),h=t("./listenerManager"),v=t("./constants"),d=t("./utils/customMerge");e.exports=function(t){var f,e=t||{},n=[],r=[],o={},a={getState:function(){return o},getDataLayer:function(){return n}};function i(t){o=d(o,t.data)}function u(t){t.valid?{data:function(t){i(t),f.triggerListeners(t)},fctn:function(t){t.config.call(n,n)},event:function(t){t.data&&i(t),f.triggerListeners(t)},listenerOn:function(t){var e=b(t);switch(e.scope){case v.listenerScope.PAST:var n,r=_createForOfIteratorHelper(c(t));try{for(r.s();!(n=r.n()).done;){var o=n.value;f.triggerListener(e,o)}}catch(t){r.e(t)}finally{r.f()}break;case v.listenerScope.FUTURE:f.register(e);break;case v.listenerScope.ALL:if(f.register(e)){var a,i=_createForOfIteratorHelper(c(t));try{for(i.s();!(a=i.n()).done;){var u=a.value;f.triggerListener(e,u)}}catch(t){i.e(t)}finally{i.f()}}}},listenerOff:function(t){f.unregister(b(t))}}[t.type](t):s(t);function c(t){return 0===n.length||t.index>n.length-1?[]:n.slice(0,t.index).map(function(t){return y(t)})}}function s(t){var e="The following item cannot be handled by the data layer because it does not have a valid format: "+JSON.stringify(t.config);console.error(e)}return function(){Array.isArray(e.dataLayer)||(e.dataLayer=[]);r=e.dataLayer.splice(0,e.dataLayer.length),(n=e.dataLayer).version=c,o={},f=h(a)}(),n.push=function(t){var n=arguments,r=arguments;if(Object.keys(n).forEach(function(t){var e=y(n[t]);switch(e.valid||(s(e),delete r[t]),e.type){case v.itemType.DATA:case v.itemType.EVENT:u(e);break;case v.itemType.FCTN:delete r[t],u(e);break;case v.itemType.LISTENER_ON:case v.itemType.LISTENER_OFF:delete r[t]}}),r[0])return Array.prototype.push.apply(this,r)},n.getState=function(t){return t?p(l(o),t):l(o)},n.addEventListener=function(t,e,n){u(y({on:t,handler:e,scope:n&&n.scope,path:n&&n.path}))},n.removeEventListener=function(t,e){u(y({off:t,handler:e}))},function(){for(var t=0;t<r.length;t++)n.push(r[t])}(),a}},{"../custom-lodash":1,"../version.json":14,"./constants":2,"./item":5,"./listener":7,"./listenerManager":8,"./utils/customMerge":10}],4:[function(t,e,n){var r={Manager:t("./dataLayerManager")};window.adobeDataLayer=window.adobeDataLayer||[],window.adobeDataLayer.version?console.warn("Adobe Client Data Layer v".concat(window.adobeDataLayer.version," has already been imported/initialized on this page. You may be erroneously loading it a second time.")):r.Manager({dataLayer:window.adobeDataLayer}),e.exports=r},{"./dataLayerManager":3}],5:[function(t,e,n){var r=t("../custom-lodash"),i=r.isPlainObject,u=r.isEmpty,c=r.omit,f=r.find,s=t("./utils/dataMatchesContraints"),l=t("./itemConstraints"),p=t("./constants");e.exports=function(t,e){var n=t,r=e,o=f(Object.keys(l),function(t){return s(n,l[t])})||"function"==typeof n&&p.itemType.FCTN||i(n)&&p.itemType.DATA,a=function(){var t=c(n,Object.keys(l.event));if(!u(t))return t}();return{config:n,type:o,data:a,valid:!!o,index:r}}},{"../custom-lodash":1,"./constants":2,"./itemConstraints":6,"./utils/dataMatchesContraints":11}],6:[function(t,e,n){e.exports={event:{event:{type:"string"},eventInfo:{optional:!0}},listenerOn:{on:{type:"string"},handler:{type:"function"},scope:{type:"string",values:["past","future","all"],optional:!0},path:{type:"string",optional:!0}},listenerOff:{off:{type:"string"},handler:{type:"function",optional:!0},scope:{type:"string",values:["past","future","all"],optional:!0},path:{type:"string",optional:!0}}}},{}],7:[function(t,e,n){var r=t("./constants");e.exports=function(t){return{event:t.config.on||t.config.off,handler:t.config.handler||null,scope:t.config.scope||t.config.on&&r.listenerScope.ALL||null,path:t.config.path||null}}},{"./constants":2}],8:[function(t,e,n){var u=t("../custom-lodash").cloneDeep,c=t("./constants"),f=t("./utils/listenerMatch"),s=t("./utils/indexOfListener");e.exports=function(t){var o={},r=t,a=s.bind(null,o);function i(t,e){if(f(t,e)){var n=[u(e.config)];t.handler.apply(r.getDataLayer(),n)}}return{register:function(t){var e=t.event;return Object.prototype.hasOwnProperty.call(o,e)?-1===a(t)&&(o[t.event].push(t),!0):(o[t.event]=[t],!0)},unregister:function(t){var e=t.event;if(Object.prototype.hasOwnProperty.call(o,e))if(t.handler||t.scope||t.path){var n=a(t);-1<n&&o[e].splice(n,1)}else o[e]=[]},triggerListeners:function(r){(function(t){var e=[];switch(t.type){case c.itemType.DATA:e.push(c.dataLayerEvent.CHANGE);break;case c.itemType.EVENT:e.push(c.dataLayerEvent.EVENT),t.data&&e.push(c.dataLayerEvent.CHANGE),t.config.event!==c.dataLayerEvent.CHANGE&&e.push(t.config.event)}return e})(r).forEach(function(t){if(Object.prototype.hasOwnProperty.call(o,t)){var e,n=_createForOfIteratorHelper(o[t]);try{for(n.s();!(e=n.n()).done;){i(e.value,r)}}catch(t){n.e(t)}finally{n.f()}}})},triggerListener:function(t,e){i(t,e)}}}},{"../custom-lodash":1,"./constants":2,"./utils/indexOfListener":12,"./utils/listenerMatch":13}],9:[function(t,e,n){var r=t("../../custom-lodash"),o=r.has,a=r.get;e.exports=function(t,e){for(var n=e.substring(0,e.lastIndexOf("."));n;){if(o(t,n)){var r=a(t,n);if(null==r)return!0}n=n.substring(0,n.lastIndexOf("."))}return!1}},{"../../custom-lodash":1}],10:[function(t,e,n){var r=t("../../custom-lodash"),s=r.cloneDeepWith,l=r.isObject,p=r.isArray,y=r.reject,o=r.mergeWith,a=r.isNull;e.exports=function(t,e){return o(t,e,function(t,e,n,r){if(null==e)return null}),t=function(t,e){return s(t,function(f){return function e(t,n,r,o){if(l(t)){if(p(t))return y(t,f).map(function(t){return s(t,e)});for(var a={},i=0,u=Object.keys(t);i<u.length;i++){var c=u[i];f(t[c])||(a[c]=s(t[c],e))}return a}}}(1<arguments.length&&void 0!==e?e:function(t){return!t}))}(t,a)}},{"../../custom-lodash":1}],11:[function(t,e,n){var r=t("../../custom-lodash"),o=r.find,s=r.includes;e.exports=function(c,f){return void 0===o(Object.keys(f),function(t){var e=f[t].type,n=t&&f[t].values,r=!f[t].optional,o=c[t],a=_typeof(o),i=e&&a!==e,u=n&&!s(n,o);return r?!o||i||u:o&&(i||u)})}},{"../../custom-lodash":1}],12:[function(t,e,n){var c=t("../../custom-lodash").isEqual;e.exports=function(t,e){var n=e.event;if(Object.prototype.hasOwnProperty.call(t,n)){var r,o=_createForOfIteratorHelper(t[n].entries());try{for(o.s();!(r=o.n()).done;){var a=_slicedToArray(r.value,2),i=a[0],u=a[1];if(c(u.handler,e.handler))return i}}catch(t){o.e(t)}finally{o.f()}}return-1}},{"../../custom-lodash":1}],13:[function(t,e,n){var r=t("../../custom-lodash").has,a=t("../constants"),o=t("./ancestorRemoved");function i(t,e){return!e.data||!t.path||(r(e.data,t.path)||o(e.data,t.path))}
4210e.exports=function(t,e){var n=t.event,r=e.config,o=!1;return e.type===a.itemType.DATA?n===a.dataLayerEvent.CHANGE&&(o=i(t,e)):e.type===a.itemType.EVENT&&(n!==a.dataLayerEvent.EVENT&&n!==r.event||(o=i(t,e)),e.data&&n===a.dataLayerEvent.CHANGE&&(o=i(t,e))),o}},{"../../custom-lodash":1,"../constants":2,"./ancestorRemoved":9}],14:[function(t,e,n){e.exports={version:"2.0.2"}},{}]},{},[4]); 4211//# sourceMappingURL=adobe-client-data-layer.min.js.map 4212 4213/******************************************************************************* 4214 * Copyright 2020 Adobe 4215 * 4216 * Licensed under the Apache License, Version 2.0 (the "License"); 4217 * you may not use this file except in compliance with the License. 4218 * You may obtain a copy of the License at 4219 * 4220 * http://www.apache.org/licenses/LICENSE-2.0 4221 * 4222 * Unless required by applicable law or agreed to in writing, software 4223 * distributed under the License is distributed on an "AS IS" BASIS, 4224 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4225 * See the License for the specific language governing permissions and 4226 * limitations under the License. 4227 ******************************************************************************/ 4228(function() { 4229 "use strict"; 4230 4231 var dataLayerEnabled; 4232 var dataLayerName; 4233 var dataLayer; 4234 4235 function addComponentToDataLayer(component) { 4236 dataLayer.push({ 4237 component: getComponentObject(component) 4238 }); 4239 } 4240 4241 function attachClickEventListener(element) { 4242 element.addEventListener("click", addClickToDataLayer); 4243 } 4244 4245 function getComponentObject(element) { 4246 var component = getComponentData(element); 4247 var componentID = Object.keys(component)[0]; 4248 // if the component does not have a parent ID property, use the ID of the parent element 4249 if (component && component[componentID] && !component[componentID].parentId) { 4250 var parentElement = element.parentNode.closest("[data-cmp-data-layer], body"); 4251 if (parentElement) { 4252 component[componentID].parentId = parentElement.id; 4253 } 4254 } 4255 4256 return component; 4257 } 4258 4259 function addClickToDataLayer(event) { 4260 var element = event.currentTarget; 4261 var componentId = getClickId(element); 4262 4263 dataLayer.push({ 4264 event: "cmp:click", 4265 eventInfo: { 4266 path: "component." + componentId 4267 } 4268 }); 4269 } 4270 4271 function getComponentData(element) { 4272 var dataLayerJson = element.dataset.cmpDataLayer; 4273 if (dataLayerJson) { 4274 return JSON.parse(dataLayerJson); 4275 } else { 4276 return undefined; 4277 } 4278 } 4279 4280 function getClickId(element) { 4281 if (element.dataset.cmpDataLayer) { 4282 return Object.keys(JSON.parse(element.dataset.cmpDataLayer))[0]; 4283 } 4284 4285 var componentElement = element.closest("[data-cmp-data-layer]"); 4286 4287 return Object.keys(JSON.parse(componentElement.dataset.cmpDataLayer))[0]; 4288 } 4289 4290 function onDocumentReady() { 4291 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 4292 if (dataLayerEnabled) { 4293 dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer"; 4294 dataLayer = window[dataLayerName] = window[dataLayerName] || []; 4295 4296 var components = document.querySelectorAll("[data-cmp-data-layer]"); 4297 var clickableElements = document.querySelectorAll("[data-cmp-clickable]"); 4298 4299 components.forEach(function(component) { 4300 addComponentToDataLayer(component); 4301 }); 4302 4303 clickableElements.forEach(function(element) { 4304 attachClickEventListener(element); 4305 }); 4306 4307 dataLayer.push({ 4308 event: "cmp:loaded" 4309 }); 4310 } 4311 } 4312 4313 if (document.readyState !== "loading") { 4314 onDocumentReady(); 4315 } else { 4316 document.addEventListener("DOMContentLoaded", onDocumentReady); 4317 } 4318 4319}()); 4320 4321 4322(function (document) { 4323 if(document.getElementsByTagName("main")[0] != null) { 4324 document.getElementsByTagName("main")[0].setAttribute("id", "main"); 4325 } 4326})(document); 4327 4328// ScrollTop 4329$(window).on("scroll", function () { 4330 if ($(this).scrollTop() >= 350) { 4331 $("#scroll-top-btn").fadeIn(200); 4332 } else { 4333 $("#scroll-top-btn").fadeOut(200); 4334 } 4335}); 4336$("#scroll-top-btn").on("click", function (e) { 4337 $("body,html").animate({ 4338 scrollTop: 0 4339 }, 500); 4340 e.preventDefault(); 4341}); 4342 4343$(function () { 4344 $(document).on('foundation-contentloaded',function(){ 4345 $('[data-toggle="tooltip"]').tooltip() 4346 }) 4347 4348}) 4349 4350// IE11 Object-fit image 4351var isIE11 = !!window.MSInputMethodContext && !!document.documentMode; 4352if (isIE11) { 4353 $('.img-wrapper, .card-image-left').each(function () { 4354 var $container = $(this), 4355 imgUrl = $container.find('img').prop('src') 4356 if (imgUrl) { 4357 $container 4358 .css('backgroundImage', 'url(' + imgUrl + ')') 4359 .addClass('custom-object-fit') 4360 } 4361 }) 4362} 4363 4364// GESTIONE MENU PRINCIPALE 4365$('.nav-open').click(function (e) { 4366 $(".nav").addClass("show"); 4367 $("body").addClass("overflow-hidden"); 4368 $(".nav").on('click', function (e) { 4369 if ($(e.target).closest("#nav").length === 0) { 4370 closeMenu(); 4371 } 4372 }); 4373}); 4374function closeMenu() { 4375 $(".nav").removeClass("show").off(); 4376 $("body").removeClass("overflow-hidden"); 4377} 4378$('.nav-close').click(function (e) { 4379 closeMenu(); 4380}); 4381 4382// Click esterno al menu per la chiusura 4383$(document).on('click', function (e) { 4384 if ($(".navbar-collapse.show").length > 0 || $("#cerca-top.show").length > 0) { 4385 if ($(e.target).closest(".divMenu").length === 0) { 4386 $("#menu-top").collapse('hide'); 4387 $("body").removeClass("overflow-hidden"); 4388 } 4389 if ($(e.target).closest(".divCerca").length === 0) { 4390 $("#cerca-top").collapse('hide'); 4391 $("body").removeClass("overflow-hidden"); 4392 } 4393 } 4394}); 4395$(function () { 4396 var navMain = $(".navbar-collapse"); // avoid dependency on #id 4397 // "a:not([data-toggle])" - to avoid issues caused 4398 // when you have dropdown inside navbar 4399 navMain.on("click", "a:not([data-toggle])", null, function () { 4400 navMain.collapse('hide'); 4401 }); 4402}); 4403$(document).on('click', 'a[href="#menu-top"]', function (e) { 4404 $("#menu-top a").first().focus(); 4405 if ($(this).is('[data-toggle="collapse"]')) { 4406 $("body").addClass("overflow-hidden"); 4407 } 4408}); 4409$(document).on('click', 'a[href="#cerca-top"][data-toggle="collapse"]', function (e) { 4410 $("#cerca-top a").first().focus(); 4411 $("body").addClass("overflow-hidden"); 4412}); 4413$(document).on('click', 'a[href="#sidebar-menu-mobile"][data-toggle="collapse"]', function (e) { 4414 $("#sidebar-menu-mobile a").first().focus(); 4415 $("body").addClass("overflow-hidden"); 4416}); 4417$(document).on('click', 'a[href="#menu-top"][data-toggle="collapse"][aria-expanded="true"], a[href="#cerca-top"][data-toggle="collapse"][aria-expanded="true"], a[href="#sidebar-menu-mobile"][data-toggle="collapse"][aria-expanded="true"]', function (e) { 4418 $("body").removeClass("overflow-hidden"); 4419}); 4420$(document).on('keydown', function (e) { 4421 if (e.key === "Escape") { 4422 if ($("#menu-top.show").length > 0) { 4423 $("#menu-top").collapse('hide'); 4424 $("body").removeClass("overflow-hidden"); 4425 $("a[href='#menu-top']").first().focus(); 4426 } 4427 if ($("#cerca-top.show").length > 0) { 4428 $("#cerca-top").collapse('hide'); 4429 $("body").removeClass("overflow-hidden"); 4430 $("a[href='#cerca-top']").first().focus(); 4431 } 4432 if ($("#sidebar-menu-mobile.show").length > 0) { 4433 $("#sidebar-menu-mobile").collapse('hide'); 4434 $("body").removeClass("overflow-hidden"); 4435 $("a[href='#sidebar-menu-mobile']").first().focus(); 4436 } 4437 } 4438 if (e.key === "Tab") { 4439 if ($("#menu-top.show").length > 0) { 4440 if ($(e.target).closest("#menu-top").length === 0) { 4441 $("#menu-top a").first().focus(); 4442 } 4443 } 4444 if ($("#cerca-top.show").length > 0) { 4445 if ($(e.target).closest("#cerca-top").length === 0) { 4446 $("#cerca-top a").first().focus(); 4447 } 4448 } 4449 if ($("#sidebar-menu-mobile.show").length > 0) { 4450 if ($(e.target).closest("#sidebar-menu-mobile").length === 0) { 4451 $("#sidebar-menu-mobile button").first().focus(); 4452 } 4453 } 4454 } 4455}); 4456 4457// Accesso rapido tabs 4458$(document).on('click', '.accesso-rapido .nav-link', function (e) { 4459 id = $(this).attr("href"); 4460 $(".accesso-rapido .tab-pane").removeClass("active").removeClass("show"); 4461 $(id).addClass("active show"); 4462}); 4463 4464// Input text, textarea, select filled 4465$("textarea.form-control, input.form-control, select.form-control").on('keyup change', '', function (e) { 4466 if ($(this).hasClass("thin-ui-multiselect")) { 4467 if (!$(this).val().length) { 4468 $(this).next().find("button.form-control").removeClass("filled"); 4469 } else { 4470 $(this).next().find("button.form-control").addClass("filled"); 4471 } 4472 } else { 4473 if (!$(this).val()) { 4474 $(this).removeClass("filled"); 4475 } else { 4476 $(this).addClass("filled"); 4477 } 4478 } 4479}); 4480$("textarea.form-control, input.form-control").keyup(); 4481$("select.form-control").change(); 4482 4483 4484// Inizializzazione Calendario VanillaJs Datepicker Sirio Version 4485// Lingua italiana modifica per ottenere la grafica del design 4486(function () { 4487 Datepicker.locales.it = { 4488 // Termini di base 4489 days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"], 4490 daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"], 4491 daysMin: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"], 4492 months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], 4493 monthsShort: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], 4494 today: "Oggi", 4495 monthsTitle: "Mesi", 4496 clear: "Cancella", 4497 format: "dd/mm/yyyy", 4498 4499 // Aggiunte per l'aria-label dei bottoni in testata 4500 btnMonth: "Cambia il mese", 4501 btnPrevMonth: "Mese precedente", 4502 btnNextMonth: "Mese successivo", 4503 // Utilizzati dopo aver cliccato sul bottone centrale prima volta 4504 btnYear: "Cambia l\'anno", 4505 btnPrevYear: "Anno precedente", 4506 btnNextYear: "Anno successivo", 4507 // Utilizzati dopo aver cliccato sul bottone centrale seconda volta 4508 btnDecade: "Cambia il decennio", 4509 btnPrevDecade: "Decennio precedente", 4510 btnNextDecade: "Decennio successivo", 4511 // Utilizzati dopo aver cliccato sul bottone centrale terza volta 4512 btnPrevCentury: "Secolo precedente", 4513 btnNextCentury: "Secolo successivo" 4514 }; 4515}()); 4516 4517var elems = document.getElementsByClassName("form-datepicker"); 4518for (var elem of elems) { 4519 if (!elem.parentNode.classList.contains("form-datepicker-range")) { 4520 var datepicker = new Datepicker(elem, { 4521 format: "dd/mm/yyyy", 4522 language: "it", 4523 weekStart: 1, 4524 prevArrow: '<span class="icon-xs icon-chevron-small-left" aria-hidden="true"></span>', 4525 nextArrow: '<span class="icon-xs icon-chevron-small-right" aria-hidden="true"></span>', 4526 autohide: true 4527 }); 4528 } 4529} 4530 4531var elemsRange = document.getElementsByClassName("form-datepicker-range"); 4532for (var elemRange of elemsRange) { 4533 var datepickerRange = new DateRangePicker(elemRange, { 4534 format: "dd/mm/yyyy", 4535 language: "it", 4536 weekStart: 1, 4537 prevArrow: '<span class="icon-xs icon-chevron-small-left" aria-hidden="true"></span>', 4538 nextArrow: '<span class="icon-xs icon-chevron-small-right" aria-hidden="true"></span>' 4539 }); 4540} 4541 4542// Splide carousel
4543const splideDataMap = new Map(); 4544window.SplideData = class { 4545 static set(element, instance) { 4546 if (!splideDataMap.has(element)) { 4547 splideDataMap.set(element, instance); 4548 } 4549 } 4550 static get(element) { 4551 if (splideDataMap.has(element)) { 4552 return splideDataMap.get(element); 4553 } 4554 4555 return null; 4556 } 4557 static remove(element) { 4558 if (!elementMap.has(element)) { 4559 return 4560 } 4561 4562 splideDataMap.delete(element) 4563 } 4564} 4565 4566var splide1 = { 4567 0: { 4568 perPage: 1 4569 } 4570} 4571var splide2 = { 4572 0: { 4573 gap: 12, 4574 perPage: 1 4575 }, 4576 768: { 4577 gap: 24, 4578 perPage: 2 4579 } 4580} 4581var splide3 = { 4582 0: { 4583 gap: 12, 4584 perPage: 1 4585 }, 4586 768: { 4587 gap: 24, 4588 perPage: 2 4589 }, 4590 992: { 4591 perPage: 3 4592 } 4593} 4594var splide4 = { 4595 0: { 4596 gap: 12, 4597 perPage: 1 4598 }, 4599 768: { 4600 gap: 24, 4601 perPage: 2 4602 }, 4603 992: { 4604 perPage: 3 4605 }, 4606 1280: { 4607 perPage: 4 4608 } 4609} 4610var splideSubsite = { 4611 0: { 4612 gap: 12, 4613 perPage: 1 4614 }, 4615 768: { 4616 destroy: true 4617 } 4618} 4619var splideAccessoRapido = { 4620 0: { 4621 gap: 12, 4622 perPage: 1 4623 }, 4624 768: { 4625 destroy: true 4626 } 4627} 4628var fotogallery = { 4629 0: { 4630 perPage: 3 4631 }, 4632 768: { 4633 perPage: 4, 4634 pagination: true 4635 }, 4636 992: { 4637 perPage: 5 4638 }, 4639 1280: { 4640 perPage: 6 4641 } 4642} 4643var gallery = { 4644 0: { 4645 fixedWidth: 100, 4646 fixedHeight: 60 4647 }, 4648 768: { 4649 fixedWidth: 150, 4650 fixedHeight: 90, 4651 } 4652} 4653var infografica = { 4654 0: { 4655 perPage: 3 4656 }, 4657 768: { 4658 perPage: 4, 4659 arrows: true 4660 }, 4661 992: { 4662 destroy: true 4663 } 4664} 4665var splideFaq = { 4666 0: { perPage: 1, gap: "1rem", pagination: true, arrows: true }, 4667 768: { perPage: 1, gap: "1rem" }, 4668 1200: { perPage: 1, gap: "1rem" } 4669}; 4670 4671if ($(".splide").length) { 4672 var splideElem = document.getElementsByClassName("splide"); 4673 for (var i = 0; i < splideElem.length; i++) { 4674 var bp = splide3 4675 if ($(splideElem[i]).hasClass("splide-1")) { 4676 bp = splide1; 4677 } 4678 if ($(splideElem[i]).hasClass("splide-faq")) { 4679 bp = splideFaq; 4680 } 4681 if ($(splideElem[i]).hasClass("splide-2")) { 4682 bp = splide2; 4683 } 4684 if ($(splideElem[i]).hasClass("splide-4") || $(splideElem[i]).hasClass("videogallery-slider")) { 4685 bp = splide4; 4686 } 4687 if ($(splideElem[i]).hasClass("splide-subsite")) { 4688 bp = splideSubsite; 4689 } 4690 if ($(splideElem[i]).hasClass("splide-accesso-rapido")) { 4691 bp = splideAccessoRapido; 4692 } 4693 if ($(splideElem[i]).hasClass("fotogallery-slider")) { 4694 bp = fotogallery; 4695 } 4696 if ($(splideElem[i]).hasClass("infografica-slider")) { 4697 bp = infografica; 4698 } 4699 if ($(splideElem[i]).hasClass("splide-slider")) { 4700 bp = {}; 4701 arrOptions = { 4702 type: 'fade', 4703 rewind: true, 4704 pagination: false, 4705 arrows: false, 4706 padding: { 4707 left: 3, 4708 right: 3, 4709 }, 4710 perPage: 1 4711 } 4712 } else if ($(splideElem[i]).hasClass("splide-thumb")) { 4713 bp = gallery; 4714 arrOptions = { 4715 fixedWidth: 150, 4716 fixedHeight: 90, 4717 gap: 10, 4718 padding: { 4719 left: 3, 4720 right: 3, 4721 }, 4722 rewind: true, 4723 pagination: false, 4724 cover: true, 4725 isNavigation: true, 4726 classes: { 4727 prev: 'splide__arrow--prev text-white icon-xs icon-chevron-small-left', 4728 next: 'splide__arrow--next text-white icon-xs icon-chevron-small-right', 4729 }, 4730 i18n: { 4731 prev: 'Slide precedente', 4732 next: 'Slide successiva', 4733 pageX: 'Vai alla pagina %s', 4734 slideX: 'Vai alla slide %s', 4735 first: 'Vai alla prima slide', 4736 last: 'Vai all\'ultima slide', 4737 play: 'Avvia riproduzione automatica', 4738 pause: 'Ferma riproduzione automatica', 4739 select: 'Seleziona la slide da visualizzare', 4740 slideLabel: '%s di %s' 4741 } 4742 } 4743 } else if ($(splideElem[i]).hasClass("splide-autoplay")) { 4744 arrOptions = { 4745 type: 'loop', 4746 perPage: 3, 4747 perMove: 1, 4748 autoplay: true, 4749 slideFocus: false, 4750 /* 4751 rewind: true, 4752 pauseOnHover: false, 4753 pauseOnFocus: false, 4754 focus: false,
4755 trimSpace: false, 4756 arrows: true, 4757 pagination: true, 4758 */ 4759 gap: 24, 4760 padding: { 4761 left: 0, 4762 right: 0, 4763 }, 4764 mediaQuery: 'min', 4765 breakpoints: bp, 4766 classes: { 4767 prev: 'splide__arrow--prev text-white icon-xs icon-chevron-small-left', 4768 next: 'splide__arrow--next text-white icon-xs icon-chevron-small-right', 4769 }, 4770 i18n: { 4771 prev: 'Slide precedente', 4772 next: 'Slide successiva', 4773 pageX: 'Vai alla pagina %s', 4774 slideX: 'Vai alla slide %s', 4775 first: 'Vai alla prima slide', 4776 last: 'Vai all\'ultima slide', 4777 play: 'Avvia riproduzione automatica', 4778 pause: 'Ferma riproduzione automatica', 4779 select: 'Seleziona la slide da visualizzare', 4780 slideLabel: '%s di %s' 4781 } 4782 } 4783 } else { 4784 arrOptions = { 4785 perPage: 3, 4786 perMove: 1, 4787 slideFocus: false, 4788 /* 4789 focus: false, 4790 trimSpace: false, 4791 arrows: true, 4792 pagination: true,*/ 4793 gap: 24, 4794 padding: { 4795 left: 0, 4796 right: 0, 4797 }, 4798 mediaQuery: 'min', 4799 breakpoints: bp, 4800 classes: { 4801 prev: 'splide__arrow--prev text-white icon-xs icon-chevron-small-left', 4802 next: 'splide__arrow--next text-white icon-xs icon-chevron-small-right', 4803 }, 4804 i18n: { 4805 prev: 'Slide precedente', 4806 next: 'Slide successiva', 4807 pageX: 'Vai alla pagina %s', 4808 slideX: 'Vai alla slide %s', 4809 first: 'Vai alla prima slide', 4810 last: 'Vai all\'ultima slide', 4811 select: 'Seleziona la slide da visualizzare', 4812 slideLabel: '%s di %s' 4813 } 4814 } 4815 } 4816 4817 if ($(splideElem[i]).hasClass("splide-subsite")) { 4818 id = $(splideElem[i]).closest(".section-subsite").attr("id"); 4819 if (id.includes('section-subsite')) { 4820 $('[id*="section-subsite"]').find(".img-wrapper").each(function () { 4821 $(this).find("img").not(":eq(0)").addClass("d-none"); 4822 }); 4823 new Splide(splideElem[i], arrOptions).mount().on('move', function (i) { 4824 $('[id*="section-subsite"]').find(".img-wrapper img").addClass("d-none"); 4825 $('[id*="section-subsite"]').find(".img-wrapper img:eq(" + (i + 1) + ")").removeClass("d-none") 4826 }); 4827 } 4828 } else { 4829 var splideInstance = new Splide(splideElem[i], arrOptions); 4830 splideInstance.mount(); 4831 SplideData.set(splideElem[i], splideInstance); 4832 } 4833 } 4834 for (var i = 0; i < splideElem.length; i++) { 4835 if ($(splideElem[i]).hasClass("splide-thumb")) { 4836 SplideData.get(splideElem[i - 1]).sync(SplideData.get(splideElem[i])); 4837 } 4838 4839 if ($(splideElem[i]).hasClass("splide-thumb-video")) { 4840 var istanzaSplider = $(splideElem[i - 1]); 4841 SplideData.get(splideElem[i - 1]).on("active", function (e) { 4842 istanzaSplider.attr("tabindex", "0").focus(); 4843 $('html, body').animate({ 4844 scrollTop: $("#" + istanzaSplider.attr("id")).offset().top - 100 4845 }, 500); 4846 }); 4847 $(splideElem[i]).find("li").keydown(function (event) { 4848 if (event.which === 13) { 4849 indice = $(this).index() 4850 contentVideo = istanzaSplider.find("li:eq(" + $(this).index() + ")"); 4851 contentVideo.attr('tabindex', '0').focus(); 4852 4853 id = "#" + contentVideo.parent().attr("id"); 4854 $('html, body').animate({ 4855 scrollTop: $(id).offset().top - 100 4856 }, 500); 4857 } 4858 }); 4859 } 4860 } 4861} 4862/* 4863$(".splide-thumb li").keydown(function (event) { 4864 if (event.which === 13) { 4865 console.log('hai premuto enter sulla miniatura ') 4866 console.log($(this).parent().parent().parent().siblings().children()) 4867 4868 $(this).parent().parent().parent().siblings().children().attr('tabindex', '0').focus() 4869 } 4870}) */ 4871 4872// Carousel Subsite change images 4873$(document).on('mouseenter', '.splide-subsite .splide__slide .card', function () { 4874 eq = $(this).closest(".splide__slide").index(); 4875 $(this).closest(".section-subsite").find(".img-wrapper img").addClass("d-none"); 4876 $(this).closest(".section-subsite").find(".img-wrapper img:eq(" + (eq + 1) + ")").removeClass("d-none") 4877}); 4878$(document).on('mouseleave', '.splide-subsite', function () { 4879 $(this).closest(".section-subsite").find(".img-wrapper img").addClass("d-none"); 4880 $(this).closest(".section-subsite").find(".img-wrapper img:first").removeClass("d-none") 4881}); 4882 4883 4884// Modals autofocus 4885$('.modal').on('shown.bs.modal', function () { 4886 $(this).trigger('focus'); 4887}) 4888 4889// Fotogallery 4890$(document).on('click', '[data-src-hq]', function (e) { 4891 if ($(this).closest(".fotogallery-slider").length <= 0 && $(this).closest(".infografica-slider").length <= 0) {
4892 if ($("#modal-zoom").length == 0) { 4893 modal = '<div class="modal modal-zoom" id="modal-zoom" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><h2 class="h3">Zoom immagine</h2><button type="button" class="close" data-dismiss="modal" aria-label="Chiudi"><span class="icon icon-close" aria-hidden="true"></span></button></div><div class="modal-body p-0"><figure><img src="" alt="" class="w-100 img-fluid"><figcaption><p></p></figcaption></figure></div></div></div></div>'; 4894 $("body").append(modal); 4895 } 4896 figcaption = $(this).parent().find("figcaption").text(); 4897 figure = $(this).attr("data-src-hq"); 4898 if (figcaption == "undefined") { 4899 figcaption = ""; 4900 } 4901 $("#modal-zoom figcaption p").html(figcaption); 4902 $("#modal-zoom img").attr("src", figure); 4903 $("#modal-zoom").modal("show"); 4904 } 4905 4906}); 4907 4908$(document).on('click', '.fotogallery-slider a', function (e) { 4909 $(".fotogallery-slider a").removeClass("active"); 4910 $(this).addClass("active"); 4911 id = $(this).closest(".fotogallery-slider").attr("data-slider-img"); 4912 figcaption = $(this).parent().find("figcaption").text(); 4913 figure = $(this).find("img").attr("data-src-hq"); 4914 if (figcaption == "undefined") { 4915 figcaption = ""; 4916 } 4917 $("#" + id + " figcaption p").html(figcaption); 4918 $("#" + id + " img").attr("src", figure); 4919 $("#" + id + " img").attr("data-src-hq", figure); 4920 e.preventDefault(); 4921}); 4922 4923 4924$(document).on('click', '.videogallery-slider a', function (e) { 4925 $(".videogallery-slider a").removeClass("active"); 4926 $(this).addClass("active"); 4927 id = "#" + $(this).attr("data-slider-video"); 4928 $(".videogallery > div").addClass("d-none"); 4929 $(id).removeClass("d-none"); 4930 $('html, body').animate({ 4931 scrollTop: $(id).offset().top - 200 4932 }, 500); 4933 // Servirebbe portare il focus sul video per accessibilità 4934 e.preventDefault(); 4935}); 4936 4937 4938// Stycky top 4939$(document).ready(function () { 4940 4941 $(".cmp-navigation__group").each(function() { 4942 if ($(this).children().length === 0) { 4943 $(this).remove(); 4944 } 4945 }); 4946 // Custom 4947 var stickyToggle = function (sticky, stickyWrapper, scrollElement) { 4948 var stickyHeight = sticky.outerHeight(); 4949 var lastScrollTop = sticky.attr('data-scroll'); 4950 4951 if (scrollElement.scrollTop() == 0) { 4952 sticky.removeClass("is-sticky"); 4953 stickyWrapper.height('auto'); 4954 sticky.removeClass("is-sticky-onscroll"); 4955 } else if (scrollElement.scrollTop() < lastScrollTop) { 4956 sticky.addClass("is-sticky-onscroll"); 4957 } else if (scrollElement.scrollTop() >= lastScrollTop) { 4958 stickyWrapper.height(stickyHeight); 4959 sticky.addClass("is-sticky"); 4960 sticky.removeClass("is-sticky-onscroll"); 4961 } 4962 lastScrollTop = scrollElement.scrollTop(); 4963 sticky.attr('data-scroll', lastScrollTop); 4964 }; 4965 4966 // Find all data-toggle="sticky-onscroll" elements 4967 $('[data-toggle="sticky-onscroll"]').each(function () { 4968 var sticky = $(this); 4969 var stickyWrapper = $('<div>').addClass('sticky-wrapper'); // insert hidden element to maintain actual top offset on page 4970 sticky.before(stickyWrapper); 4971 sticky.addClass('sticky'); 4972 sticky.attr('data-scroll', '0'); 4973 4974 // Scroll & resize events 4975 // $(window).on('scroll.sticky-onscroll resize.sticky-onscroll', function() { 4976 $(window).on('scroll.is-sticky resize.is-sticky', function () { 4977 stickyToggle(sticky, stickyWrapper, $(this)); 4978 }); 4979 4980 // On page load 4981 stickyToggle(sticky, stickyWrapper, $(window)); 4982 }); 4983}); 4984 4985// Gestione focus 4986$(document).on("keydown mousedown", function (t) { 4987 e = "keydown" === t.type; 4988 k = $("[data-keyboard='true']").length; 4989 if (k == 0 && e) { 4990 $("html").attr("data-keyboard", e); 4991 } else if (k > 0 && e == false) { 4992 $("html").removeAttr("data-keyboard"); 4993 } 4994}) 4995 4996// Organigramma 4997if ($("img[usemap]").length) { 4998 $("img[usemap]").each(function () { 4999 $(this).rwdImageMaps(); 5000 id = "#" + $(this).closest("div").attr("id"); 5001 lc_mouseDrag(id, 0.3, false, false); 5002 }) 5003} 5004 5005// Dropdown search 5006$(".dropdown-menu-search .dropdown-item:not(.dropdown-item-link)").on('click', function (e) { 5007 $(".dropdown-menu-search .dropdown-item").removeClass("active"); 5008 $(this).addClass("active"); 5009 $(".btn-dropdown-search span").text($(this).text()); 5010 $(".dropdown-menu-search input[type=hidden]").val($(this).text()); 5011 e.preventDefault(); 5012}); 5013 5014$('#dropdown-menu-search').on('show.bs.dropdown', function () { 5015 $(".search-bar").addClass("active"); 5016}) 5017$('#dropdown-menu-search').on('hide.bs.dropdown', function () { 5018 $(".search-bar").removeClass("active"); 5019}) 5020$('#dropdown-header-search').on('show.bs.dropdown', function () { 5021 $(".divCerca").addClass("active"); 5022}) 5023$('#dropdown-header-search').on('hide.bs.dropdown', function () { 5024 $(".divCerca").removeClass("active"); 5025}) 5026 5027//custom splide per frecce quando sono meno di 4 card 5028if ($(".splide").length) { 5029 if ($(".splide.splide")) { 5030 $("[data-attr='cardGallery'] .splide__arrows").attr("data-attr", "card-gallery-arrows") 5031 const numeroCard = $("[data-attr='cardGallery'] ul.splide__list li").length 5032 let pagination = $("[data-attr='cardGallery'] .splide__pagination") 5033 if (numeroCard <= 3) { 5034 $("[data-attr='card-gallery-arrows']").toggle() 5035 arrOptions = {
5036 arrows: false 5037 } 5038 $(pagination).hide() 5039 } 5040 } 5041} 5042 5043//custom splide autoplay per frecce quando sono meno di 4 card 5044if ($(".splide").length) { 5045 if ($(".splide.splide-autoplay").length) { 5046 $("[id*='carouselCard'].splide.splide-autoplay").each(function () { 5047 let carouselArrows = $(this).find(".splide__arrows") 5048 let pagination = $(this).find(".splide__pagination") 5049 carouselArrows.attr("data-attr", "carousel-card-arrows") 5050 const numeroCardTotale = $(this).find("ul.splide__list li") 5051 const numCardReali = $(numeroCardTotale).not(".splide__slide--clone").length 5052 if ($(this).hasClass("splide-4")) { 5053 if (numCardReali <= 4) { 5054 $(carouselArrows).hide() 5055 $(pagination).hide() 5056 } else { 5057 $(carouselArrows).show() 5058 $(pagination).show() 5059 } 5060 } else { 5061 if (numCardReali <= 3) { 5062 $(carouselArrows).hide() 5063 $(pagination).hide() 5064 } else { 5065 $(carouselArrows).show() 5066 $(pagination).show() 5067 } 5068 } 5069 }) 5070 } 5071 if(!$(".splide.splide-autoplay").length){ 5072 $("[id*='carouselCard'].splide.splide--slide").each(function (){ 5073 let carouselArrows = $(this).find(".splide__arrows") 5074 let pagination = $(this).find(".splide__pagination") 5075 carouselArrows.attr("data-attr", "carousel-card-arrows") 5076 const numeroCardTotale = $(this).find("ul.splide__list li") 5077 const numCardReali = $(numeroCardTotale).not(".splide__slide--clone").length 5078 if ($(this).hasClass("splide-4")) { 5079 if (numCardReali <= 4) { 5080 $(carouselArrows).hide() 5081 $(pagination).hide() 5082 } else { 5083 $(carouselArrows).show() 5084 $(pagination).show() 5085 } 5086 } else { 5087 if (numCardReali <= 3) { 5088 $(carouselArrows).hide() 5089 $(pagination).hide() 5090 } else { 5091 $(carouselArrows).show() 5092 $(pagination).show() 5093 } 5094 } 5095 }) 5096 } 5097} 5098 5099$(document).on('keypress', '.splide__slide', function (e) { 5100 if (e.keyCode == 13 || e.keyCode == 32) { 5101 $(".w-100 img-fluid").removeClass("active"); 5102 $(this).children().children().addClass("active"); 5103 id = $(this).children().children().closest(".fotogallery-slider").attr("data-slider-img"); 5104 figcaption = $(this).children().children().parent().find("figcaption").text(); 5105 figure = $(this).children().children().attr("data-src-hq"); 5106 if (figcaption == "undefined") { 5107 figcaption = ""; 5108 } 5109 $("#" + id + " figcaption p").html(figcaption); 5110 $("#" + id + " img").attr("src", figure); 5111 $("#" + id + " img").attr("data-src-hq", figure); 5112 } 5113}); 5114 5115 5116// Script per creazione dinamica aria-label degli accordion 5117$('button[id*=accordion]').each(function () { 5118 let accordion = $(this) 5119 let buttonText = $(accordion).children().eq(0).text() 5120 5121 if ($(accordion).attr('aria-expanded') == "true") { 5122 $(accordion).attr('aria-label', buttonText + ' Aperto') 5123 } else { 5124 $(accordion).attr('aria-label', buttonText + ' Chiuso') 5125 } 5126 5127 $(accordion).on('click', function () { 5128 let value = $(accordion).attr('aria-expanded') 5129 if (value == 'false') { 5130 $(accordion).attr('aria-label', buttonText + ' Aperto') 5131 } else { 5132 $(accordion).attr('aria-label', buttonText + ' Chiuso') 5133 } 5134 }) 5135 5136 5137 $(accordion).on('keydown', function (e) { 5138 if (e.key === 'Enter' || e.key === ' ') { 5139 e.preventDefault() 5140 let value = $(accordion).attr('aria-expanded') 5141 if (value == 'false') { 5142 $(accordion).attr('aria-label', buttonText + ' Aperto') 5143 } else { 5144 $(accordion).attr('aria-label', buttonText + ' Chiuso') 5145 } 5146 } 5147 }) 5148}) 5149 5150 5151 5152// function trapFocus(element) { 5153// debugger; 5154// const misura = getSizes(); 5155// if($(element).attr('id') === 'cerca-top' && misura < 199){ 5156// $(element).blur(); 5157// }else{ 5158// element.addEventListener('keydown', function (e) { 5159// var focusableEls; 5160 5161// var suggerimento = $("#suggerimento"); 5162// if(suggerimento && suggerimento.hasClass('d-none')){ 5163 5164// if(misura < 199){ 5165// focusableEls = $(element).find(` 5166// div:not(.form-group.d-none) ul li a, 5167// a[role="button"]:not([disabled]), 5168// a[href]:not([disabled]), 5169// button:not([disabled]), 5170// textarea:not([disabled]), 5171// input[type="text"]:not([disabled]), 5172// input[type="radio"]:not([disabled]), 5173// input[type="checkbox"]:not([disabled]), 5174// select:not([disabled]) 5175// `) 5176// }else{ 5177// focusableEls = $(element).find(` 5178// div:not(.form-group.d-none) ul li a, 5179// a[role="button"]:not([disabled]), 5180// a[href]:not([disabled]), 5181// button:not([disabled]), 5182// textarea:not([disabled]), 5183// input[type="text"]:not([disabled]), 5184// input[type="radio"]:not([disabled]), 5185// input[type="checkbox"]:not([disabled]), 5186// select:not([disabled]) 5187// `).filter(':visible').toArray(); 5188// focusableEls = Array.from(focusableEls).filter(el => { 5189// if (el.tagName.toLowerCase() === 'a') { 5190// return !el.closest('div.form-group.d-none'); 5191// } 5192// return true; 5193// }); 5194// } 5195 5196 // }else if((suggerimento && !suggerimento.hasClass('d-none')) || !suggerimento){ 5197 // focusableEls = $(element).find(` 5198 // div:not(.form-group.d-none) ul li a, 5199 // a[role="button"]:not([disabled]), 5200 // a[href]:not([disabled]), 5201 // button:not([disabled]), 5202 // textarea:not([disabled]), 5203 // input[type="text"]:not([disabled]), 5204 // input[type="radio"]:not([disabled]), 5205 // input[type="checkbox"]:not([disabled]), 5206 // select:not([disabled]) 5207 // `).filter(':visible').toArray(); 5208 5209 5210 // if(misura < 199){ 5211 // focusableEls = element.querySelectorAll('div:not(.form-group.d-none) ul li a, a[role="button"]:not([disabled]), a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])'); 5212 // }else{ 5213 // let allFocusableEls = element.querySelectorAll( 5214 // 'div:not(.form-group.d-none) ul li a, a[role="button"]:not([disabled]), a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])' 5215 // ); 5216 5217 // focusableEls = Array.from(allFocusableEls).filter(el => { 5218 // if (el.tagName.toLowerCase() === 'a') { 5219 // // Esclude i link non visibili 5220 // const style = window.getComputedStyle(el); 5221 // return style.display !== 'none' && style.visibility !== 'hidden' && el.offsetParent !== null; 5222 // } 5223 // return true; 5224 // }); 5225 // } 5226 5227 5228 5229// // focusableEls = $('div:not(.form-group.d-none) ul li a, a[role="button"]:not([disabled]), a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])', element); 5230// //focusableEls = $('div:not(.form-group.d-none) ul li a:visible, a[role="button"]:not([disabled]):visible, a[href]:not([disabled]):visible, button:not([disabled]):visible, textarea:not([disabled]):visible, input[type="text"]:not([disabled]):visible, input[type="radio"]:not([disabled]):visible, input[type="checkbox"]:not([disabled]):visible, select:not([disabled]):visible', element); 5231 5232// } 5233// var firstFocusableEl = focusableEls[0]; 5234// var lastFocusableEl = focusableEls[focusableEls.length - 1]; 5235// var KEYCODE_TAB = 9; 5236 5237// var isTabPressed = (e.key === 'Tab' || e.keyCode === KEYCODE_TAB); 5238 5239// if (!isTabPressed) { 5240// return; 5241// } 5242 5243// if (e.shiftKey) /* shift + tab */ { 5244// if (document.activeElement === firstFocusableEl) {
5245// lastFocusableEl.focus(); 5246// e.preventDefault(); 5247// } 5248// } else /* tab */ { 5249// if (document.activeElement === lastFocusableEl) { 5250// firstFocusableEl.focus(); 5251// e.preventDefault(); 5252// } 5253// } 5254// }); 5255// } 5256 5257// } 5258 5259const trappedElements = new Map(); // id -> handler 5260 5261function trapFocus(element) { 5262 const id = element.id; 5263 const misura = getSizes(); 5264 5265 // Se esiste già un listener, lo rimuoviamo 5266 if (trappedElements.has(id)) { 5267 element.removeEventListener('keydown', trappedElements.get(id)); 5268 trappedElements.delete(id); 5269 } 5270 5271 // Se siamo su cerca-top e zoom < 199, NON riapplichiamo trap 5272 if ((id === 'cerca-top' || id == 'sidebar-menu-mobile') && misura < 199) { 5273 return; 5274 } 5275 5276 const handler = function (e) { 5277 let focusableEls; 5278 const suggerimento = $("#suggerimento"); 5279 5280 if (suggerimento && suggerimento.hasClass('d-none')) { 5281 focusableEls = $(element).find(` 5282 div:not(.form-group.d-none) ul li a, 5283 a[role="button"]:not([disabled]), 5284 a[href]:not([disabled]), 5285 button:not([disabled]), 5286 textarea:not([disabled]), 5287 input[type="text"]:not([disabled]), 5288 input[type="radio"]:not([disabled]), 5289 input[type="checkbox"]:not([disabled]), 5290 select:not([disabled]) 5291 `); 5292 5293 if (misura >= 199) { 5294 focusableEls = focusableEls.filter(':visible').toArray().filter(el => { 5295 if (el.tagName.toLowerCase() === 'a') { 5296 return !el.closest('div.form-group.d-none'); 5297 } 5298 return true; 5299 }); 5300 } 5301 } else if((suggerimento && !suggerimento.hasClass('d-none')) || !suggerimento){ 5302 focusableEls = $(element).find(` 5303 div:not(.form-group.d-none) ul li a, 5304 a[role="button"]:not([disabled]), 5305 a[href]:not([disabled]), 5306 button:not([disabled]), 5307 textarea:not([disabled]), 5308 input[type="text"]:not([disabled]), 5309 input[type="radio"]:not([disabled]), 5310 input[type="checkbox"]:not([disabled]), 5311 select:not([disabled]) 5312 `).filter(':visible').toArray(); 5313 5314 5315 if(misura < 199){ 5316 focusableEls = $(element).find( 5317 'div:not(.form-group.d-none) ul li a, a[role="button"]:not([disabled]), a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])' 5318 ).toArray(); 5319 }else{ 5320 focusableEls = $(element).find( 5321 'div:not(.form-group.d-none) ul li a, a[role="button"]:not([disabled]), a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])' 5322 ).toArray().filter(el => { 5323 if (el.tagName.toLowerCase() === 'a') { 5324 // Esclude i link non visibili 5325 const style = window.getComputedStyle(el); 5326 return style.display !== 'none' && style.visibility !== 'hidden' && el.offsetParent !== null; 5327 } 5328 return true; 5329 }); 5330 } 5331 } 5332 const firstEl = focusableEls[0]; 5333 const lastEl = focusableEls[focusableEls.length - 1]; 5334 const isTab = (e.key === 'Tab' || e.keyCode === 9); 5335 if (!isTab) return; 5336 5337 if (e.shiftKey) { 5338 if (document.activeElement === firstEl) { 5339 lastEl.focus(); 5340 e.preventDefault(); 5341 } 5342 } else { 5343 if (document.activeElement === lastEl) { 5344 firstEl.focus(); 5345 e.preventDefault(); 5346 } 5347 } 5348 }; 5349 5350 // Applichiamo il nuovo listener 5351 element.addEventListener('keydown', handler); 5352 trappedElements.set(id, handler); 5353} 5354 5355 5356if ($("#menu-top").length) { 5357 var trapMenuTop = document.getElementById('menu-top') 5358 trapFocus(trapMenuTop) 5359} 5360 5361if ($("#cerca-top").length && window.innerWidth < 992) { 5362 var trapCercaTop = document.getElementById('cerca-top') 5363 trapFocus(trapCercaTop) 5364} 5365 5366if ($("#sidebar-menu-mobile").length) { 5367 var trapMenuMobile = document.getElementById('sidebar-menu-mobile') 5368 trapFocus(trapMenuMobile) 5369} 5370 5371function moveButton() { 5372 $('#scroll-top-btn').attr('class', (i, prevClass) => { 5373 return prevClass + ' captcha' 5374 }) 5375} 5376 5377function getSizes() { 5378 var zoom = Math.round(((window.outerWidth - 10)
5379 / window.innerWidth) * 100); 5380 return zoom; 5381} 5382 5383$( window ).on( "resize", function(){ 5384 5385 if ($("#menu-top").length) { 5386 var trapMenuTop = document.getElementById('menu-top') 5387 trapFocus(trapMenuTop) 5388 } 5389 5390if ($("#cerca-top").length) { 5391 var trapCercaTop = document.getElementById('cerca-top') 5392 trapFocus(trapCercaTop) 5393 } 5394 5395 5396if ($("#sidebar-menu-mobile").length) { 5397 var trapMenuMobile = document.getElementById('sidebar-menu-mobile') 5398 trapFocus(trapMenuMobile) 5399 } 5400}); 5401const $tables = $("table"); 5402if ($tables) { 5403 $tables.each(function () { 5404 let table = $(this); 5405 table.addClass("table"); 5406 //let $parent = table.parent(); 5407 5408 //$parent.html(""); 5409 table.wrap('<div class="table-responsive"></div>'); 5410 //$parent.find(".table-responsive").append(table); 5411 5412 $("table").removeAttr("border"); 5413 $("table").removeAttr("cellspacing"); 5414 $("table").removeAttr("cellpadding"); 5415 $("table").find("*").removeAttr("width"); 5416 $("table").find("*").removeAttr("valign"); 5417 //$("table").find("strong").contents().unwrap(); 5418 }) 5419} 5420 5421//script scriba per amministrazione-trasparente 5422document.addEventListener("DOMContentLoaded", function () { 5423 5424 var linkSelector = 'a[title="Vai a Nuova richiesta (modalità autenticata) - apertura in nuova finestra"]'; 5425 5426 5427 // Funzione per ottenere il valore di un parametro dalla URL 5428 function getQueryParam(param) { 5429 const urlParams = new URLSearchParams(window.location.search); 5430 return urlParams.get(param); 5431 } 5432 5433 // Recupera il valore del parametro "tipologia_accesso" 5434 const tipologiaAccesso = getQueryParam("scriba_tipologia_accesso"); 5435 5436 if (tipologiaAccesso) { 5437 // Trova il link <a> 5438 const link = document.querySelector(linkSelector); 5439 5440 if (link) { 5441 // Crea un oggetto URL per modificare i parametri della href 5442 const url = new URL(link.href, window.location.origin); 5443 url.searchParams.set("tipologia_accesso", tipologiaAccesso); 5444 5445 // Aggiorna l'href del link 5446 link.href = url.toString(); 5447 } 5448 } 5449}); 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468$(document).ready(function(){ 5469 $(window).scroll(function(){ 5470 var iframe = $("iframe[class*=aemform]") 5471 if(iframe.length > 0 && iframe.attr("scrolling") == 'yes'){ 5472 iframe.removeAttr('scrolling'); 5473 } 5474 }) 5475}) 5476$(document).ready(function () { 5477 if($(".data-layer").find('video').length > 0){ 5478 5479 let video = $(".data-layer").find('video'); 5480 let percentuale; 5481 $(video).on("play", function() { 5482 //TO DO: Your code goes here... 5483 let cTime=this.currentTime; 5484 let duration = this.duration; // Get current time in seconds 5485 5486 // Convert seconds to hh:mm:ss format 5487 let hours = Math.floor(duration / 3600); 5488 let minutes = Math.floor((duration % 3600) / 60); 5489 let seconds = Math.floor(duration % 60); 5490 5491 let timeString = hours.toString().padStart(2, '0') + ':' + 5492 minutes.toString().padStart(2, '0') + ':' + 5493 seconds.toString().padStart(2, '0'); 5494 if(cTime < 1){ 5495 //play 5496 console.log("Video start"); 5497 window.adobeDataLayer.push({ 5498 "data": { 5499 "pageInfo": { 5500 "pageName": $('title').text(), // Prende il testo del titolo della pagina 5501 "sectionName": "Main Section" 5502 }, 5503 5504 "media": { 5505 "type": "video", 5506 "fileName": $('.videoTitle').text(), 5507 "fileURL": $(this).find('source').attr('src'), // Trova l'URL del file video
5508 "duration": timeString // percentuale del video visto 5509 } 5510 } 5511 }); 5512 5513 adobeDataLayer.push({ 5514 "event": "mediaStart" 5515 }); 5516 5517 } else{ 5518 //restart 5519 console.log("Video restart"); 5520 percentuale = (this.currentTime / this.duration) * 100; 5521 adobeDataLayer.push({ 5522 "event": "mediaRestart", 5523 "data": { 5524 "media":{ 5525 "completion":percentuale 5526 } 5527 } 5528 }); 5529 5530 } 5531 }); 5532 5533 5534 //fine video 5535 $(video).on("ended", function() { 5536 //TO DO: Your code goes here... 5537 console.log("Video finito"); 5538 adobeDataLayer.push({ 5539 "event": "mediaComplete" 5540 }); 5541 }); 5542 5543 //video pausa 5544 $(video).on('pause', function() { 5545 console.log("Video pausa"); 5546 // Calcola la percentuale guardata 5547 percentuale = (this.currentTime / this.duration) * 100; 5548 adobeDataLayer.push({ 5549 "event": "mediaPause", 5550 "data": { 5551 "media":{ 5552 "completion":percentuale 5553 } 5554 } 5555 }); 5556 }); 5557 } 5558 5559 5560 //vimeo 5561 if($('#vimeo-player').length > 0){ 5562 // 1. Seleziona l'iframe Vimeo 5563 let iframe = $('#vimeo-player'); 5564 5565 // 2. Crea un oggetto Player con l'iframe selezionato 5566 let player = new Vimeo.Player(iframe); 5567 let percentuale; 5568 // 3. Ascolta l'evento play 5569 player.on('play', function() { 5570 5571 durataVideo().then(function(duration) { 5572 // Convert seconds to hh:mm:ss format 5573 let hours = Math.floor(duration / 3600); 5574 let minutes = Math.floor((duration % 3600) / 60); 5575 let seconds = Math.floor(duration % 60); 5576 5577 let timeString = hours.toString().padStart(2, '0') + ':' + 5578 minutes.toString().padStart(2, '0') + ':' + 5579 seconds.toString().padStart(2, '0'); 5580 5581 currentTime().then(function(current) { 5582 if(current == 0){ 5583 //play 5584 console.log('Il video è stato avviato') 5585 window.adobeDataLayer.push({ 5586 "data": { 5587 "pageInfo": { 5588 "pageName": $('title').text(), // Prende il testo del titolo della pagina 5589 "sectionName": "Main Section" 5590 }, 5591 "media": { 5592 "type": "video Vimeo", 5593 "fileName": $('.videoTitle').text(), 5594 "fileURL": $('#vimeo-player').attr('src'), // Trova l'URL del file video
5595 "duration": timeString // percentuale del video visto 5596 } 5597 } 5598 5599 }); 5600 5601 adobeDataLayer.push({ 5602 "event": "mediaStart" 5603 }); 5604 5605 }else{ 5606 //restart 5607 console.log("Il video è stato riavviato"); 5608 percentuale = (current / duration) * 100; 5609 adobeDataLayer.push({ 5610 "event": "mediaRestart", 5611 "data": { 5612 "media":{ 5613 "completion":percentuale 5614 } 5615 } 5616 }); 5617 } 5618 5619 }); 5620 }); 5621 }); 5622 5623 // 4. Ascolta l'evento pause 5624 player.on('pause', function() { 5625 durataVideo().then(function(duration) { 5626 // Convert seconds to hh:mm:ss format 5627 let hours = Math.floor(duration / 3600); 5628 let minutes = Math.floor((duration % 3600) / 60); 5629 let seconds = Math.floor(duration % 60); 5630 5631 let timeString = hours.toString().padStart(2, '0') + ':' + 5632 minutes.toString().padStart(2, '0') + ':' + 5633 seconds.toString().padStart(2, '0'); 5634 5635 currentTime().then(function(current) { 5636 console.log('Il video è in pausa') 5637 // Calcola la percentuale guardata 5638 percentuale = (current / duration) * 100; 5639 adobeDataLayer.push({ 5640 "event": "mediaPause", 5641 "data": { 5642 "media":{ 5643 "completion":percentuale 5644 } 5645 } 5646 }); 5647 }); 5648 }); 5649 }); 5650 5651 // 5. Ascolta l'evento ended 5652 player.on('ended', function() { 5653 console.log("Il video e' terminato"); 5654 adobeDataLayer.push({ 5655 "event": "mediaComplete" 5656 }); 5657 }); 5658 5659 function durataVideo() { 5660 return player.getDuration().then(function(duration) { 5661 return duration; // Restituisce la durata del video 5662 }).catch(function(error) { 5663 console.error("Errore nel recuperare la durata del video:", error); 5664 }); 5665 } 5666 5667 function currentTime(){ 5668 return player.getCurrentTime().then(function(current) { 5669 return current 5670 }).catch(function(error) { 5671 console.error("Errore nel recuperare il tempo corrente:", error); 5672 }); 5673 } 5674 } 5675 5676 5677 5678}) 5679 5680 5681 5682//Gestione per textarea captcha 5683const observer = new MutationObserver(() => { 5684 const captchaTextarea = document.querySelector('.g-recaptcha-response'); 5685 if (captchaTextarea) { 5686 captchaTextarea.setAttribute('aria-label', 'Token di sicurezza CAPTCHA'); 5687 observer.disconnect(); // Una volta modificata, fermiamo l'osservatore 5688 } 5689}); 5690 5691observer.observe(document.body, { childList: true, subtree: true }); 5692 5693//Gestione dei dell 5694$(document).ready(function () { 5695 $('del').each(function () { 5696 $(this).after( 5697 '<span class="sr-only">Attenzione! Il valore appena letto è stato cancellato e non è più attivo</span>' 5698 ); 5699 }); 5700}); 5701 5702//Gestione testo header nome sottodomini 5703function detectZoom() { 5704 const ratio = Math.round(((window.outerWidth - 10) 5705 / window.innerWidth) * 100); 5706 5707 // Trova tutti gli strong nei contenitori specificati 5708 const $strongs = $('.header h1 strong, .header .py-3.d-flex.align-items-center strong'); 5709 const $firstStrong = $strongs.first(); 5710 5711 if ($firstStrong.length) { 5712 if (ratio >= 397) { 5713 $firstStrong.addClass('zoom-400'); 5714 } else { 5715 $firstStrong.removeClass('zoom-400'); 5716 } 5717 } 5718} 5719 5720$(document).ready(function () { 5721 detectZoom(); 5722 $(window).on('resize', detectZoom); 5723}); 5724document.addEventListener("DOMContentLoaded", function () { 5725 // Seleziona tutti i tab container verticali 5726 const verticalTabs = Array.from(document.getElementsByClassName('cmp-tabs vertical')); 5727
5728 verticalTabs.forEach(tabs => { 5729 // Individua il wrapper principale 5730 const tabsContainer = tabs.closest('.tabsCustom.panelcontainer'); 5731 tabsContainer.classList.add('d-flex'); 5732 if (!tabsContainer) return; 5733 5734 // Aggiunge listener su tutti i tab link 5735 const tabLinks = Array.from(tabs.getElementsByTagName('*')).filter(el => { 5736 return el.dataset.cmpHookTabs === "tab" 5737 }); 5738 tabLinks.forEach(link => { 5739 link.addEventListener('click', () => { 5740 // Aspetta che AEM aggiorni il tab attivo 5741 setTimeout(() => { 5742 const extraOffset = -200; 5743 const y = tabsContainer.getBoundingClientRect().top + window.scrollY + extraOffset; 5744 window.scrollTo({ top: y, behavior: 'smooth' }); 5745 }, 150); 5746 }); 5747 }); 5748 }); 5749});
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.