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 2022 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/LICENSE-2.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(function(document) { 1186 "use strict"; 1187 1188 window.CMP = window.CMP || {}; 1189 window.CMP.utils = (function() { 1190 var NS = "cmp"; 1191 1192 /**
1193 * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes 1194 * 1195 * @param {HTMLElement} element The component element to read options data from 1196 * @param {String} is The component identifier 1197 * @returns {String[]} The options read from the component data attributes 1198 */ 1199 var readData = function(element, is) { 1200 var data = element.dataset; 1201 var options = []; 1202 var capitalized = is; 1203 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1204 var reserved = ["is", "hook" + capitalized]; 1205 1206 for (var key in data) { 1207 if (Object.prototype.hasOwnProperty.call(data, key)) { 1208 var value = data[key]; 1209 1210 if (key.indexOf(NS) === 0) { 1211 key = key.slice(NS.length); 1212 key = key.charAt(0).toLowerCase() + key.substring(1); 1213 1214 if (reserved.indexOf(key) === -1) { 1215 options[key] = value; 1216 } 1217 } 1218 } 1219 } 1220 return options; 1221 }; 1222 1223 /** 1224 * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand 1225 * @param {String[]} options the options to transform 1226 * @param {Object} properties object of properties of property functions 1227 * @returns {Object} transformed properties 1228 */ 1229 var setupProperties = function(options, properties) { 1230 var transformedProperties = {}; 1231 1232 for (var key in properties) { 1233 if (Object.prototype.hasOwnProperty.call(properties, key)) { 1234 var property = properties[key]; 1235 if (options && options[key] != null) { 1236 if (property && typeof property.transform === "function") { 1237 transformedProperties[key] = property.transform(options[key]); 1238 } else { 1239 transformedProperties[key] = options[key]; 1240 } 1241 } else { 1242 transformedProperties[key] = properties[key]["default"]; 1243 } 1244 } 1245 } 1246 return transformedProperties; 1247 }; 1248 1249 1250 return { 1251 readData: readData, 1252 setupProperties: setupProperties 1253 }; 1254 }()); 1255}(window.document)); 1256 1257/******************************************************************************* 1258 * Copyright 2018 Adobe 1259 * 1260 * Licensed under the Apache License, Version 2.0 (the "License"); 1261 * you may not use this file except in compliance with the License. 1262 * You may obtain a copy of the License at 1263 * 1264 * http://www.apache.org/licenses/LICENSE-2.0 1265 * 1266 * Unless required by applicable law or agreed to in writing, software 1267 * distributed under the License is distributed on an "AS IS" BASIS, 1268 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1269 * See the License for the specific language governing permissions and 1270 * limitations under the License. 1271 ******************************************************************************/ 1272(function() { 1273 "use strict"; 1274 1275 var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined; 1276 if (!containerUtils) { 1277 // eslint-disable-next-line no-console 1278 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."); 1279 } 1280 var dataLayerEnabled; 1281 var dataLayer; 1282 var dataLayerName; 1283 1284 var NS = "cmp"; 1285 var IS = "carousel"; 1286 1287 var keyCodes = { 1288 SPACE: 32, 1289 END: 35, 1290 HOME: 36, 1291 ARROW_LEFT: 37, 1292 ARROW_UP: 38, 1293 ARROW_RIGHT: 39, 1294 ARROW_DOWN: 40 1295 }; 1296 1297 var selectors = { 1298 self: "[data-" + NS + '-is="' + IS + '"]' 1299 }; 1300 1301 var properties = { 1302 /** 1303 * Determines whether the Carousel will automatically transition between slides 1304 * 1305 * @memberof Carousel
1306 * @type {Boolean} 1307 * @default false 1308 */ 1309 "autoplay": { 1310 "default": false, 1311 "transform": function(value) { 1312 return !(value === null || typeof value === "undefined"); 1313 } 1314 }, 1315 /** 1316 * Duration (in milliseconds) before automatically transitioning to the next slide 1317 * 1318 * @memberof Carousel 1319 * @type {Number} 1320 * @default 5000 1321 */ 1322 "delay": { 1323 "default": 5000, 1324 "transform": function(value) { 1325 value = parseFloat(value); 1326 return !isNaN(value) ? value : null; 1327 } 1328 }, 1329 /** 1330 * Determines whether automatic pause on hovering the carousel is disabled 1331 * 1332 * @memberof Carousel 1333 * @type {Boolean} 1334 * @default false 1335 */ 1336 "autopauseDisabled": { 1337 "default": false, 1338 "transform": function(value) { 1339 return !(value === null || typeof value === "undefined"); 1340 } 1341 } 1342 }; 1343 1344 /** 1345 * Carousel Configuration 1346 * 1347 * @typedef {Object} CarouselConfig Represents a Carousel configuration 1348 * @property {HTMLElement} element The HTMLElement representing the Carousel 1349 * @property {*[]} options The Carousel options 1350 */ 1351 1352 /** 1353 * Carousel 1354 * 1355 * @class Carousel 1356 * @classdesc An interactive Carousel component for navigating a list of generic items 1357 * @param {CarouselConfig} config The Carousel configuration 1358 */ 1359 function Carousel(config) { 1360 var that = this; 1361 1362 if (config && config.element) { 1363 init(config); 1364 } 1365 1366 /** 1367 * Initializes the Carousel 1368 * 1369 * @private 1370 * @param {CarouselConfig} config The Carousel configuration 1371 */ 1372 function init(config) { 1373 that._config = config; 1374 1375 // prevents multiple initialization 1376 config.element.removeAttribute("data-" + NS + "-is"); 1377 1378 setupProperties(config.options); 1379 cacheElements(config.element); 1380 1381 that._active = 0; 1382 that._paused = false; 1383 1384 if (that._elements.item) { 1385 initializeActive(); 1386 bindEvents(); 1387 resetAutoplayInterval(); 1388 refreshPlayPauseActions(); 1389 scrollToDeepLinkIdInCarousel(); 1390 } 1391 1392 // TODO: This section is only relevant in edit mode and should move to the editor clientLib 1393 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 1394 /* 1395 * Editor message handling: 1396 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame 1397 * - check that the message data panel container type is correct and that the id (path) matches this specific Carousel component 1398 * - if so, route the "navigate" operation to enact a navigation of the Carousel based on index data 1399 */ 1400 window.CQ = window.CQ || {}; 1401 window.CQ.CoreComponents = window.CQ.CoreComponents || {}; 1402 window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 1403 window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 1404 if (message.data && message.data.type === "cmp-carousel" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 1405 if (message.data.operation === "navigate") { 1406 navigate(message.data.index); 1407 } 1408 } 1409 }); 1410 } 1411 } 1412 1413 /** 1414 * Displays the slide containing the element that corresponds to the deep link in the URI fragment 1415 * and scrolls the browser to this element. 1416 */ 1417 function scrollToDeepLinkIdInCarousel() { 1418 if (containerUtils) { 1419 var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "item", "item"); 1420 if (deepLinkItemIdx > -1) { 1421 var deepLinkItem = that._elements["item"][deepLinkItemIdx]; 1422 if (deepLinkItem && that._elements["item"][that._active].id !== deepLinkItem.id) { 1423 navigateAndFocusIndicator(deepLinkItemIdx, true); 1424 // pause the carousel auto-rotation 1425 pause(); 1426 } 1427 var hashId = window.location.hash.substring(1); 1428 if (hashId) { 1429 var hashItem = document.querySelector("[id='" + hashId + "']"); 1430 if (hashItem) { 1431 hashItem.scrollIntoView(); 1432 } 1433 } 1434 } 1435 } 1436 } 1437 1438 /** 1439 * Caches the Carousel elements as defined via the {@code data-carousel-hook="ELEMENT_NAME"} markup API 1440 * 1441 * @private 1442 * @param {HTMLElement} wrapper The Carousel wrapper element 1443 */ 1444 function cacheElements(wrapper) { 1445 that._elements = {}; 1446 that._elements.self = wrapper; 1447 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 1448 1449 for (var i = 0; i < hooks.length; i++) { 1450 var hook = hooks[i]; 1451 var capitalized = IS; 1452 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1453 var key = hook.dataset[NS + "Hook" + capitalized]; 1454 if (that._elements[key]) { 1455 if (!Array.isArray(that._elements[key])) { 1456 var tmp = that._elements[key]; 1457 that._elements[key] = [tmp]; 1458 } 1459 that._elements[key].push(hook); 1460 } else { 1461 that._elements[key] = hook; 1462 } 1463 } 1464 } 1465 1466 /** 1467 * Sets up properties for the Carousel based on the passed options. 1468 * 1469 * @private 1470 * @param {Object} options The Carousel options 1471 */ 1472 function setupProperties(options) { 1473 that._properties = {}; 1474 1475 for (var key in properties) { 1476 if (Object.prototype.hasOwnProperty.call(properties, key)) { 1477 var property = properties[key]; 1478 var value = null; 1479 1480 if (options && options[key] != null) { 1481 value = options[key]; 1482 1483 // transform the provided option 1484 if (property && typeof property.transform === "function") { 1485 value = property.transform(value); 1486 } 1487 } 1488 1489 if (value === null) { 1490 // value still null, take the property default 1491 value = properties[key]["default"]; 1492 } 1493 1494 that._properties[key] = value; 1495 } 1496 } 1497 } 1498 1499 /** 1500 * Binds Carousel event handling 1501 * 1502 * @private 1503 */ 1504 function bindEvents() { 1505 window.addEventListener("hashchange", scrollToDeepLinkIdInCarousel, false); 1506 if (that._elements["previous"]) { 1507 that._elements["previous"].addEventListener("click", function() { 1508 var index = getPreviousIndex(); 1509 navigate(index); 1510 if (dataLayerEnabled) { 1511 dataLayer.push({ 1512 event: "cmp:show", 1513 eventInfo: { 1514 path: "component." + getDataLayerId(that._elements.item[index]) 1515 } 1516 }); 1517 } 1518 }); 1519 } 1520 1521 if (that._elements["next"]) { 1522 that._elements["next"].addEventListener("click", function() { 1523 var index = getNextIndex(); 1524 navigate(index); 1525 if (dataLayerEnabled) { 1526 dataLayer.push({ 1527 event: "cmp:show", 1528 eventInfo: { 1529 path: "component." + getDataLayerId(that._elements.item[index]) 1530 } 1531 }); 1532 } 1533 }); 1534 } 1535 1536 var indicators = that._elements["indicator"]; 1537 if (indicators) { 1538 for (var i = 0; i < indicators.length; i++) { 1539 (function(index) { 1540 indicators[i].addEventListener("click", function(event) { 1541 navigateAndFocusIndicator(index); 1542 // pause the carousel auto-rotation 1543 pause(); 1544 }); 1545 })(i); 1546 } 1547 } 1548 1549 if (that._elements["pause"]) { 1550 if (that._properties.autoplay) { 1551 that._elements["pause"].addEventListener("click", onPauseClick); 1552 } 1553 } 1554 1555 if (that._elements["play"]) { 1556 if (that._properties.autoplay) { 1557 that._elements["play"].addEventListener("click", onPlayClick); 1558 } 1559 } 1560 1561 that._elements.self.addEventListener("keydown", onKeyDown); 1562 1563 if (!that._properties.autopauseDisabled) { 1564 that._elements.self.addEventListener("mouseenter", onMouseEnter); 1565 that._elements.self.addEventListener("mouseleave", onMouseLeave); 1566 } 1567 1568 // for accessibility we pause animation when a element get focused 1569 var items = that._elements["item"]; 1570 if (items) { 1571 for (var j = 0; j < items.length; j++) { 1572 items[j].addEventListener("focusin", onMouseEnter); 1573 items[j].addEventListener("focusout", onMouseLeave); 1574 } 1575 } 1576 } 1577 1578 /**
1579 * Handles carousel keydown events 1580 * 1581 * @private 1582 * @param {Object} event The keydown event 1583 */ 1584 function onKeyDown(event) { 1585 var index = that._active; 1586 var lastIndex = that._elements["indicator"].length - 1; 1587 1588 switch (event.keyCode) { 1589 case keyCodes.ARROW_LEFT: 1590 case keyCodes.ARROW_UP: 1591 event.preventDefault(); 1592 if (index > 0) { 1593 navigateAndFocusIndicator(index - 1); 1594 } 1595 break; 1596 case keyCodes.ARROW_RIGHT: 1597 case keyCodes.ARROW_DOWN: 1598 event.preventDefault(); 1599 if (index < lastIndex) { 1600 navigateAndFocusIndicator(index + 1); 1601 } 1602 break; 1603 case keyCodes.HOME: 1604 event.preventDefault(); 1605 navigateAndFocusIndicator(0); 1606 break; 1607 case keyCodes.END: 1608 event.preventDefault(); 1609 navigateAndFocusIndicator(lastIndex); 1610 break; 1611 case keyCodes.SPACE: 1612 if (that._properties.autoplay && (event.target !== that._elements["previous"] && event.target !== that._elements["next"])) { 1613 event.preventDefault(); 1614 if (!that._paused) { 1615 pause(); 1616 } else { 1617 play(); 1618 } 1619 } 1620 if (event.target === that._elements["pause"]) { 1621 that._elements["play"].focus(); 1622 } 1623 if (event.target === that._elements["play"]) { 1624 that._elements["pause"].focus(); 1625 } 1626 break; 1627 default: 1628 return; 1629 } 1630 } 1631 1632 /** 1633 * Handles carousel mouseenter events 1634 * 1635 * @private 1636 * @param {Object} event The mouseenter event 1637 */ 1638 function onMouseEnter(event) { 1639 clearAutoplayInterval(); 1640 } 1641 1642 /** 1643 * Handles carousel mouseleave events 1644 * 1645 * @private 1646 * @param {Object} event The mouseleave event 1647 */ 1648 function onMouseLeave(event) { 1649 resetAutoplayInterval(); 1650 } 1651 1652 /** 1653 * Handles pause element click events 1654 * 1655 * @private 1656 * @param {Object} event The click event 1657 */ 1658 function onPauseClick(event) { 1659 pause(); 1660 that._elements["play"].focus(); 1661 } 1662 1663 /** 1664 * Handles play element click events 1665 * 1666 * @private 1667 * @param {Object} event The click event 1668 */ 1669 function onPlayClick() { 1670 play(); 1671 that._elements["pause"].focus(); 1672 } 1673 1674 /** 1675 * Pauses the playing of the Carousel. Sets {@code Carousel#_paused} marker. 1676 * Only relevant when autoplay is enabled 1677 * 1678 * @private 1679 */ 1680 function pause() { 1681 that._paused = true; 1682 clearAutoplayInterval(); 1683 refreshPlayPauseActions(); 1684 } 1685 1686 /** 1687 * Enables the playing of the Carousel. Sets {@code Carousel#_paused} marker. 1688 * Only relevant when autoplay is enabled 1689 * 1690 * @private 1691 */ 1692 function play() { 1693 that._paused = false; 1694 1695 // If the Carousel is hovered, don't begin auto transitioning until the next mouse leave event 1696 var hovered = false; 1697 if (that._elements.self.parentElement) { 1698 hovered = that._elements.self.parentElement.querySelector(":hover") === that._elements.self; 1699 } 1700 if (that._properties.autopauseDisabled || !hovered) { 1701 resetAutoplayInterval(); 1702 } 1703 1704 refreshPlayPauseActions(); 1705 } 1706 1707 /** 1708 * Refreshes the play/pause action markup based on the {@code Carousel#_paused} state 1709 * 1710 * @private 1711 */ 1712 function refreshPlayPauseActions() {
1713 setActionDisabled(that._elements["pause"], that._paused); 1714 setActionDisabled(that._elements["play"], !that._paused); 1715 } 1716 1717 /** 1718 * Initialize {@code Carousel#_active} based on the active item of the carousel. 1719 */ 1720 function initializeActive() { 1721 var items = that._elements["item"]; 1722 if (items && Array.isArray(items)) { 1723 for (var i = 0; i < items.length; i++) { 1724 if (items[i].classList.contains("cmp-carousel__item--active")) { 1725 that._active = i; 1726 break; 1727 } 1728 } 1729 } 1730 } 1731 1732 /** 1733 * Refreshes the item markup based on the current {@code Carousel#_active} index 1734 * 1735 * @private 1736 */ 1737 function refreshActive() { 1738 var items = that._elements["item"]; 1739 var indicators = that._elements["indicator"]; 1740 1741 if (items) { 1742 if (Array.isArray(items)) { 1743 for (var i = 0; i < items.length; i++) { 1744 if (i === parseInt(that._active)) { 1745 items[i].classList.add("cmp-carousel__item--active"); 1746 items[i].removeAttribute("aria-hidden"); 1747 indicators[i].classList.add("cmp-carousel__indicator--active"); 1748 indicators[i].setAttribute("aria-selected", true); 1749 indicators[i].setAttribute("tabindex", "0"); 1750 } else { 1751 items[i].classList.remove("cmp-carousel__item--active"); 1752 items[i].setAttribute("aria-hidden", true); 1753 indicators[i].classList.remove("cmp-carousel__indicator--active"); 1754 indicators[i].setAttribute("aria-selected", false); 1755 indicators[i].setAttribute("tabindex", "-1"); 1756 } 1757 } 1758 } else { 1759 // only one item 1760 items.classList.add("cmp-carousel__item--active"); 1761 indicators.classList.add("cmp-carousel__indicator--active"); 1762 } 1763 } 1764 } 1765 1766 /** 1767 * Focuses the element and prevents scrolling the element into view 1768 * 1769 * @param {HTMLElement} element Element to focus 1770 */ 1771 function focusWithoutScroll(element) { 1772 var x = window.scrollX || window.pageXOffset; 1773 var y = window.scrollY || window.pageYOffset; 1774 element.focus(); 1775 window.scrollTo(x, y); 1776 } 1777 1778 /** 1779 * Retrieves the next active index, with looping 1780 * 1781 * @private 1782 * @returns {Number} Index of the next carousel item 1783 */ 1784 function getNextIndex() { 1785 return that._active === (that._elements["item"].length - 1) ? 0 : that._active + 1; 1786 } 1787 1788 /** 1789 * Retrieves the previous active index, with looping 1790 * 1791 * @private 1792 * @returns {Number} Index of the previous carousel item 1793 */ 1794 function getPreviousIndex() { 1795 return that._active === 0 ? (that._elements["item"].length - 1) : that._active - 1; 1796 } 1797 1798 /** 1799 * Navigates to the item at the provided index 1800 * 1801 * @private 1802 * @param {Number} index The index of the item to navigate to 1803 * @param {Boolean} keepHash true to keep the hash in the URL, false to update it 1804 */ 1805 function navigate(index, keepHash) { 1806 if (index < 0 || index > (that._elements["item"].length - 1)) { 1807 return; 1808 } 1809 1810 that._active = index; 1811 refreshActive(); 1812 1813 if (!keepHash && containerUtils) { 1814 containerUtils.updateUrlHash(that, "item", index); 1815 } 1816 1817 if (dataLayerEnabled) { 1818 var carouselId = that._elements.self.id; 1819 var activeItem = getDataLayerId(that._elements.item[index]); 1820 var updatePayload = { component: {} }; 1821 updatePayload.component[carouselId] = { shownItems: [activeItem] }; 1822 1823 var removePayload = { component: {} }; 1824 removePayload.component[carouselId] = { shownItems: undefined }; 1825 1826 dataLayer.push(removePayload); 1827 dataLayer.push(updatePayload); 1828 } 1829 1830 // reset the autoplay transition interval following navigation, if not already hovering the carousel
1831 if (that._elements.self.parentElement) { 1832 if (that._elements.self.parentElement.querySelector(":hover") !== that._elements.self) { 1833 resetAutoplayInterval(); 1834 } 1835 } 1836 } 1837 1838 /** 1839 * Navigates to the item at the provided index and ensures the active indicator gains focus 1840 * 1841 * @private 1842 * @param {Number} index The index of the item to navigate to 1843 * @param {Boolean} keepHash true to keep the hash in the URL, false to update it 1844 */ 1845 function navigateAndFocusIndicator(index, keepHash) { 1846 navigate(index, keepHash); 1847 focusWithoutScroll(that._elements["indicator"][index]); 1848 1849 if (dataLayerEnabled) { 1850 dataLayer.push({ 1851 event: "cmp:show", 1852 eventInfo: { 1853 path: "component." + getDataLayerId(that._elements.item[index]) 1854 } 1855 }); 1856 } 1857 } 1858 1859 /** 1860 * Starts/resets automatic slide transition interval 1861 * 1862 * @private 1863 */ 1864 function resetAutoplayInterval() { 1865 if (that._paused || !that._properties.autoplay) { 1866 return; 1867 } 1868 clearAutoplayInterval(); 1869 that._autoplayIntervalId = window.setInterval(function() { 1870 if (document.visibilityState && document.hidden) { 1871 return; 1872 } 1873 var indicators = that._elements["indicators"]; 1874 if (indicators !== document.activeElement && indicators.contains(document.activeElement)) { 1875 // if an indicator has focus, ensure we switch focus following navigation 1876 navigateAndFocusIndicator(getNextIndex(), true); 1877 } else { 1878 navigate(getNextIndex(), true); 1879 } 1880 }, that._properties.delay); 1881 } 1882 1883 /** 1884 * Clears/pauses automatic slide transition interval 1885 * 1886 * @private 1887 */ 1888 function clearAutoplayInterval() { 1889 window.clearInterval(that._autoplayIntervalId); 1890 that._autoplayIntervalId = null; 1891 } 1892 1893 /** 1894 * Sets the disabled state for an action and toggles the appropriate CSS classes 1895 * 1896 * @private 1897 * @param {HTMLElement} action Action to disable 1898 * @param {Boolean} [disable] {@code true} to disable, {@code false} to enable 1899 */ 1900 function setActionDisabled(action, disable) { 1901 if (!action) { 1902 return; 1903 } 1904 if (disable !== false) { 1905 action.disabled = true; 1906 action.classList.add("cmp-carousel__action--disabled"); 1907 } else { 1908 action.disabled = false; 1909 action.classList.remove("cmp-carousel__action--disabled"); 1910 } 1911 } 1912 } 1913 1914 /** 1915 * Parses the dataLayer string and returns the ID 1916 * 1917 * @private 1918 * @param {HTMLElement} item the accordion item 1919 * @returns {String} dataLayerId or undefined 1920 */ 1921 function getDataLayerId(item) { 1922 if (item) { 1923 if (item.dataset.cmpDataLayer) { 1924 return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0]; 1925 } else { 1926 return item.id; 1927 } 1928 } 1929 return null; 1930 } 1931 1932 /** 1933 * Document ready handler and DOM mutation observers. Initializes Carousel components as necessary. 1934 * 1935 * @private 1936 */ 1937 function onDocumentReady() { 1938 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 1939 if (dataLayerEnabled) { 1940 dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer"; 1941 dataLayer = window[dataLayerName] = window[dataLayerName] || []; 1942 } 1943 1944 var elements = document.querySelectorAll(selectors.self); 1945 for (var i = 0; i < elements.length; i++) { 1946 new Carousel({ element: elements[i], options: CMP.utils.readData(elements[i], IS) }); 1947 } 1948 1949 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 1950 var body = document.querySelector("body"); 1951 var observer = new MutationObserver(function(mutations) { 1952 mutations.forEach(function(mutation) { 1953 // needed for IE 1954 var nodesArray = [].slice.call(mutation.addedNodes); 1955 if (nodesArray.length > 0) { 1956 nodesArray.forEach(function(addedNode) { 1957 if (addedNode.querySelectorAll) { 1958 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 1959 elementsArray.forEach(function(element) { 1960 new Carousel({ element: element, options: CMP.utils.readData(element, IS) }); 1961 }); 1962 } 1963 }); 1964 } 1965 }); 1966 }); 1967 1968 observer.observe(body, { 1969 subtree: true, 1970 childList: true, 1971 characterData: true 1972 }); 1973 } 1974 1975 var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) { 1976 document.addEventListener("DOMContentLoaded", resolve); 1977 }); 1978 Promise.all([documentReady]).then(onDocumentReady); 1979 1980 if (containerUtils) { 1981 window.addEventListener("load", containerUtils.scrollToAnchor, false); 1982 } 1983 1984}()); 1985 1986 1987/******************************************************************************* 1988 * Copyright 2017 Adobe 1989 * 1990 * Licensed under the Apache License, Version 2.0 (the "License");
1991 * you may not use this file except in compliance with the License. 1992 * You may obtain a copy of the License at 1993 * 1994 * http://www.apache.org/licenses/LICENSE-2.0 1995 * 1996 * Unless required by applicable law or agreed to in writing, software 1997 * distributed under the License is distributed on an "AS IS" BASIS, 1998 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1999 * See the License for the specific language governing permissions and 2000 * limitations under the License. 2001 ******************************************************************************/ 2002if (window.Element && !Element.prototype.closest) { 2003 // eslint valid-jsdoc: "off" 2004 Element.prototype.closest = 2005 function(s) { 2006 "use strict"; 2007 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 2008 var el = this; 2009 var i; 2010 do { 2011 i = matches.length; 2012 while (--i >= 0 && matches.item(i) !== el) { 2013 // continue 2014 } 2015 } while ((i < 0) && (el = el.parentElement)); 2016 return el; 2017 }; 2018} 2019 2020if (window.Element && !Element.prototype.matches) { 2021 Element.prototype.matches = 2022 Element.prototype.matchesSelector || 2023 Element.prototype.mozMatchesSelector || 2024 Element.prototype.msMatchesSelector || 2025 Element.prototype.oMatchesSelector || 2026 Element.prototype.webkitMatchesSelector || 2027 function(s) { 2028 "use strict"; 2029 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 2030 var i = matches.length; 2031 while (--i >= 0 && matches.item(i) !== this) { 2032 // continue 2033 } 2034 return i > -1; 2035 }; 2036} 2037 2038if (!Object.assign) { 2039 Object.assign = function(target, varArgs) { // .length of function is 2 2040 "use strict"; 2041 if (target === null) { 2042 throw new TypeError("Cannot convert undefined or null to object"); 2043 } 2044 2045 var to = Object(target); 2046 2047 for (var index = 1; index < arguments.length; index++) { 2048 var nextSource = arguments[index]; 2049 2050 if (nextSource !== null) { 2051 for (var nextKey in nextSource) { 2052 if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 2053 to[nextKey] = nextSource[nextKey]; 2054 } 2055 } 2056 } 2057 } 2058 return to; 2059 }; 2060} 2061 2062(function(arr) { 2063 "use strict"; 2064 arr.forEach(function(item) { 2065 if (Object.prototype.hasOwnProperty.call(item, "remove")) { 2066 return; 2067 } 2068 Object.defineProperty(item, "remove", { 2069 configurable: true, 2070 enumerable: true, 2071 writable: true, 2072 value: function remove() { 2073 this.parentNode.removeChild(this); 2074 } 2075 }); 2076 }); 2077})([Element.prototype, CharacterData.prototype, DocumentType.prototype]); 2078 2079/******************************************************************************* 2080 * Copyright 2022 Adobe 2081 * 2082 * Licensed under the Apache License, Version 2.0 (the "License"); 2083 * you may not use this file except in compliance with the License. 2084 * You may obtain a copy of the License at 2085 * 2086 * http://www.apache.org/licenses/LICENSE-2.0 2087 * 2088 * Unless required by applicable law or agreed to in writing, software 2089 * distributed under the License is distributed on an "AS IS" BASIS, 2090 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2091 * See the License for the specific language governing permissions and 2092 * limitations under the License. 2093 ******************************************************************************/ 2094(function(document) { 2095 "use strict"; 2096 2097 window.CMP = window.CMP || {}; 2098 window.CMP.utils = (function() { 2099 var NS = "cmp"; 2100 2101 /** 2102 * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes 2103 * 2104 * @param {HTMLElement} element The component element to read options data from 2105 * @param {String} is The component identifier 2106 * @returns {String[]} The options read from the component data attributes 2107 */ 2108 var readData = function(element, is) { 2109 var data = element.dataset; 2110 var options = []; 2111 var capitalized = is; 2112 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2113 var reserved = ["is", "hook" + capitalized]; 2114 2115 for (var key in data) { 2116 if (Object.prototype.hasOwnProperty.call(data, key)) { 2117 var value = data[key]; 2118 2119 if (key.indexOf(NS) === 0) { 2120 key = key.slice(NS.length); 2121 key = key.charAt(0).toLowerCase() + key.substring(1); 2122 2123 if (reserved.indexOf(key) === -1) { 2124 options[key] = value; 2125 } 2126 } 2127 } 2128 } 2129 return options; 2130 }; 2131 2132 /** 2133 * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand 2134 * @param {String[]} options the options to transform 2135 * @param {Object} properties object of properties of property functions 2136 * @returns {Object} transformed properties 2137 */ 2138 var setupProperties = function(options, properties) { 2139 var transformedProperties = {}; 2140 2141 for (var key in properties) { 2142 if (Object.prototype.hasOwnProperty.call(properties, key)) { 2143 var property = properties[key]; 2144 if (options && options[key] != null) { 2145 if (property && typeof property.transform === "function") { 2146 transformedProperties[key] = property.transform(options[key]); 2147 } else { 2148 transformedProperties[key] = options[key]; 2149 } 2150 } else { 2151 transformedProperties[key] = properties[key]["default"]; 2152 } 2153 } 2154 } 2155 return transformedProperties; 2156 }; 2157 2158 2159 return { 2160 readData: readData, 2161 setupProperties: setupProperties 2162 }; 2163 }()); 2164}(window.document)); 2165 2166/******************************************************************************* 2167 * Copyright 2022 Adobe 2168 * 2169 * Licensed under the Apache License, Version 2.0 (the "License");
2170 * you may not use this file except in compliance with the License. 2171 * You may obtain a copy of the License at 2172 * 2173 * http://www.apache.org/licenses/LICENSE-2.0 2174 * 2175 * Unless required by applicable law or agreed to in writing, software 2176 * distributed under the License is distributed on an "AS IS" BASIS, 2177 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2178 * See the License for the specific language governing permissions and 2179 * limitations under the License. 2180 ******************************************************************************/ 2181(function(document) { 2182 "use strict"; 2183 2184 window.CMP = window.CMP || {}; 2185 window.CMP.image = window.CMP.image || {}; 2186 window.CMP.image.dynamicMedia = (function() { 2187 var autoSmartCrops = {}; 2188 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 2189 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}"; 2190 var SRC_URI_DPR_OFF = "dpr=off"; 2191 var SRC_URI_DPR_ON = "dpr=on,{dpr}"; 2192 var dpr = window.devicePixelRatio || 1; 2193 var config = { 2194 minWidth: 20 2195 }; 2196 2197 /** 2198 * get auto smart crops from dm 2199 * @param {String} src the src uri 2200 * @returns {{}} the smart crop json object 2201 */ 2202 var getAutoSmartCrops = function(src) { 2203 var request = new XMLHttpRequest(); 2204 var url = src.split(SRC_URI_TEMPLATE_WIDTH_VAR)[0] + "?req=set,json"; 2205 request.open("GET", url, false); 2206 request.onload = function() { 2207 if (request.status >= 200 && request.status < 400) { 2208 // success status 2209 var responseText = request.responseText; 2210 var rePayload = new RegExp(/^(?:\/\*jsonp\*\/)?\s*([^()]+)\(([\s\S]+),\s*"[0-9]*"\);?$/gmi); 2211 var rePayloadJSON = new RegExp(/^{[\s\S]*}$/gmi); 2212 var resPayload = rePayload.exec(responseText); 2213 var payload; 2214 if (resPayload) { 2215 var payloadStr = resPayload[2]; 2216 if (rePayloadJSON.test(payloadStr)) { 2217 payload = JSON.parse(payloadStr); 2218 } 2219 2220 } 2221 // check "relation" - only in case of smartcrop preset 2222 if (payload && payload.set.relation && payload.set.relation.length > 0) { 2223 for (var i = 0; i < payload.set.relation.length; i++) { 2224 autoSmartCrops[parseInt(payload.set.relation[i].userdata.SmartCropWidth)] = 2225 ":" + payload.set.relation[i].userdata.SmartCropDef; 2226 } 2227 } 2228 } else { 2229 // error status 2230 } 2231 }; 2232 request.send(); 2233 return autoSmartCrops; 2234 }; 2235 2236 /** 2237 * Build and return the srcset value based on the available auto smart crops 2238 * @param {String} src the src uri 2239 * @param {Object} smartCrops the smart crops object 2240 * @returns {String} the srcset 2241 */ 2242 var getSrcSet = function(src, smartCrops) { 2243 var srcset; 2244 var keys = Object.keys(smartCrops); 2245 if (keys.length > 0) { 2246 srcset = []; 2247 for (var key in autoSmartCrops) { 2248 srcset.push(src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, smartCrops[key]) + " " + key + "w"); 2249 } 2250 } 2251 return srcset.join(","); 2252 }; 2253 2254 /** 2255 * Get the optimal width based on the available sizes 2256 * @param {[Number]} sizes the available sizes 2257 * @param {Number} width the element width 2258 * @returns {String} the optimal width 2259 */ 2260 function getOptimalWidth(sizes, width) { 2261 var len = sizes.length; 2262 var key = 0; 2263 2264 while ((key < len - 1) && (sizes[key] < width)) { 2265 key++; 2266 } 2267 2268 return sizes[key] !== undefined ? sizes[key].toString() : width; 2269 } 2270 2271 /** 2272 * Get the width of an element or parent element if the width is smaller than the minimum width 2273 * @param {HTMLElement} component the image component 2274 * @param {HTMLElement | Node} parent the parent element 2275 * @returns {Number} the width of the element 2276 */ 2277 var getWidth = function(component, parent) { 2278 var width = component.offsetWidth; 2279 while (width < config.minWidth && parent && !component._autoWidth) { 2280 width = parent.offsetWidth; 2281 parent = parent.parentNode; 2282 } 2283 return width; 2284 }; 2285 2286 /** 2287 * Set the src and srcset attribute for a Dynamic Media Image which auto smart crops enabled. 2288 * @param {HTMLElement} component the image component 2289 * @param {{}} properties the component properties 2290 */ 2291 var setDMAttributes = function(component, properties) { 2292 // for v3 we first have to turn the dpr on
2293 var src = properties.src.replace(SRC_URI_DPR_OFF, SRC_URI_DPR_ON); 2294 src = src.replace(SRC_URI_TEMPLATE_DPR_VAR, dpr); 2295 var smartCrops = {}; 2296 var width; 2297 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 2298 smartCrops = getAutoSmartCrops(src); 2299 } 2300 var hasWidths = (properties.widths && properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 2301 if (hasWidths) { 2302 var image = component.querySelector("img"); 2303 var elemWidth = getWidth(component, component.parentNode); 2304 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 2305 image.setAttribute("srcset", CMP.image.dynamicMedia.getSrcSet(src, smartCrops)); 2306 width = getOptimalWidth(Object.keys(smartCrops, elemWidth)); 2307 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, smartCrops[width])); 2308 } else { 2309 width = getOptimalWidth(properties.widths, elemWidth); 2310 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, width)); 2311 } 2312 } 2313 }; 2314 2315 /** 2316 * Get the src attribute based on the optimal width 2317 * @param {String} src the src uri 2318 * @param {String} width the element width 2319 * @returns {String} the final src attribute 2320 */ 2321 var getSrc = function(src, width) { 2322 if (src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR) > -1) { 2323 src = src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, width); 2324 } 2325 return src; 2326 }; 2327 2328 2329 return { 2330 getAutoSmartCrops: getAutoSmartCrops, 2331 getSrcSet: getSrcSet, 2332 getSrc: getSrc, 2333 setDMAttributes: setDMAttributes, 2334 getWidth: getWidth 2335 }; 2336 }()); 2337 document.dispatchEvent(new CustomEvent("core.wcm.components.commons.site.image.dynamic-media.loaded")); 2338}(window.document)); 2339 2340/******************************************************************************* 2341 * Copyright 2016 Adobe 2342 * 2343 * Licensed under the Apache License, Version 2.0 (the "License"); 2344 * you may not use this file except in compliance with the License. 2345 * You may obtain a copy of the License at 2346 * 2347 * http://www.apache.org/licenses/LICENSE-2.0 2348 * 2349 * Unless required by applicable law or agreed to in writing, software 2350 * distributed under the License is distributed on an "AS IS" BASIS, 2351 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2352 * See the License for the specific language governing permissions and 2353 * limitations under the License. 2354 ******************************************************************************/ 2355(function() { 2356 "use strict"; 2357 2358 var NS = "cmp"; 2359 var IS = "image"; 2360 2361 var EMPTY_PIXEL = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; 2362 var LAZY_THRESHOLD_DEFAULT = 0; 2363 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 2364 var SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY = "width={width}"; 2365 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}"; 2366 2367 var selectors = { 2368 self: "[data-" + NS + '-is="' + IS + '"]', 2369 image: '[data-cmp-hook-image="image"]', 2370 map: '[data-cmp-hook-image="map"]', 2371 area: '[data-cmp-hook-image="area"]' 2372 }; 2373 2374 var lazyLoader = { 2375 "cssClass": "cmp-image__image--is-loading", 2376 "style": { 2377 "height": 0, 2378 "padding-bottom": "" // will be replaced with % ratio 2379 } 2380 }; 2381 2382 var properties = { 2383 /** 2384 * An array of alternative image widths (in pixels). 2385 * Used to replace a {.width} variable in the src property with an optimal width if a URI template is provided. 2386 * 2387 * @memberof Image 2388 * @type {Number[]} 2389 * @default [] 2390 */ 2391 "widths": { 2392 "default": [], 2393 "transform": function(value) { 2394 var widths = []; 2395 value.split(",").forEach(function(item) { 2396 item = parseFloat(item); 2397 if (!isNaN(item)) { 2398 widths.push(item); 2399 } 2400 }); 2401 return widths; 2402 } 2403 }, 2404 /** 2405 * Indicates whether the image should be rendered lazily. 2406 * 2407 * @memberof Image 2408 * @type {Boolean} 2409 * @default false 2410 */ 2411 "lazy": { 2412 "default": false, 2413 "transform": function(value) { 2414 return !(value === null || typeof value === "undefined"); 2415 } 2416 }, 2417 /** 2418 * Indicates image is DynamicMedia image. 2419 * 2420 * @memberof Image 2421 * @type {Boolean} 2422 * @default false 2423 */ 2424 "dmimage": { 2425 "default": false, 2426 "transform": function(value) { 2427 return !(value === null || typeof value === "undefined"); 2428 } 2429 }, 2430 /** 2431 * The lazy threshold. 2432 * This is the number of pixels, in advance of becoming visible, when an lazy-loading image should begin 2433 * to load. 2434 * 2435 * @memberof Image 2436 * @type {Number} 2437 * @default 0 2438 */ 2439 "lazythreshold": { 2440 "default": 0, 2441 "transform": function(value) { 2442 var val = parseInt(value); 2443 if (isNaN(val)) { 2444 return LAZY_THRESHOLD_DEFAULT; 2445 } 2446 return val; 2447 } 2448 }, 2449 /** 2450 * The image source. 2451 * 2452 * Can be a simple image source, or a URI template representation that 2453 * can be variable expanded - useful for building an image configuration with an alternative width. 2454 * e.g. '/path/image.coreimg{.width}.jpeg/1506620954214.jpeg' 2455 * 2456 * @memberof Image 2457 * @type {String} 2458 */ 2459 "src": { 2460 "transform": function(value) { 2461 return decodeURIComponent(value); 2462 } 2463 } 2464 }; 2465 2466 var devicePixelRatio = window.devicePixelRatio || 1; 2467 2468 function Image(config) { 2469 var that = this; 2470 2471 var smartCrops = {}; 2472 2473 var useAssetDelivery = false;
2474 var srcUriTemplateWidthVar = SRC_URI_TEMPLATE_WIDTH_VAR; 2475 2476 function init(config) { 2477 // prevents multiple initialization 2478 config.element.removeAttribute("data-" + NS + "-is"); 2479 2480 // check if asset delivery is used 2481 if (config.options.src && config.options.src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY) >= 0) { 2482 useAssetDelivery = true; 2483 srcUriTemplateWidthVar = SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY; 2484 } 2485 2486 that._properties = CMP.utils.setupProperties(config.options, properties); 2487 cacheElements(config.element); 2488 // check image is DM asset; if true try to make req=set 2489 if (config.options.src && Object.prototype.hasOwnProperty.call(config.options, "dmimage") && (config.options["smartcroprendition"] === "SmartCrop:Auto")) { 2490 smartCrops = CMP.image.dynamicMedia.getAutoSmartCrops(config.options.src); 2491 } 2492 2493 if (!that._elements.noscript) { 2494 return; 2495 } 2496 2497 that._elements.container = that._elements.link ? that._elements.link : that._elements.self; 2498 2499 unwrapNoScript(); 2500 2501 if (that._properties.lazy) { 2502 addLazyLoader(); 2503 } 2504 2505 if (that._elements.map) { 2506 that._elements.image.addEventListener("load", onLoad); 2507 } 2508 2509 window.addEventListener("resize", onWindowResize); 2510 ["focus", "click", "load", "transitionend", "animationend", "scroll"].forEach(function(name) { 2511 document.addEventListener(name, that.update); 2512 }); 2513 2514 that._elements.image.addEventListener("cmp-image-redraw", that.update); 2515 2516 that._interSectionObserver = new IntersectionObserver(function(entries, interSectionObserver) { 2517 entries.forEach(function(entry) { 2518 if (entry.intersectionRatio > 0) { 2519 that.update(); 2520 } 2521 }); 2522 }); 2523 that._interSectionObserver.observe(that._elements.self); 2524 2525 that.update(); 2526 } 2527 2528 function loadImage() { 2529 var hasWidths = (that._properties.widths && that._properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 2530 var replacement; 2531 if (Object.keys(smartCrops).length > 0) { 2532 var optimalWidth = getOptimalWidth(Object.keys(smartCrops), false); 2533 replacement = smartCrops[optimalWidth]; 2534 } else { 2535 replacement = hasWidths ? (that._properties.dmimage ? "" : ".") + getOptimalWidth(that._properties.widths, true) : ""; 2536 } 2537 if (useAssetDelivery) { 2538 replacement = replacement !== "" ? ("width=" + replacement.substring(1)) : ""; 2539 } 2540 var url = that._properties.src.replace(srcUriTemplateWidthVar, replacement); 2541 url = url.replace(SRC_URI_TEMPLATE_DPR_VAR, devicePixelRatio); 2542 2543 var imgSrcAttribute = that._elements.image.getAttribute("src"); 2544 2545 if (url !== imgSrcAttribute) { 2546 if (imgSrcAttribute === null || imgSrcAttribute === EMPTY_PIXEL) { 2547 that._elements.image.setAttribute("src", url); 2548 } else { 2549 var urlTemplateParts = that._properties.src.split(srcUriTemplateWidthVar); 2550 // check if image src was dynamically swapped meanwhile (e.g. by Target) 2551 var isImageRefSame = imgSrcAttribute.startsWith(urlTemplateParts[0]); 2552 if (isImageRefSame && urlTemplateParts.length > 1) { 2553 isImageRefSame = imgSrcAttribute.endsWith(urlTemplateParts[urlTemplateParts.length - 1]); 2554 } 2555 if (isImageRefSame) { 2556 that._elements.image.setAttribute("src", url); 2557 if (!hasWidths) { 2558 window.removeEventListener("scroll", that.update); 2559 } 2560 } 2561 } 2562 } 2563 if (that._lazyLoaderShowing) { 2564 that._elements.image.addEventListener("load", removeLazyLoader); 2565 } 2566 that._interSectionObserver.unobserve(that._elements.self); 2567 } 2568 2569 function getOptimalWidth(widths, useDevicePixelRatio) { 2570 var container = that._elements.self; 2571 var containerWidth = container.clientWidth; 2572 while (containerWidth === 0 && container.parentNode) { 2573 container = container.parentNode; 2574 containerWidth = container.clientWidth; 2575 } 2576 2577 var dpr = useDevicePixelRatio ? devicePixelRatio : 1; 2578 var optimalWidth = containerWidth * dpr; 2579 var len = widths.length; 2580 var key = 0; 2581 2582 while ((key < len - 1) && (widths[key] < optimalWidth)) { 2583 key++; 2584 } 2585 2586 return widths[key].toString(); 2587 } 2588 2589 function addLazyLoader() { 2590 var width = that._elements.image.getAttribute("width"); 2591 var height = that._elements.image.getAttribute("height"); 2592 2593 if (width && height) { 2594 var ratio = (height / width) * 100; 2595 var styles = lazyLoader.style; 2596 2597 styles["padding-bottom"] = ratio + "%"; 2598 2599 for (var s in styles) { 2600 if (Object.prototype.hasOwnProperty.call(styles, s)) { 2601 that._elements.image.style[s] = styles[s]; 2602 } 2603 } 2604 } 2605 that._elements.image.setAttribute("src", EMPTY_PIXEL); 2606 that._elements.image.classList.add(lazyLoader.cssClass); 2607 that._lazyLoaderShowing = true; 2608 } 2609 2610 function unwrapNoScript() { 2611 var markup = decodeNoscript(that._elements.noscript.textContent.trim()); 2612 var parser = new DOMParser(); 2613 2614 // temporary document avoids requesting the image before removing its src 2615 var temporaryDocument = parser.parseFromString(markup, "text/html"); 2616 var imageElement = temporaryDocument.querySelector(selectors.image); 2617 imageElement.removeAttribute("src"); 2618 that._elements.container.insertBefore(imageElement, that._elements.noscript); 2619 2620 var mapElement = temporaryDocument.querySelector(selectors.map); 2621 if (mapElement) { 2622 that._elements.container.insertBefore(mapElement, that._elements.noscript); 2623 } 2624 2625 that._elements.noscript.parentNode.removeChild(that._elements.noscript); 2626 if (that._elements.container.matches(selectors.image)) { 2627 that._elements.image = that._elements.container; 2628 } else { 2629 that._elements.image = that._elements.container.querySelector(selectors.image); 2630 } 2631 2632 that._elements.map = that._elements.container.querySelector(selectors.map); 2633 that._elements.areas = that._elements.container.querySelectorAll(selectors.area); 2634 } 2635 2636 function removeLazyLoader() { 2637 that._elements.image.classList.remove(lazyLoader.cssClass); 2638 for (var property in lazyLoader.style) { 2639 if (Object.prototype.hasOwnProperty.call(lazyLoader.style, property)) { 2640 that._elements.image.style[property] = ""; 2641 } 2642 } 2643 that._elements.image.removeEventListener("load", removeLazyLoader); 2644 that._lazyLoaderShowing = false;
2645 } 2646 2647 function isLazyVisible() { 2648 if (that._elements.container.offsetParent === null) { 2649 return false; 2650 } 2651 2652 var wt = window.pageYOffset; 2653 var wb = wt + document.documentElement.clientHeight; 2654 var et = that._elements.container.getBoundingClientRect().top + wt; 2655 var eb = et + that._elements.container.clientHeight; 2656 2657 return eb >= wt - that._properties.lazythreshold && et <= wb + that._properties.lazythreshold; 2658 } 2659 2660 function resizeAreas() { 2661 if (that._elements.areas && that._elements.areas.length > 0) { 2662 for (var i = 0; i < that._elements.areas.length; i++) { 2663 var width = that._elements.image.width; 2664 var height = that._elements.image.height; 2665 2666 if (width && height) { 2667 var relcoords = that._elements.areas[i].dataset.cmpRelcoords; 2668 if (relcoords) { 2669 var relativeCoordinates = relcoords.split(","); 2670 var coordinates = new Array(relativeCoordinates.length); 2671 2672 for (var j = 0; j < coordinates.length; j++) { 2673 if (j % 2 === 0) { 2674 coordinates[j] = parseInt(relativeCoordinates[j] * width); 2675 } else { 2676 coordinates[j] = parseInt(relativeCoordinates[j] * height); 2677 } 2678 } 2679 2680 that._elements.areas[i].coords = coordinates; 2681 } 2682 } 2683 } 2684 } 2685 } 2686 2687 function cacheElements(wrapper) { 2688 that._elements = {}; 2689 that._elements.self = wrapper; 2690 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 2691 2692 for (var i = 0; i < hooks.length; i++) { 2693 var hook = hooks[i]; 2694 var capitalized = IS; 2695 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2696 var key = hook.dataset[NS + "Hook" + capitalized]; 2697 that._elements[key] = hook; 2698 } 2699 } 2700 2701 function onWindowResize() { 2702 that.update(); 2703 resizeAreas(); 2704 } 2705 2706 function onLoad() { 2707 resizeAreas(); 2708 } 2709 2710 that.update = function() { 2711 if (that._properties.lazy) { 2712 if (isLazyVisible()) { 2713 loadImage(); 2714 } 2715 } else { 2716 loadImage(); 2717 } 2718 }; 2719 2720 if (config && config.element) { 2721 init(config); 2722 } 2723 } 2724 2725 function onDocumentReady() { 2726 var elements = document.querySelectorAll(selectors.self); 2727 for (var i = 0; i < elements.length; i++) { 2728 new Image({ element: elements[i], options: CMP.utils.readData(elements[i], IS) }); 2729 } 2730 2731 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 2732 var body = document.querySelector("body"); 2733 var observer = new MutationObserver(function(mutations) { 2734 mutations.forEach(function(mutation) { 2735 // needed for IE 2736 var nodesArray = [].slice.call(mutation.addedNodes); 2737 if (nodesArray.length > 0) { 2738 nodesArray.forEach(function(addedNode) { 2739 if (addedNode.querySelectorAll) { 2740 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 2741 elementsArray.forEach(function(element) { 2742 new Image({ element: element, options: CMP.utils.readData(element, IS) }); 2743 }); 2744 } 2745 }); 2746 } 2747 }); 2748 }); 2749 2750 observer.observe(body, { 2751 subtree: true, 2752 childList: true, 2753 characterData: true 2754 }); 2755 } 2756 2757 var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) { 2758 document.addEventListener("DOMContentLoaded", resolve); 2759 }); 2760 2761 Promise.all([documentReady]).then(onDocumentReady); 2762 /* 2763 on drag & drop of the component into a parsys, noscript's content will be escaped multiple times by the editor which creates 2764 the DOM for editing; the HTML parser cannot be used here due to the multiple escaping 2765 */ 2766 function decodeNoscript(text) { 2767 text = text.replace(/&(amp;)*lt;/g, "<"); 2768 text = text.replace(/&(amp;)*gt;/g, ">"); 2769 return text; 2770 } 2771 2772})(); 2773 2774 2775/******************************************************************************* 2776 * Copyright 2017 Adobe 2777 * 2778 * Licensed under the Apache License, Version 2.0 (the "License");
2779 * you may not use this file except in compliance with the License. 2780 * You may obtain a copy of the License at 2781 * 2782 * http://www.apache.org/licenses/LICENSE-2.0 2783 * 2784 * Unless required by applicable law or agreed to in writing, software 2785 * distributed under the License is distributed on an "AS IS" BASIS, 2786 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2787 * See the License for the specific language governing permissions and 2788 * limitations under the License. 2789 ******************************************************************************/ 2790(function() { 2791 "use strict"; 2792 2793 var NS = "cmp"; 2794 var IS = "search"; 2795 2796 var DELAY = 300; // time before fetching new results when the user is typing a search string 2797 var LOADING_DISPLAY_DELAY = 300; // minimum time during which the loading indicator is displayed 2798 var PARAM_RESULTS_OFFSET = "resultsOffset"; 2799 2800 var keyCodes = { 2801 TAB: 9, 2802 ENTER: 13, 2803 ESCAPE: 27, 2804 ARROW_UP: 38, 2805 ARROW_DOWN: 40 2806 }; 2807 2808 var selectors = { 2809 self: "[data-" + NS + '-is="' + IS + '"]', 2810 item: { 2811 self: "[data-" + NS + "-hook-" + IS + '="item"]', 2812 title: "[data-" + NS + "-hook-" + IS + '="itemTitle"]', 2813 focused: "." + NS + "-search__item--is-focused" 2814 } 2815 }; 2816 2817 var properties = { 2818 /** 2819 * The minimum required length of the search term before results are fetched. 2820 * 2821 * @memberof Search 2822 * @type {Number} 2823 * @default 3 2824 */ 2825 minLength: { 2826 "default": 3, 2827 transform: function(value) { 2828 value = parseFloat(value); 2829 return isNaN(value) ? null : value; 2830 } 2831 }, 2832 /** 2833 * The maximal number of results fetched by a search request. 2834 * 2835 * @memberof Search 2836 * @type {Number} 2837 * @default 10 2838 */ 2839 resultsSize: { 2840 "default": 10, 2841 transform: function(value) { 2842 value = parseFloat(value); 2843 return isNaN(value) ? null : value; 2844 } 2845 } 2846 }; 2847 2848 var idCount = 0; 2849 2850 function readData(element) { 2851 var data = element.dataset; 2852 var options = []; 2853 var capitalized = IS; 2854 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2855 var reserved = ["is", "hook" + capitalized]; 2856 2857 for (var key in data) { 2858 if (Object.prototype.hasOwnProperty.call(data, key)) { 2859 var value = data[key]; 2860 2861 if (key.indexOf(NS) === 0) { 2862 key = key.slice(NS.length); 2863 key = key.charAt(0).toLowerCase() + key.substring(1); 2864 2865 if (reserved.indexOf(key) === -1) { 2866 options[key] = value; 2867 } 2868 } 2869 } 2870 } 2871 2872 return options; 2873 } 2874 2875 function toggleShow(element, show) { 2876 if (element) { 2877 if (show !== false) { 2878 element.style.display = "block"; 2879 element.setAttribute("aria-hidden", false); 2880 } else { 2881 element.style.display = "none"; 2882 element.setAttribute("aria-hidden", true); 2883 } 2884 } 2885 } 2886 2887 function serialize(form) { 2888 var query = []; 2889 if (form && form.elements) { 2890 for (var i = 0; i < form.elements.length; i++) { 2891 var node = form.elements[i]; 2892 if (!node.disabled && node.name) { 2893 var param = [node.name, encodeURIComponent(node.value)]; 2894 query.push(param.join("=")); 2895 } 2896 } 2897 } 2898 return query.join("&"); 2899 } 2900 2901 function mark(node, regex) { 2902 if (!node || !regex) { 2903 return; 2904 } 2905 2906 // text nodes 2907 if (node.nodeType === 3) { 2908 var nodeValue = node.nodeValue; 2909 var match = regex.exec(nodeValue); 2910 2911 if (nodeValue && match) { 2912 var element = document.createElement("mark"); 2913 element.className = NS + "-search__item-mark"; 2914 element.appendChild(document.createTextNode(match[0])); 2915 2916 var after = node.splitText(match.index); 2917 after.nodeValue = after.nodeValue.substring(match[0].length); 2918 node.parentNode.insertBefore(element, after); 2919 } 2920 } else if (node.hasChildNodes()) { 2921 for (var i = 0; i < node.childNodes.length; i++) { 2922 // recurse 2923 mark(node.childNodes[i], regex); 2924 } 2925 } 2926 } 2927 2928 function Search(config) { 2929 if (config.element) { 2930 // prevents multiple initialization 2931 config.element.removeAttribute("data-" + NS + "-is"); 2932 } 2933 2934 this._cacheElements(config.element); 2935 this._setupProperties(config.options); 2936 2937 this._action = this._elements.form.getAttribute("action"); 2938 this._resultsOffset = 0; 2939 this._hasMoreResults = true; 2940 2941 this._elements.input.addEventListener("input", this._onInput.bind(this)); 2942 this._elements.input.addEventListener("focus", this._onInput.bind(this)); 2943 this._elements.input.addEventListener("keydown", this._onKeydown.bind(this)); 2944 this._elements.clear.addEventListener("click", this._onClearClick.bind(this)); 2945 document.addEventListener("click", this._onDocumentClick.bind(this)); 2946 this._elements.results.addEventListener("scroll", this._onScroll.bind(this)); 2947 2948 this._makeAccessible(); 2949 } 2950 2951 Search.prototype._displayResults = function() { 2952 if (this._elements.input.value.length === 0) { 2953 toggleShow(this._elements.clear, false); 2954 this._cancelResults(); 2955 } else if (this._elements.input.value.length < this._properties.minLength) { 2956 toggleShow(this._elements.clear, true); 2957 } else { 2958 this._updateResults(); 2959 toggleShow(this._elements.clear, true); 2960 } 2961 }; 2962 2963 Search.prototype._onScroll = function(event) { 2964 // fetch new results when the results to be scrolled down are less than the visible results 2965 if (this._elements.results.scrollTop + 2 * this._elements.results.clientHeight >= this._elements.results.scrollHeight) { 2966 this._resultsOffset += this._properties.resultsSize; 2967 this._displayResults(); 2968 } 2969 }; 2970 2971 Search.prototype._onInput = function(event) { 2972 var self = this; 2973 self._cancelResults(); 2974 // start searching when the search term reaches the minimum length 2975 this._timeout = setTimeout(function() { 2976 self._displayResults(); 2977 }, DELAY); 2978 }; 2979 2980 Search.prototype._onKeydown = function(event) { 2981 var self = this; 2982 2983 switch (event.keyCode) { 2984 case keyCodes.TAB: 2985 if (self._resultsOpen()) { 2986 toggleShow(self._elements.results, false); 2987 self._elements.input.setAttribute("aria-expanded", "false"); 2988 } 2989 break;
2990 case keyCodes.ENTER: 2991 event.preventDefault(); 2992 if (self._resultsOpen()) { 2993 var focused = self._elements.results.querySelector(selectors.item.focused); 2994 if (focused) { 2995 focused.click(); 2996 } 2997 } 2998 break; 2999 case keyCodes.ESCAPE: 3000 self._cancelResults(); 3001 break; 3002 case keyCodes.ARROW_UP: 3003 if (self._resultsOpen()) { 3004 event.preventDefault(); 3005 self._stepResultFocus(true); 3006 } 3007 break; 3008 case keyCodes.ARROW_DOWN: 3009 if (self._resultsOpen()) { 3010 event.preventDefault(); 3011 self._stepResultFocus(); 3012 } else { 3013 // test the input and if necessary fetch and display the results 3014 self._onInput(); 3015 } 3016 break; 3017 default: 3018 return; 3019 } 3020 }; 3021 3022 Search.prototype._onClearClick = function(event) { 3023 event.preventDefault(); 3024 this._elements.input.value = ""; 3025 toggleShow(this._elements.clear, false); 3026 toggleShow(this._elements.results, false); 3027 this._elements.input.setAttribute("aria-expanded", "false"); 3028 }; 3029 3030 Search.prototype._onDocumentClick = function(event) { 3031 var inputContainsTarget = this._elements.input.contains(event.target); 3032 var resultsContainTarget = this._elements.results.contains(event.target); 3033 3034 if (!(inputContainsTarget || resultsContainTarget)) { 3035 toggleShow(this._elements.results, false); 3036 this._elements.input.setAttribute("aria-expanded", "false"); 3037 } 3038 }; 3039 3040 Search.prototype._resultsOpen = function() { 3041 return this._elements.results.style.display !== "none"; 3042 }; 3043 3044 Search.prototype._makeAccessible = function() { 3045 var id = NS + "-search-results-" + idCount; 3046 this._elements.input.setAttribute("aria-owns", id); 3047 this._elements.results.id = id; 3048 idCount++; 3049 }; 3050 3051 Search.prototype._generateItems = function(data, results) { 3052 var self = this; 3053 3054 data.forEach(function(item) { 3055 var el = document.createElement("span"); 3056 el.innerHTML = self._elements.itemTemplate.innerHTML; 3057 el.querySelectorAll(selectors.item.title)[0].appendChild(document.createTextNode(item.title)); 3058 el.querySelectorAll(selectors.item.self)[0].setAttribute("href", self._safeHref(item.url)); 3059 results.innerHTML += el.innerHTML; 3060 }); 3061 }; 3062 3063 Search.prototype._safeHref = function(href) { 3064 var a = document.createElement("a"); 3065 a.href = href; 3066 return a.pathname; 3067 }; 3068 3069 Search.prototype._markResults = function() { 3070 var nodeList = this._elements.results.querySelectorAll(selectors.item.self); 3071 var escapedTerm = this._elements.input.value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 3072 var regex = new RegExp("(" + escapedTerm + ")", "gi"); 3073 3074 for (var i = this._resultsOffset - 1; i < nodeList.length; ++i) { 3075 var result = nodeList[i]; 3076 mark(result, regex); 3077 } 3078 }; 3079 3080 Search.prototype._stepResultFocus = function(reverse) { 3081 var results = this._elements.results.querySelectorAll(selectors.item.self); 3082 var focused = this._elements.results.querySelector(selectors.item.focused); 3083 var newFocused; 3084 var index = Array.prototype.indexOf.call(results, focused); 3085 var focusedCssClass = NS + "-search__item--is-focused"; 3086 3087 if (results.length > 0) { 3088 3089 if (!reverse) { 3090 // highlight the next result 3091 if (index < 0) { 3092 results[0].classList.add(focusedCssClass); 3093 results[0].setAttribute("aria-selected", "true"); 3094 } else if (index + 1 < results.length) { 3095 results[index].classList.remove(focusedCssClass); 3096 results[index].setAttribute("aria-selected", "false"); 3097 results[index + 1].classList.add(focusedCssClass); 3098 results[index + 1].setAttribute("aria-selected", "true"); 3099 } 3100 3101 // if the last visible result is partially hidden, scroll up until it's completely visible 3102 newFocused = this._elements.results.querySelector(selectors.item.focused); 3103 if (newFocused) { 3104 var bottomHiddenHeight = newFocused.offsetTop + newFocused.offsetHeight - this._elements.results.scrollTop - this._elements.results.clientHeight; 3105 if (bottomHiddenHeight > 0) { 3106 this._elements.results.scrollTop += bottomHiddenHeight; 3107 } else { 3108 this._onScroll(); 3109 } 3110 } 3111 3112 } else { 3113 // highlight the previous result 3114 if (index >= 1) { 3115 results[index].classList.remove(focusedCssClass); 3116 results[index].setAttribute("aria-selected", "false"); 3117 results[index - 1].classList.add(focusedCssClass); 3118 results[index - 1].setAttribute("aria-selected", "true"); 3119 } 3120 3121 // if the first visible result is partially hidden, scroll down until it's completely visible 3122 newFocused = this._elements.results.querySelector(selectors.item.focused); 3123 if (newFocused) { 3124 var topHiddenHeight = this._elements.results.scrollTop - newFocused.offsetTop; 3125 if (topHiddenHeight > 0) { 3126 this._elements.results.scrollTop -= topHiddenHeight; 3127 } 3128 } 3129 } 3130 } 3131 }; 3132 3133 Search.prototype._updateResults = function() { 3134 var self = this; 3135 if (self._hasMoreResults) { 3136 var request = new XMLHttpRequest(); 3137 var url = self._action + "?" + serialize(self._elements.form) + "&" + PARAM_RESULTS_OFFSET + "=" + self._resultsOffset; 3138 3139 request.open("GET", url, true); 3140 request.onload = function() { 3141 // when the results are loaded: hide the loading indicator and display the search icon after a minimum period 3142 setTimeout(function() { 3143 toggleShow(self._elements.loadingIndicator, false); 3144 toggleShow(self._elements.icon, true); 3145 }, LOADING_DISPLAY_DELAY); 3146 if (request.status >= 200 && request.status < 400) { 3147 // success status 3148 var data = JSON.parse(request.responseText); 3149 if (data.length > 0) { 3150 self._generateItems(data, self._elements.results); 3151 self._markResults(); 3152 toggleShow(self._elements.results, true); 3153 self._elements.input.setAttribute("aria-expanded", "true"); 3154 } else { 3155 self._hasMoreResults = false;
3156 } 3157 // the total number of results is not a multiple of the fetched results: 3158 // -> we reached the end of the query 3159 if (self._elements.results.querySelectorAll(selectors.item.self).length % self._properties.resultsSize > 0) { 3160 self._hasMoreResults = false; 3161 } 3162 } else { 3163 // error status 3164 } 3165 }; 3166 // when the results are loading: display the loading indicator and hide the search icon 3167 toggleShow(self._elements.loadingIndicator, true); 3168 toggleShow(self._elements.icon, false); 3169 request.send(); 3170 } 3171 }; 3172 3173 Search.prototype._cancelResults = function() { 3174 clearTimeout(this._timeout); 3175 this._elements.results.scrollTop = 0; 3176 this._resultsOffset = 0; 3177 this._hasMoreResults = true; 3178 this._elements.results.innerHTML = ""; 3179 this._elements.input.setAttribute("aria-expanded", "false"); 3180 }; 3181 3182 Search.prototype._cacheElements = function(wrapper) { 3183 this._elements = {}; 3184 this._elements.self = wrapper; 3185 var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 3186 3187 for (var i = 0; i < hooks.length; i++) { 3188 var hook = hooks[i]; 3189 var capitalized = IS; 3190 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3191 var key = hook.dataset[NS + "Hook" + capitalized]; 3192 this._elements[key] = hook; 3193 } 3194 }; 3195 3196 Search.prototype._setupProperties = function(options) { 3197 this._properties = {}; 3198 3199 for (var key in properties) { 3200 if (Object.prototype.hasOwnProperty.call(properties, key)) { 3201 var property = properties[key]; 3202 if (options && options[key] != null) { 3203 if (property && typeof property.transform === "function") { 3204 this._properties[key] = property.transform(options[key]); 3205 } else { 3206 this._properties[key] = options[key]; 3207 } 3208 } else { 3209 this._properties[key] = properties[key]["default"]; 3210 } 3211 } 3212 } 3213 }; 3214 3215 function onDocumentReady() { 3216 var elements = document.querySelectorAll(selectors.self); 3217 for (var i = 0; i < elements.length; i++) { 3218 new Search({ element: elements[i], options: readData(elements[i]) }); 3219 } 3220 3221 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 3222 var body = document.querySelector("body"); 3223 var observer = new MutationObserver(function(mutations) { 3224 mutations.forEach(function(mutation) { 3225 // needed for IE 3226 var nodesArray = [].slice.call(mutation.addedNodes); 3227 if (nodesArray.length > 0) { 3228 nodesArray.forEach(function(addedNode) { 3229 if (addedNode.querySelectorAll) { 3230 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 3231 elementsArray.forEach(function(element) { 3232 new Search({ element: element, options: readData(element) }); 3233 }); 3234 } 3235 }); 3236 } 3237 }); 3238 }); 3239 3240 observer.observe(body, { 3241 subtree: true, 3242 childList: true, 3243 characterData: true 3244 }); 3245 } 3246 3247 if (document.readyState !== "loading") { 3248 onDocumentReady(); 3249 } else { 3250 document.addEventListener("DOMContentLoaded", onDocumentReady); 3251 } 3252 3253})(); 3254 3255 3256/******************************************************************************* 3257 * Copyright 2016 Adobe 3258 * 3259 * Licensed under the Apache License, Version 2.0 (the "License"); 3260 * you may not use this file except in compliance with the License. 3261 * You may obtain a copy of the License at 3262 * 3263 * http://www.apache.org/licenses/LICENSE-2.0 3264 * 3265 * Unless required by applicable law or agreed to in writing, softw
3265are 3266 * distributed under the License is distributed on an "AS IS" BASIS, 3267 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3268 * See the License for the specific language governing permissions and 3269 * limitations under the License. 3270 ******************************************************************************/ 3271(function() { 3272 "use strict"; 3273 3274 var NS = "cmp"; 3275 var IS = "formText"; 3276 var IS_DASH = "form-text"; 3277 var SELF_SELECTOR = "[data-" + NS + '-is="' + IS + '"]'; 3278 3279 var selectors = { 3280 self: SELF_SELECTOR, 3281 validationMessage: SELF_SELECTOR + " .cmp-form-text__validation-message" 3282 }; 3283 3284 var displayValidationMessage = false; 3285 3286 var properties = { 3287 /** 3288 * A validation message to display if there is a type mismatch between the user input and expected input. 3289 * 3290 * @type {String} 3291 */ 3292 constraintMessage: "", 3293 /** 3294 * A validation message to display if no input is supplied, but input is expected for the field. 3295 * 3296 * @type {String} 3297 */ 3298 requiredMessage: "" 3299 }; 3300 3301 function readData(element) { 3302 var data = element.dataset; 3303 var options = []; 3304 var capitalized = IS; 3305 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3306 var reserved = ["is", "hook" + capitalized]; 3307 3308 for (var key in data) { 3309 if (Object.prototype.hasOwnProperty.call(data, key)) { 3310 var value = data[key]; 3311 3312 if (key.indexOf(NS) === 0) { 3313 key = key.slice(NS.length); 3314 key = key.charAt(0).toLowerCase() + key.substring(1); 3315 3316 if (reserved.indexOf(key) === -1) { 3317 options[key] = value; 3318 } 3319 } 3320 } 3321 } 3322 3323 return options; 3324 } 3325 3326 function FormText(config) { 3327 if (config.element) { 3328 // prevents multiple initialization 3329 config.element.removeAttribute("data-" + NS + "-is"); 3330 } 3331 3332 this._cacheElements(config.element); 3333 this._setupProperties(config.options); 3334 3335 this._elements.input.addEventListener("invalid", this._onInvalid.bind(this)); 3336 this._elements.input.addEventListener("input", this._onInput.bind(this)); 3337 if (displayValidationMessage) { 3338 this._elements.input.checkValidity(); 3339 } 3340 } 3341 3342 FormText.prototype._onInvalid = function(event) { 3343 event.target.setCustomValidity(""); 3344 if (event.target.validity.typeMismatch) { 3345 if (this._properties.constraintMessage) { 3346 event.target.setCustomValidity(this._properties.constraintMessage); 3347 } 3348 } else if (event.target.validity.valueMissing) { 3349 if (this._properties.requiredMessage) { 3350 event.target.setCustomValidity(this._properties.requiredMessage); 3351 } 3352 } 3353 if (displayValidationMessage) { 3354 var validationMessage = event.target.parentElement.querySelector(".cmp-form-text__validation-message"); 3355 if (validationMessage) { 3356 validationMessage.innerText = event.target.validationMessage; 3357 } 3358 } 3359 }; 3360 3361 FormText.prototype._onInput = function(event) { 3362 event.target.setCustomValidity(""); 3363 if (displayValidationMessage) { 3364 event.target.checkValidity(); 3365 } 3366 }; 3367 3368 FormText.prototype._cacheElements = function(wrapper) { 3369 this._elements = {}; 3370 this._elements.self = wrapper; 3371 var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS_DASH + "]"); 3372 for (var i = 0; i < hooks.length; i++) { 3373 var hook = hooks[i]; 3374 var capitalized = IS; 3375 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 3376 var key = hook.dataset[NS + "Hook" + capitalized]; 3377 this._elements[key] = hook; 3378 } 3379 }; 3380 3381 FormText.prototype._setupProperties = function(options) { 3382 this._properties = {}; 3383 3384 for (var key in properties) { 3385 if (Object.prototype.hasOwnProperty.call(properties, key)) { 3386 var property = properties[key]; 3387 if (options && options[key] != null) { 3388 if (property && typeof property.transform === "function") { 3389 this._properties[key] = property.transform(options[key]); 3390 } else { 3391 this._properties[key] = options[key]; 3392 } 3393 } else { 3394 this._properties[key] = properties[key]["default"]; 3395 } 3396 } 3397 } 3398 }; 3399 3400 function onDocumentReady() {
3401 var validationMessages = document.querySelectorAll(selectors.validationMessage); 3402 if (validationMessages && validationMessages.length > 0) { 3403 displayValidationMessage = true; 3404 } 3405 3406 var elements = document.querySelectorAll(selectors.self); 3407 for (var i = 0; i < elements.length; i++) { 3408 new FormText({ element: elements[i], options: readData(elements[i]) }); 3409 } 3410 3411 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 3412 var body = document.querySelector("body"); 3413 var observer = new MutationObserver(function(mutations) { 3414 mutations.forEach(function(mutation) { 3415 // needed for IE 3416 var nodesArray = [].slice.call(mutation.addedNodes); 3417 if (nodesArray.length > 0) { 3418 nodesArray.forEach(function(addedNode) { 3419 if (addedNode.querySelectorAll) { 3420 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 3421 elementsArray.forEach(function(element) { 3422 new FormText({ element: element, options: readData(element) }); 3423 }); 3424 } 3425 }); 3426 } 3427 }); 3428 }); 3429 3430 observer.observe(body, { 3431 subtree: true, 3432 childList: true, 3433 characterData: true 3434 }); 3435 } 3436 3437 if (document.readyState !== "loading") { 3438 onDocumentReady(); 3439 } else { 3440 document.addEventListener("DOMContentLoaded", onDocumentReady); 3441 } 3442 3443})(); 3444 3445 3446/******************************************************************************* 3447 * Copyright 2020 Adobe 3448 * 3449 * Licensed under the Apache License, Version 2.0 (the "License"); 3450 * you may not use this file except in compliance with the License. 3451 * You may obtain a copy of the License at 3452 * 3453 * http://www.apache.org/licenses/LICENSE-2.0 3454 * 3455 * Unless required by applicable law or agreed to in writing, software 3456 * distributed under the License is distributed on an "AS IS" BASIS, 3457 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3458 * See the License for the specific language governing permissions and 3459 * limitations under the License. 3460 ******************************************************************************/ 3461(function() { 3462 "use strict"; 3463 3464 var NS = "cmp"; 3465 var IS = "pdfviewer"; 3466 var SDK_URL = "https://acrobatservices.adobe.com/view-sdk/viewer.js"; 3467 var SDK_READY_EVENT = "adobe_dc_view_sdk.ready"; 3468 3469 var selectors = { 3470 self: "[data-" + NS + '-is="' + IS + '"]', 3471 sdkScript: 'script[src="' + SDK_URL + '"]' 3472 }; 3473 3474 function initSDK() { 3475 var sdkIncluded = document.querySelectorAll(selectors.sdkScript).length > 0; 3476 if (!window.adobe_dc_view_sdk && !sdkIncluded) { 3477 var dcv = document.createElement("script"); 3478 dcv.type = "text/javascript"; 3479 dcv.src = SDK_URL; 3480 document.body.appendChild(dcv); 3481 } 3482 } 3483 3484 function previewPdf(component) { 3485 // prevents multiple initialization 3486 component.removeAttribute("data-" + NS + "-is"); 3487 3488 // add the view sdk to the page 3489 initSDK(); 3490 3491 // manage the preview 3492 if (component.dataset && component.id) { 3493 if (window.AdobeDC && window.AdobeDC.View) { 3494 dcView(component); 3495 } else { 3496 document.addEventListener(SDK_READY_EVENT, function() { 3497 dcView(component); 3498 }); 3499 } 3500 } 3501 } 3502 3503 function dcView(component) { 3504 var adobeDCView = new window.AdobeDC.View({ 3505 clientId: component.dataset.cmpClientId, 3506 divId: component.id + "-content", 3507 reportSuiteId: component.dataset.cmpReportSuiteId, 3508 locale: typeof Granite !== "undefined" && Granite && Granite.I18n ? Granite.I18n.getLocale() : navigator.language || navigator.userLanguage 3509 }); 3510 adobeDCView.previewFile({ 3511 content: { location: { url: component.dataset.cmpDocumentPath } }, 3512 metaData: { fileName: component.dataset.cmpDocumentFileName } 3513 }, JSON.parse(component.dataset.cmpViewerConfigJson)); 3514 } 3515 3516 /** 3517 * Document ready handler and DOM mutation observers. Initializes Accordion components as necessary. 3518 * 3519 * @private 3520 */ 3521 function onDocumentReady() { 3522 var elements = document.querySelectorAll(selectors.self); 3523 for (var i = 0; i < elements.length; i++) { 3524 previewPdf(elements[i]); 3525 } 3526 3527 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 3528 var body = document.querySelector("body"); 3529 var observer = new MutationObserver(function(mutations) { 3530 mutations.forEach(function(mutation) { 3531 // needed for IE 3532 var nodesArray = [].slice.call(mutation.addedNodes); 3533 if (nodesArray.length > 0) { 3534 nodesArray.forEach(function(addedNode) { 3535 if (addedNode.querySelectorAll) { 3536 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 3537 elementsArray.forEach(function(element) { 3538 previewPdf(element); 3539 }); 3540 } 3541 }); 3542 } 3543 }); 3544 }); 3545 3546 observer.observe(body, { 3547 subtree: true, 3548 childList: true, 3549 characterData: true 3550 }); 3551 3552 } 3553 3554 if (document.readyState !== "loading") { 3555 onDocumentReady(); 3556 } else { 3557 document.addEventListener("DOMContentLoaded", onDocumentReady); 3558 } 3559}()); 3560 3561 3562/******************************************************************************* 3563 * Copyright 2020 Adobe 3564 * 3565 * Licensed under the Apache License, Version 2.0 (the "License");
3566 * you may not use this file except in compliance with the License. 3567 * You may obtain a copy of the License at 3568 * 3569 * http://www.apache.org/licenses/LICENSE2.0 3570 * 3571 * Unless required by applicable law or agreed to in writing, software 3572 * distributed under the License is distributed on an "AS IS" BASIS, 3573 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3574 * See the License for the specific language governing permissions and 3575 * limitations under the License. 3576 ******************************************************************************/ 3577 3578/** 3579 * Element.matches() 3580 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill 3581 */ 3582if (!Element.prototype.matches) { 3583 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 3584} 3585 3586// eslint-disable-next-line valid-jsdoc 3587/** 3588 * Element.closest() 3589 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill 3590 */ 3591if (!Element.prototype.closest) { 3592 Element.prototype.closest = function(s) { 3593 "use strict"; 3594 var el = this; 3595 if (!document.documentElement.contains(el)) { 3596 return null; 3597 } 3598 do { 3599 if (el.matches(s)) { 3600 return el; 3601 } 3602 el = el.parentElement || el.parentNode; 3603 } while (el !== null && el.nodeType === 1); 3604 return null; 3605 }; 3606} 3607 3608// https://tc39.github.io/ecma262/#sec-array.prototype.find 3609if (!Array.prototype.find) { 3610 Object.defineProperty(Array.prototype, "find", { 3611 value: function(predicate) { 3612 "use strict"; 3613 // 1. Let O be ? ToObject(this value). 3614 if (this == null) { 3615 throw TypeError('"this" is null or not defined'); 3616 } 3617 3618 var o = Object(this); 3619 3620 // 2. Let len be ? ToLength(? Get(O, "length")). 3621 var len = o.length >>> 0; 3622 3623 // 3. If IsCallable(predicate) is false, throw a TypeError exception. 3624 if (typeof predicate !== "function") { 3625 throw TypeError("predicate must be a function"); 3626 } 3627 3628 // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. 3629 var thisArg = arguments[1]; 3630 3631 // 5. Let k be 0. 3632 var k = 0; 3633 3634 // 6. Repeat, while k < len 3635 while (k < len) { 3636 // a. Let Pk be ! ToString(k). 3637 // b. Let kValue be ? Get(O, Pk). 3638 // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). 3639 // d. If testResult is true, return kValue. 3640 var kValue = o[k]; 3641 if (predicate.call(thisArg, kValue, k, o)) { 3642 return kValue; 3643 } 3644 // e. Increase k by 1. 3645 k++; 3646 } 3647 3648 // 7. Return undefined. 3649 return undefined; 3650 }, 3651 configurable: true, 3652 writable: true 3653 }); 3654} 3655 3656"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;
3656if(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;
3656){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={};
3656Yt["[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)}
3656,_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))}
3656e.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]); 3657//# sourceMappingURL=adobe-client-data-layer.min.js.map 3658 3659/******************************************************************************* 3660 * Copyright 2020 Adobe 3661 * 3662 * Licensed under the Apache License, Version 2.0 (the "License"); 3663 * you may not use this file except in compliance with the License. 3664 * You may obtain a copy of the License at 3665 * 3666 * http://www.apache.org/licenses/LICENSE-2.0 3667 * 3668 * Unless required by applicable law or agreed to in writing, software 3669 * distributed under the License is distributed on an "AS IS" BASIS, 3670 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3671 * See the License for the specific language governing permissions and 3672 * limitations under the License. 3673 ******************************************************************************/ 3674(function() { 3675 "use strict"; 3676 3677 var dataLayerEnabled; 3678 var dataLayerName; 3679 var dataLayer; 3680 3681 function addComponentToDataLayer(component) { 3682 dataLayer.push({ 3683 component: getComponentObject(component) 3684 }); 3685 } 3686 3687 function attachClickEventListener(element) { 3688 element.addEventListener("click", addClickToDataLayer); 3689 } 3690 3691 function getComponentObject(element) { 3692 var component = getComponentData(element); 3693 var componentID = Object.keys(component)[0]; 3694 // if the component does not have a parent ID property, use the ID of the parent element 3695 if (component && component[componentID] && !component[componentID].parentId) { 3696 var parentElement = element.parentNode.closest("[data-cmp-data-layer], body"); 3697 if (parentElement) { 3698 component[componentID].parentId = parentElement.id; 3699 } 3700 } 3701 3702 return component; 3703 } 3704 3705 function addClickToDataLayer(event) { 3706 var element = event.currentTarget; 3707 var componentId = getClickId(element); 3708 3709 dataLayer.push({ 3710 event: "cmp:click", 3711 eventInfo: { 3712 path: "component." + componentId 3713 } 3714 }); 3715 } 3716 3717 function getComponentData(element) { 3718 var dataLayerJson = element.dataset.cmpDataLayer; 3719 if (dataLayerJson) { 3720 return JSON.parse(dataLayerJson); 3721 } else { 3722 return undefined; 3723 } 3724 } 3725 3726 function getClickId(element) { 3727 if (element.dataset.cmpDataLayer) { 3728 return Object.keys(JSON.parse(element.dataset.cmpDataLayer))[0]; 3729 } 3730 3731 var componentElement = element.closest("[data-cmp-data-layer]"); 3732 3733 return Object.keys(JSON.parse(componentElement.dataset.cmpDataLayer))[0]; 3734 } 3735 3736 function onDocumentReady() { 3737 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 3738 if (dataLayerEnabled) { 3739 dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer"; 3740 dataLayer = window[dataLayerName] = window[dataLayerName] || []; 3741 3742 var components = document.querySelectorAll("[data-cmp-data-layer]"); 3743 var clickableElements = document.querySelectorAll("[data-cmp-clickable]"); 3744 3745 components.forEach(function(component) { 3746 addComponentToDataLayer(component); 3747 }); 3748 3749 clickableElements.forEach(function(element) { 3750 attachClickEventListener(element); 3751 }); 3752 3753 dataLayer.push({ 3754 event: "cmp:loaded" 3755 }); 3756 } 3757 } 3758 3759 if (document.readyState !== "loading") { 3760 onDocumentReady(); 3761 } else { 3762 document.addEventListener("DOMContentLoaded", onDocumentReady); 3763 } 3764 3765}()); 3766 3767 3768(function () { 3769 "use strict"; 3770 3771 function normalizeTargetIdGlobally() { 3772 // document.querySelectorAll('.aem-GridColumn, .responsivegrid').forEach(function (wrapper) { 3773 document.querySelectorAll('.aem-GridColumn, .responsivegrid:not
3773(.aem-GridColumn)').forEach(function (wrapper) { 3774 // Skip the top-level <main> container 3775 if (wrapper.tagName.toLowerCase() === 'main') return; 3776 3777 // Find the first descendant with data-target-id or id 3778 var inner = wrapper.querySelector('[data-target-id], [id]'); 3779 if (!inner) return; 3780 3781 // Prefer data-target-id, fallback to id 3782 var value = inner.getAttribute('data-target-id') || inner.getAttribute('id'); 3783 if (!value || value.trim() === '') return; 3784 3785 // Apply to wrapper 3786 wrapper.setAttribute('data-target-id', value); 3787 3788 // Remove from child if it had data-target-id 3789 if (inner.hasAttribute('data-target-id')) { 3790 inner.removeAttribute('data-target-id'); 3791 } 3792 }); 3793 } 3794 3795 if (document.readyState === "loading") { 3796 document.addEventListener("DOMContentLoaded", normalizeTargetIdGlobally); 3797 } else { 3798 normalizeTargetIdGlobally(); 3799 } 3800})();
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.