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 dataLayerEnabled; 66 var dataLayer; 67 68 var NS = "cmp"; 69 var IS = "accordion"; 70 71 var keyCodes = { 72 ENTER: 13, 73 SPACE: 32, 74 END: 35, 75 HOME: 36, 76 ARROW_LEFT: 37, 77 ARROW_UP: 38, 78 ARROW_RIGHT: 39, 79 ARROW_DOWN: 40 80 }; 81 82 var selectors = { 83 self: "[data-" + NS + '-is="' + IS + '"]' 84 }; 85
86 var cssClasses = { 87 button: { 88 disabled: "cmp-accordion__button--disabled", 89 expanded: "cmp-accordion__button--expanded" 90 }, 91 panel: { 92 hidden: "cmp-accordion__panel--hidden", 93 expanded: "cmp-accordion__panel--expanded" 94 } 95 }; 96 97 var dataAttributes = { 98 item: { 99 expanded: "data-cmp-expanded" 100 } 101 }; 102 103 var properties = { 104 /** 105 * Determines whether a single accordion item is forced to be expanded at a time. 106 * Expanding one item will collapse all others. 107 * 108 * @memberof Accordion 109 * @type {Boolean} 110 * @default false 111 */ 112 "singleExpansion": { 113 "default": false, 114 "transform": function(value) { 115 return !(value === null || typeof value === "undefined"); 116 } 117 } 118 }; 119 120 /** 121 * Accordion Configuration. 122 * 123 * @typedef {Object} AccordionConfig Represents an Accordion configuration 124 * @property {HTMLElement} element The HTMLElement representing the Accordion 125 * @property {Object} options The Accordion options 126 */ 127 128 /** 129 * Accordion. 130 * 131 * @class Accordion 132 * @classdesc An interactive Accordion component for toggling panels of related content 133 * @param {AccordionConfig} config The Accordion configuration 134 */ 135 function Accordion(config) { 136 var that = this; 137 138 if (config && config.element) { 139 init(config); 140 } 141 142 /** 143 * Initializes the Accordion. 144 * 145 * @private 146 * @param {AccordionConfig} config The Accordion configuration 147 */ 148 function init(config) { 149 that._config = config; 150 151 // prevents multiple initialization 152 config.element.removeAttribute("data-" + NS + "-is"); 153 154 setupProperties(config.options); 155 cacheElements(config.element); 156 157 if (that._elements["item"]) { 158 // ensures multiple element types are arrays. 159 that._elements["item"] = Array.isArray(that._elements["item"]) ? that._elements["item"] : [that._elements["item"]]; 160 that._elements["button"] = Array.isArray(that._elements["button"]) ? that._elements["button"] : [that._elements["button"]]; 161 that._elements["panel"] = Array.isArray(that._elements["panel"]) ? that._elements["panel"] : [that._elements["panel"]]; 162 163 // Expand the item based on deep-link-id if it matches with any existing accordion item id 164 var deepLinkItem = CQ.CoreComponents.container.utils.getDeepLinkItem(that, "item"); 165 if (deepLinkItem && !deepLinkItem.hasAttribute(dataAttributes.item.expanded)) { 166 setItemExpanded(deepLinkItem, true); 167 } 168 169 if (that._properties.singleExpansion) { 170 // No deep linking 171 if (!deepLinkItem) { 172 var expandedItems = getExpandedItems(); 173 // no expanded item annotated, force the first item to display. 174 if (expandedItems.length === 0) { 175 toggle(0); 176 } 177 // multiple expanded items annotated, display the last item open. 178 if (expandedItems.length > 1) { 179 toggle(expandedItems.length - 1); 180 } 181 } else { 182 // Deep link case 183 // Collapse the items other than which is deep linked 184 for (var j = 0; j < that._elements["item"].length; j++) { 185 if (that._elements["item"][j].id !== deepLinkItem.id && 186 that._elements["item"][j].hasAttribute(dataAttributes.item.expanded)) { 187 setItemExpanded(that._elements["item"][j], false); 188 } 189 } 190 } 191 } 192 193 refreshItems(); 194 bindEvents(); 195 196 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 197 /* 198 * Editor message handling: 199 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
200 * - check that the message data panel container type is correct and that the id (path) matches this specific Accordion component 201 * - if so, route the "navigate" operation to enact a navigation of the Accordion based on index data 202 */ 203 CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 204 CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 205 if (message.data && message.data.type === "cmp-accordion" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 206 if (message.data.operation === "navigate") { 207 // switch to single expansion mode when navigating in edit mode. 208 var singleExpansion = that._properties.singleExpansion; 209 that._properties.singleExpansion = true; 210 toggle(message.data.index); 211 212 // revert to the configured state. 213 that._properties.singleExpansion = singleExpansion; 214 } 215 } 216 }); 217 } 218 } 219 } 220 221 /** 222 * Caches the Accordion elements as defined via the {@code data-accordion-hook="ELEMENT_NAME"} markup API. 223 * 224 * @private 225 * @param {HTMLElement} wrapper The Accordion wrapper element 226 */ 227 function cacheElements(wrapper) { 228 that._elements = {}; 229 that._elements.self = wrapper; 230 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 231 232 for (var i = 0; i < hooks.length; i++) { 233 var hook = hooks[i]; 234 if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own accordion elements 235 var capitalized = IS; 236 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 237 var key = hook.dataset[NS + "Hook" + capitalized]; 238 if (that._elements[key]) { 239 if (!Array.isArray(that._elements[key])) { 240 var tmp = that._elements[key]; 241 that._elements[key] = [tmp]; 242 } 243 that._elements[key].push(hook); 244 } else { 245 that._elements[key] = hook; 246 } 247 } 248 } 249 } 250 251 /** 252 * Sets up properties for the Accordion based on the passed options. 253 * 254 * @private 255 * @param {Object} options The Accordion options 256 */ 257 function setupProperties(options) { 258 that._properties = {}; 259 260 for (var key in properties) { 261 if (properties.hasOwnProperty(key)) { 262 var property = properties[key]; 263 var value = null; 264 265 if (options && options[key] != null) { 266 value = options[key]; 267 268 // transform the provided option 269 if (property && typeof property.transform === "function") { 270 value = property.transform(value); 271 } 272 } 273 274 if (value === null) { 275 // value still null, take the property default 276 value = properties[key]["default"]; 277 } 278 279 that._properties[key] = value; 280 } 281 } 282 } 283 284 /** 285 * Binds Accordion event handling. 286 * 287 * @private 288 */ 289 function bindEvents() { 290 var buttons = that._elements["button"]; 291 if (buttons) { 292 for (var i = 0; i < buttons.length; i++) { 293 (function(index) { 294 buttons[i].addEventListener("click", function(event) { 295 toggle(index); 296 focusButton(index); 297 }); 298 buttons[i].addEventListener("keydown", function(event) { 299 onButtonKeyDown(event, index); 300 }); 301 })(i); 302 } 303 } 304 } 305 306 /** 307 * Handles button keydown events. 308 * 309 * @private 310 * @param {Object} event The keydown event 311 * @param {Number} index The index of the button triggering the event 312 */ 313 function onButtonKeyDown(event, index) { 314 var lastIndex = that._elements["button"].length - 1; 315 316 switch (event.keyCode) { 317 case keyCodes.ARROW_LEFT: 318 case keyCodes.ARROW_UP: 319 event.preventDefault(); 320 if (index > 0) { 321 focusButton(index - 1); 322 } 323 break; 324 case keyCodes.ARROW_RIGHT: 325 case keyCodes.ARROW_DOWN: 326 event.preventDefault(); 327 if (index < lastIndex) { 328 focusButton(index + 1); 329 } 330 break; 331 case keyCodes.HOME: 332 event.preventDefault(); 333 focusButton(0); 334 break; 335 case keyCodes.END: 336 event.preventDefault(); 337 focusButton(lastIndex); 338 break;
339 case keyCodes.ENTER: 340 case keyCodes.SPACE: 341 event.preventDefault(); 342 toggle(index); 343 focusButton(index); 344 break; 345 default: 346 return; 347 } 348 } 349 350 /** 351 * General handler for toggle of an item. 352 * 353 * @private 354 * @param {Number} index The index of the item to toggle 355 */ 356 function toggle(index) { 357 var item = that._elements["item"][index]; 358 if (item) { 359 if (that._properties.singleExpansion) { 360 // ensure only a single item is expanded if single expansion is enabled. 361 for (var i = 0; i < that._elements["item"].length; i++) { 362 if (that._elements["item"][i] !== item) { 363 var expanded = getItemExpanded(that._elements["item"][i]); 364 if (expanded) { 365 setItemExpanded(that._elements["item"][i], false); 366 } 367 } 368 } 369 setItemExpanded(item, true); 370 } else { 371 setItemExpanded(item, !getItemExpanded(item)); 372 } 373 374 if (dataLayerEnabled) { 375 var accordionId = that._elements.self.id; 376 var expandedItems = getExpandedItems() 377 .map(function(item) { 378 return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0]; 379 }); 380 381 var uploadPayload = {component: {}}; 382 uploadPayload.component[accordionId] = { shownItems: expandedItems }; 383 384 var removePayload = {component: {}}; 385 removePayload.component[accordionId] = { shownItems: undefined }; 386 387 dataLayer.push(removePayload); 388 dataLayer.push(uploadPayload); 389 } 390 } 391 } 392 393 /** 394 * Sets an item's expanded state based on the provided flag and refreshes its internals. 395 * 396 * @private 397 * @param {HTMLElement} item The item to mark as expanded, or not expanded 398 * @param {Boolean} expanded true to mark the item expanded, false otherwise 399 */ 400 function setItemExpanded(item, expanded) { 401 if (expanded) { 402 item.setAttribute(dataAttributes.item.expanded, ""); 403 if (dataLayerEnabled) { 404 dataLayer.push({ 405 event: "cmp:show", 406 eventInfo: { 407 path: "component." + getDataLayerId(item.dataset.cmpDataLayer) 408 } 409 }); 410 } 411 412 } else { 413 item.removeAttribute(dataAttributes.item.expanded); 414 if (dataLayerEnabled) { 415 dataLayer.push({ 416 event: "cmp:hide", 417 eventInfo: { 418 path: "component." + getDataLayerId(item.dataset.cmpDataLayer) 419 } 420 }); 421 } 422 } 423 refreshItem(item); 424 } 425 426 /** 427 * Gets an item's expanded state. 428 * 429 * @private 430 * @param {HTMLElement} item The item for checking its expanded state 431 * @returns {Boolean} true if the item is expanded, false otherwise 432 */ 433 function getItemExpanded(item) { 434 return item && item.dataset && item.dataset["cmpExpanded"] !== undefined; 435 } 436 437 /** 438 * Refreshes an item based on its expanded state. 439 * 440 * @private 441 * @param {HTMLElement} item The item to refresh 442 */ 443 function refreshItem(item) { 444 var expanded = getItemExpanded(item); 445 if (expanded) { 446 expandItem(item); 447 } else { 448 collapseItem(item); 449 } 450 } 451 452 /** 453 * Refreshes all items based on their expanded state. 454 * 455 * @private 456 */ 457 function refreshItems() { 458 for (var i = 0; i < that._elements["item"].length; i++) { 459 refreshItem(that._elements["item"][i]); 460 } 461 } 462 463 /** 464 * Returns all expanded items. 465 * 466 * @private 467 * @returns {HTMLElement[]} The expanded items 468 */ 469 function getExpandedItems() { 470 var expandedItems = []; 471 472 for (var i = 0; i < that._elements["item"].length; i++) { 473 var item = that._elements["item"][i]; 474 var expanded = getItemExpanded(item); 475 if (expanded) { 476 expandedItems.push(item); 477 } 478 } 479 480 return expandedItems; 481 } 482 483 /** 484 * Annotates the item and its internals with 485 * the necessary style and accessibility attributes to indicate it is expanded. 486 * 487 * @private 488 * @param {HTMLElement} item The item to annotate as expanded 489 */ 490 function expandItem(item) { 491 var index = that._elements["item"].indexOf(item); 492 if (index > -1) { 493 var button = that._elements["button"][index]; 494 var panel = that._elements["panel"][index];
495 button.classList.add(cssClasses.button.expanded); 496 button.setAttribute("aria-expanded", true); 497 panel.classList.add(cssClasses.panel.expanded); 498 panel.classList.remove(cssClasses.panel.hidden); 499 panel.setAttribute("aria-hidden", false); 500 501 if (that._properties.singleExpansion) { 502 button.classList.add(cssClasses.button.disabled); 503 button.setAttribute("aria-disabled", true); 504 } 505 } 506 } 507 508 /** 509 * Annotates the item and its internals with 510 * the necessary style and accessibility attributes to indicate it is not expanded. 511 * 512 * @private 513 * @param {HTMLElement} item The item to annotate as not expanded 514 */ 515 function collapseItem(item) { 516 var index = that._elements["item"].indexOf(item); 517 if (index > -1) { 518 var button = that._elements["button"][index]; 519 var panel = that._elements["panel"][index]; 520 button.classList.remove(cssClasses.button.disabled); 521 button.classList.remove(cssClasses.button.expanded); 522 button.removeAttribute("aria-disabled"); 523 button.setAttribute("aria-expanded", false); 524 panel.classList.add(cssClasses.panel.hidden); 525 panel.classList.remove(cssClasses.panel.expanded); 526 panel.setAttribute("aria-hidden", true); 527 } 528 } 529 530 /** 531 * Focuses the button at the provided index. 532 * 533 * @private 534 * @param {Number} index The index of the button to focus 535 */ 536 function focusButton(index) { 537 var button = that._elements["button"][index]; 538 button.focus(); 539 } 540 } 541 542 /** 543 * Reads options data from the Accordion wrapper element, defined via {@code data-cmp-*} data attributes. 544 * 545 * @private 546 * @param {HTMLElement} element The Accordion element to read options data from 547 * @returns {Object} The options read from the component data attributes 548 */ 549 function readData(element) { 550 var data = element.dataset; 551 var options = []; 552 var capitalized = IS; 553 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 554 var reserved = ["is", "hook" + capitalized]; 555 556 for (var key in data) { 557 if (data.hasOwnProperty(key)) { 558 var value = data[key]; 559 560 if (key.indexOf(NS) === 0) { 561 key = key.slice(NS.length); 562 key = key.charAt(0).toLowerCase() + key.substring(1); 563 564 if (reserved.indexOf(key) === -1) { 565 options[key] = value; 566 } 567 } 568 } 569 } 570 571 return options; 572 } 573 574 /** 575 * Parses the dataLayer string and returns the ID 576 * 577 * @private 578 * @param {String} componentDataLayer the dataLayer string 579 * @returns {String} dataLayerId or undefined 580 */ 581 function getDataLayerId(componentDataLayer) { 582 return Object.keys(JSON.parse(componentDataLayer))[0]; 583 } 584 585 /** 586 * Document ready handler and DOM mutation observers. Initializes Accordion components as necessary. 587 * 588 * @private 589 */ 590 function onDocumentReady() { 591 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 592 dataLayer = (dataLayerEnabled)? window.adobeDataLayer = window.adobeDataLayer || [] : undefined; 593 594 var elements = document.querySelectorAll(selectors.self); 595 for (var i = 0; i < elements.length; i++) { 596 new Accordion({ element: elements[i], options: readData(elements[i]) }); 597 } 598 599 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 600 var body = document.querySelector("body"); 601 var observer = new MutationObserver(function(mutations) { 602 mutations.forEach(function(mutation) { 603 // needed for IE 604 var nodesArray = [].slice.call(mutation.addedNodes); 605 if (nodesArray.length > 0) { 606 nodesArray.forEach(function(addedNode) { 607 if (addedNode.querySelectorAll) { 608 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 609 elementsArray.forEach(function(element) { 610 new Accordion({ element: element, options: readData(element) }); 611 }); 612 } 613 }); 614 } 615 }); 616 }); 617 618 observer.observe(body, { 619 subtree: true, 620 childList: true, 621 characterData: true 622 }); 623 } 624 625 if (document.readyState !== "loading") { 626 onDocumentReady(); 627 } else { 628 document.addEventListener("DOMContentLoaded", onDocumentReady); 629 } 630}()); 631 632/******************************************************************************* 633 * Copyright 2018 Adobe 634 * 635 * Licensed under the Apache License, Version 2.0 (the "License");
636 * you may not use this file except in compliance with the License. 637 * You may obtain a copy of the License at 638 * 639 * http://www.apache.org/licenses/LICENSE2.0 640 * 641 * Unless required by applicable law or agreed to in writing, software 642 * distributed under the License is distributed on an "AS IS" BASIS, 643 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 644 * See the License for the specific language governing permissions and 645 * limitations under the License. 646 ******************************************************************************/ 647 648/** 649 * Element.matches() 650 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill 651 */ 652if (!Element.prototype.matches) { 653 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 654} 655 656// eslint-disable-next-line valid-jsdoc 657/** 658 * Element.closest() 659 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill 660 */ 661if (!Element.prototype.closest) { 662 Element.prototype.closest = function(s) { 663 "use strict"; 664 var el = this; 665 if (!document.documentElement.contains(el)) { 666 return null; 667 } 668 do { 669 if (el.matches(s)) { 670 return el; 671 } 672 el = el.parentElement || el.parentNode; 673 } while (el !== null && el.nodeType === 1); 674 return null; 675 }; 676} 677 678/******************************************************************************* 679 * Copyright 2018 Adobe 680 * 681 * Licensed under the Apache License, Version 2.0 (the "License"); 682 * you may not use this file except in compliance with the License. 683 * You may obtain a copy of the License at 684 * 685 * http://www.apache.org/licenses/LICENSE-2.0 686 * 687 * Unless required by applicable law or agreed to in writing, software 688 * distributed under the License is distributed on an "AS IS" BASIS, 689 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 690 * See the License for the specific language governing permissions and 691 * limitations under the License. 692 ******************************************************************************/ 693(function() { 694 "use strict"; 695 696 var dataLayerEnabled; 697 var dataLayer; 698 699 var NS = "cmp"; 700 var IS = "tabs"; 701 702 var keyCodes = { 703 END: 35, 704 HOME: 36, 705 ARROW_LEFT: 37, 706 ARROW_UP: 38, 707 ARROW_RIGHT: 39, 708 ARROW_DOWN: 40 709 }; 710 711 var selectors = { 712 self: "[data-" + NS + '-is="' + IS + '"]', 713 active: { 714 tab: "cmp-tabs__tab--active", 715 tabpanel: "cmp-tabs__tabpanel--active" 716 } 717 }; 718 719 /** 720 * Tabs Configuration 721 * 722 * @typedef {Object} TabsConfig Represents a Tabs configuration 723 * @property {HTMLElement} element The HTMLElement representing the Tabs 724 * @property {Object} options The Tabs options 725 */ 726 727 /** 728 * Tabs 729 * 730 * @class Tabs 731 * @classdesc An interactive Tabs component for navigating a list of tabs 732 * @param {TabsConfig} config The Tabs configuration 733 */ 734 function Tabs(config) { 735 var that = this; 736 737 if (config && config.element) { 738 init(config); 739 } 740 741 /** 742 * Initializes the Tabs 743 * 744 * @private 745 * @param {TabsConfig} config The Tabs configuration 746 */ 747 function init(config) { 748 that._config = config; 749 750 // prevents multiple initialization 751 config.element.removeAttribute("data-" + NS + "-is"); 752 753 cacheElements(config.element); 754 that._active = getActiveIndex(that._elements["tab"]); 755 756 if (that._elements.tabpanel) { 757 refreshActive(); 758 bindEvents(); 759 } 760 761 // Show the tab based on deep-link-id if it matches with any existing tab item id 762 var deepLinkItemIdx = CQ.CoreComponents.container.utils.getDeepLinkItemIdx(that, "tabpanel"); 763 if (deepLinkItemIdx) { 764 var deepLinkItem = that._elements["tab"][deepLinkItemIdx]; 765 if (deepLinkItem && that._elements["tab"][that._active].id !== deepLinkItem.id) { 766 navigateAndFocusTab(deepLinkItemIdx); 767 } 768 } 769 770 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 771 /* 772 * Editor message handling: 773 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
774 * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component 775 * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data 776 */ 777 CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 778 CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 779 if (message.data && message.data.type === "cmp-tabs" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 780 if (message.data.operation === "navigate") { 781 navigate(message.data.index); 782 } 783 } 784 }); 785 } 786 } 787 788 /** 789 * Returns the index of the active tab, if no tab is active returns 0 790 * 791 * @param {Array} tabs Tab elements 792 * @returns {Number} Index of the active tab, 0 if none is active 793 */ 794 function getActiveIndex(tabs) { 795 if (tabs) { 796 for (var i = 0; i < tabs.length; i++) { 797 if (tabs[i].classList.contains(selectors.active.tab)) { 798 return i; 799 } 800 } 801 } 802 return 0; 803 } 804 805 /** 806 * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API 807 * 808 * @private 809 * @param {HTMLElement} wrapper The Tabs wrapper element 810 */ 811 function cacheElements(wrapper) { 812 that._elements = {}; 813 that._elements.self = wrapper; 814 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 815 816 for (var i = 0; i < hooks.length; i++) { 817 var hook = hooks[i]; 818 if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own tab elements 819 var capitalized = IS; 820 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 821 var key = hook.dataset[NS + "Hook" + capitalized]; 822 if (that._elements[key]) { 823 if (!Array.isArray(that._elements[key])) { 824 var tmp = that._elements[key]; 825 that._elements[key] = [tmp]; 826 } 827 that._elements[key].push(hook); 828 } else { 829 that._elements[key] = hook; 830 } 831 } 832 } 833 } 834 835 /** 836 * Binds Tabs event handling 837 * 838 * @private 839 */ 840 function bindEvents() { 841 var tabs = that._elements["tab"]; 842 if (tabs) { 843 for (var i = 0; i < tabs.length; i++) { 844 (function(index) { 845 tabs[i].addEventListener("click", function(event) { 846 navigateAndFocusTab(index); 847 }); 848 tabs[i].addEventListener("keydown", function(event) { 849 onKeyDown(event); 850 }); 851 })(i); 852 } 853 } 854 } 855 856 /** 857 * Handles tab keydown events 858 * 859 * @private 860 * @param {Object} event The keydown event 861 */ 862 function onKeyDown(event) { 863 var index = that._active; 864 var lastIndex = that._elements["tab"].length - 1; 865 866 switch (event.keyCode) { 867 case keyCodes.ARROW_LEFT: 868 case keyCodes.ARROW_UP: 869 event.preventDefault(); 870 if (index > 0) { 871 navigateAndFocusTab(index - 1); 872 } 873 break; 874 case keyCodes.ARROW_RIGHT: 875 case keyCodes.ARROW_DOWN: 876 event.preventDefault(); 877 if (index < lastIndex) { 878 navigateAndFocusTab(index + 1); 879 } 880 break; 881 case keyCodes.HOME: 882 event.preventDefault(); 883 navigateAndFocusTab(0); 884 break; 885 case keyCodes.END: 886 event.preventDefault(); 887 navigateAndFocusTab(lastIndex); 888 break; 889 default: 890 return; 891 } 892 } 893 894 /** 895 * Refreshes the tab markup based on the current {@code Tabs#_active} index 896 * 897 * @private 898 */ 899 function refreshActive() { 900 var tabpanels = that._elements["tabpanel"]; 901 var tabs = that._elements["tab"]; 902 903 if (tabpanels) { 904 if (Array.isArray(tabpanels)) { 905 for (var i = 0; i < tabpanels.length; i++) { 906 if (i === parseInt(that._active)) { 907 tabpanels[i].classList.add(selectors.active.tabpanel); 908 tabpanels[i].removeAttribute("aria-hidden"); 909 tabs[i].classList.add(selectors.active.tab); 910 tabs[i].setAttribute("aria-selected", true); 911 tabs[i].setAttribute("tabindex", "0"); 912 } else { 913 tabpanels[i].classList.remove(selectors.active.tabpanel); 914 tabpanels[i].setAttribute("aria-hidden", true); 915 tabs[i].classList.remove(selectors.active.tab); 916 tabs[i].setAttribute("aria-selected", false); 917 tabs[i].setAttribute("tabindex", "-1"); 918 } 919 } 920 } else { 921 // only one tab 922 tabpanels.classList.add(selectors.active.tabpanel); 923 tabs.classList.add(selectors.active.tab); 924 } 925 } 926 } 927 928 /** 929 * Focuses the element and prevents scrolling the element into view 930 * 931 * @param {HTMLElement} element Element to focus 932 */ 933 function focusWithoutScroll(element) { 934 var x = window.scrollX || window.pageXOffset; 935 var y = window.scrollY || window.pageYOffset; 936 element.focus(); 937 window.scrollTo(x, y); 938 } 939 940 /** 941 * Navigates to the tab at the provided index 942 * 943 * @private 944 * @param {Number} index The index of the tab to navigate to 945 */ 946 function navigate(index) { 947 that._active = index; 948 refreshActive(); 949 } 950 951 /** 952 * Navigates to the item at the provided index and ensures the active tab gains focus 953 * 954 * @private 955 * @param {Number} index The index of the item to navigate to 956 */ 957 function navigateAndFocusTab(index) { 958 var exActive = that._active; 959 navigate(index); 960 focusWithoutScroll(that._elements["tab"][index]); 961 962 if (dataLayerEnabled) { 963 964 var activeItem = getDataLayerId(that._elements.tabpanel[index].dataset.cmpDataLayer); 965 var exActiveItem = getDataLayerId(that._elements.tabpanel[exActive].dataset.cmpDataLayer); 966 967 dataLayer.push({ 968 event: "cmp:show", 969 eventInfo: { 970 path: "component." + activeItem 971 } 972 }); 973 974 dataLayer.push({ 975 event: "cmp:hide", 976 eventInfo: { 977 path: "component." + exActiveItem 978 } 979 }); 980 981 var tabsId = that._elements.self.id; 982 var uploadPayload = { component: {} }; 983 uploadPayload.component[tabsId] = { shownItems: [activeItem] }; 984 985 var removePayload = { component: {} }; 986 removePayload.component[tabsId] = { shownItems: undefined }; 987 988 dataLayer.push(removePayload); 989 dataLayer.push(uploadPayload); 990 } 991 } 992 } 993 994 /**
995 * Reads options data from the Tabs wrapper element, defined via {@code data-cmp-*} data attributes 996 * 997 * @private 998 * @param {HTMLElement} element The Tabs element to read options data from 999 * @returns {Object} The options read from the component data attributes 1000 */ 1001 function readData(element) { 1002 var data = element.dataset; 1003 var options = []; 1004 var capitalized = IS; 1005 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1006 var reserved = ["is", "hook" + capitalized]; 1007 1008 for (var key in data) { 1009 if (data.hasOwnProperty(key)) { 1010 var value = data[key]; 1011 1012 if (key.indexOf(NS) === 0) { 1013 key = key.slice(NS.length); 1014 key = key.charAt(0).toLowerCase() + key.substring(1); 1015 1016 if (reserved.indexOf(key) === -1) { 1017 options[key] = value; 1018 } 1019 } 1020 } 1021 } 1022 1023 return options; 1024 } 1025 1026 /** 1027 * Parses the dataLayer string and returns the ID 1028 * 1029 * @private 1030 * @param {String} componentDataLayer the dataLayer string 1031 * @returns {String} dataLayerId or undefined 1032 */ 1033 function getDataLayerId(componentDataLayer) { 1034 return Object.keys(JSON.parse(componentDataLayer))[0]; 1035 } 1036 1037 /** 1038 * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary. 1039 * 1040 * @private 1041 */ 1042 function onDocumentReady() { 1043 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 1044 dataLayer = (dataLayerEnabled)? window.adobeDataLayer = window.adobeDataLayer || [] : undefined; 1045 1046 var elements = document.querySelectorAll(selectors.self); 1047 for (var i = 0; i < elements.length; i++) { 1048 new Tabs({ element: elements[i], options: readData(elements[i]) }); 1049 } 1050 1051 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 1052 var body = document.querySelector("body"); 1053 var observer = new MutationObserver(function(mutations) { 1054 mutations.forEach(function(mutation) { 1055 // needed for IE 1056 var nodesArray = [].slice.call(mutation.addedNodes); 1057 if (nodesArray.length > 0) { 1058 nodesArray.forEach(function(addedNode) { 1059 if (addedNode.querySelectorAll) { 1060 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 1061 elementsArray.forEach(function(element) { 1062 new Tabs({ element: element, options: readData(element) }); 1063 }); 1064 } 1065 }); 1066 } 1067 }); 1068 }); 1069 1070 observer.observe(body, { 1071 subtree: true, 1072 childList: true, 1073 characterData: true 1074 }); 1075 } 1076 1077 if (document.readyState !== "loading") { 1078 onDocumentReady(); 1079 } else { 1080 document.addEventListener("DOMContentLoaded", onDocumentReady); 1081 } 1082 1083}()); 1084 1085/******************************************************************************* 1086 * Copyright 2018 Adobe 1087 * 1088 * Licensed under the Apache License, Version 2.0 (the "License"); 1089 * you may not use this file except in compliance with the License. 1090 * You may obtain a copy of the License at 1091 * 1092 * http://www.apache.org/licenses/LICENSE-2.0 1093 * 1094 * Unless required by applicable law or agreed to in writing, software 1095 * distributed under the License is distributed on an "AS IS" BASIS, 1096 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1097 * See the License for the specific language governing permissions and 1098 * limitations under the License. 1099 ******************************************************************************/ 1100(function() { 1101 "use strict"; 1102 1103 var dataLayerEnabled; 1104 var dataLayer; 1105 1106 var NS = "cmp"; 1107 var IS = "carousel"; 1108 1109 var keyCodes = { 1110 SPACE: 32, 1111 END: 35, 1112 HOME: 36, 1113 ARROW_LEFT: 37, 1114 ARROW_UP: 38, 1115 ARROW_RIGHT: 39, 1116 ARROW_DOWN: 40 1117 }; 1118 1119 var selectors = { 1120 self: "[data-" + NS + '-is="' + IS + '"]' 1121 }; 1122 1123 var properties = { 1124 /** 1125 * Determines whether the Carousel will automatically transition between slides 1126 * 1127 * @memberof Carousel
1128 * @type {Boolean} 1129 * @default false 1130 */ 1131 "autoplay": { 1132 "default": false, 1133 "transform": function(value) { 1134 return !(value === null || typeof value === "undefined"); 1135 } 1136 }, 1137 /** 1138 * Duration (in milliseconds) before automatically transitioning to the next slide 1139 * 1140 * @memberof Carousel 1141 * @type {Number} 1142 * @default 5000 1143 */ 1144 "delay": { 1145 "default": 5000, 1146 "transform": function(value) { 1147 value = parseFloat(value); 1148 return !isNaN(value) ? value : null; 1149 } 1150 }, 1151 /** 1152 * Determines whether automatic pause on hovering the carousel is disabled 1153 * 1154 * @memberof Carousel 1155 * @type {Boolean} 1156 * @default false 1157 */ 1158 "autopauseDisabled": { 1159 "default": false, 1160 "transform": function(value) { 1161 return !(value === null || typeof value === "undefined"); 1162 } 1163 } 1164 }; 1165 1166 /** 1167 * Carousel Configuration 1168 * 1169 * @typedef {Object} CarouselConfig Represents a Carousel configuration 1170 * @property {HTMLElement} element The HTMLElement representing the Carousel 1171 * @property {Object} options The Carousel options 1172 */ 1173 1174 /** 1175 * Carousel 1176 * 1177 * @class Carousel 1178 * @classdesc An interactive Carousel component for navigating a list of generic items 1179 * @param {CarouselConfig} config The Carousel configuration 1180 */ 1181 function Carousel(config) { 1182 var that = this; 1183 1184 if (config && config.element) { 1185 init(config); 1186 } 1187 1188 /** 1189 * Initializes the Carousel 1190 * 1191 * @private 1192 * @param {CarouselConfig} config The Carousel configuration 1193 */ 1194 function init(config) { 1195 // prevents multiple initialization 1196 config.element.removeAttribute("data-" + NS + "-is"); 1197 1198 setupProperties(config.options); 1199 cacheElements(config.element); 1200 1201 that._active = 0; 1202 that._paused = false; 1203 1204 if (that._elements.item) { 1205 refreshActive(); 1206 bindEvents(); 1207 resetAutoplayInterval(); 1208 refreshPlayPauseActions(); 1209 } 1210 1211 // TODO: This section is only relevant in edit mode and should move to the editor clientLib 1212 if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) { 1213 /* 1214 * Editor message handling: 1215 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame 1216 * - check that the message data panel container type is correct and that the id (path) matches this specific Carousel component 1217 * - if so, route the "navigate" operation to enact a navigation of the Carousel based on index data 1218 */ 1219 window.CQ = window.CQ || {}; 1220 window.CQ.CoreComponents = window.CQ.CoreComponents || {}; 1221 CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window); 1222 CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) { 1223 if (message.data && message.data.type === "cmp-carousel" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) { 1224 if (message.data.operation === "navigate") { 1225 navigate(message.data.index); 1226 } 1227 } 1228 }); 1229 } 1230 } 1231 1232 /** 1233 * Caches the Carousel elements as defined via the {@code data-carousel-hook="ELEMENT_NAME"} markup API 1234 * 1235 * @private 1236 * @param {HTMLElement} wrapper The Carousel wrapper element 1237 */ 1238 function cacheElements(wrapper) { 1239 that._elements = {}; 1240 that._elements.self = wrapper; 1241 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 1242 1243 for (var i = 0; i < hooks.length; i++) { 1244 var hook = hooks[i]; 1245 var capitalized = IS; 1246 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1247 var key = hook.dataset[NS + "Hook" + capitalized]; 1248 if (that._elements[key]) { 1249 if (!Array.isArray(that._elements[key])) { 1250 var tmp = that._elements[key]; 1251 that._elements[key] = [tmp]; 1252 } 1253 that._elements[key].push(hook); 1254 } else { 1255 that._elements[key] = hook; 1256 } 1257 } 1258 } 1259 1260 /** 1261 * Sets up properties for the Carousel based on the passed options. 1262 * 1263 * @private 1264 * @param {Object} options The Carousel options 1265 */ 1266 function setupProperties(options) { 1267 that._properties = {}; 1268 1269 for (var key in properties) { 1270 if (properties.hasOwnProperty(key)) { 1271 var property = properties[key]; 1272 var value = null; 1273 1274 if (options && options[key] != null) { 1275 value = options[key]; 1276 1277 // transform the provided option 1278 if (property && typeof property.transform === "function") { 1279 value = property.transform(value); 1280 } 1281 } 1282 1283 if (value === null) { 1284 // value still null, take the property default 1285 value = properties[key]["default"]; 1286 } 1287 1288 that._properties[key] = value; 1289 } 1290 } 1291 } 1292 1293 /** 1294 * Binds Carousel event handling 1295 * 1296 * @private 1297 */ 1298 function bindEvents() { 1299 if (that._elements["previous"]) { 1300 that._elements["previous"].addEventListener("click", function() { 1301 var index = getPreviousIndex(); 1302 navigate(index); 1303 if (dataLayerEnabled) { 1304 dataLayer.push({ 1305 event: "cmp:show", 1306 eventInfo: { 1307 path: "component." + getDataLayerId(that._elements.item[index].dataset.cmpDataLayer) 1308 } 1309 }); 1310 } 1311 }); 1312 } 1313 1314 if (that._elements["next"]) { 1315 that._elements["next"].addEventListener("click", function() { 1316 var index = getNextIndex(); 1317 navigate(index); 1318 if (dataLayerEnabled) { 1319 dataLayer.push({ 1320 event: "cmp:show", 1321 eventInfo: { 1322 path: "component." + getDataLayerId(that._elements.item[index].dataset.cmpDataLayer) 1323 } 1324 }); 1325 } 1326 }); 1327 } 1328 1329 var indicators = that._elements["indicator"]; 1330 if (indicators) { 1331 for (var i = 0; i < indicators.length; i++) { 1332 (function(index) { 1333 indicators[i].addEventListener("click", function(event) { 1334 navigateAndFocusIndicator(index); 1335 }); 1336 })(i); 1337 } 1338 } 1339 1340 if (that._elements["pause"]) { 1341 if (that._properties.autoplay) { 1342 that._elements["pause"].addEventListener("click", onPauseClick); 1343 } 1344 } 1345 1346 if (that._elements["play"]) { 1347 if (that._properties.autoplay) { 1348 that._elements["play"].addEventListener("click", onPlayClick); 1349 } 1350 } 1351 1352 that._elements.self.addEventListener("keydown", onKeyDown); 1353 1354 if (!that._properties.autopauseDisabled) { 1355 that._elements.self.addEventListener("mouseenter", onMouseEnter); 1356 that._elements.self.addEventListener("mouseleave", onMouseLeave); 1357 } 1358 } 1359 1360 /**
1361 * Handles carousel keydown events 1362 * 1363 * @private 1364 * @param {Object} event The keydown event 1365 */ 1366 function onKeyDown(event) { 1367 var index = that._active; 1368 var lastIndex = that._elements["indicator"].length - 1; 1369 1370 switch (event.keyCode) { 1371 case keyCodes.ARROW_LEFT: 1372 case keyCodes.ARROW_UP: 1373 event.preventDefault(); 1374 if (index > 0) { 1375 navigateAndFocusIndicator(index - 1); 1376 } 1377 break; 1378 case keyCodes.ARROW_RIGHT: 1379 case keyCodes.ARROW_DOWN: 1380 event.preventDefault(); 1381 if (index < lastIndex) { 1382 navigateAndFocusIndicator(index + 1); 1383 } 1384 break; 1385 case keyCodes.HOME: 1386 event.preventDefault(); 1387 navigateAndFocusIndicator(0); 1388 break; 1389 case keyCodes.END: 1390 event.preventDefault(); 1391 navigateAndFocusIndicator(lastIndex); 1392 break; 1393 case keyCodes.SPACE: 1394 if (that._properties.autoplay && (event.target !== that._elements["previous"] && event.target !== that._elements["next"])) { 1395 event.preventDefault(); 1396 if (!that._paused) { 1397 pause(); 1398 } else { 1399 play(); 1400 } 1401 } 1402 if (event.target === that._elements["pause"]) { 1403 that._elements["play"].focus(); 1404 } 1405 if (event.target === that._elements["play"]) { 1406 that._elements["pause"].focus(); 1407 } 1408 break; 1409 default: 1410 return; 1411 } 1412 } 1413 1414 /** 1415 * Handles carousel mouseenter events 1416 * 1417 * @private 1418 * @param {Object} event The mouseenter event 1419 */ 1420 function onMouseEnter(event) { 1421 clearAutoplayInterval(); 1422 } 1423 1424 /** 1425 * Handles carousel mouseleave events 1426 * 1427 * @private 1428 * @param {Object} event The mouseleave event 1429 */ 1430 function onMouseLeave(event) { 1431 resetAutoplayInterval(); 1432 } 1433 1434 /** 1435 * Handles pause element click events 1436 * 1437 * @private 1438 * @param {Object} event The click event 1439 */ 1440 function onPauseClick(event) { 1441 pause(); 1442 that._elements["play"].focus(); 1443 } 1444 1445 /** 1446 * Handles play element click events 1447 * 1448 * @private 1449 * @param {Object} event The click event 1450 */ 1451 function onPlayClick() { 1452 play(); 1453 that._elements["pause"].focus(); 1454 } 1455 1456 /** 1457 * Pauses the playing of the Carousel. Sets {@code Carousel#_paused} marker. 1458 * Only relevant when autoplay is enabled 1459 * 1460 * @private 1461 */ 1462 function pause() { 1463 that._paused = true; 1464 clearAutoplayInterval(); 1465 refreshPlayPauseActions(); 1466 } 1467 1468 /** 1469 * Enables the playing of the Carousel. Sets {@code Carousel#_paused} marker. 1470 * Only relevant when autoplay is enabled 1471 * 1472 * @private 1473 */ 1474 function play() { 1475 that._paused = false; 1476 1477 // If the Carousel is hovered, don't begin auto transitioning until the next mouse leave event 1478 var hovered = false; 1479 if (that._elements.self.parentElement) { 1480 hovered = that._elements.self.parentElement.querySelector(":hover") === that._elements.self; 1481 } 1482 if (that._properties.autopauseDisabled || !hovered) { 1483 resetAutoplayInterval(); 1484 } 1485 1486 refreshPlayPauseActions(); 1487 } 1488 1489 /** 1490 * Refreshes the play/pause action markup based on the {@code Carousel#_paused} state 1491 * 1492 * @private 1493 */ 1494 function refreshPlayPauseActions() {
1495 setActionDisabled(that._elements["pause"], that._paused); 1496 setActionDisabled(that._elements["play"], !that._paused); 1497 } 1498 1499 /** 1500 * Refreshes the item markup based on the current {@code Carousel#_active} index 1501 * 1502 * @private 1503 */ 1504 function refreshActive() { 1505 var items = that._elements["item"]; 1506 var indicators = that._elements["indicator"]; 1507 1508 if (items) { 1509 if (Array.isArray(items)) { 1510 for (var i = 0; i < items.length; i++) { 1511 if (i === parseInt(that._active)) { 1512 items[i].classList.add("cmp-carousel__item--active"); 1513 items[i].removeAttribute("aria-hidden"); 1514 indicators[i].classList.add("cmp-carousel__indicator--active"); 1515 indicators[i].setAttribute("aria-selected", true); 1516 indicators[i].setAttribute("tabindex", "0"); 1517 } else { 1518 items[i].classList.remove("cmp-carousel__item--active"); 1519 items[i].setAttribute("aria-hidden", true); 1520 indicators[i].classList.remove("cmp-carousel__indicator--active"); 1521 indicators[i].setAttribute("aria-selected", false); 1522 indicators[i].setAttribute("tabindex", "-1"); 1523 } 1524 } 1525 } else { 1526 // only one item 1527 items.classList.add("cmp-carousel__item--active"); 1528 indicators.classList.add("cmp-carousel__indicator--active"); 1529 } 1530 } 1531 } 1532 1533 /** 1534 * Focuses the element and prevents scrolling the element into view 1535 * 1536 * @param {HTMLElement} element Element to focus 1537 */ 1538 function focusWithoutScroll(element) { 1539 var x = window.scrollX || window.pageXOffset; 1540 var y = window.scrollY || window.pageYOffset; 1541 element.focus(); 1542 window.scrollTo(x, y); 1543 } 1544 1545 /** 1546 * Retrieves the next active index, with looping 1547 * 1548 * @private 1549 * @returns {Number} Index of the next carousel item 1550 */ 1551 function getNextIndex() { 1552 return that._active === (that._elements["item"].length - 1) ? 0 : that._active + 1; 1553 } 1554 1555 /** 1556 * Retrieves the previous active index, with looping 1557 * 1558 * @private 1559 * @returns {Number} Index of the previous carousel item 1560 */ 1561 function getPreviousIndex() { 1562 return that._active === 0 ? (that._elements["item"].length - 1) : that._active - 1; 1563 } 1564 1565 /** 1566 * Navigates to the item at the provided index 1567 * 1568 * @private 1569 * @param {Number} index The index of the item to navigate to 1570 */ 1571 function navigate(index) { 1572 if (index < 0 || index > (that._elements["item"].length - 1)) { 1573 return; 1574 } 1575 1576 that._active = index; 1577 refreshActive(); 1578 1579 if (dataLayerEnabled) { 1580 var carouselId = that._elements.self.id; 1581 var activeItem = getDataLayerId(that._elements.item[index].dataset.cmpDataLayer); 1582 var updatePayload = { component: {} }; 1583 updatePayload.component[carouselId] = { shownItems: [activeItem] }; 1584 1585 var removePayload = { component: {} }; 1586 removePayload.component[carouselId] = { shownItems: undefined }; 1587 1588 dataLayer.push(removePayload); 1589 dataLayer.push(updatePayload); 1590 } 1591 1592 // reset the autoplay transition interval following navigation, if not already hovering the carousel 1593 if (that._elements.self.parentElement) { 1594 if (that._elements.self.parentElement.querySelector(":hover") !== that._elements.self) { 1595 resetAutoplayInterval(); 1596 } 1597 } 1598 } 1599 1600 /** 1601 * Navigates to the item at the provided index and ensures the active indicator gains focus 1602 * 1603 * @private 1604 * @param {Number} index The index of the item to navigate to 1605 */ 1606 function navigateAndFocusIndicator(index) { 1607 navigate(index); 1608 focusWithoutScroll(that._elements["indicator"][index]); 1609 1610 if (dataLayerEnabled) { 1611 dataLayer.push({ 1612 event: "cmp:show", 1613 eventInfo: { 1614 path: "component." + getDataLayerId(that._elements.item[index].dataset.cmpDataLayer) 1615 } 1616 }); 1617 } 1618 } 1619 1620 /** 1621 * Starts/resets automatic slide transition interval 1622 * 1623 * @private 1624 */ 1625 function resetAutoplayInterval() { 1626 if (that._paused || !that._properties.autoplay) { 1627 return; 1628 } 1629 clearAutoplayInterval(); 1630 that._autoplayIntervalId = window.setInterval(function() { 1631 if (document.visibilityState && document.hidden) { 1632 return; 1633 } 1634 var indicators = that._elements["indicators"]; 1635 if (indicators !== document.activeElement && indicators.contains(document.activeElement)) { 1636 // if an indicator has focus, ensure we switch focus following navigation 1637 navigateAndFocusIndicator(getNextIndex()); 1638 } else { 1639 navigate(getNextIndex()); 1640 } 1641 }, that._properties.delay); 1642 } 1643 1644 /** 1645 * Clears/pauses automatic slide transition interval 1646 * 1647 * @private 1648 */ 1649 function clearAutoplayInterval() { 1650 window.clearInterval(that._autoplayIntervalId); 1651 that._autoplayIntervalId = null; 1652 } 1653 1654 /** 1655 * Sets the disabled state for an action and toggles the appropriate CSS classes 1656 * 1657 * @private 1658 * @param {HTMLElement} action Action to disable 1659 * @param {Boolean} [disable] {@code true} to disable, {@code false} to enable 1660 */ 1661 function setActionDisabled(action, disable) { 1662 if (!action) { 1663 return; 1664 } 1665 if (disable !== false) { 1666 action.disabled = true; 1667 action.classList.add("cmp-carousel__action--disabled"); 1668 } else { 1669 action.disabled = false;
1670 action.classList.remove("cmp-carousel__action--disabled"); 1671 } 1672 } 1673 } 1674 1675 /** 1676 * Reads options data from the Carousel wrapper element, defined via {@code data-cmp-*} data attributes 1677 * 1678 * @private 1679 * @param {HTMLElement} element The Carousel element to read options data from 1680 * @returns {Object} The options read from the component data attributes 1681 */ 1682 function readData(element) { 1683 var data = element.dataset; 1684 var options = []; 1685 var capitalized = IS; 1686 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1687 var reserved = ["is", "hook" + capitalized]; 1688 1689 for (var key in data) { 1690 if (data.hasOwnProperty(key)) { 1691 var value = data[key]; 1692 1693 if (key.indexOf(NS) === 0) { 1694 key = key.slice(NS.length); 1695 key = key.charAt(0).toLowerCase() + key.substring(1); 1696 1697 if (reserved.indexOf(key) === -1) { 1698 options[key] = value; 1699 } 1700 } 1701 } 1702 } 1703 1704 return options; 1705 } 1706 1707 /** 1708 * Parses the dataLayer string and returns the ID 1709 * 1710 * @private 1711 * @param {String} componentDataLayer the dataLayer string 1712 * @returns {String} dataLayerId or undefined 1713 */ 1714 function getDataLayerId(componentDataLayer) { 1715 return Object.keys(JSON.parse(componentDataLayer))[0]; 1716 } 1717 1718 /** 1719 * Document ready handler and DOM mutation observers. Initializes Carousel components as necessary. 1720 * 1721 * @private 1722 */ 1723 function onDocumentReady() { 1724 dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled"); 1725 dataLayer = (dataLayerEnabled)? window.adobeDataLayer = window.adobeDataLayer || [] : undefined; 1726 1727 var elements = document.querySelectorAll(selectors.self); 1728 for (var i = 0; i < elements.length; i++) { 1729 new Carousel({ element: elements[i], options: readData(elements[i]) }); 1730 } 1731 1732 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 1733 var body = document.querySelector("body"); 1734 var observer = new MutationObserver(function(mutations) { 1735 mutations.forEach(function(mutation) { 1736 // needed for IE 1737 var nodesArray = [].slice.call(mutation.addedNodes); 1738 if (nodesArray.length > 0) { 1739 nodesArray.forEach(function(addedNode) { 1740 if (addedNode.querySelectorAll) { 1741 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 1742 elementsArray.forEach(function(element) { 1743 new Carousel({ element: element, options: readData(element) }); 1744 }); 1745 } 1746 }); 1747 } 1748 }); 1749 }); 1750 1751 observer.observe(body, { 1752 subtree: true, 1753 childList: true, 1754 characterData: true 1755 }); 1756 } 1757 1758 if (document.readyState !== "loading") { 1759 onDocumentReady(); 1760 } else { 1761 document.addEventListener("DOMContentLoaded", onDocumentReady); 1762 } 1763 1764}()); 1765 1766/******************************************************************************* 1767 * Copyright 2017 Adobe 1768 * 1769 * Licensed under the Apache License, Version 2.0 (the "License"); 1770 * you may not use this file except in compliance with the License. 1771 * You may obtain a copy of the License at 1772 * 1773 * http://www.apache.org/licenses/LICENSE-2.0 1774 * 1775 * Unless required by applicable law or agreed to in writing, software 1776 * distributed under the License is distributed on an "AS IS" BASIS, 1777 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1778 * See the License for the specific language governing permissions and 1779 * limitations under the License. 1780 ******************************************************************************/ 1781if (window.Element && !Element.prototype.closest) { 1782 // eslint valid-jsdoc: "off" 1783 Element.prototype.closest = 1784 function(s) { 1785 "use strict"; 1786 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 1787 var el = this; 1788 var i; 1789 do { 1790 i = matches.length; 1791 while (--i >= 0 && matches.item(i) !== el) { 1792 // continue 1793 } 1794 } while ((i < 0) && (el = el.parentElement)); 1795 return el; 1796 }; 1797} 1798 1799if (window.Element && !Element.prototype.matches) { 1800 Element.prototype.matches = 1801 Element.prototype.matchesSelector || 1802 Element.prototype.mozMatchesSelector || 1803 Element.prototype.msMatchesSelector || 1804 Element.prototype.oMatchesSelector || 1805 Element.prototype.webkitMatchesSelector || 1806 function(s) { 1807 "use strict"; 1808 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 1809 var i = matches.length; 1810 while (--i >= 0 && matches.item(i) !== this) { 1811 // continue 1812 } 1813 return i > -1; 1814 }; 1815} 1816 1817if (!Object.assign) { 1818 Object.assign = function(target, varArgs) { // .length of function is 2 1819 "use strict"; 1820 if (target === null) { 1821 throw new TypeError("Cannot convert undefined or null to object"); 1822 } 1823 1824 var to = Object(target); 1825 1826 for (var index = 1; index < arguments.length; index++) { 1827 var nextSource = arguments[index]; 1828 1829 if (nextSource !== null) { 1830 for (var nextKey in nextSource) { 1831 if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 1832 to[nextKey] = nextSource[nextKey]; 1833 } 1834 } 1835 } 1836 } 1837 return to; 1838 }; 1839} 1840 1841(function(arr) { 1842 "use strict"; 1843 arr.forEach(function(item) { 1844 if (item.hasOwnProperty("remove")) { 1845 return; 1846 } 1847 Object.defineProperty(item, "remove", { 1848 configurable: true, 1849 enumerable: true, 1850 writable: true, 1851 value: function remove() { 1852 this.parentNode.removeChild(this); 1853 } 1854 }); 1855 }); 1856})([Element.prototype, CharacterData.prototype, DocumentType.prototype]); 1857 1858/******************************************************************************* 1859 * Copyright 2016 Adobe 1860 * 1861 * Licensed under the Apache License, Version 2.0 (the "License");
1862 * you may not use this file except in compliance with the License. 1863 * You may obtain a copy of the License at 1864 * 1865 * http://www.apache.org/licenses/LICENSE-2.0 1866 * 1867 * Unless required by applicable law or agreed to in writing, software 1868 * distributed under the License is distributed on an "AS IS" BASIS, 1869 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1870 * See the License for the specific language governing permissions and 1871 * limitations under the License. 1872 ******************************************************************************/ 1873(function() { 1874 "use strict"; 1875 1876 var NS = "cmp"; 1877 var IS = "image"; 1878 1879 var EMPTY_PIXEL = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; 1880 var LAZY_THRESHOLD_DEFAULT = 0; 1881 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 1882 1883 var selectors = { 1884 self: "[data-" + NS + '-is="' + IS + '"]', 1885 image: '[data-cmp-hook-image="image"]', 1886 map: '[data-cmp-hook-image="map"]', 1887 area: '[data-cmp-hook-image="area"]' 1888 }; 1889 1890 var lazyLoader = { 1891 "cssClass": "cmp-image__image--is-loading", 1892 "style": { 1893 "height": 0, 1894 "padding-bottom": "" // will be replaced with % ratio 1895 } 1896 }; 1897 1898 var properties = { 1899 /** 1900 * An array of alternative image widths (in pixels). 1901 * Used to replace a {.width} variable in the src property with an optimal width if a URI template is provided. 1902 * 1903 * @memberof Image 1904 * @type {Number[]} 1905 * @default [] 1906 */ 1907 "widths": { 1908 "default": [], 1909 "transform": function(value) { 1910 var widths = []; 1911 value.split(",").forEach(function(item) { 1912 item = parseFloat(item); 1913 if (!isNaN(item)) { 1914 widths.push(item); 1915 } 1916 }); 1917 return widths; 1918 } 1919 }, 1920 /** 1921 * Indicates whether the image should be rendered lazily. 1922 * 1923 * @memberof Image 1924 * @type {Boolean} 1925 * @default false 1926 */ 1927 "lazy": { 1928 "default": false, 1929 "transform": function(value) { 1930 return !(value === null || typeof value === "undefined"); 1931 } 1932 }, 1933 /** 1934 * Indicates image is DynamicMedia image. 1935 * 1936 * @memberof Image 1937 * @type {Boolean} 1938 * @default false 1939 */ 1940 "dmimage": { 1941 "default": false, 1942 "transform": function(value) { 1943 return !(value === null || typeof value === "undefined"); 1944 } 1945 }, 1946 /** 1947 * The lazy threshold. 1948 * This is the number of pixels, in advance of becoming visible, when an lazy-loading image should begin 1949 * to load. 1950 * 1951 * @memberof Image 1952 * @type {Number} 1953 * @default 0 1954 */ 1955 "lazythreshold": { 1956 "default": 0, 1957 "transform": function(value) { 1958 const val = parseInt(value); 1959 if (isNaN(val)) { 1960 return LAZY_THRESHOLD_DEFAULT; 1961 } 1962 return val; 1963 } 1964 }, 1965 /** 1966 * The image source. 1967 * 1968 * Can be a simple image source, or a URI template representation that 1969 * can be variable expanded - useful for building an image configuration with an alternative width. 1970 * e.g. '/path/image.coreimg{.width}.jpeg/1506620954214.jpeg' 1971 * 1972 * @memberof Image 1973 * @type {String} 1974 */ 1975 "src": { 1976 "transform": function(value) { 1977 return decodeURIComponent(value); 1978 } 1979 } 1980 }; 1981 1982 var devicePixelRatio = window.devicePixelRatio || 1; 1983 1984 function readData(element) { 1985 var data = element.dataset; 1986 var options = []; 1987 var capitalized = IS; 1988 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 1989 var reserved = ["is", "hook" + capitalized]; 1990 1991 for (var key in data) { 1992 if (data.hasOwnProperty(key)) { 1993 var value = data[key]; 1994 1995 if (key.indexOf(NS) === 0) { 1996 key = key.slice(NS.length); 1997 key = key.charAt(0).toLowerCase() + key.substring(1); 1998 1999 if (reserved.indexOf(key) === -1) { 2000 options[key] = value; 2001 } 2002 } 2003 } 2004 } 2005 2006 return options; 2007 } 2008 2009 function Image(config) { 2010 var that = this; 2011 2012 var smartCrops = {}; 2013 2014 function init(config) { 2015 // prevents multiple initialization 2016 config.element.removeAttribute("data-" + NS + "-is"); 2017 2018 setupProperties(config.options); 2019 cacheElements(config.element); 2020 //check image is DM asset; if true try to make req=set 2021 if (config.options.src && config.options.hasOwnProperty("dmimage") && (config.options["smartcroprendition"] === "SmartCrop:Auto")) { 2022 var request = new XMLHttpRequest(); 2023 var url = decodeURIComponent(config.options.src).split(SRC_URI_TEMPLATE_WIDTH_VAR)[0] + "?req=set,json"; 2024 2025 2026 request.open("GET", url, false); 2027 request.onload = function() { 2028 if (request.status >= 200 && request.status < 400) { 2029 // success status 2030 var responseText = request.responseText; 2031 var rePayload = new RegExp(/^(?:\/\*jsonp\*\/)?\s*([^()]+)\(([\s\S]+),\s*"[0-9]*"\);?$/gmi); 2032 var rePayloadJSON = new RegExp(/^{[\s\S]*}$/gmi); 2033 var resPayload = rePayload.exec(responseText); 2034 var smartcropList = ""; 2035 var payload; 2036 if (resPayload) { 2037 var payloadStr = resPayload[2]; 2038 if (rePayloadJSON.test(payloadStr)) { 2039 payload = JSON.parse(payloadStr); 2040 } 2041 2042 } 2043 //check "relation" - only in case of smartcrop preset 2044 if (payload && payload.set.relation && payload.set.relation.length > 0) { 2045 for(var i = 0; i < payload.set.relation.length ; i++) { 2046 smartcropList += payload.set.relation[i].n +"\n"; 2047 smartCrops[parseInt(payload.set.relation[i].userdata.SmartCropWidth)] = ":" + payload.set.relation[i].userdata.SmartCropDef; 2048 } 2049 } 2050 } else { 2051 // error status 2052 } 2053 }; 2054 request.send(); 2055 } 2056 2057 if (!that._elements.noscript) { 2058 return; 2059 } 2060 2061 that._elements.container = that._elements.link ? that._elements.link : that._elements.self; 2062 2063 unwrapNoScript(); 2064 2065 if (that._properties.lazy) { 2066 addLazyLoader(); 2067 } 2068 2069 if (that._elements.map) { 2070 that._elements.image.addEventListener("load", onLoad); 2071 } 2072 2073 window.addEventListener("resize", onWindowResize); 2074 ["focus", "click", "load", "transitionend", "animationend", "scroll"].forEach(function(name) { 2075 document.addEventListener(name, that.update); 2076 }); 2077 2078 that._elements.image.addEventListener("cmp-image-redraw", that.update);
2079 that.update(); 2080 } 2081 2082 function loadImage() { 2083 var hasWidths = (that._properties.widths && that._properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 2084 var replacement; 2085 if (Object.keys(smartCrops).length > 0) { 2086 var optimalWidth = getOptimalWidth(Object.keys(smartCrops)); 2087 replacement = smartCrops[optimalWidth]; 2088 } else { 2089 replacement = hasWidths ? (that._properties.dmimage ? "" : ".") + getOptimalWidth(that._properties.widths) : ""; 2090 } 2091 var url = that._properties.src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, replacement); 2092 2093 if (that._elements.image.getAttribute("src") !== url) { 2094 that._elements.image.setAttribute("src", url); 2095 if (!hasWidths) { 2096 window.removeEventListener("scroll", that.update); 2097 } 2098 } 2099 2100 if (that._lazyLoaderShowing) { 2101 that._elements.image.addEventListener("load", removeLazyLoader); 2102 } 2103 } 2104 2105 function getOptimalWidth(widths) { 2106 var container = that._elements.self; 2107 var containerWidth = container.clientWidth; 2108 while (containerWidth === 0 && container.parentNode) { 2109 container = container.parentNode; 2110 containerWidth = container.clientWidth; 2111 } 2112 var optimalWidth = containerWidth * devicePixelRatio; 2113 var len = widths.length; 2114 var key = 0; 2115 2116 while ((key < len - 1) && (widths[key] < optimalWidth)) { 2117 key++; 2118 } 2119 2120 return widths[key].toString(); 2121 } 2122 2123 function addLazyLoader() { 2124 var width = that._elements.image.getAttribute("width"); 2125 var height = that._elements.image.getAttribute("height"); 2126 2127 if (width && height) { 2128 var ratio = (height / width) * 100; 2129 var styles = lazyLoader.style; 2130 2131 styles["padding-bottom"] = ratio + "%"; 2132 2133 for (var s in styles) { 2134 if (styles.hasOwnProperty(s)) { 2135 that._elements.image.style[s] = styles[s]; 2136 } 2137 } 2138 } 2139 that._elements.image.setAttribute("src", EMPTY_PIXEL); 2140 that._elements.image.classList.add(lazyLoader.cssClass); 2141 that._lazyLoaderShowing = true; 2142 } 2143 2144 function unwrapNoScript() { 2145 var markup = decodeNoscript(that._elements.noscript.textContent.trim()); 2146 var parser = new DOMParser(); 2147 2148 // temporary document avoids requesting the image before removing its src 2149 var temporaryDocument = parser.parseFromString(markup, "text/html"); 2150 var imageElement = temporaryDocument.querySelector(selectors.image); 2151 imageElement.removeAttribute("src"); 2152 that._elements.container.insertBefore(imageElement, that._elements.noscript); 2153 2154 var mapElement = temporaryDocument.querySelector(selectors.map); 2155 if (mapElement) { 2156 that._elements.container.insertBefore(mapElement, that._elements.noscript); 2157 } 2158 2159 that._elements.noscript.parentNode.removeChild(that._elements.noscript); 2160 if (that._elements.container.matches(selectors.image)) { 2161 that._elements.image = that._elements.container; 2162 } else { 2163 that._elements.image = that._elements.container.querySelector(selectors.image); 2164 } 2165 2166 that._elements.map = that._elements.container.querySelector(selectors.map); 2167 that._elements.areas = that._elements.container.querySelectorAll(selectors.area); 2168 } 2169 2170 function removeLazyLoader() { 2171 that._elements.image.classList.remove(lazyLoader.cssClass); 2172 for (var property in lazyLoader.style) { 2173 if (lazyLoader.style.hasOwnProperty(property)) { 2174 that._elements.image.style[property] = ""; 2175 } 2176 } 2177 that._elements.image.removeEventListener("load", removeLazyLoader); 2178 that._lazyLoaderShowing = false;
2179 } 2180 2181 function isLazyVisible() { 2182 if (that._elements.container.offsetParent === null) { 2183 return false; 2184 } 2185 2186 var wt = window.pageYOffset; 2187 var wb = wt + document.documentElement.clientHeight; 2188 var et = that._elements.container.getBoundingClientRect().top + wt; 2189 var eb = et + that._elements.container.clientHeight; 2190 2191 return eb >= wt - that._properties.lazythreshold && et <= wb + that._properties.lazythreshold; 2192 } 2193 2194 function resizeAreas() { 2195 if (that._elements.areas && that._elements.areas.length > 0) { 2196 for (var i = 0; i < that._elements.areas.length; i++) { 2197 var width = that._elements.image.width; 2198 var height = that._elements.image.height; 2199 2200 if (width && height) { 2201 var relcoords = that._elements.areas[i].dataset.cmpRelcoords; 2202 if (relcoords) { 2203 var relativeCoordinates = relcoords.split(","); 2204 var coordinates = new Array(relativeCoordinates.length); 2205 2206 for (var j = 0; j < coordinates.length; j++) { 2207 if (j % 2 === 0) { 2208 coordinates[j] = parseInt(relativeCoordinates[j] * width); 2209 } else { 2210 coordinates[j] = parseInt(relativeCoordinates[j] * height); 2211 } 2212 } 2213 2214 that._elements.areas[i].coords = coordinates; 2215 } 2216 } 2217 } 2218 } 2219 } 2220 2221 function cacheElements(wrapper) { 2222 that._elements = {}; 2223 that._elements.self = wrapper; 2224 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 2225 2226 for (var i = 0; i < hooks.length; i++) { 2227 var hook = hooks[i]; 2228 var capitalized = IS; 2229 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2230 var key = hook.dataset[NS + "Hook" + capitalized]; 2231 that._elements[key] = hook; 2232 } 2233 } 2234 2235 function setupProperties(options) { 2236 that._properties = {}; 2237 2238 for (var key in properties) { 2239 if (properties.hasOwnProperty(key)) { 2240 var property = properties[key]; 2241 if (options && options[key] != null) { 2242 if (property && typeof property.transform === "function") { 2243 that._properties[key] = property.transform(options[key]); 2244 } else { 2245 that._properties[key] = options[key]; 2246 } 2247 } else { 2248 that._properties[key] = properties[key]["default"]; 2249 } 2250 } 2251 } 2252 } 2253 2254 function onWindowResize() { 2255 that.update(); 2256 resizeAreas(); 2257 } 2258 2259 function onLoad() { 2260 resizeAreas(); 2261 } 2262 2263 that.update = function() { 2264 if (that._properties.lazy) { 2265 if (isLazyVisible()) { 2266 loadImage(); 2267 } 2268 } else { 2269 loadImage(); 2270 } 2271 }; 2272 2273 if (config && config.element) { 2274 init(config); 2275 } 2276 } 2277 2278 function onDocumentReady() { 2279 var elements = document.querySelectorAll(selectors.self); 2280 for (var i = 0; i < elements.length; i++) { 2281 new Image({ element: elements[i], options: readData(elements[i]) }); 2282 } 2283 2284 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 2285 var body = document.querySelector("body"); 2286 var observer = new MutationObserver(function(mutations) { 2287 mutations.forEach(function(mutation) { 2288 // needed for IE 2289 var nodesArray = [].slice.call(mutation.addedNodes); 2290 if (nodesArray.length > 0) { 2291 nodesArray.forEach(function(addedNode) { 2292 if (addedNode.querySelectorAll) { 2293 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 2294 elementsArray.forEach(function(element) { 2295 new Image({ element: element, options: readData(element) }); 2296 }); 2297 } 2298 }); 2299 } 2300 }); 2301 }); 2302 2303 observer.observe(body, { 2304 subtree: true, 2305 childList: true, 2306 characterData: true 2307 }); 2308 } 2309 2310 if (document.readyState !== "loading") { 2311 onDocumentReady(); 2312 } else { 2313 document.addEventListener("DOMContentLoaded", onDocumentReady); 2314 } 2315 2316 /* 2317 on drag & drop of the component into a parsys, noscript's content will be escaped multiple times by the editor which creates 2318 the DOM for editing; the HTML parser cannot be used here due to the multiple escaping 2319 */ 2320 function decodeNoscript(text) { 2321 text = text.replace(/&(amp;)*lt;/g, "<"); 2322 text = text.replace(/&(amp;)*gt;/g, ">"); 2323 return text; 2324 } 2325 2326})(); 2327 2328/******************************************************************************* 2329 * Copyright 2017 Adobe 2330 * 2331 * Licensed under the Apache License, Version 2.0 (the "License");
2332 * you may not use this file except in compliance with the License. 2333 * You may obtain a copy of the License at 2334 * 2335 * http://www.apache.org/licenses/LICENSE-2.0 2336 * 2337 * Unless required by applicable law or agreed to in writing, software 2338 * distributed under the License is distributed on an "AS IS" BASIS, 2339 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2340 * See the License for the specific language governing permissions and 2341 * limitations under the License. 2342 ******************************************************************************/ 2343(function() { 2344 "use strict"; 2345 2346 var NS = "cmp"; 2347 var IS = "search"; 2348 2349 var DELAY = 300; // time before fetching new results when the user is typing a search string 2350 var LOADING_DISPLAY_DELAY = 300; // minimum time during which the loading indicator is displayed 2351 var PARAM_RESULTS_OFFSET = "resultsOffset"; 2352 2353 var keyCodes = { 2354 TAB: 9, 2355 ENTER: 13, 2356 ESCAPE: 27, 2357 ARROW_UP: 38, 2358 ARROW_DOWN: 40 2359 }; 2360 2361 var selectors = { 2362 self: "[data-" + NS + '-is="' + IS + '"]', 2363 item: { 2364 self: "[data-" + NS + "-hook-" + IS + '="item"]', 2365 title: "[data-" + NS + "-hook-" + IS + '="itemTitle"]', 2366 focused: "." + NS + "-search__item--is-focused" 2367 } 2368 }; 2369 2370 var properties = { 2371 /** 2372 * The minimum required length of the search term before results are fetched. 2373 * 2374 * @memberof Search 2375 * @type {Number} 2376 * @default 3 2377 */ 2378 minLength: { 2379 "default": 3, 2380 transform: function(value) { 2381 value = parseFloat(value); 2382 return isNaN(value) ? null : value; 2383 } 2384 }, 2385 /** 2386 * The maximal number of results fetched by a search request. 2387 * 2388 * @memberof Search 2389 * @type {Number} 2390 * @default 10 2391 */ 2392 resultsSize: { 2393 "default": 10, 2394 transform: function(value) { 2395 value = parseFloat(value); 2396 return isNaN(value) ? null : value; 2397 } 2398 } 2399 }; 2400 2401 var idCount = 0; 2402 2403 function readData(element) { 2404 var data = element.dataset; 2405 var options = []; 2406 var capitalized = IS; 2407 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2408 var reserved = ["is", "hook" + capitalized]; 2409 2410 for (var key in data) { 2411 if (data.hasOwnProperty(key)) { 2412 var value = data[key]; 2413 2414 if (key.indexOf(NS) === 0) { 2415 key = key.slice(NS.length); 2416 key = key.charAt(0).toLowerCase() + key.substring(1); 2417 2418 if (reserved.indexOf(key) === -1) { 2419 options[key] = value; 2420 } 2421 } 2422 } 2423 } 2424 2425 return options; 2426 } 2427 2428 function toggleShow(element, show) { 2429 if (element) { 2430 if (show !== false) { 2431 element.style.display = "block"; 2432 element.setAttribute("aria-hidden", false); 2433 } else { 2434 element.style.display = "none"; 2435 element.setAttribute("aria-hidden", true); 2436 } 2437 } 2438 } 2439 2440 function serialize(form) { 2441 var query = []; 2442 if (form && form.elements) { 2443 for (var i = 0; i < form.elements.length; i++) { 2444 var node = form.elements[i]; 2445 if (!node.disabled && node.name) { 2446 var param = [node.name, encodeURIComponent(node.value)]; 2447 query.push(param.join("=")); 2448 } 2449 } 2450 } 2451 return query.join("&"); 2452 } 2453 2454 function mark(node, regex) { 2455 if (!node || !regex) { 2456 return; 2457 } 2458 2459 // text nodes 2460 if (node.nodeType === 3) { 2461 var nodeValue = node.nodeValue; 2462 var match = regex.exec(nodeValue); 2463 2464 if (nodeValue && match) { 2465 var element = document.createElement("mark"); 2466 element.className = NS + "-search__item-mark"; 2467 element.appendChild(document.createTextNode(match[0])); 2468 2469 var after = node.splitText(match.index); 2470 after.nodeValue = after.nodeValue.substring(match[0].length); 2471 node.parentNode.insertBefore(element, after); 2472 } 2473 } else if (node.hasChildNodes()) { 2474 for (var i = 0; i < node.childNodes.length; i++) { 2475 // recurse 2476 mark(node.childNodes[i], regex); 2477 } 2478 } 2479 } 2480 2481 function Search(config) { 2482 if (config.element) { 2483 // prevents multiple initialization 2484 config.element.removeAttribute("data-" + NS + "-is"); 2485 } 2486 2487 this._cacheElements(config.element); 2488 this._setupProperties(config.options); 2489 2490 this._action = this._elements.form.getAttribute("action"); 2491 this._resultsOffset = 0; 2492 this._hasMoreResults = true; 2493 2494 this._elements.input.addEventListener("input", this._onInput.bind(this)); 2495 this._elements.input.addEventListener("focus", this._onInput.bind(this)); 2496 this._elements.input.addEventListener("keydown", this._onKeydown.bind(this)); 2497 this._elements.clear.addEventListener("click", this._onClearClick.bind(this)); 2498 document.addEventListener("click", this._onDocumentClick.bind(this)); 2499 this._elements.results.addEventListener("scroll", this._onScroll.bind(this)); 2500 2501 this._makeAccessible(); 2502 } 2503 2504 Search.prototype._displayResults = function() { 2505 if (this._elements.input.value.length === 0) { 2506 toggleShow(this._elements.clear, false); 2507 this._cancelResults(); 2508 } else if (this._elements.input.value.length < this._properties.minLength) { 2509 toggleShow(this._elements.clear, true); 2510 } else { 2511 this._updateResults(); 2512 toggleShow(this._elements.clear, true); 2513 } 2514 }; 2515 2516 Search.prototype._onScroll = function(event) { 2517 // fetch new results when the results to be scrolled down are less than the visible results 2518 if (this._elements.results.scrollTop + 2 * this._elements.results.clientHeight >= this._elements.results.scrollHeight) { 2519 this._resultsOffset += this._properties.resultsSize; 2520 this._displayResults(); 2521 } 2522 }; 2523 2524 Search.prototype._onInput = function(event) { 2525 var self = this; 2526 self._cancelResults(); 2527 // start searching when the search term reaches the minimum length 2528 this._timeout = setTimeout(function() { 2529 self._displayResults(); 2530 }, DELAY); 2531 }; 2532 2533 Search.prototype._onKeydown = function(event) { 2534 var self = this; 2535 2536 switch (event.keyCode) { 2537 case keyCodes.TAB: 2538 if (self._resultsOpen()) { 2539 event.preventDefault(); 2540 } 2541 break;
2542 case keyCodes.ENTER: 2543 event.preventDefault(); 2544 if (self._resultsOpen()) { 2545 var focused = self._elements.results.querySelector(selectors.item.focused); 2546 if (focused) { 2547 focused.click(); 2548 } 2549 } 2550 break; 2551 case keyCodes.ESCAPE: 2552 self._cancelResults(); 2553 break; 2554 case keyCodes.ARROW_UP: 2555 if (self._resultsOpen()) { 2556 event.preventDefault(); 2557 self._stepResultFocus(true); 2558 } 2559 break; 2560 case keyCodes.ARROW_DOWN: 2561 if (self._resultsOpen()) { 2562 event.preventDefault(); 2563 self._stepResultFocus(); 2564 } else { 2565 // test the input and if necessary fetch and display the results 2566 self._onInput(); 2567 } 2568 break; 2569 default: 2570 return; 2571 } 2572 }; 2573 2574 Search.prototype._onClearClick = function(event) { 2575 event.preventDefault(); 2576 this._elements.input.value = ""; 2577 toggleShow(this._elements.clear, false); 2578 toggleShow(this._elements.results, false); 2579 }; 2580 2581 Search.prototype._onDocumentClick = function(event) { 2582 var inputContainsTarget = this._elements.input.contains(event.target); 2583 var resultsContainTarget = this._elements.results.contains(event.target); 2584 2585 if (!(inputContainsTarget || resultsContainTarget)) { 2586 toggleShow(this._elements.results, false); 2587 } 2588 }; 2589 2590 Search.prototype._resultsOpen = function() { 2591 return this._elements.results.style.display !== "none"; 2592 }; 2593 2594 Search.prototype._makeAccessible = function() { 2595 var id = NS + "-search-results-" + idCount; 2596 this._elements.input.setAttribute("aria-owns", id); 2597 this._elements.results.id = id; 2598 idCount++; 2599 }; 2600 2601 Search.prototype._generateItems = function(data, results) { 2602 var self = this; 2603 2604 data.forEach(function(item) { 2605 var el = document.createElement("span"); 2606 el.innerHTML = self._elements.itemTemplate.innerHTML; 2607 el.querySelectorAll(selectors.item.title)[0].appendChild(document.createTextNode(item.title)); 2608 el.querySelectorAll(selectors.item.self)[0].setAttribute("href", item.url); 2609 results.innerHTML += el.innerHTML; 2610 }); 2611 }; 2612 2613 Search.prototype._markResults = function() { 2614 var nodeList = this._elements.results.querySelectorAll(selectors.item.self); 2615 var escapedTerm = this._elements.input.value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 2616 var regex = new RegExp("(" + escapedTerm + ")", "gi"); 2617 2618 for (var i = this._resultsOffset - 1; i < nodeList.length; ++i) { 2619 var result = nodeList[i]; 2620 mark(result, regex); 2621 } 2622 }; 2623 2624 Search.prototype._stepResultFocus = function(reverse) { 2625 var results = this._elements.results.querySelectorAll(selectors.item.self); 2626 var focused = this._elements.results.querySelector(selectors.item.focused); 2627 var newFocused; 2628 var index = Array.prototype.indexOf.call(results, focused); 2629 var focusedCssClass = NS + "-search__item--is-focused"; 2630 2631 if (results.length > 0) { 2632 2633 if (!reverse) { 2634 // highlight the next result 2635 if (index < 0) { 2636 results[0].classList.add(focusedCssClass); 2637 } else if (index + 1 < results.length) { 2638 results[index].classList.remove(focusedCssClass); 2639 results[index + 1].classList.add(focusedCssClass); 2640 } 2641 2642 // if the last visible result is partially hidden, scroll up until it's completely visible 2643 newFocused = this._elements.results.querySelector(selectors.item.focused); 2644 if (newFocused) { 2645 var bottomHiddenHeight = newFocused.offsetTop + newFocused.offsetHeight - this._elements.results.scrollTop - this._elements.results.clientHeight; 2646 if (bottomHiddenHeight > 0) { 2647 this._elements.results.scrollTop += bottomHiddenHeight; 2648 } else { 2649 this._onScroll(); 2650 } 2651 } 2652 2653 } else { 2654 // highlight the previous result 2655 if (index >= 1) { 2656 results[index].classList.remove(focusedCssClass); 2657 results[index - 1].classList.add(focusedCssClass); 2658 } 2659 2660 // if the first visible result is partially hidden, scroll down until it's completely visible 2661 newFocused = this._elements.results.querySelector(selectors.item.focused); 2662 if (newFocused) { 2663 var topHiddenHeight = this._elements.results.scrollTop - newFocused.offsetTop; 2664 if (topHiddenHeight > 0) { 2665 this._elements.results.scrollTop -= topHiddenHeight; 2666 } 2667 } 2668 } 2669 } 2670 }; 2671 2672 Search.prototype._updateResults = function() { 2673 var self = this; 2674 if (self._hasMoreResults) { 2675 var request = new XMLHttpRequest(); 2676 var url = self._action + "?" + serialize(self._elements.form) + "&" + PARAM_RESULTS_OFFSET + "=" + self._resultsOffset; 2677 2678 request.open("GET", url, true); 2679 request.onload = function() { 2680 // when the results are loaded: hide the loading indicator and display the search icon after a minimum period 2681 setTimeout(function() { 2682 toggleShow(self._elements.loadingIndicator, false); 2683 toggleShow(self._elements.icon, true); 2684 }, LOADING_DISPLAY_DELAY); 2685 if (request.status >= 200 && request.status < 400) { 2686 // success status 2687 var data = JSON.parse(request.responseText); 2688 if (data.length > 0) { 2689 self._generateItems(data, self._elements.results); 2690 self._markResults(); 2691 toggleShow(self._elements.results, true); 2692 } else { 2693 self._hasMoreResults = false;
2694 } 2695 // the total number of results is not a multiple of the fetched results: 2696 // -> we reached the end of the query 2697 if (self._elements.results.querySelectorAll(selectors.item.self).length % self._properties.resultsSize > 0) { 2698 self._hasMoreResults = false; 2699 } 2700 } else { 2701 // error status 2702 } 2703 }; 2704 // when the results are loading: display the loading indicator and hide the search icon 2705 toggleShow(self._elements.loadingIndicator, true); 2706 toggleShow(self._elements.icon, false); 2707 request.send(); 2708 } 2709 }; 2710 2711 Search.prototype._cancelResults = function() { 2712 clearTimeout(this._timeout); 2713 this._elements.results.scrollTop = 0; 2714 this._resultsOffset = 0; 2715 this._hasMoreResults = true; 2716 this._elements.results.innerHTML = ""; 2717 }; 2718 2719 Search.prototype._cacheElements = function(wrapper) { 2720 this._elements = {}; 2721 this._elements.self = wrapper; 2722 var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 2723 2724 for (var i = 0; i < hooks.length; i++) { 2725 var hook = hooks[i]; 2726 var capitalized = IS; 2727 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2728 var key = hook.dataset[NS + "Hook" + capitalized]; 2729 this._elements[key] = hook; 2730 } 2731 }; 2732 2733 Search.prototype._setupProperties = function(options) { 2734 this._properties = {}; 2735 2736 for (var key in properties) { 2737 if (properties.hasOwnProperty(key)) { 2738 var property = properties[key]; 2739 if (options && options[key] != null) { 2740 if (property && typeof property.transform === "function") { 2741 this._properties[key] = property.transform(options[key]); 2742 } else { 2743 this._properties[key] = options[key]; 2744 } 2745 } else { 2746 this._properties[key] = properties[key]["default"]; 2747 } 2748 } 2749 } 2750 }; 2751 2752 function onDocumentReady() { 2753 var elements = document.querySelectorAll(selectors.self); 2754 for (var i = 0; i < elements.length; i++) { 2755 new Search({ element: elements[i], options: readData(elements[i]) }); 2756 } 2757 2758 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 2759 var body = document.querySelector("body"); 2760 var observer = new MutationObserver(function(mutations) { 2761 mutations.forEach(function(mutation) { 2762 // needed for IE 2763 var nodesArray = [].slice.call(mutation.addedNodes); 2764 if (nodesArray.length > 0) { 2765 nodesArray.forEach(function(addedNode) { 2766 if (addedNode.querySelectorAll) { 2767 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 2768 elementsArray.forEach(function(element) { 2769 new Search({ element: element, options: readData(element) }); 2770 }); 2771 } 2772 }); 2773 } 2774 }); 2775 }); 2776 2777 observer.observe(body, { 2778 subtree: true, 2779 childList: true, 2780 characterData: true 2781 }); 2782 } 2783 2784 if (document.readyState !== "loading") { 2785 onDocumentReady(); 2786 } else { 2787 document.addEventListener("DOMContentLoaded", onDocumentReady); 2788 } 2789 2790})(); 2791 2792/******************************************************************************* 2793 * Copyright 2016 Adobe 2794 * 2795 * Licensed under the Apache License, Version 2.0 (the "License"); 2796 * you may not use this file except in compliance with the License. 2797 * You may obtain a copy of the License at 2798 * 2799 * http://www.apache.org/licenses/LICENSE-2.0 2800 * 2801 * Unless required by applicable law or agreed to in writing, softw
2801are 2802 * distributed under the License is distributed on an "AS IS" BASIS, 2803 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2804 * See the License for the specific language governing permissions and 2805 * limitations under the License. 2806 ******************************************************************************/ 2807(function() { 2808 "use strict"; 2809 2810 var NS = "cmp"; 2811 var IS = "formText"; 2812 var IS_DASH = "form-text"; 2813 2814 var selectors = { 2815 self: "[data-" + NS + '-is="' + IS + '"]' 2816 }; 2817 2818 var properties = { 2819 /** 2820 * A validation message to display if there is a type mismatch between the user input and expected input. 2821 * 2822 * @type {String} 2823 */ 2824 constraintMessage: { 2825 }, 2826 /** 2827 * A validation message to display if no input is supplied, but input is expected for the field. 2828 * 2829 * @type {String} 2830 */ 2831 requiredMessage: { 2832 } 2833 }; 2834 2835 function readData(element) { 2836 var data = element.dataset; 2837 var options = []; 2838 var capitalized = IS; 2839 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2840 var reserved = ["is", "hook" + capitalized]; 2841 2842 for (var key in data) { 2843 if (data.hasOwnProperty(key)) { 2844 var value = data[key]; 2845 2846 if (key.indexOf(NS) === 0) { 2847 key = key.slice(NS.length); 2848 key = key.charAt(0).toLowerCase() + key.substring(1); 2849 2850 if (reserved.indexOf(key) === -1) { 2851 options[key] = value; 2852 } 2853 } 2854 } 2855 } 2856 2857 return options; 2858 } 2859 2860 function FormText(config) { 2861 if (config.element) { 2862 // prevents multiple initialization 2863 config.element.removeAttribute("data-" + NS + "-is"); 2864 } 2865 2866 this._cacheElements(config.element); 2867 this._setupProperties(config.options); 2868 2869 this._elements.input.addEventListener("invalid", this._onInvalid.bind(this)); 2870 this._elements.input.addEventListener("input", this._onInput.bind(this)); 2871 } 2872 2873 FormText.prototype._onInvalid = function(event) { 2874 event.target.setCustomValidity(""); 2875 if (event.target.validity.typeMismatch) { 2876 if (this._properties.constraintMessage) { 2877 event.target.setCustomValidity(this._properties.constraintMessage); 2878 } 2879 } else if (event.target.validity.valueMissing) { 2880 if (this._properties.requiredMessage) { 2881 event.target.setCustomValidity(this._properties.requiredMessage); 2882 } 2883 } 2884 }; 2885 2886 FormText.prototype._onInput = function(event) { 2887 event.target.setCustomValidity(""); 2888 }; 2889 2890 FormText.prototype._cacheElements = function(wrapper) { 2891 this._elements = {}; 2892 this._elements.self = wrapper; 2893 var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS_DASH + "]"); 2894 for (var i = 0; i < hooks.length; i++) { 2895 var hook = hooks[i]; 2896 var capitalized = IS; 2897 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 2898 var key = hook.dataset[NS + "Hook" + capitalized]; 2899 this._elements[key] = hook; 2900 } 2901 }; 2902 2903 FormText.prototype._setupProperties = function(options) { 2904 this._properties = {}; 2905 2906 for (var key in properties) { 2907 if (properties.hasOwnProperty(key)) { 2908 var property = properties[key]; 2909 if (options && options[key] != null) { 2910 if (property && typeof property.transform === "function") { 2911 this._properties[key] = property.transform(options[key]); 2912 } else { 2913 this._properties[key] = options[key]; 2914 } 2915 } else { 2916 this._properties[key] = properties[key]["default"]; 2917 } 2918 } 2919 } 2920 }; 2921 2922 function onDocumentReady() { 2923 var elements = document.querySelectorAll(selectors.self); 2924 for (var i = 0; i < elements.length; i++) { 2925 new FormText({ element: elements[i], options: readData(elements[i]) }); 2926 } 2927 2928 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 2929 var body = document.querySelector("body"); 2930 var observer = new MutationObserver(function(mutations) { 2931 mutations.forEach(function(mutation) { 2932 // needed for IE 2933 var nodesArray = [].slice.call(mutation.addedNodes); 2934 if (nodesArray.length > 0) { 2935 nodesArray.forEach(function(addedNode) { 2936 if (addedNode.querySelectorAll) { 2937 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 2938 elementsArray.forEach(function(element) { 2939 new FormText({ element: element, options: readData(element) }); 2940 }); 2941 } 2942 }); 2943 } 2944 }); 2945 }); 2946 2947 observer.observe(body, { 2948 subtree: true, 2949 childList: true, 2950 characterData: true 2951 }); 2952 } 2953 2954 if (document.readyState !== "loading") { 2955 onDocumentReady(); 2956 } else { 2957 document.addEventListener("DOMContentLoaded", onDocumentReady); 2958 } 2959 2960})(); 2961 2962/*! @license DOMPurify 3.2.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.6/LICENSE */ 2963!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=R(Array.prototype.forEach),m=R(Array.prototype.lastIndexOf),p=R(Array.prototype.pop),f=R(Array.prototype.push),d=R(Array.prototype.splice),h=R(String.prototype.toLowerCase),g=R(String.prototype.toString),T=R(String.prototype.match),y=R(String.prototype.replace),E=R(String.prototype.indexOf),A=R(String.prototype.trim),_=R(Object.prototype.hasOwnProperty),S=R(RegExp.prototype.test),b=(N=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return s(N,t)});var N;function R(e){return function(t){t instanceof RegExp&&(t.lastIndex=0);for(var n=arguments.length,o=new Array(n>1?n-1:0),r=1;r<n;r++)o[r-1]=arguments[r];return c(e,t,o)}}function w(e,o){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:h;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function O(e){for(let t=0;t<e.length;t++){_(e,t)||(e[t]=null)}return e}function D(t){const n=l(null);for(const[o,r]of e(t)){_(t,o)&&(Array.isArray(r)?n[o]=O(r):r&&"object"==typeof r&&r.constructor===Object?n[o]=D(r):n[o]=r)}return n}function v(e,t){for(;null!==e;){const n=r(e,t);if(n){if(n.get)return R(n.get);if("function"==typeof n.value)return R(n.value)}e=o(e)}return function(){return null}}const L=i(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),C=i(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),x=i(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),I=i(["animate","color-profile","cursor","discard","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),M=i(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover","mprescripts"]),k=i(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),U=i(["#text"]),z=i(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","face","for","headers","height","hidden","high","href","hreflang","id","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","playsinline","popover","popovertarget","popovertargetaction","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","
2963spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","wrap","xmlns","slot"]),P=i(["accent-height","accumulate","additive","alignment-baseline","amplitude","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","exponent","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","intercept","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","slope","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","tablevalues","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),H=i(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),F=i(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),B=a(/\{\{[\w\W]*|[\w\W]*\}\}/gm),W=a(/<%[\w\W]*|[\w\W]*%>/gm),G=a(/\$\{[\w\W]*/gm),Y=a(/^data-[\-\w.\u00B7-\uFFFF]+$/),j=a(/^aria-[\-\w]+$/),X=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),q=a(/^(?:\w+script|data):/i),$=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),K=a(/^html$/i),V=a(/^[a-z][.\w]*(-[.\w]+)+$/i);var Z=Object.freeze({__proto__:null,ARIA_ATTR:j,ATTR_WHITESPACE:$,CUSTOM_ELEMENT:V,DATA_ATTR:Y,DOCTYPE_NAME:K,ERB_EXPR:W,IS_ALLOWED_URI:X,IS_SCRIPT_OR_DATA:q,MUSTACHE_EXPR:B,TMPLIT_EXPR:G});const J=1,Q=3,ee=7,te=8,ne=9,oe=function(){return"undefined"==typeof window?null:window};var re=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:oe();const o=e=>t(e);if(o.version="3.2.6",o.removed=[],!n||!n.document||n.document.nodeType!==ne||!n.Element)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:N,Node:R,Element:O,NodeFilter:B,NamedNodeMap:W=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:G,DOMParser:Y,trustedTypes:j}=n,q=O.prototype,$=v(q,"cloneNode"),V=v(q,"remove"),re=v(q,"nextSibling"),ie=v(q,"childNodes"),ae=v(q,"parentNode");if("function"==typeof N){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let le,ce="";const{implementation:se,createNodeIterator:ue,createDocumentFragment:me,getElementsByTagName:pe}=r,{importNode:fe}=a;let de={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]};o.isSupported="function"==typeof e&&"function"==typeof ae&&se&&void 0!==se.createHTMLDocument;const{MUSTACHE_EXPR:he,ERB_EXPR:ge,TMPLIT_EXPR:Te,DATA_ATTR:ye,ARIA_ATTR:Ee,IS_SCRIPT_OR_DATA:Ae,ATTR_WHITESPACE:_e,CUSTOM_ELEMENT:Se}=Z;let{IS_ALLOWED_URI:be}=Z,Ne=null;const Re=w({},[...L,...C,...x,...M,...U]);let we=null;const Oe=w({},[...z,...P,...H,...F]);let De=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),ve=null,Le=null,Ce=!0,xe=!0,Ie=!1,Me=!0,ke=!1,Ue=!0,ze=!1,Pe=!1,He=!1,Fe=!1,Be=!1,We=!1,Ge=!0,Ye=!1,je=!0,Xe=!1,qe={},$e=null;const Ke=w({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Ve=null;const Ze=w({},["audio","video","img","source","image","track"]);let Je=null;const Qe=w({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),et="http://www.w3.org/1998/Math/MathML",tt="http://www.w3.org/2000/svg",nt="http://www.w3.org/1999/xhtml";let ot=nt,rt=!1,it=null;const at=w({},[et,tt,nt],g);let lt=w({},["mi","mo","mn","ms","mtext"]),ct=w({},["annotation-xml"]);const st=w({},["title","style","font","a","script"]);let ut=null;const mt=["application/xhtml+xml","text/html"];let pt=null,ft=null;const dt=r.createElement("form"),ht=function(e){return e instanceof RegExp||e instanceof Function},gt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!ft||ft!==e){if(e&&"object"==typeof e||(e={}
vendor: 4,915 bytes, line 2963
2963),e=D(e),ut=-1===mt.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,pt="application/xhtml+xml"===ut?g:h,Ne=_(e,"ALLOWED_TAGS")?w({},e.ALLOWED_TAGS,pt):Re,we=_(e,"ALLOWED_ATTR")?w({},e.ALLOWED_ATTR,pt):Oe,it=_(e,"ALLOWED_NAMESPACES")?w({},e.ALLOWED_NAMESPACES,g):at,Je=_(e,"ADD_URI_SAFE_ATTR")?w(D(Qe),e.ADD_URI_SAFE_ATTR,pt):Qe,Ve=_(e,"ADD_DATA_URI_TAGS")?w(D(Ze),e.ADD_DATA_URI_TAGS,pt):Ze,$e=_(e,"FORBID_CONTENTS")?w({},e.FORBID_CONTENTS,pt):Ke,ve=_(e,"FORBID_TAGS")?w({},e.FORBID_TAGS,pt):D({}),Le=_(e,"FORBID_ATTR")?w({},e.FORBID_ATTR,pt):D({}),qe=!!_(e,"USE_PROFILES")&&e.USE_PROFILES,Ce=!1!==e.ALLOW_ARIA_ATTR,xe=!1!==e.ALLOW_DATA_ATTR,Ie=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Me=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,ke=e.SAFE_FOR_TEMPLATES||!1,Ue=!1!==e.SAFE_FOR_XML,ze=e.WHOLE_DOCUMENT||!1,Fe=e.RETURN_DOM||!1,Be=e.RETURN_DOM_FRAGMENT||!1,We=e.RETURN_TRUSTED_TYPE||!1,He=e.FORCE_BODY||!1,Ge=!1!==e.SANITIZE_DOM,Ye=e.SANITIZE_NAMED_PROPS||!1,je=!1!==e.KEEP_CONTENT,Xe=e.IN_PLACE||!1,be=e.ALLOWED_URI_REGEXP||X,ot=e.NAMESPACE||nt,lt=e.MATHML_TEXT_INTEGRATION_POINTS||lt,ct=e.HTML_INTEGRATION_POINTS||ct,De=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&ht(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(De.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&ht(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(De.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(De.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),ke&&(xe=!1),Be&&(Fe=!0),qe&&(Ne=w({},U),we=[],!0===qe.html&&(w(Ne,L),w(we,z)),!0===qe.svg&&(w(Ne,C),w(we,P),w(we,F)),!0===qe.svgFilters&&(w(Ne,x),w(we,P),w(we,F)),!0===qe.mathMl&&(w(Ne,M),w(we,H),w(we,F))),e.ADD_TAGS&&(Ne===Re&&(Ne=D(Ne)),w(Ne,e.ADD_TAGS,pt)),e.ADD_ATTR&&(we===Oe&&(we=D(we)),w(we,e.ADD_ATTR,pt)),e.ADD_URI_SAFE_ATTR&&w(Je,e.ADD_URI_SAFE_ATTR,pt),e.FORBID_CONTENTS&&($e===Ke&&($e=D($e)),w($e,e.FORBID_CONTENTS,pt)),je&&(Ne["#text"]=!0),ze&&w(Ne,["html","head","body"]),Ne.table&&(w(Ne,["tbody"]),delete ve.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw b('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw b('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');le=e.TRUSTED_TYPES_POLICY,ce=le.createHTML("")}else void 0===le&&(le=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}}(j,c)),null!==le&&"string"==typeof ce&&(ce=le.createHTML(""));i&&i(e),ft=e}},Tt=w({},[...C,...x,...I]),yt=w({},[...M,...k]),Et=function(e){f(o.removed,{element:e});try{ae(e).removeChild(e)}catch(t){V(e)}},At=function(e,t){try{f(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){f(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e)if(Fe||Be)try{Et(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},_t=function(e){let t=null,n=null;if(He)e="<remove></remove>"+e;else{const t=T(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===ut&&ot===nt&&(e='<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>'+e+"</body></html>");const o=le?le.createHTML(e):e;if(ot===nt)try{t=(new Y).parseFromString(o,ut)}catch(e){}if(!t||!t.documentElement){t=se.createDocument(ot,"template",null);try{t.documentElement.innerHTML=rt?ce:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),ot===nt?pe.call(t,ze?"html":"body")[0]:ze?t.documentElement:i},St=function(e){return ue.call(e.ownerDocument||e,e,B.SHOW_ELEMENT|B.SHOW_COMMENT|B.SHOW_TEXT|B.SHOW_PROCESSING_INSTRUCTION|B.SHOW_CDATA_SECTION,null)},bt=function(e){return e instanceof G&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof W)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Nt=function(e){return"function"==typeof R&&e instanceof R};function Rt(e,t,n){u(e,(e=>{e.call(o,t,n,ft)}))}const wt=function(e){let t=null;if(Rt(de.beforeSanitizeElements,e,null),bt(e))return Et(e),!0;const n=pt(e.nodeName);if(Rt(de.uponSanitizeElement,e,{tagName:n,allowedTags:Ne}),Ue&&e.hasChildNodes()&&!Nt(e.firstElementChild)&&S(/<[/\w!]/g,e.innerHTML)&&S(/<[/\w!]/g,e.textContent))return Et(e),!0;if(e.nodeType===ee)return Et(e),!0;if(Ue&&e.nodeType===te&&S(/<[/\w]/g,e.data))return Et(e),!0;
vendor: 5,068 bytes, line 2963
2963if(!Ne[n]||ve[n]){if(!ve[n]&&Dt(n)){if(De.tagNameCheck instanceof RegExp&&S(De.tagNameCheck,n))return!1;if(De.tagNameCheck instanceof Function&&De.tagNameCheck(n))return!1}if(je&&!$e[n]){const t=ae(e)||e.parentNode,n=ie(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o){const r=$(n[o],!0);r.__removalCount=(e.__removalCount||0)+1,t.insertBefore(r,re(e))}}}return Et(e),!0}return e instanceof O&&!function(e){let t=ae(e);t&&t.tagName||(t={namespaceURI:ot,tagName:"template"});const n=h(e.tagName),o=h(t.tagName);return!!it[e.namespaceURI]&&(e.namespaceURI===tt?t.namespaceURI===nt?"svg"===n:t.namespaceURI===et?"svg"===n&&("annotation-xml"===o||lt[o]):Boolean(Tt[n]):e.namespaceURI===et?t.namespaceURI===nt?"math"===n:t.namespaceURI===tt?"math"===n&&ct[o]:Boolean(yt[n]):e.namespaceURI===nt?!(t.namespaceURI===tt&&!ct[o])&&!(t.namespaceURI===et&&!lt[o])&&!yt[n]&&(st[n]||!Tt[n]):!("application/xhtml+xml"!==ut||!it[e.namespaceURI]))}(e)?(Et(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!S(/<\/no(script|embed|frames)/i,e.innerHTML)?(ke&&e.nodeType===Q&&(t=e.textContent,u([he,ge,Te],(e=>{t=y(t,e," ")})),e.textContent!==t&&(f(o.removed,{element:e.cloneNode()}),e.textContent=t)),Rt(de.afterSanitizeElements,e,null),!1):(Et(e),!0)},Ot=function(e,t,n){if(Ge&&("id"===t||"name"===t)&&(n in r||n in dt))return!1;if(xe&&!Le[t]&&S(ye,t));else if(Ce&&S(Ee,t));else if(!we[t]||Le[t]){if(!(Dt(e)&&(De.tagNameCheck instanceof RegExp&&S(De.tagNameCheck,e)||De.tagNameCheck instanceof Function&&De.tagNameCheck(e))&&(De.attributeNameCheck instanceof RegExp&&S(De.attributeNameCheck,t)||De.attributeNameCheck instanceof Function&&De.attributeNameCheck(t))||"is"===t&&De.allowCustomizedBuiltInElements&&(De.tagNameCheck instanceof RegExp&&S(De.tagNameCheck,n)||De.tagNameCheck instanceof Function&&De.tagNameCheck(n))))return!1}else if(Je[t]);else if(S(be,y(n,_e,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==E(n,"data:")||!Ve[e]){if(Ie&&!S(Ae,y(n,_e,"")));else if(n)return!1}else;return!0},Dt=function(e){return"annotation-xml"!==e&&T(e,Se)},vt=function(e){Rt(de.beforeSanitizeAttributes,e,null);const{attributes:t}=e;if(!t||bt(e))return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:we,forceKeepAttr:void 0};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=pt(a),m=c;let f="value"===a?m:A(m);if(n.attrName=s,n.attrValue=f,n.keepAttr=!0,n.forceKeepAttr=void 0,Rt(de.uponSanitizeAttribute,e,n),f=n.attrValue,!Ye||"id"!==s&&"name"!==s||(At(a,e),f="user-content-"+f),Ue&&S(/((--!?|])>)|<\/(style|title)/i,f)){At(a,e);continue}if(n.forceKeepAttr)continue;if(!n.keepAttr){At(a,e);continue}if(!Me&&S(/\/>/i,f)){At(a,e);continue}ke&&u([he,ge,Te],(e=>{f=y(f,e," ")}));const d=pt(e.nodeName);if(Ot(d,s,f)){if(le&&"object"==typeof j&&"function"==typeof j.getAttributeType)if(l);else switch(j.getAttributeType(d,s)){case"TrustedHTML":f=le.createHTML(f);break;case"TrustedScriptURL":f=le.createScriptURL(f)}if(f!==m)try{l?e.setAttributeNS(l,a,f):e.setAttribute(a,f),bt(e)?Et(e):p(o.removed)}catch(t){At(a,e)}}else At(a,e)}Rt(de.afterSanitizeAttributes,e,null)},Lt=function e(t){let n=null;const o=St(t);for(Rt(de.beforeSanitizeShadowDOM,t,null);n=o.nextNode();)Rt(de.uponSanitizeShadowNode,n,null),wt(n),vt(n),n.content instanceof s&&e(n.content);Rt(de.afterSanitizeShadowDOM,t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(rt=!e,rt&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Nt(e)){if("function"!=typeof e.toString)throw b("toString is not a function");if("string"!=typeof(e=e.toString()))throw b("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Pe||gt(t),o.removed=[],"string"==typeof e&&(Xe=!1),Xe){if(e.nodeName){const t=pt(e.nodeName);if(!Ne[t]||ve[t])throw b("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof R)n=_t("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===J&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!Fe&&!ke&&!ze&&-1===e.indexOf("<"))return le&&We?le.createHTML(e):e;if(n=_t(e),!n)return Fe?null:We?ce:""}n&&He&&Et(n.firstChild);const c=St(Xe?e:n);for(;i=c.nextNode();)wt(i),vt(i),i.content instanceof s&&Lt(i.content);if(Xe)return e;if(Fe){if(Be)for(l=me.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(we.shadowroot||we.shadowrootmode)&&(l=fe.call(a,l,!0)),l}let m=ze?n.outerHTML:n.innerHTML;return ze&&Ne["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&S(K,n.ownerDocument.doctype.name)&&(m="<!DOCTYPE "+n.ownerDocument.doctype.name+">\n"+m),ke&&u([he,ge,Te],(e=>{m=y(m,e," ")})),le&&We?le.createHTML(m):m},o.setConfig=function(){gt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Pe=!0},o.clearConfig=function(){ft=null,Pe=!1},o.isValidAttribute=function(e,t,n){ft||gt({});const o=pt(e),r=pt(t);return Ot(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&f(de[e],t)},o.removeHook=function(e,t){if(void 0!==t){const n=m(de[e],t);
2963return-1===n?void 0:d(de[e],n,1)[0]}return p(de[e])},o.removeHooks=function(e){de[e]=[]},o.removeAllHooks=function(){de={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},o}();return re})); 2964//# sourceMappingURL=purify.min.js.map 2965var getGeoLocationJS = { 2966 locationVal: "", 2967 cookieValue: "", 2968 postalCode: "", 2969 langId: "", 2970 storeId: "", 2971 domain: "", 2972 reversePath: "", 2973 addressPath: "", 2974 key: "", 2975 locationDesc: "", 2976 locationLabel: "", 2977 locErrorMsg: "", 2978 zipCodeReqErrMsg:"", 2979 locText: "", 2980 maxLength: 5, 2981 locationPrompt: "locationPrompt", 2982 locationPromptValue: "", 2983 2984 prepopulateZipCode: function() { 2985 let locationCookie = getGeoLocationJS.getCookie('location') || getGeoLocationJS.getCookie('zipCode') || getGeoLocationJS.getCookie('userZipCode'); 2986 let zipCode = locationCookie; 2987 // Step 2: If cookie is empty or not found, try to get from localStorage and set cookie 2988 if (!locationCookie) { 2989 // Try to get location data from localStorage (MapQuest API response format) 2990 let locationData = localStorage.getItem('locationData'); 2991 if (locationData) { 2992 try { 2993 let parsedLocationData = JSON.parse(locationData); 2994 if (parsedLocationData.results && parsedLocationData.results[0] && parsedLocationData.results[0].locations && parsedLocationData.results[0].locations[0]) { 2995 let locationObj = parsedLocationData.results[0].locations[0]; 2996 let zipFromLocationData = locationObj.postalCode; 2997 2998 if (zipFromLocationData) { 2999 if (zipFromLocationData.indexOf('-') > -1) { 3000 zipFromLocationData = zipFromLocationData.substring(0, zipFromLocationData.indexOf('-')); 3001 } 3002 // Set the location cookie using the zip code from localStorage 3003 let cookieDuration = document.getElementById('configdata')?.getAttribute('data-cookie'); 3004 if (cookieDuration) { 3005 let d = new Date(); 3006 d.setSeconds(d.getSeconds() + parseInt(cookieDuration)); 3007 if (window.location.protocol === "https:") { 3008 document.cookie = "location=" + zipFromLocationData + "; expires=" + d.toUTCString() + "; path=/;secure;sameSite=Strict"; 3009 document.cookie = "locationState=" + (locationObj.adminArea3 || '') + "; expires=" + d.toUTCString() + "; path=/;secure;sameSite=Strict"; 3010 } else { 3011 document.cookie = "location=" + zipFromLocationData + "; expires=" + d.toUTCString() + "; path=/;sameSite=Strict"; 3012 document.cookie = "locationState=" + (locationObj.adminArea3 || '') + "; expires=" + d.toUTCString() + "; path=/;sameSite=Strict"; 3013 } 3014 zipCode = zipFromLocationData; 3015 } 3016 } 3017 } 3018 } catch (e) { 3019 console.error('[LocationJS] Error parsing locationData from localStorage:', e); 3020 } 3021 } 3022 if (!zipCode) { 3023 zipCode = localStorage.getItem('zipCode') || localStorage.getItem('userZipCode') || localStorage.getItem('location'); 3024 } 3025 } 3026 if (zipCode) { 3027 const possibleSelectors = [ 3028 '#updateLoc', 3029 '#zipCode', 3030 'input[name="zipCode"]', 3031 '.zipcode-input', 3032 'input[placeholder*="ZIP"]', 3033 'input[placeholder*="zip"]', 3034 'input[data-zip]' 3035 ]; 3036 let inputFound = false;
3037 for (let selector of possibleSelectors) { 3038 let zipInput = document.querySelector(selector); 3039 if (zipInput && !zipInput.value) { 3040 zipInput.value = DOMPurify.sanitize(zipCode); 3041 3042 if (selector === '#updateLoc') { 3043 getGeoLocationJS.validateLocationInput(zipInput.value); 3044 } 3045 zipInput.dispatchEvent(new Event('change', { bubbles: true })); 3046 inputFound = true; 3047 3048 this.changeLinkBgColor('#dfdfdf','#000d59'); 3049 break; 3050 } 3051 } 3052 3053 if (!inputFound) { 3054 console.log('[LocationJS] No suitable zip code input field found on this page.'); 3055 } 3056 } else { 3057 console.log('[LocationJS] No zip code found in cookie or localStorage.'); 3058 } 3059 }, 3060 3061 getHexColor: function(rgbColor) { 3062 const match = rgbColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); 3063 if (!match) { 3064 return null; // Handle cases where the string is not in rgb() format 3065 } 3066 const r = parseInt(match[1]); 3067 const g = parseInt(match[2]); 3068 const b = parseInt(match[3]); 3069 3070 const toHex = (c) => { 3071 const hex = c.toString(16); 3072 return hex.length === 1 ? "0" + hex : hex; 3073 }; 3074 3075 return `#${toHex(r)}${toHex(g)}${toHex(b)}`; 3076 }, 3077 3078 getLocation: function() { 3079 getGeoLocationJS.locationDesc = document.getElementById('geo-update')?.getAttribute('data-desc'); 3080 getGeoLocationJS.locationLabel = document.getElementById('geo-update')?.getAttribute('data-label'); 3081 getGeoLocationJS.locErrorMsg = document.getElementById('geo-update')?.getAttribute('data-errormsg'); 3082 getGeoLocationJS.zipCodeReqErrMsg = document.getElementById('geo-update')?.getAttribute('data-noziperrormsg'); 3083 getGeoLocationJS.locText = document.getElementById('geo-update')?.getAttribute('data-loctext'); 3084 getGeoLocationJS.privacyPolicyInfo = document.getElementById('geo-update')?.getAttribute('data-privacypolicyinfo'); 3085 3086 if (document.getElementById("loc-desc")) { 3087 document.getElementById("loc-desc").innerHTML = DOMPurify.sanitize(getGeoLocationJS.locationDesc); 3088 } 3089 if (document.getElementById("loc-label")) { 3090 document.getElementById("loc-label").innerHTML = DOMPurify.sanitize(getGeoLocationJS.locationLabel); 3091 } 3092 if (document.getElementById("loc-text")) { 3093 document.getElementById("loc-text").innerHTML = DOMPurify.sanitize(getGeoLocationJS.locText); 3094 } 3095 if (document.getElementById("location-box")) { 3096 document.getElementById("location-box")?.setAttribute('aria-label',`${getGeoLocationJS.locText} ${document.getElementById("location-box")?.getAttribute('data-modal-label')}`); 3097 } 3098 if (document.getElementById("loc-privacypolicyinfo")) { 3099 document.getElementById("loc-privacypolicyinfo").innerHTML = DOMPurify.sanitize(getGeoLocationJS.privacyPolicyInfo); 3100 } 3101 3102 // Set initial styling for TracFone brand when page loads 3103 let brand = document.querySelector(".section-api-container")?.dataset.brand?.toLowerCase(); 3104 if (brand === "tracfone") { 3105 // Set initial label color to gray for TracFone 3106 if (document.querySelector("label[for='updateLoc']")) { 3107 document.querySelector("label[for='updateLoc']").style.color = "#808080"; 3108 } 3109 } 3110 3111 let hideZipCodeModal = document.querySelector(".section-api-container")?.dataset.hidezipcodemodal; 3112 3113 console.time('executionTimeForCapturingUserLocationZipCode'); 3114 let actCookie = getGeoLocationJS.getCookie("actWebviewEnabled"); 3115 if (hideZipCodeModal !== "true") { 3116 if (navigator.geolocation && !actCookie) { 3117 getGeoLocationJS.locationPromptValue = sessionStorage.getItem(getGeoLocationJS.locationPrompt); 3118 3119 if (!getGeoLocationJS.locationPromptValue) { 3120 navigator.geolocation.getCurrentPosition(getGeoLocationJS.showPosition, getGeoLocationJS.showError); 3121 } 3122 else if (getGeoLocationJS.locationPromptValue == "N") { 3123 const errorPrompt = { 3124 code: 1, 3125 PERMISSION_DENIED: 1 3126 }; 3127 getGeoLocationJS.showError(errorPrompt); 3128 } 3129 else if (getGeoLocationJS.locationPromptValue == "Y") 3130 { 3131 getGeoLocationJS.mapRequestAPICall(true); 3132 } 3133 } 3134 } else { 3135 var locationBox = document.getElementById("location-box"); 3136 if (locationBox) { 3137 locationBox.remove(); 3138 } 3139 console.log("Geolocation is not supported by this browser."); 3140 } 3141 }, 3142 showPosition: function(position) { 3143 getGeoLocationJS.locationVal = position.coords.latitude + "," + position.coords.longitude; 3144 getGeoLocationJS.mapRequestAPICall(true); 3145 if (!sessionStorage.getItem(getGeoLocationJS.locationPrompt)) { 3146 sessionStorage.setItem(getGeoLocationJS.locationPrompt, "Y"); 3147 } 3148 3149 3150 }, 3151 3152 getCookie: function(cookieName) { 3153 var decodedCookie = DOMPurify.sanitize(decodeURIComponent(document.cookie)); 3154 var ca = decodedCookie.split(';'); 3155 var cookieValue = ""; 3156 var name = cookieName + "="; 3157 for (var i = 0; i < ca.length; i++) { 3158 var c = ca[i]; 3159 while (c.charAt(0) == ' ') { 3160 c = c.substring(1); 3161 } 3162 if (c.indexOf(name) == 0) { 3163 cookieValue = c.substring(name.length, c.length); 3164 } 3165 3166 3167 3168 } 3169 return cookieValue; 3170 }, 3171 3172 processLocationData: function (response) { 3173 var zipCode = DOMPurify.sanitize(response.results[0].locations[0].postalCode); 3174 if (zipCode.indexOf('-') > -1) { 3175 zipCode = zipCode.substring(0, zipCode.indexOf('-')); 3176 } 3177 var city = response.results[0].locations[0].adminArea5; 3178 var state = DOMPurify.sanitize(response.results[0].locations[0].adminArea3); 3179 var cityDisplayText = city == '' ? state : city + ' ' + state; 3180 var displayText = zipCode + ' (' + cityDisplayText + ')'; 3181 if(document.getElementById('city')) 3182 document.getElementById('city').innerHTML = DOMPurify.sanitize(displayText); 3183 //setting location cookie on page load if it does not exists 3184 var cookieDuration = document.getElementById('configdata')?.getAttribute('data-cookie'); 3185 var d = new Date(); 3186 if (cookieDuration) { 3187 d.setSeconds(d.getSeconds() + parseInt(cookieDuration)); 3188 } 3189 if (d && zipCode && !document.cookie.split(';').some((item) => item.trim().startsWith('location='))) { 3190 createCookieCommon('location', zipCode, d.toUTCString()); 3191 createCookieCommon('locationState', state, d.toUTCString()); 3192 if ( 3193 $('.product-listing-container').length > 0 && 3194 $('.purchase-flow-wrapper').length == 0 && 3195 $('.filter-location').length > 0 3196 ) { 3197 document.dispatchEvent( 3198 new Event('DOMContentLoaded', { 3199 bubbles: true, 3200 }), 3201 ); 3202 } 3203 } 3204 if ($('.filter-location').length > 0) { 3205 document.getElementById('location-update').innerHTML = DOMPurify.sanitize(displayText); 3206 document.getElementById('available-in').innerHTML = DOMPurify.sanitize(document 3207 .getElementById('available-in') 3208 .getAttribute('data-ziplabel')); 3209 document.getElementById('geo-update').setAttribute('data-gtm-asset', displayText); 3210 document.getElementById('location-update').setAttribute('data-gtm-asset', displayText); 3211 let arialabel = displayText + ' ' + document.querySelector('#location-update').dataset.updatelocation; 3212 document.querySelector('#location-update').setAttribute("aria-label", arialabel); 3213 } 3214 }, 3215 3216 mapRequestAPICall: function(isBrowserGeolocation) { 3217 var xhttp = new XMLHttpRequest(); 3218 var name = "location"; 3219 getGeoLocationJS.domain = document.getElementById('configdata')?.getAttribute('data-domain'); 3220 getGeoLocationJS.reversePath = document.getElementById('configdata')?.getAttribute('data-reverse'); 3221 getGeoLocationJS.addressPath = document.getElementById('configdata')?.getAttribute('data-path'); 3222 getGeoLocationJS.key = document.getElementById('configdata')?.getAttribute('data-key'); 3223 getGeoLocationJS.cookieValue = DOMPurify.sanitize(getGeoLocationJS.getCookie(name)); 3224 var url = ""; 3225 if (getGeoLocationJS.cookieValue != "") { 3226 url = getGeoLocationJS.domain + getGeoLocationJS.addressPath + "?key=" + getGeoLocationJS.key + "&location=" + getGeoLocationJS.cookieValue + "&outFormat=json&maxResults=1"; 3227 } else { 3228 url = getGeoLocationJS.domain + getGeoLocationJS.reversePath + "?key=" + getGeoLocationJS.key + "&location=" + getGeoLocationJS.locationVal + "&outFormat=json"; 3229 } 3230 3231 xhttp.onreadystatechange = function() { 3232 console.info("onreadystatechange :: User accepted the request for Geolocation"); 3233 if (this.readyState == 4 && this.status == 200) { 3234 var response = JSON.parse(this.responseText); 3235 if (response !== null && response !== undefined && response.info !== null && response.info !== undefined) { 3236 if (response.info.statuscode !== null && response.info.statuscode !== undefined) { 3237 if (response.info.statuscode == 0) { 3238 if ((response.results[0].locations[0].adminArea5 != "" || response.results[0].locations[0].adminArea3 != "") && (response.results[0].locations[0].adminArea1 == "US" || response.results[0].locations[0].adminArea1 == "PR")) { 3239 getGeoLocationJS.addLocationDataToLocalStorage(response); 3240 getGeoLocationJS.processLocationData(response); 3241 if (isBrowserGeolocation) createCookieCommon("fccZip", "2", document.getElementById('configdata').getAttribute('data-cookie')); 3242 document.dispatchEvent(new Event("BrowserGeolocationUpdated")); 3243 } else { 3244 var enterZip = document.getElementById('geo-update').getAttribute('data-enterzip'); 3245 document.getElementById("city").innerHTML = DOMPurify.sanitize(enterZip); 3246 document.getElementById('geo-update').setAttribute("data-gtm-asset", enterZip); 3247 if ($('.filter-location').length > 0) { 3248 document.getElementById('location-update').innerHTML = DOMPurify.sanitize(enterZip); 3249 document.getElementById('available-in').innerHTML = ""; 3250 document.getElementById('location-update').setAttribute("data-gtm-asset", enterZip); 3251 document.querySelector('#location-update').setAttribute("aria-label", enterZip); 3252 } 3253 } 3254 } else { 3255 getGeoLocationJS.handleMapQuestApiError(response.info.statuscode); 3256 } 3257 } 3258 } 3259 } 3260 }; 3261 3262 if (getGeoLocationJS.cookieValue != '') { 3263 var response = JSON.parse(localStorage.getItem('locationData')); 3264 if (response !== null && response !== undefined) { 3265 getGeoLocationJS.processLocationData(response); 3266 } else {
3267 getGeoLocationJS.invokeRequest(xhttp, url); 3268 } 3269 } else { 3270 console.info("mapRequestAPICall :: User accepted the request for Geolocation"); 3271 getGeoLocationJS.invokeRequest(xhttp, url); 3272 } 3273 }, 3274 3275 addLocationDataToLocalStorage: function (response) { 3276 localStorage.setItem('locationData', JSON.stringify(response)); 3277 }, 3278 3279 invokeRequest: function (requestObject, url) { 3280 console.info("invokeRequest :: User accepted the request for Geolocation"); 3281 requestObject.open('GET', url, true); 3282 requestObject.onerror = function () { 3283 console.log('Error while trying to fetch data from MaQuest API'); 3284 }; 3285 requestObject.send(); 3286 }, 3287 3288 updateLocation: function(e, isUpdate) { 3289 if (e.keyCode == 13 || isUpdate) { 3290 getGeoLocationJS.domain = document.getElementById('configdata').getAttribute('data-domain'); 3291 getGeoLocationJS.reversePath = document.getElementById('configdata').getAttribute('data-reverse'); 3292 getGeoLocationJS.addressPath = document.getElementById('configdata').getAttribute('data-path'); 3293 getGeoLocationJS.key = document.getElementById('configdata').getAttribute('data-key'); 3294 var cookieDuration = document.getElementById('configdata').getAttribute('data-cookie'); 3295 var req = new XMLHttpRequest(); 3296 var name = "location"; 3297 var inputText = DOMPurify.sanitize(document.getElementById("updateLoc").value); 3298 var isError = false; 3299 if (inputText.length < getGeoLocationJS.maxLength) { 3300 if(inputText.length == 0){ 3301 getGeoLocationJS.showErrorMessage("showZipReqError"); 3302 }else{ 3303 getGeoLocationJS.showErrorMessage(); 3304 } 3305 isError = true; 3306 } 3307 var url = getGeoLocationJS.domain + getGeoLocationJS.addressPath + "?key=" + getGeoLocationJS.key + "&location=" + inputText + "&outFormat=json&maxResults=1"; 3308 3309 req.onreadystatechange = function() { 3310 if (this.readyState == 4 && this.status == 200) { 3311 var response = JSON.parse(this.responseText); 3312 if (response !== null && response !== undefined && response.info !== null && response.info !== undefined) { 3313 if (response.info.statuscode !== null && response.info.statuscode !== undefined) { 3314 if (response.info.statuscode == 0) { 3315 if ((response.results[0].locations[0].adminArea5 != "" || response.results[0].locations[0].adminArea3 != "") && (response.results[0].locations[0].adminArea1 == "US" || response.results[0].locations[0].adminArea1 == "PR")) { 3316 createCookieCommon("fccZip", "1", cookieDuration); 3317 getGeoLocationJS.hideError(); 3318 getGeoLocationJS.addLocationDataToLocalStorage(response); 3319 var zipCode = response.results[0].locations[0].postalCode; 3320 if (zipCode.indexOf('-') > -1) { 3321 zipCode = zipCode.substring(0, zipCode.indexOf('-')); 3322 } 3323 var city = response.results[0].locations[0].adminArea5; 3324 var state = DOMPurify.sanitize(response.results[0].locations[0].adminArea3); 3325 var cityDisplayText = city == "" ? state : city + " " + state; 3326 var displayText = zipCode + " (" + cityDisplayText + ")"; 3327 document.getElementById("city").innerHTML = DOMPurify.sanitize(displayText); 3328 if ($('.filter-location').length > 0) { 3329 document.getElementById('location-update').innerHTML = DOMPurify.sanitize(displayText); 3330 document.getElementById('available-in').innerHTML = DOMPurify.sanitize(document.querySelector('#available-in').dataset.z
3330iplabel); 3331 document.getElementById('geo-update').setAttribute("data-gtm-asset", displayText); 3332 document.getElementById('location-update').setAttribute("data-gtm-asset", displayText); 3333 } 3334 3335 var d = new Date(); 3336 d.setSeconds(d.getSeconds() + parseInt(cookieDuration)); 3337 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/'; 3338 3339 if (window.location.protocol === "https:") { 3340 document.cookie = name + "=" + inputText + "; expires=" + d.toUTCString() + "; path=/;secure;sameSite=Strict"; 3341 document.cookie = "locationState" + "=" + state + "; expires=" + d.toUTCString() + "; path=/;secure;sameSite=Strict"; 3342 } else { 3343 document.cookie = name + "=" + inputText + "; expires=" + d.toUTCString() + "; path=/;sameSite=Strict"; 3344 document.cookie = "locationState" + "=" + state + "; expires=" + d.toUTCString() + "; path=/;sameSite=Strict"; 3345 } 3346 document.dispatchEvent(new Event('CallMarketingAPI', { 3347 'bubbles': true 3348 })); 3349 $('#location-box').modal('hide'); 3350 } else { 3351 getGeoLocationJS.showErrorMessage(); 3352 if (!$("#location-box").data('bs.modal')._isShown && !hideZipCodeModal) 3353 $('#location-box').modal('show'); 3354 } 3355 } else { 3356 getGeoLocationJS.handleMapQuestApiError(response.info.statuscode); 3357 } 3358 } 3359 } 3360 } 3361 }; 3362 3363 req.open("GET", url, true); 3364 req.onerror = function() { 3365 console.log("Error while trying to fetch data from MaQuest API"); 3366 } 3367 if (!isError) { 3368 req.send(); 3369 } 3370 } 3371 }, 3372 3373 showError: function(error) { 3374 switch (error.code) { 3375 case error.PERMISSION_DENIED: 3376 console.info("User denied the request for Geolocation"); 3377 var name = "location"; 3378 getGeoLocationJS.cookieValue = getGeoLocationJS.getCookie(name); 3379 if (!getGeoLocationJS.locationPromptValue) { 3380 sessionStorage.setItem(getGeoLocationJS.locationPrompt, "N"); 3381 } 3382 if (getGeoLocationJS.cookieValue == "") { 3383 var enterZip = document.getElementById('geo-update').getAttribute('data-enterzip'); 3384 document.getElementById("city").innerHTML = DOMPurify.sanitize(enterZip); 3385 if ($('.filter-location').length > 0) { 3386 document.getElementById('location-update').innerHTML = DOMPurify.sanitize(enterZip); 3387 document.getElementById('available-in').innerHTML = ""; 3388 document.getElementById('location-update').setAttribute("data-gtm-asset", enterZip); 3389 } 3390 3391 3392 3393 } else { 3394 getGeoLocationJS.mapRequestAPICall(); 3395 } 3396 break; 3397 case error.POSITION_UNAVAILABLE: 3398 console.log("Location information is unavailable."); 3399 break; 3400 case error.TIMEOUT: 3401 console.log("The request to get user location timed out."); 3402 break; 3403 case error.UNKNOWN_ERROR: 3404 console.log("An unknown error occurred."); 3405 break; 3406 } 3407 }, 3408 3409 handleMapQuestApiError: function(error) { 3410 switch (error) { 3411 case 400: 3412 console.log("Error in MAPQuestAPI - Error with Input"); 3413 break; 3414 case 403: 3415 console.log("Error in MAPQuestAPI - Key related Error"); 3416 break; 3417 case 500: 3418 console.log("Error in MAPQuestAPI - Unknown Error"); 3419 break; 3420 default: 3421 console.log("Error in MAPQuestAPI - An unknown error occurred."); 3422 break; 3423 } 3424 }, 3425 handleLocationInput: function(value) { 3426 var length = value.length; 3427 var presentValue = value[length - 1]; 3428 var isnum = /^\d+$/.test(presentValue); 3429 if (!isnum) { 3430 value = value.slice(0, length - 1); 3431 document.getElementById('updateLoc').value = value; 3432 } 3433 if (value.length > getGeoLocationJS.maxLength) { 3434 value = value.slice(0, getGeoLocationJS.maxLength); 3435 document.getElementById('updateLoc').value = value; 3436 } else if(value.length === getGeoLocationJS.maxLength){ 3437 document.querySelector('#locator-button')?.classList.remove('disabled'); 3438 getGeoLocationJS.hideError(); 3439 } else { 3440 document.querySelector("#updateLoc")?.classList.remove("success"); 3441 document.querySelector('#locator-button')?.classList.add('disabled'); 3442 } 3443 }, 3444 validateLocationInput: function(value) { 3445 if(value && value.length<getGeoLocationJS.maxLength){ 3446 getGeoLocationJS.showErrorMessage(); 3447 } else if(value && value.length===getGeoLocationJS.maxLength){ 3448 getGeoLocationJS.hideError(); 3449 } 3450 }, 3451 showErrorMessage: function(msgType) { 3452 3453 let locErrorMsg = document.getElementById('geo-update')?.getAttribute('data-errormsg'); 3454 let zipCodeReqErrMsg = document.getElementById('geo-update')?.getAttribute('data-noziperrormsg'); 3455 let brand = document.querySelector(".section-api-container").dataset.brand.toLowerCase(); 3456 3457 let hideZipCodeModal = document.querySelector(".section-api-container")?.dataset.hidezipcodemodal; 3458 3459 hideZipCodeModal === "true" ? document.getElementById("updateLoc")?.classList.add("error-nozip") : document.getElementById("updateLoc")?.classList.add("error"); 3460 document.getElementById("updateLoc")?.classList.remove("success"); 3461 if(document.querySelector("label[for='updateLoc']") ) { 3462 document.querySelector("label[for='updateLoc']").style.color="#A41412"; 3463 } 3464 3465 if(document.getElementById("errorMsg")){ 3466 document.getElementById("errorMsg").innerHTML = document.getElementById("errorMsg") ? msgType == "showZipReqError" ? DOMPurify.sanitize(zipCodeReqErrMsg) : DOMPurify.sanitize(locErrorMsg) : ""; 3467 } 3468 3469 this.changeLinkBgColor('#000d59','#dfdfdf'); 3470 3471 //tracfone specific styling 3472 if(brand === "tracfone") { 3473 if(document.querySelector("label[for='updateLoc']") ) { 3474 // For required field error (no zip entered), use red color 3475 // For invalid zip format error, use gray color 3476 if(msgType === "showZipReqError") { 3477 document.querySelector("label[for='updateLoc']").style.color="#A41412"; 3478 } else { 3479 document.querySelector("label[for='updateLoc']").style.color="#808080"; 3480 } 3481 } 3482 3483 if(document.querySelector("#updateLoc") ) { 3484 document.querySelector("#updateLoc").style.color="#a41412"; 3485 } 3486 3487 } 3488 3489 }, 3490 hideError: function() { 3491 document.getElementById("updateLoc")?.classList.remove("error"); 3492 document.getElementById("updateLoc")?.classList.remove("error-nozip"); 3493 document.getElementById("updateLoc")?.classList.add("success"); 3494 if(document.querySelector("label[for='updateLoc']") ) { 3495 document.querySelector("label[for='updateLoc']").style.color="#666"; 3496 } 3497 3498 if(document.getElementById("errorMsg")){ 3499 document.getElementById("errorMsg").innerHTML = ""; 3500 } 3501 3502 this.changeLinkBgColor('#dfdfdf','#000d59'); 3503 3504 //tracfone specific styling 3505 let brand = document.querySelector(".section-api-container").dataset.brand.toLowerCase(); 3506 3507 if(brand === "tracfone") { 3508 if(document.querySelector("label[for='updateLoc']") ) { 3509 document.querySelector("label[for='updateLoc']").style.color="#808080"; 3510 } 3511 3512 if(document.querySelector("#updateLoc") ) { 3513 document.querySelector("#updateLoc").style.color="#313334"; 3514 } 3515 3516 } 3517 3518 }, 3519 changeLinkBgColor:function(fromColor,toColor) { 3520 3521 let plpLinkSelector=".broadband-plans-list .plan-list-heading .containerZip a"; 3522 let pdpLinkSelector = ".fcc-review-details .review-details-tab .containerZip a"; 3523 3524 let linkSelector = document.querySelector(plpLinkSelector) ? plpLinkSelector : pdpLinkSelector; 3525 3526 let linkBgColor = document.querySelector(linkSelector+" .input-group-addon") ? this.getHexColor(window.getComputedStyle(document.querySelector(linkSelector+" .input-group-addon")).backgroundColor) : ""; 3527 if(linkBgColor && linkBgColor.toLowerCase().indexOf(fromColor)>=0) { 3528 document.querySelector(linkSelector).style.backgroundColor=toColor; 3529 document.querySelector(linkSelector+" .input-group-addon").style.backgroundColor=toColor; 3530 } 3531 } 3532 3533}; 3534 3535if (document.getElementById("geo-update") || document.getElementById("updateLoc")) { 3536 getGeoLocationJS.prepopulateZipCode(); 3537 getGeoLocationJS.getLocation(); 3538} 3539 3540// Add event listeners for zip code prepopulation 3541document.addEventListener('DOMContentLoaded', function() { 3542 getGeoLocationJS.prepopulateZipCode(); 3543}); 3544 3545document.addEventListener('LoadPDPDetails', function() { 3546 setTimeout(() => { 3547 getGeoLocationJS.prepopulateZipCode(); 3548 }, 200); 3549}); 3550 3551document.addEventListener('LoadProductDetailContent', function() { 3552 setTimeout(() => { 3553 getGeoLocationJS.prepopulateZipCode(); 3554 }, 300); 3555}); 3556 3557$(document).on("PurchasePLPLoaded", function() { 3558 if (document.getElementById("geo-update")) { 3559 getGeoLocationJS.getLocation(); 3560 } 3561 getGeoLocationJS.prepopulateZipCode(); 3562}); 3563var rangeSlider = (function(){ 3564 var maxRange; 3565 var minRange; 3566 var stepValue;
3567 function init(){ 3568 $(".slider").each(function(){ 3569 maxRange = parseInt($(this).attr('data-maxrange')); 3570 minRange = parseInt($(this).attr('data-minrange')); 3571 stepValue = parseInt($(this).attr('data-stepvalue')); 3572 var unlimitedLabel = $(this).attr('data-unlimitedlabel'); 3573 var sliderType = $(this).attr('data-type'); 3574 if(sliderType!=null){ 3575 sliderType = sliderType.toLowerCase(); 3576 } 3577 var tooltip1 = ""; 3578 var tooltip2 = ""; 3579 var showUnlimited = $(this).attr('data-showUnlimited'); 3580 var currentSlider = $(this); 3581 if(sliderType === 'price'){ 3582 $( ".start-price" ).html( "$" + minRange ); 3583 $( ".end-price" ).html( "$" + maxRange ); 3584 tooltip1 = $('<span class="tooltip-min legal text-color-grey"/>').html( "$" + minRange ).css({position: 'absolute',top: -21,left: '10%'}).attr('data-minVal',minRange); 3585 tooltip2 = $('<span class="tooltip-max legal text-color-grey"/>').html( "$" + maxRange ).css({position: 'absolute',top: 33,left: '10%'}).attr('data-maxVal',maxRange); 3586 3587 } else if(sliderType === 'data'){ 3588 var minDataUnit = maxDataUnit ="MB"; 3589 var minRangeDsp =minRange; 3590 var maxRangeDsp =maxRange; 3591 if(minRange>=1024){ 3592 minRangeDsp = (minRange/1024).toFixed(1); 3593 minDataUnit ="GB"; 3594 } 3595 $( ".start-price" ).html( minRangeDsp +" "+minDataUnit); 3596 tooltip1 = $('<span class="tooltip-min legal text-color-grey"/>').html( minRangeDsp+" "+minDataUnit).css({position: 'absolute',top: -21}).attr('data-minVal',minRange-1); 3597 3598 if(showUnlimited==="true"){ 3599 $( ".end-price" ).html(unlimitedLabel); 3600 tooltip2 = $('<span class="tooltip-max legal text-color-grey"/>').html( unlimitedLabel).css({position: 'absolute',top: 33}).attr('data-maxVal',maxRange+1); 3601 }else{ 3602 3603 if(maxRange>=1024){ 3604 maxRangeDsp =(maxRange/1024).toFixed(1); 3605 maxDataUnit ="GB"; 3606 } 3607 $( ".end-price" ).html( maxRangeDsp+" "+maxDataUnit); 3608 tooltip2 = $('<span class="tooltip-max legal text-color-grey"/>').html( maxRangeDsp+" "+maxDataUnit).css({position: 'absolute',top: 33}); 3609 } 3610 }else if(sliderType === 'text'){ 3611 $( ".start-price" ).html( minRange ); 3612 $( ".end-price" ).html( maxRange ); 3613 tooltip1 = $('<span class="tooltip-min legal text-color-grey"/>').html( minRange ).css({position: 'absolute',top: -21,left: '10%'}).attr('data-minVal',minRange); 3614 tooltip2 = $('<span class="tooltip-max legal text-color-grey"/>').html( maxRange ).css({position: 'absolute',top: 33,left: '10%'}).attr('data-maxVal',maxRange); 3615 } else if(sliderType === 'talk'){ 3616 $( ".start-price" ).html( minRange ); 3617 $( ".end-price" ).html( maxRange ); 3618 tooltip1 = $('<span class="tooltip-min legal text-color-grey"/>').html( minRange + "minutes" ).css({position: 'absolute',top: -21,left: '10%'}).attr('data-minVal',minRange); 3619 tooltip2 = $('<span class="tooltip-max legal text-color-grey"/>').html( maxRange + "minutes" ).css({position: 'absolute',top: 33,left: '10%'}).attr('data-maxVal',maxRange); 3620 } 3621 $( function() { 3622 $(currentSlider).slider({ 3623 range: true, 3624 step: stepValue, 3625 min: minRange, 3626 max: maxRange, 3627 values: [ minRange , maxRange ], 3628 slide: function( event, ui ) { 3629 var minVal = ui.values[ 0 ]; 3630 var maxVal = ui.values[ 1 ]; 3631 if(sliderType === 'price'){ 3632 $(currentSlider).find( ".tooltip-min" ).text( "$" + minVal ).attr('data-minVal',minVal); 3633 $(currentSlider).find( ".tooltip-max" ).text( "$" + maxVal ).attr('data-maxVal',maxVal); 3634 3635 } 3636 else if(sliderType === 'data'){ 3637 var minDataUnit = maxDataUnit ="MB"; 3638 var minRangeDsp =minVal; 3639 var maxRangeDsp =maxVal; 3640 if(minVal>=1024){ 3641 minRangeDsp = (minVal/1024).toFixed(1); 3642 minDataUnit ="GB"; 3643 } 3644 $( ".tooltip-min" ).text( minRangeDsp +" "+minDataUnit).attr('data-minVal',minVal - 1); 3645 if(showUnlimited==="true" && maxVal===maxRange){ 3646 $(currentSlider).find( ".tooltip-max" ).text(unlimitedLabel).attr('data-maxVal',unlimitedLabel); 3647 }else{ 3648 if(maxVal>=1024){ 3649 maxRangeDsp = (maxVal/1024).toFixed(1); 3650 maxDataUnit ="GB"; 3651 } 3652 $(currentSlider).find( ".tooltip-max" ).text( maxRangeDsp+" "+maxDataUnit).attr('data-maxVal',maxVal + 1); 3653 } 3654 3655 } else if(sliderType === 'text'){ 3656 $(currentSlider).find( ".tooltip-min" ).text( minVal ).attr('data-minVal',minVal); 3657 $(currentSlider).find( ".tooltip-max" ).text( maxVal ).attr('data-maxVal',maxVal); 3658 } else if(sliderType === 'talk'){ 3659 $(currentSlider).find( ".tooltip-min" ).text( minVal + "minutes" ).attr('data-minVal',minVal); 3660 $(currentSlider).find( ".tooltip-max" ).text( maxVal + "minutes" ).attr('data-maxVal',maxVal); 3661 } 3662 var slideEvent = new CustomEvent('slidechangenew', { bubbles: true }); 3663 this.dispatchEvent(slideEvent); 3664 $(currentSlider).find('ul.slider-checkboxes li input[type=checkbox]').each(function(){ 3665 if($(this).attr('checked') == 'checked'){ 3666 $(this).removeAttr("checked"); 3667 } 3668 }); 3669 $(currentSlider).addClass('selectedRange'); 3670 $(currentSlider).find('ul.slider-checkboxes').removeClass('selectedRange'); 3671 }, 3672 }); 3673 setTimeout(function () { 3674 $(currentSlider).find("span.ui-slider-handle:eq(0)").append( tooltip1 ); 3675 $(currentSlider).find("span.ui-slider-handle:eq( 1 )" ).append( tooltip2 ); 3676 }, 0); 3677 3678 } ); 3679 3680 3681 $('ul.slider-checkboxes li input[type=checkbox]').on('click',function(){ 3682 currentSlider.removeClass('selectedRange'); 3683 $(this).closest('ul.slider-checkboxes').addClass('selectedRange'); 3684 resetSlider(); 3685 }) 3686 3687 3688 //Clear All Start 3689 $(".clear-all > a").on('click', function(){ 3690 clearAllFilters(); 3691 document.dispatchEvent(new Event('filterclearevent', { 'bubbles': true })); 3692 }); 3693 //Clear All End 3694 }); 3695 } 3696 3697 function clearAllFilters() { 3698 $('.filter-rating li').each(function(){ 3699 $(this).removeClass('filter-rating-black'); 3700 $(this).removeClass('selected'); 3701 }); 3702 resetSlider(); 3703 $('.filter-fields li').each(function(){ 3704 if($(this).find('.custom-checkbox .custom-control-input').attr("checked")){ 3705 $(this).find('.custom-checkbox .custom-control-input').removeAttr("checked"); 3706 } 3707 }); 3708 if($('.all-filter-count')){ 3709 $('.all-filter-count').parent().removeClass('disabled'); 3710 $('.all-filter-error').addClass('d-none'); 3711 } 3712 } 3713 3714 function resetSlider(){ 3715 $(".slider").each(function(){ 3716 var $sliderReset = $(this); 3717 $(this).removeClass("selectedRange"); 3718 $sliderReset.slider("values", 0, minRange); 3719 $sliderReset.slider("values", 1, maxRange); 3720 $(".tooltip-min").html($( ".start-price" ).html()); 3721 $(".tooltip-max").html($( ".end-price" ).html()); 3722 }); 3723 } 3724 3725 return{ 3726 init: init,resetSlider: resetSlider, clearAllFilters: clearAllFilters 3727 } 3728})(); 3729 3730$( document ).ready( function(){ 3731 rangeSlider.init(); 3732}); 3733 3734 3735//Compare Page Close button functionality - Start 3736$('body').on('click',".product-compare-nav .close-container", function(){ 3737 let id = $(this).attr('data-productId'); 3738 let productId = $(this).attr('data-id'); 3739 var itemLength = $('.close-compare').length; 3740 var prdctJson = JSON.parse(window.localStorage.getItem('compareProducts')); 3741 3742 3743 if(itemLength-1>0){ 3744 for (let count =0; count<prdctJson.compareProducts.length;count++) 3745 { 3746 if(prdctJson.compareProducts[count] != null && productId==prdctJson.compareProducts[count].productid) 3747 { 3748 prdctJson.compareProducts.splice(count,1); 3749 } 3750 } 3751 if(prdctJson.compareProducts.length>0) 3752 { 3753 localStorage.setItem('compareProducts', JSON.stringify(prdctJson)); 3754 } 3755 else 3756 {
3757 localStorage.removeItem('compareProducts'); 3758 } 3759 3760 $('.compare-wrapper').find('a[data-closeid="'+productId+'"]').trigger('click'); 3761 $("div[data-productId='" + id +"']").remove(); 3762 if($('.phone-compare-carousel').find('.addAnotherPhone').length ==0){ 3763 $('.phone-compare-carousel').trigger('add.owl.carousel', [$('<div class ="text-center addAnotherPhone"><div class="phone-card '+($('#horizontal-nav-compare').data('comptype')==='plan'?'plan-card':'')+' text-center d-flex flex-column addAnotherPhoneContainer" aria-label="Phone One"></div></div>')]).trigger('refresh.owl.carousel'); 3764 } 3765 if(window.matchMedia("(min-width: 1024px)").matches){ 3766 $(".addAnotherPhone").removeClass('d-none'); 3767 $('.phone-compare-carousel').find('.owl-item.active').each(function(index) { 3768 if($(this).find('.phone-card').length ==0){ 3769 $(this).remove(); 3770 } 3771 }); 3772 } 3773 else if(window.matchMedia("(max-width: 1023px)").matches){ 3774 $('.phone-compare-carousel').find('.owl-item.active').each(function(index) { 3775 if($(this).find('.phone-card').length ==0){ 3776 $(this).remove(); 3777 } 3778 }); 3779 $('.phone-compare-carousel').trigger('destroy.owl.carousel'); 3780 $('.phone-compare-carousel').owlCarousel(optionCompare); 3781 } 3782 const plpPage = $('.addAnotherPhone a').prop('href'); 3783 if(itemLength==2 && plpPage) { 3784 window.location.href = plpPage; 3785 } 3786 } 3787}); 3788//Compare Page Close button functionality - End 3789var optionCompare = { 3790 loop:false, 3791 nav:false, 3792 responsive:{ 3793 0:{ 3794 items:2, 3795 onTranslated:updateCompareTable, 3796 onInitialized:updateCompareTable 3797 }, 3798 1024:{ 3799 items:3, 3800 dots:false, 3801 mouseDrag:false, 3802 touchDrag:false, 3803 3804 } 3805 }, 3806 onResized:updateCompareTable 3807 }; 3808 //$('.phone-compare-carousel').owlCarousel(optionCompare); 3809 function updateCompareTable(e){ 3810 $(e.target).find('.owl-item').each(function(index) { 3811 var id = $(this).find('.phone-card').attr('data-productId'); 3812 if($(this).hasClass('active')){ 3813 $("div[data-productId='" + id +"']").show(); 3814 if($(this).find('.addAnotherPhone').length>0){ 3815 3816 $(".addAnotherPhone").removeClass('d-none'); 3817 } 3818 } 3819 else{ 3820 $("div[data-productId='" + id +"']").hide(); 3821 $(".addAnotherPhone").addClass('d-none'); 3822 } 3823 }); 3824 var count = $(e.target).find('.owl-dot').length; 3825 var widthDots = ((count*24)+10)+"px"; 3826 $(e.target).find('.owl-dots').css('width',widthDots); 3827 $(e.target).find('.owl-dot').each(function(index) { 3828 let slidenbr = index+1; 3829 let desc = "Slide "+slidenbr+ " of " +count; 3830 $(this).attr('aria-label', desc); 3831 }); 3832 } 3833 3834document.addEventListener('compareCarouselLoad', function(){ 3835 $('.phone-compare-carousel').owlCarousel(optionCompare); 3836}); 3837 3838//Compare Tab Start 3839$('body').on("click", ".compare-wrapper .clear-compare-selection ", function() { 3840 var id = $(this).attr('data-closeid'); 3841 var accesiblityRemovedLabel = '<span class="sr-only" role="alert">'+$(this).attr('data-removelabel')+'</span>'; 3842 var compareData = window.localStorage.getItem('compareProducts'); 3843 if (compareData != null && compareData != undefined) { 3844 var prdctJson = JSON.parse(compareData); 3845 3846 for (let count = 0; count < prdctJson.compareProducts.length; count++) { 3847 if (prdctJson.compareProducts[count] != null && id == prdctJson.compareProducts[count].productid) { 3848 prdctJson.compareProducts.splice(count, 1); 3849 } 3850 } 3851 if (prdctJson.compareProducts.length > 0) { 3852 setLocalStorage('compareProducts', JSON.stringify(prdctJson)); 3853 } else { 3854 localStorage.removeItem('compareProducts'); 3855 } 3856 } 3857 $('.compare-bar .compare-item-removed').html(accesiblityRemovedLabel); 3858 const escapeId = id.indexOf('.') ? id.replaceAll('.','\\.') : id; 3859 const productType = $("div[data-productid='" + id + "']").attr('data-producttype'); 3860 if (document.querySelector('.eligible-offer-wrapper input[id="' + escapeId+'"]')) { 3861 $('.eligible-offer-wrapper')?.find('input[id="' + escapeId+'"]').trigger('click'); 3862 } else if (document.querySelector('.compare-plp-cards input[id="' + escapeId+'"]')){ 3863 $('.compare-plp-cards').find('input[id="' + escapeId+'"]').trigger('click'); 3864 } else { 3865 closeCompareTab(id); 3866 } 3867}); 3868 3869function compareCheckBoxCommonCode(checkbox, productType) { 3870 var id = checkbox.id; 3871 var modelJsonUrl = checkbox.getAttribute("data-modeljson");
3872 var compareItemSelected = $(".compare-bar .compare-row .phone-wrapper .item-wrapper").length; 3873 var defaultThumbnail = $('section').attr('data-defaultphonethumbnail'); 3874 if (productType === 'plan') { 3875 checkbox.getAttribute("checked") !== "checked" ? checkbox.setAttribute("checked", "checked") : checkbox.removeAttribute("checked"); 3876 } else { 3877 if ($(checkbox).parents('.eligible-offer-wrapper').length > 0) { 3878 const plpCardVersion = document.querySelector(`.compare-plp-cards .custom-checkbox input[id='${id}']`); 3879 if (plpCardVersion) { 3880 if (checkbox.checked === "checked") { 3881 plpCardVersion.setAttribute("checked", "checked"); 3882 } else { 3883 plpCardVersion.removeAttribute("checked"); 3884 } 3885 } 3886 } 3887 } 3888 if ($(checkbox).parents('.compare-plp-cards').length > 0) { 3889 const queryString = `.eligible-offer-wrapper .custom-checkbox input[id='${id}']`; 3890 const eligibleOfferCardEquivalent = document.querySelector(queryString); 3891 if (eligibleOfferCardEquivalent) { 3892 if (checkbox.getAttribute("checked") === "checked") { 3893 eligibleOfferCardEquivalent.setAttribute("checked", "checked"); 3894 } else { 3895 eligibleOfferCardEquivalent.removeAttribute("checked"); 3896 } 3897 } 3898 } else if ($(checkbox).parents('.eligible-offer-wrapper').length > 0) { 3899 const queryString = `.compare-plp-cards .custom-checkbox input[id='${id}']`; 3900 const eligibleOfferCardEquivalent = document.querySelector(queryString); 3901 if (eligibleOfferCardEquivalent) { 3902 if (checkbox.getAttribute("checked") === "checked") { 3903 eligibleOfferCardEquivalent.setAttribute("checked", "checked"); 3904 } else { 3905 eligibleOfferCardEquivalent.removeAttribute("checked"); 3906 } 3907 } 3908 } 3909 if (checkbox.getAttribute("checked")) { // add attributes on check box 3910 if ($('.compare-bar .compare-wrapper').find('[data-id ="' + id + '"]').length == 0) { 3911 $('.compare-bar-close-alert').hide(); 3912 if (compareItemSelected < 3) { 3913 var compareImge = $("div[data-productid='" + id + "']").attr('data-compareimage'); 3914 var compareImgeAssetId = $("div[data-productid='" + id + "']").attr('data-compareassetid'); 3915 var compareImgeAgencyId = $("div[data-productid='" + id + "']").attr('data-compareassetagencyid'); 3916 var productName = $("div[data-productid='" + id + "']").attr('data-productName'); 3917 var pageUrl = $("div[data-productid='" + id + "'] .product-button a").attr('data-href'); 3918 var planDetailList = $("div[data-productid='" + id + "'] .multiple-bucket").is(':visible')? 3919 '<ul class="pl-0 text-left plan-details-list">'+$("div[data-productid='" + id + "'] .plan-details-list").html()+'</ul>' 3920 :$("div[data-productid='" + id + "'] .single-bucket .plan-detail").html(); 3921 var planPrice = $("div[data-productid='" + id + "'] .plan-price").data('planprice'); 3922 var serviceDays = $("div[data-productid='" + id + "']").data('servicedays'); 3923 var planDeviceType = $("div[data-productid='" + id + "']").data('plandevicetype'); 3924 3925 if(!planPrice) { 3926 planPrice = productName; 3927 } 3928 if (compareImge == null || compareImge == undefined || compareImge == "") { 3929 compareImge = defaultThumbnail; 3930 } 3931 3932 if (pageUrl == undefined || pageUrl == null) 3933 pageUrl = $("div[data-productid='" + id + "'] .product-button a").attr('href') || $("div[data-productid='" + id + "']").parent().attr('data-href') || $("div[data-productid='" + id + "']").attr('data-href'); 3934 3935 var serviceDaysArray = serviceDays ? serviceDays.split(" ") : ["",""]; 3936 var compareItemHtml = productType !== 'plan' ? 3937 `<li class="wrapper item-wrapper" data-id="${id}" data-modelUrl="${modelJsonUrl}" data-imageurl="${compareImge}" data-pageurl="${pageUrl}" data-productname="${productName}" 3938 data-compareassetid="${compareImgeAssetId}
3938" data-compareassetagencyid="${compareImgeAgencyId}"> 3939 <div class="phone-image-wrap d-inline-block"> 3940 <img data-src="${compareImge}" src="" data-gtm-asset="${compareImgeAssetId}" data-gtm-agencyid="${compareImgeAgencyId}" class="responsiveimage" alt="Icon of ${productName}"> 3941 </div> 3942 <div class="phone-name-wrap caption-one d-inline-block"> 3943 <span class="text-break">${productName}</span> 3944 </div> 3945 <a class="clear-compare-selection" href="javascript:void(0)" data-closeid ="${id}" role="button" 3946 data-removelabel="${productName} has been removed" aria-label="Remove ${productName} from compare"> 3947 <span class="icon dark-theme large-icon"><i class="clear"></i></span> 3948 </a> 3949 </li>`: 3950 `<li class="wrapper plan-wrapper item-wrapper" data-id="${id}" data-modelUrl="${modelJsonUrl}" data-pageurl="${pageUrl}" data-productname="${planPrice}" 3951 data-servicedays="${serviceDays}" data-plandevicetype="${planDeviceType}"> 3952 <div class="d-flex flex-row justify-content-between"> 3953 <div class="plan-wrap caption-one"> 3954 <div> 3955 <div class="legal font-weight-bolder">${planDeviceType}</div> 3956 <div class="plan-price border-bottom-medium-grey pb-05"> 3957 ${planPrice}<span class="plan-days">/${serviceDaysArray[0]}</span> 3958 <span class="legal color-black">${serviceDaysArray[1]?serviceDaysArray[1]:''}</span> 3959 </div> 3960 </div> 3961 <div class="plan-detail mx-auto">${planDetailList}</div> 3962 </div> 3963 <a class="clear-compare-selection" data-closeid="${id}" href="javascript:void(0)" role="button" 3964 aria-label="Remove ${planPrice} ${planDeviceType} from compare" data-removelabel="${productName} has been removed" > 3965 <span class="icon dark-theme large-icon"><i class="clear"></i></span> 3966 </a> 3967 </div> 3968 </li>`; 3969 document.querySelector(".compare-wrapper ul.phone-wrapper .empty-wrapper").insertAdjacentHTML('beforebegin', compareItemHtml); 3970 3971 let updatedCount = $(".compare-bar .compare-row .phone-wrapper .item-wrapper").length; 3972 if ($(".compare-bar").is(":hidden")) $(".compare-bar").show(); 3973 const compareBtn = $(".compare-button .btn"); 3974 if (updatedCount == 2) { 3975 const ariaLabel = compareBtn.data('arialabel'); 3976 compareBtn.attr('aria-label', ariaLabel); 3977 $(".compare-button .extra-small").removeClass('disabled'); 3978 compareBtn.focus(); 3979 } else if (updatedCount > 2) { 3980 $(".compare-wrapper ul .empty-wrapper").hide(); 3981 $(".compare-plp-cards .custom-checkbox .custom-control-input:not(:checked)").attr("disabled", "disabled"); 3982 compareBtn.focus(); 3983 } 3984 loadDynamicMediaImages(); 3985 } else { 3986 $(this).removeAttr("checked", "checked"); 3987 $(".compare-wrapper ul .empty-wrapper").hide(); 3988 $(".compare-plp-cards .custom-checkbox .custom-control-input:not(:checked)").attr("disabled", "disabled"); 3989 } 3990 } 3991 } else { 3992 closeCompareTab(id); 3993 } 3994} 3995 3996$('body').on("click", ".eligible-offer-wrapper .custom-checkbox .custom-control-input, .compare-plp-cards .custom-checkbox .custom-control-input", function() { 3997 compareCheckBoxCommonCode(this); 3998}); 3999 4000function closeCompareTab(id) { 4001 if ($(".compare-bar .compare-row .phone-wrapper .item-wrapper").length <= 3) { 4002 $(".compare-wrapper ul .empty-wrapper").show(); 4003 } 4004 $("li.wrapper[data-id='" + id + "']").remove(); 4005 $(".eligible-offer-wrapper .custom-checkbox .custom-control-input:not(:checked), .compare-plp-cards .custom-checkbox .custom-control-input:not(:checked)").removeAttr("disabled", "disabled"); 4006 4007 var length = $(".compare-bar li.wrapper").length; 4008 if (length == 1) { 4009 $('.compare-bar-close-alert').show(); 4010 $(".compare-bar").hide(); 4011 $('.compare-bar .compare-item-removed').html(''); 4012 const escapeId = id.indexOf('.') ? id.replaceAll('.','\\.') : id; 4013 $('.compare-plp-cards').find('[id="' + escapeId+'"]').focus(); 4014 } 4015 if (length == 2) { 4016 const compareBtn = $(".compare-button .btn"); 4017 $(".compare-button .extra-small").addClass('disabled'); 4018 var disabledLabel = compareBtn.attr('data-disabledarialabel'); 4019 compareBtn.attr('aria-label', disabledLabel); 4020 } 4021 4022} 4023//Compare Tab Ends 4024 4025$('body').on("click", ".compare-bar .compare-button a", function() { 4026 4027 var selectedList = $(".compare-bar .compare-wrapper li.item-wrapper"); 4028 var filterList = ''; 4029 4030 var compareData = { 4031 compareProducts: [] 4032 }; 4033 4034 var filterList = { 4035 phoneType: [], 4036 brands: [], 4037 price: [], 4038 ratings: [] 4039 }; 4040 4041 $('.filter-checkbox li').each(function() { 4042 var brandId = $(this).find('input[checked ="checked"]').attr("id"); 4043 if (brandId != "" && brandId != null && brandId != undefined) { 4044 var brandData = { 4045 "brandId": brandId 4046 } 4047 4048 filterList.brands.push(brandData); 4049 } 4050 4051 }); 4052 4053 if ($('.slider').length > 0 && $('.slider').hasClass('selectedRange')) { 4054 4055 var priceRange = $(".range-slider").attr("data-permanentval"); 4056 if (priceRange != "" && priceRange != null && priceRange != undefined) { 4057 var priceData = { 4058 "minVal": priceRange.split(',')[0], 4059 "maxVal": priceRange.split(',')[1] 4060 4061 } 4062 4063 filterList.price.push(priceData); 4064 } 4065 4066 } else if ($('.slider-checkboxes') != null) { 4067 4068 if ($('.slider-checkboxes').length > 0 && $('.slider-checkboxes').hasClass('selectedRange')) { 4069 4070 $('.slider-checkboxes li').each(function() { 4071 var sliderCheckboxId = $(this).find('input[checked ="checked"]').attr("id"); 4072 if (sliderCheckboxId != "" && sliderCheckboxId != null && sliderCheckboxId != undefined) { 4073 var sliderPriceId = { 4074 "sliderPriceId": sliderPriceId 4075 } 4076 4077 filterList.price.push(sliderPriceId); 4078 } 4079 4080 }); 4081 4082 } 4083 4084 } 4085 4086 4087 4088 $('.phone-selector.product-type-selector li').each(function() { 4089 var phoneTypeId = $(this).find("label.selected input").attr("id");
4090 if (phoneTypeId != "" && phoneTypeId != null && phoneTypeId != undefined) { 4091 var phoneTypeData = { 4092 "phoneTypeId": phoneTypeId 4093 } 4094 4095 filterList.phoneType.push(phoneTypeData); 4096 } 4097 4098 }); 4099 4100 var ratingVal = $('.filter-rating li.selected').attr("data-index"); 4101 if (ratingVal != "" && ratingVal != null && ratingVal != undefined) { 4102 var ratingData = { 4103 "rating": ratingVal 4104 } 4105 4106 filterList.ratings.push(ratingData); 4107 } 4108 4109 4110 $('.compare-bar .compare-wrapper li.item-wrapper').each(function() { 4111 var productId = $(this).attr("data-id"); 4112 var url = $(this).attr("data-modelurl"); 4113 var imageUrl = $(this).attr("data-imageurl"); 4114 var compareImgeAssetId = $(this).attr('data-compareassetid'); 4115 var compareImgeAgencyId = $(this).attr('data-compareassetagencyid'); 4116 var productName = $(this).attr("data-productname"); 4117 var pageUrl = $(this).attr("data-pageurl"); 4118 var serviceDays = $(this).attr("data-servicedays"); 4119 var planDetailList = $(this).find(".plan-detail").html(); 4120 var planDeviceType = $(this).attr("data-plandevicetype"); 4121 4122 if (productId != "" && productId != null && productId != undefined) { 4123 var jsonData = { 4124 "compareImage": imageUrl, 4125 "productName": productName, 4126 "productid": productId, 4127 "url": url, 4128 "pageurl": pageUrl, 4129 "serviceDays": serviceDays, 4130 "planDetailList": planDetailList, 4131 "planDeviceType": planDeviceType, 4132 "compareImgeAssetId": compareImgeAssetId, 4133 "compareImgeAgencyId": compareImgeAgencyId 4134 } 4135 4136 compareData.compareProducts.push(jsonData); 4137 } 4138 4139 4140 }); 4141 4142 compareData.compareType = document.querySelector('.product-filter-container')?.dataset.categorytype||document.querySelector('.multiline-plan-card-wrapper')?.dataset.categorytype; 4143 setLocalStorage('compareProducts', JSON.stringify(compareData)); 4144 setLocalStorage('filtersData', JSON.stringify(filterList)); 4145 4146}); 4147 4148/** 4149 * allow focus on compare buton's item's close buttons 4150 */ 4151function focusCompareItemCloseButtons() { 4152 $('.compare-bar .compare-button .btn').on('focus keydown keyup', () => { 4153 const phoneWrapperCount = $('.compare-bar .phone-wrapper .wrapper')?.length 4154 if(phoneWrapperCount && phoneWrapperCount >= 3){ 4155 $('.compare-bar .compare-row .phone-wrapper .item-wrapper a.clear-compare-selection').attr('tabindex','0').removeAttr('aria-hidden'); 4156 } 4157 }) 4158 $('.compare-bar').on('keydown', 'a.clear-compare-selection', (e) => { 4159 const phoneWrappers = $('.compare-bar .phone-wrapper .wrapper'); 4160 const phoneWrapperCount = phoneWrappers?.length; 4161 if(e.key === 'Tab' && e.target.parentElement === phoneWrappers[phoneWrapperCount - 2]){ 4162 if (e.shiftKey) { 4163 return; 4164 } 4165 e.preventDefault(); 4166 if(phoneWrapperCount === 3 ){ 4167 const targetId = e.target.dataset.closeid; 4168 const cardContainer = $('#' + targetId)[0]?.closest('.product-card-container'); 4169 const siblingContainer = cardContainer?.parentElement?.nextSibling?.querySelector('.product-card-container'); 4170 if(siblingContainer){ 4171 siblingContainer?.querySelector('.custom-control.custom-checkbox input.custom-control-input')?.focus(); 4172 }else{ 4173 cardContainer.querySelector('#' + targetId)?.focus(); 4174 } 4175 }else if(phoneWrapperCount === 4){ 4176 tabStop(document.querySelector('.compare-bar .compare-row'),false); 4177 } 4178 } 4179 }) 4180} 4181 4182function setLocalStorage(key, val) { 4183 if (window.localStorage.getItem(key) != null) { 4184 localStorage.removeItem(key); 4185 } 4186 4187 localStorage.setItem(key, val); 4188} 4189//Compare Tab End 4190$(function() { 4191 //HYLA Multi Page Form 4192 const tradeInModal = document.querySelector('.trade-in-modal'); 4193 if (tradeInModal === null) return; 4194 const BASE_HYLA_URL = tradeInModal.dataset.apibaseurl; 4195 if (!BASE_HYLA_URL || BASE_HYLA_URL.length <= 0) return console.log('Hyla base url is missing. Check that it is available for the component'); 4196 const HYLA_MODELS_PATH = BASE_HYLA_URL + '/models'; 4197 const HYLA_TOKEN_API = BASE_HYLA_URL + '/haas/token'; 4198 const HYLA_ATTRIBUTES_API = HYLA_MODELS_PATH + '/attributes'; 4199 const HYLA_TOPMODELS_API = HYLA_MODELS_PATH + '/topmodels'; 4200 const HYLA_PRICE_API = '/price'; 4201 const HYLA_QUESTIONS_API = '/questions'; 4202 const HYLA_AGENCY_ID = 'hyla' 4203 const BEARER_STRING = 'Bearer'; 4204 const GET_METHOD = 'GET';
4205 const POST_METHOD = 'POST'; 4206 const $tradeModal = $('#trade-in-box'); 4207 const $stepsForm = $tradeModal.find('.steps-form'); 4208 const $nextBtn = $tradeModal.find('.js-step-next'); 4209 const $prevBtn = $tradeModal.find('.js-step-previous'); 4210 const $submitBtn = $('.js-step-submit'); 4211 const $cancelBtn = $('.js-no-thanks-tradein'); 4212 const closeBtn = document.querySelector('.trade-in-modal .close'); 4213 const $loader = $('.tradein-loader'); 4214 const hylaGetCartEvent = new Event('hylaGetCart'); 4215 const hylaContentData = JSON.parse(localStorage.getItem('hylaContentData')); 4216 const hylaFormData = JSON.parse(localStorage.getItem('hylaFormData')); 4217 const clientId = $('.section-api-container').attr('data-clientid'); 4218 const clientIdParam = 'client_id'; 4219 4220 const brandName = $('.section-api-container').attr('data-brand'); 4221 4222 let token; 4223 let refreshToken; 4224 let orderId; 4225 let hasDeviceInCart; 4226 let isModalInReact = false; 4227 let formData = new StepsFormData('.steps-form'); 4228 let hasContentChangedFromLS = false; 4229 let hylaContentObj = {}; 4230 let hasRecalled = false; 4231 4232 if(brandName === "STRAIGHT_TALK" ){ 4233 $loader.find('img').attr('src', "/etc.clientlibs/straighttalk/clientlibs/clientlib-base/resources/loader/Bars-1.3s-114px.gif" ); 4234 }else if(brandName === "TRACFONE"){ 4235 $loader.find('img').attr('src', "/etc.clientlibs/tracfone/clientlibs/clientlib-base/resources/loader/loader.gif" ); 4236 } 4237 if (hylaFormData !== null) { 4238 formData = $.extend(formData, hylaFormData); 4239 } 4240 4241 function createRequest(url, method, tokenStr, params, body) { 4242 const headers = new Headers({ 4243 'Content-Type': 'application/json', 4244 }); 4245 const requestConfig = {}; 4246 let urlStr = url; 4247 if (method) requestConfig.method = method; 4248 if (body) requestConfig.body = body; 4249 if (tokenStr) headers.append('Authorization', `${BEARER_STRING} ${tokenStr}`); 4250 urlStr = `${url}?${clientIdParam}=${clientId}`; 4251 if (params) urlStr = `${urlStr}&${new URLSearchParams(params).toString()}`; 4252 4253 requestConfig.headers = headers; 4254 4255 if (method === POST_METHOD) { 4256 return requestConfig; 4257 } 4258 4259 return new Request(urlStr, requestConfig); 4260 } 4261 4262 async function fetchHylaApi(request, recall, postUrl, skipDefaultErrorHandling = false) { 4263 try { 4264 let response; 4265 if (postUrl) { 4266 response = await fetch(postUrl, request); 4267 } else if (request instanceof Request) { 4268 response = await fetch(request); 4269 } 4270 4271 if (!response.ok) throw await response.text(); 4272 const resJson = await response.json(); 4273 4274 return resJson; 4275 } catch (error) { 4276 if (!skipDefaultErrorHandling) await handleAPIResponseFailure(error, recall); 4277 throw error; 4278 } 4279 } 4280 4281 async function handleAPIResponseFailure(error, recall) { 4282 let errorJson = {}; 4283 //check for valid json 4284 try { 4285 errorJson = JSON.parse(error); 4286 } catch(err) {} 4287 4288 if (errorJson && errorJson.error === 'invalid_token' && !hasRecalled) { 4289 paramsObj = {}; 4290 paramsObj.grant_type = 'refresh_token'; 4291 paramsObj.refresh_token = refreshToken; 4292 const requestRefreshToken = createRequest(HYLA_TOKEN_API, GET_METHOD, false, paramsObj); 4293 const response = await fetchHylaApi(requestRefreshToken); 4294 token = response.access_token; 4295 refreshToken = response.refresh_token; 4296 hasRecalled = true; 4297 return recall(); 4298 } 4299 showErrorModal(); 4300 } 4301 4302 function createHylaAddToCartObj(orderId) { 4303 const hylaAddToCartObj = 4304 { 4305 id: orderId, 4306 orderItems: [ 4307 { 4308 orderItemExtension: [ 4309 { 4310 name: "processHyla", 4311 value: "true" 4312 }, 4313 { 4314 name: "hylaModelCode", 4315 value: formData.confirmedModel 4316 }, 4317 { 4318 name: "hylaModelName", 4319 value: formData.confirmedModelName 4320 }, 4321 { 4322 name: "hylaCurrencyCode", 4323 value: formData.currencyCode 4324 }, 4325 { 4326 name: "hylaEstimatedPrice", 4327 value: formData.price.toFixed(2).toString() 4328 }, 4329 ] 4330 } 4331 ] 4332 } 4333 4334 $.each(formData.questions, function(index, question) { 4335 const indexUp = index + 1; 4336 hylaAddToCartObj.orderItems[0].orderItemExtension.push({ 4337 name: 'hylaQuestionCode_' + indexUp, 4338 value: question.questionCode 4339 }); 4340 hylaAddToCartObj.orderItems[0].orderItemExtension.push({ 4341 name: 'hylaTextResponse_' + indexUp, 4342 value: question.answerText 4343 }); 4344 hylaAddToCartObj.orderItems[0].orderItemExtension.push({ 4345 name: 'hylaAnswerSkuCode_' + indexUp, 4346 value: question.skuCode 4347 }); 4348 }); 4349 4350 return hylaAddToCartObj; 4351 } 4352 4353 function resetFormData(skips) { 4354 $.each(formData, function(key, value) { 4355 if (skips.indexOf(key) >= 0 || typeof formData[key] === 'function') return true; 4356 if (key === 'questions') { 4357 $('.tradein-questions .tradein-question-list').empty(); 4358 return formData.setData(key, []); 4359 } 4360 formData.setData(key, undefined); 4361 }); 4362 //uncheck confirm ship checkbox 4363 $('.js-confirm-ship').prop('checked', false); 4364 } 4365 4366 //event listeners and handlers 4367 $(document).on('cartLoaded', function(event) { 4368 orderId = event.detail.orderId; 4369 hasDeviceInCart = event.detail.hasDeviceInCart; 4370 }); 4371 4372 //listen for event fired from react app and open modal 4373 $(document).on('tradeInInitiated', function(event) { 4374 isModalInReact = true; 4375 $tradeModal.modal('show'); 4376 }); 4377 4378 //listen for tradein submit success and close modal - react app related event 4379 $(document).on('tradeInSuccess', function(event) { 4380 const href = $submitBtn.attr('href'); 4381 $tradeModal.modal('hide'); 4382 hasContentChangedFromLS = false;
4383 localStorage.setItem('hylaFormData', JSON.stringify(formData)); 4384 localStorage.setItem('hylaContentData', JSON.stringify(hylaContentObj)); 4385 4386 //go to first step 4387 for (let i = 0; i < 6; i++) { 4388 $stepsForm.steps('previous'); 4389 } 4390 4391 if (isModalInReact) return; 4392 4393 return href ? window.location.href = href : false; 4394 }); 4395 4396 //listen for event fired from cif component when response failure 4397 $(document).on('hylaCartResponseFailed', function(event) { 4398 showErrorModal(); 4399 }); 4400 4401 $submitBtn.click(function(event) { 4402 event.preventDefault(); 4403 if (!validate(['confirmShip'])) { 4404 return; 4405 } 4406 4407 if (!hasContentChangedFromLS && hylaContentData !== null && hylaFormData !== null) { 4408 return; 4409 } 4410 4411 const hylaCart = createHylaAddToCartObj(orderId); 4412 4413 if (hylaContentData !== null) { 4414 hylaContentObj = $.extend(hylaContentData, hylaContentObj); 4415 } 4416 const hylaDataObj = { 4417 hyla: hylaCart 4418 } 4419 4420 return document.dispatchEvent(new CustomEvent('hylaAddToCart', {detail: hylaDataObj})); 4421 }); 4422 4423 $nextBtn.click(function(event) { 4424 event.preventDefault(); 4425 $stepsForm.steps('next'); 4426 }); 4427 4428 $prevBtn.click(function(event) { 4429 event.preventDefault(); 4430 $stepsForm.steps('previous'); 4431 }); 4432 4433 function onInitSteps(event, currentIndex) { 4434 switchNextText(currentIndex); 4435 $loader.css('opacity', ''); 4436 $submitBtn.hide(); 4437 $loader.hide(); 4438 } 4439 4440 $stepsForm.on('click', '.single-select-btn', function(event) { 4441 event.preventDefault(); 4442 const $this = $(this); 4443 const fieldName = this.parentNode.dataset.name; 4444 const fieldValue = this.value; 4445 $this.siblings().removeClass('selected'); 4446 $this.addClass('selected'); 4447 formData.setData(fieldName, fieldValue); 4448 if (fieldName === 'storage') { 4449 resetFormData(['manufacturer', 'deviceModel', 'deviceImg', 'carrier', 'storage']); 4450 return validate([fieldName, 'carrier']); 4451 } 4452 4453 if (fieldName === 'questions') { 4454 resetFormData(['manufacturer', 'deviceModel', 'deviceImg', 'carrier', 'storage', 'confirmedModel', 'confirmedModelName', 'questions']); 4455 } 4456 return validate([fieldName]); 4457 }); 4458 4459 //HYLA Manufacturers single select 4460 $stepsForm.on("click", ".manufacturer", function(){ 4461 $('.manufacturer').removeClass('border-0'); 4462 $('.manufacturer .manufacturer-checkbox').removeClass('selected'); 4463 $(this).toggleClass('border-0').find('.manufacturer-checkbox').toggleClass('selected').find('.manufacturer-check'); 4464 formData.setData('manufacturer', this.dataset.manufacturer); 4465 resetFormData(['manufacturer']); 4466 $('.tradein-summary-list').hide(); 4467 if (formData.manufacturer === 'Apple') { 4468 $('.tradein-summary-list-ios').show(); 4469 } else { 4470 $('.tradein-summary-list-android').show(); 4471 } 4472 4473 validate(['manufacturer']); 4474 }); 4475 4476 function createManufacturersFromLS() { 4477 const $manufacturers = $('.js-manufacturers'); 4478 4479 $.each(hylaContentData.manufacturers, function(index, value) { 4480 let selected = ''; 4481 if (value.value === hylaFormData.manufacturer) selected = 'selected'; 4482 $manufacturers.append( 4483 $( 4484 '<div data-manufacturer="' + value.value + '" class="col manufacturer">' + 4485 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-1').html()), value.value]) + '" type="button" aria-label="' + value.value + '" class="manufacturer-checkbox ' + selected + '">' + 4486 '<img data-gtm-asset="' + value.url + '" data-gtm-agencyid="' + HYLA_AGENCY_ID + '" src="' + value.url + '" class="manufacturer-icon"/>' + 4487 '<span class="manufacturer-check icon light-theme large-icon"><i class="success"></i></span>' + 4488 '</button>' + 4489 '</div>') 4490 ) 4491 }); 4492 } 4493 4494 function createDeviceModelsFromLS() { 4495 const $deviceSelect = $('select.select-input[name="deviceModel"]'); 4496 $deviceSelect.parents('.dropdown-wrapper').addClass('js-show-mini-placeholder'); 4497 $deviceSelect.append($('<option value="empty" data-hidden="true"></option>')) 4498 $.each(hylaContentData.productFamilies, function(index, value) { 4499 let selected = ''; 4500 if (value.value === hylaFormData.deviceModel) selected = 'selected'; 4501 $deviceSelect.append( 4502 $('<option ' + selected + ' value="' + value.value + '">' + value.value + '</option>') 4503 ) 4504 }); 4505 } 4506 4507 function createCarriersFromLS() { 4508 const $carrierSelect = $('select.select-input[name="carrier"]'); 4509 $carrierSelect.parents('.dropdown-wrapper').addClass('js-show-mini-placeholder'); 4510 $('.js-tradein-current-image').attr({ 4511 'src': formData.deviceImg, 4512 'data-gtm-asset': formData.deviceImg 4513 }); 4514 $carrierSelect.append($('<option value="empty" data-hidden="true"></option>')) 4515 $.each(hylaContentData.carriers, function(index, value) { 4516 let selected = ''; 4517 if (value.value === hylaFormData.carrier) selected = 'selected'; 4518 $carrierSelect.append( 4519 $('<option ' + selected + ' value="' + value.value + '">' + value.value + '</option>') 4520 ) 4521 }); 4522 } 4523 4524 function createStorageFromLS() { 4525 const $storageSelect = $('.single-select-group[data-name=storage]'); 4526 $.each(hylaContentData.capacities, function(index, value) { 4527 let selected = ''; 4528 if (value.value === hylaFormData.storage) selected = 'selected'; 4529 $storageSelect.append( 4530 $('<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-3').html()), value.value]) + '" class="single-select-btn ' + selected + '" value="' + value.value + '">' + value.value + '</button>') 4531 ) 4532 }); 4533 } 4534 4535 function createDeviceConfirmFromLS() { 4536 const $deviceList = $('.device-confirm-list'); 4537 $.each(hylaContentData.models, function(index, value) { 4538 let active = ''; 4539 if (value.modelCode === hylaFormData.confirmedModel) active = 'active'; 4540 4541 $deviceList.append( 4542 $('<div class="phone-card-container text-center mt-60">' + 4543 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-4').html()), value.modelCode]) + '" data-name="confirmedModel" data-modelname="' + value.consumerDisplayAlias + '" data-value="' + value.modelCode + '" class="text-center phone-card-detail
4543s js-select-ext-phone-card ' + active + '">' + 4544 '<img data-gtm-asset="' + value.imageUrl + '" data-gtm-agencyid="' + HYLA_AGENCY_ID + '" src="' + value.imageUrl + '"/>' + 4545 '<div class="tradein-confirm-text">' + 4546 '<p class="heading-container caption-one font-weight-bold">' + value.consumerDisplayAlias + '</p>' + 4547 '</div>' + 4548 '</button>' + 4549 '</div>') 4550 )}); 4551 } 4552 4553 function createQuestionsFromLS() { 4554 const $questions = $('.tradein-questions .tradein-question-list'); 4555 4556 $.each(hylaContentData.questions, function(index, value) { 4557 if (value.questionType !== 'SINGLE_SELECT') return; 4558 value.validAnswers[0].questionCode = value.code; 4559 value.validAnswers[1].questionCode = value.code; 4560 let selectedYes = ''; 4561 let selectedNo = 'selected'; 4562 if (value.validAnswers[0].answerText === formData.questions[index].answerText) { 4563 selectedYes = 'selected'; 4564 selectedNo = ''; 4565 } 4566 $questions.append( 4567 $('<li class="tradein-question-item">' + 4568 '<div class="tradein-question-wrap">' + 4569 '<label class="tradein-question-label">' + value.text + '</label>' + 4570 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-5').html()), value.validAnswers[0].answerText, 'popover']) + '" rel="popover" type="button" data-trigger="focus" class="popover-btn icon light-theme large-icon" data-toggle="popover" data-content="<p>' + value.helpText + '</p>"><i class="question-mark-black"></i></button>' + 4571 '</div>' + 4572 '<div class="d-flex flex-column tradein-answers-wrap">' + 4573 '<div data-name="questions" class="single-select-group">' + 4574 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-5').html()), value.validAnswers[0].answerText]) + '"' + ' class="single-select-btn ' + selectedYes + '" ' + 'value=' + JSON.stringify(value.validAnswers[0]) + '>' + value.validAnswers[0].answerText + '</button>' + 4575 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-5').html()), value.validAnswers[1].answerText]) + '"' + ' class="single-select-btn ' + selectedNo + '" ' + 'value=' + JSON.stringify(value.validAnswers[1]) + '>' + value.validAnswers[1].answerText + '</button>' + 4576 '</div>' + 4577 '</div>' + 4578 '</li>' 4579 ) 4580 ) 4581 }); 4582 } 4583 4584 async function createPriceFromLS() { 4585 $('.js-tradein-price').text('$' + formData.price.toFixed(2)); 4586 $('.js-confirm-ship').attr('data-gtm-cta', trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-6').html()), 'agreement'])); 4587 $('.tradein-summary-terms').attr('data-gtm-cta', trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-6').html()), 'terms_and_conditions'])); 4588 $('.js-tradein-device').text(formData.deviceModel); 4589 $('.js-tradein-storage').text(formData.storage); 4590 $('.js-tradein-carrier').text(formData.carrier); 4591 $('.tradein-summary-list-ios, .tradein-summary-list-android').hide(); 4592 if (formData.manufacturer === 'Apple') { 4593 $('.tradein-summary-list-ios').show(); 4594 } else { 4595 $('.tradein-summary-list-android').show(); 4596 } 4597 } 4598 4599 $('#trade-in-box').one('show.bs.modal', async function (e) { 4600 $loader.css('opacity', 1) 4601 $loader.show(); 4602 if (hasDeviceInCart === undefined) document.dispatchEvent(hylaGetCartEvent); 4603 if (hylaContentData !== null && hylaFormData !== null) { 4604 createManufacturersFromLS(); 4605 createDeviceModelsFromLS(); 4606 createCarriersFromLS(); 4607 createStorageFromLS(); 4608 createDeviceConfirmFromLS(); 4609 createQuestionsFromLS(); 4610 createPriceFromLS(); 4611 } 4612 4613 const request = createRequest(HYLA_TOKEN_API, GET_METHOD); 4614 const submitBtnUrl = $('.step-block')[6].dataset.submiturl; 4615 4616 if (!submitBtnUrl) { 4617 $cancelBtn.find('a').on('click', function(event) { 4618 event.preventDefault(); 4619 $tradeModal.modal('hide'); 4620 }); 4621 } 4622 4623 try { 4624 let response = await fetchHylaApi(request); 4625 4626 token = response.access_token; 4627 refreshToken = response.refresh_token; 4628 4629 $stepsForm.steps({ 4630 headerTag: "h5", 4631 bodyTag: "div", 4632 transitionEffect: "slideLeft", 4633 actionContainerTag: "footer", 4634 onInit: onInitSteps, 4635 onStepChanging: beforeStepChange, 4636 autoFocus: true, 4637 suppressPaginationOnFocus: false 4638 }); 4639 $('select.select-input').selectpicker({size: 4}); 4640 4641 $('.device-confirm-list').on('click', '.js-select-ext-phone-card', function(){ 4642 const fieldName = this.dataset.name; 4643 const fieldValue = this.dataset.value; 4644 const fieldModelName = this.dataset.modelname; 4645 $('.device-confirm-list .js-select-ext-phone-card').removeClass('active'); 4646 $(this).addClass('active'); 4647 formData.setData(fieldName, fieldValue); 4648 formData.setData("confirmedModelName", fieldModelName); 4649 resetFormData(['manufacturer', 'deviceModel', 'deviceImg', 'carrier', 'storage', 'confirmedModel', 'confirmedModelName']); 4650 validate([fieldName]); 4651 }); 4652 4653 //scroll to bottom of modal on click of checkbox 4654 $('.trade-in-modal .custom-control-label').one('click', function() { 4655 setTimeout(function(){ 4656 $('.trade-in-modal .purchase-modal-box-body').animate({ scrollTop: $('.tradein-summary-step').height() }, "slow"); 4657 }, 200); 4658 }); 4659 4660 const $confirmShip = $('.js-confirm-ship'); 4661 4662 $confirmShip.change(function() { 4663 if (this.checked) { 4664 formData.setData(this.name, this.value); 4665 } else { 4666 formData.setData(this.name, undefined); 4667 } 4668 validate([this.name]); 4669 }); 4670 4671 $('select.select-input').on("changed.bs.select", function(event, clickedIndex, newValue, oldValue) { 4672 formData.setData(this.name, this.value); 4673 $(this).parents('.dropdown-wrapper').addClass('js-show-mini-placeholder'); 4674 if (this.name === 'deviceModel') { 4675 resetFormData(['manufacturer', 'deviceModel', 'deviceImg']); 4676 $('.js-tradein-storage-label').hide(); 4677 this.dataset.gtmCta = trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-2').html()), this.value]); 4678 validate([this.name]); 4679 } 4680 4681 if (this.name === 'carrier') { 4682 $('#trade-in-box .carrier-check').show(); 4683 $loader.show(); 4684 $('.js-step-next').removeClass('js-active'); 4685 this.dataset.gtmCta = trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-3').html()), this.value]); 4686 createStorage(); 4687 } 4688 }); 4689 } catch (error) { 4690 console.log(error); 4691 }; 4692 }); 4693 4694 function beforeStepChange(event, currentIndex, newIndex) { 4695 if (createHylaContent(newIndex) === false) { 4696 return false;
4697 } 4698 4699 switchNextText(newIndex); 4700 return true; 4701 } 4702 4703 function showErrorModal() { 4704 $loader.hide(200); 4705 $('.tradein-error-background').show(200); 4706 } 4707 4708 function switchNextText(index) { 4709 let submitBtnUrl; 4710 let submitBtnText; 4711 4712 const next = $('.step-block')[index].dataset.next; 4713 const previous = $('.step-block')[index].dataset.prev; 4714 if (index === 6) { 4715 if (hasDeviceInCart) { 4716 // const stepBlockSubmit = 4717 submitBtnText = $('.step-block')[index].dataset.next; 4718 submitBtnUrl = $('.step-block')[index].dataset.submiturl; 4719 } else { 4720 submitBtnText = $('.step-block')[index].dataset.nodevice; 4721 submitBtnUrl = $('.step-block')[index].dataset.nodeviceurl; 4722 } 4723 $nextBtn.hide(); 4724 $submitBtn.attr('data-gtm-cta', trimSplitJoin(['trade_in', removeSpecialChars($('.js-tradein-step-title-' + index).html()), 'next'])); 4725 $prevBtn.attr('data-gtm-cta', trimSplitJoin(['trade_in', removeSpecialChars($('.js-tradein-step-title-' + index).html()), 'previous'])); 4726 $submitBtn.text(submitBtnText).attr('href', submitBtnUrl).show(); 4727 $submitBtn.css('display', 'inline-block'); 4728 return; 4729 } 4730 4731 $nextBtn.attr('data-gtm-cta', trimSplitJoin(['trade_in', removeSpecialChars($('.js-tradein-step-title-' + index).html()), 'next'])); 4732 $prevBtn.attr('data-gtm-cta', trimSplitJoin(['trade_in', removeSpecialChars($('.js-tradein-step-title-' + index).html()), 'previous'])); 4733 if (index === 0) { 4734 $cancelBtn.show(); 4735 $prevBtn.hide(); 4736 $nextBtn.text(next); 4737 4738 return; 4739 } 4740 4741 $submitBtn.hide(); 4742 $nextBtn.show(); 4743 $nextBtn.text(next); 4744 $prevBtn.text(previous).css('display', 'inline-block'); 4745 $cancelBtn.hide(); 4746 4747 return; 4748 } 4749 4750 function createHylaContent(index) { 4751 // reset scroll position to top on step 4752 document.querySelector('#trade-in-box .purchase-modal-box-body').scrollTop = 0; 4753 if (index === 0) { 4754 $loader.show(); 4755 $('.trade-in-modal').addClass('tradein-flow-start'); 4756 $loader.hide(); 4757 } 4758 4759 //manufacturers 4760 if (index === 1) { 4761 return createManufacturers(); 4762 } 4763 4764 //device model 4765 if (index === 2) { 4766 return createDeviceModels(); 4767 } 4768 4769 //carrier and storage 4770 if (index === 3) { 4771 return createCarriersAndStorage(); 4772 } 4773 4774 //confirm device 4775 if (index === 4) { 4776 return createDeviceConfirmtaion(); 4777 } 4778 4779 //Questions 4780 if (index === 5) { 4781 return createQuestions(); 4782 } 4783 4784 //price summary 4785 if (index === 6) { 4786 return createPrice(); 4787 } 4788 return; 4789 } 4790 4791 //HYLA API Content Setters 4792 function createStorage() { 4793 (async function() { 4794 try { 4795 const paramsObj = {}; 4796 paramsObj.manufacturer = formData.manufacturer; 4797 paramsObj.productfamily = formData.deviceModel; 4798 paramsObj.carrier = formData.carrier; 4799 const request = createRequest(HYLA_ATTRIBUTES_API, GET_METHOD, token, paramsObj); 4800 let storageRes = await fetchHylaApi(request, createStorage); 4801 const $storageSelect = $('.single-select-group[data-name=storage]'); 4802 $storageSelect.empty(); 4803 resetFormData(['manufacturer', 'deviceModel', 'deviceImg', 'carrier']); 4804 $('.js-tradein-storage-label').show(); 4805 $.each(storageRes.capacities, function(index, value) { 4806 $storageSelect.append( 4807 $('<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-3').html()), value.value]) + '"aria-label="'+ parseInt(value.value)+" "+"gigabyte" +'" class="single-select-btn" value="' + value.value + '">' + value.value + '</button>') 4808 ) 4809 }); 4810 hylaContentObj.capacities = storageRes.capacities; 4811 $loader.hide(); 4812 hasRecalled = false; 4813 } catch (error) { 4814 console.log(error); 4815 }; 4816 })(); 4817 } 4818 4819 function createPrice() { 4820 if (!validate(['questions'])) return false; 4821 if (!hasContentChangedFromLS && hylaContentData !== null && hylaFormData !== null) { 4822 $('.js-step-next').removeClass('js-active'); 4823 $submitBtn.removeClass('js-active'); 4824 document.querySelector('.js-confirm-ship').checked = true; 4825 } 4826 if (formData.price !== undefined) return; 4827 $loader.show(); 4828 $('.js-step-next').removeClass('js-active'); 4829 $submitBtn.removeClass('js-active'); 4830 4831 (async function() {
4832 try { 4833 const url = `${HYLA_MODELS_PATH}/${formData.confirmedModel}${HYLA_PRICE_API}?${clientIdParam}=${clientId}`; 4834 const request = createRequest(url, POST_METHOD, token, false, JSON.stringify(formData.questions)); 4835 let response = await fetchHylaApi(request, createPrice, url) 4836 formData.setData('price', (response.moneyDTO.amount)); 4837 formData.setData('currencyCode', (response.moneyDTO.currencyCode)); 4838 $('.js-tradein-price').text('$' + formData.price.toFixed(2)); 4839 4840 $('.js-confirm-ship')[0].focus(); 4841 $loader.hide(); 4842 4843 $('.js-confirm-ship').attr('data-gtm-cta', trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-6').html()), 'agreement'])); 4844 $('.tradein-summary-terms').attr('data-gtm-cta', trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-6').html()), 'terms_and_conditions'])); 4845 $('.js-tradein-device').text(formData.deviceModel); 4846 $('.js-tradein-storage').text(formData.storage); 4847 $('.js-tradein-carrier').text(formData.carrier); 4848 hasRecalled = false; 4849 } catch (error) { 4850 console.log(error); 4851 }; 4852 })(); 4853 } 4854 4855 function createDeviceConfirmtaion() { 4856 if (!validate(['carrier', 'storage'])) return false; 4857 if (formData.confirmedModel !== undefined) return; 4858 $('.js-step-next').removeClass('js-active'); 4859 $loader.show(); 4860 const $deviceList = $('.device-confirm-list'); 4861 4862 (async function() { 4863 try { 4864 const paramsObj = {}; 4865 paramsObj.manufacturer = formData.manufacturer; 4866 paramsObj.productfamily = formData.deviceModel; 4867 paramsObj.carrier = formData.carrier; 4868 paramsObj.capacity = formData.storage; 4869 4870 const request = createRequest(HYLA_TOPMODELS_API, GET_METHOD, token, paramsObj); 4871 let response = await fetchHylaApi(request, createDeviceConfirmtaion); 4872 $deviceList.empty(); 4873 $.each(response.models, function(index, value) { 4874 $deviceList.append( 4875 $('<div class="phone-card-container text-center mt-60">' + 4876 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-4').html()), value.modelCode]) + '" data-name="confirmedModel" data-modelname="' + value.consumerDisplayAlias + '" data-value="' + value.modelCode + '" class="text-center phone-card-details js-select-ext-phone-card">' + 4877 '<img data-gtm-asset="' + value.imageUrl + '" data-gtm-agencyid="' + HYLA_AGENCY_ID + '" src="' + value.imageUrl + '"/>' + 4878 '<div class="tradein-confirm-text">' + 4879 '<p class="heading-container caption-one font-weight-bold">' + value.consumerDisplayAlias + '</p>' + 4880 '</div>' + 4881 '</button>' + 4882 '</div>') 4883 )}); 4884 hylaContentObj.models = response.models; 4885 4886 closeBtn.focus(); 4887 document.activeElement.blur(); 4888 $loader.hide(); 4889 hasRecalled = false; 4890 } catch (error) { 4891 console.log(error); 4892 }; 4893 })(); 4894 } 4895 4896 function createCarriersAndStorage() { 4897 if (!validate(['deviceModel'])) return false; 4898 if (formData.carrier !== undefined || formData.storage !== undefined) return; 4899 $('#trade-in-box .carrier-check').hide(); 4900 const $storageSelect = $('.single-select-group[data-name=storage]'); 4901 $('.js-step-next').removeClass('js-active'); 4902 $('.js-tradein-current-description').text(formData.deviceModel); 4903 $storageSelect.empty(); 4904 $loader.show(); 4905 (async function() { 4906 try { 4907 const paramsObj = {}; 4908 paramsObj.manufacturer = formData.manufacturer; 4909 paramsObj.productfamily = formData.deviceModel; 4910 const attributesRequest = createRequest(HYLA_ATTRIBUTES_API, GET_METHOD, token, paramsObj); 4911 const topModelsRequest = createRequest(HYLA_TOPMODELS_API, GET_METHOD, token, paramsObj); 4912 let fetchAttributes = fetchHylaApi(attributesRequest, createCarriersAndStorage, false, true); 4913 let fetchTopModels = fetchHylaApi(topModelsRequest, createCarriersAndStorage, false, true); 4914 let allResponses = await Promise.all([fetchAttributes, fetchTopModels]); 4915 const attributesRes = allResponses[0]; 4916 const topModelsRes = allResponses[1]; 4917 const $carrierSelect = $('select.select-input[name="carrier"]'); 4918 $carrierSelect.empty(); 4919 $storageSelect.empty(); 4920 hylaContentObj.carriers = attributesRes.carriers; 4921 $carrierSelect.append($('<option value="empty" data-hidden="true"></option>')) 4922 $.each(attributesRes.carriers, function(index, value) { 4923 $carrierSelect.append( 4924 $('<option value="' + value.value + '">' + value.value + '</option>') 4925 ) 4926 }); 4927 $carrierSelect.selectpicker('refresh'); 4928 $carrierSelect.parents('.dropdown-wrapper').removeClass('js-show-mini-placeholder'); 4929 4930 //add first image found in topmodels response 4931 formData.setData('deviceImg', topModelsRes.models[0].imageUrl); 4932 $('.js-tradein-current-image').attr({ 4933 'src': formData.deviceImg, 4934 'data-gtm-asset': formData.deviceImg 4935 }); 4936 $('.form-select-custom')[1].focus(); 4937 $loader.hide(); 4938 hasRecalled = false;
4939 } catch(error) { 4940 handleAPIResponseFailure(error, createCarriersAndStorage); 4941 } 4942 })(); 4943 } 4944 4945 function createDeviceModels() { 4946 if (!validate(['manufacturer'])) return false; 4947 if (formData.deviceModel !== undefined) return; 4948 $('.js-step-previous').css('display', 'inline-block'); 4949 $('.js-step-next').removeClass('js-active'); 4950 $loader.show(); 4951 4952 (async function() { 4953 try { 4954 const paramsObj = {}; 4955 paramsObj.manufacturer = formData.manufacturer; 4956 const request = createRequest(HYLA_ATTRIBUTES_API, GET_METHOD, token, paramsObj); 4957 let response = await fetchHylaApi(request, createDeviceModels); 4958 const $deviceSelect = $('select.select-input[name="deviceModel"]'); 4959 $deviceSelect.empty(); 4960 $deviceSelect.parents('.dropdown-wrapper').removeClass('js-show-mini-placeholder'); 4961 $deviceSelect.append($('<option value="empty" data-hidden="true"></option>')) 4962 $.each(response.productFamilies, function(index, value) { 4963 $deviceSelect.append( 4964 $('<option value="' + value.value + '">' + value.value + '</option>') 4965 ) 4966 }); 4967 hylaContentObj.productFamilies = response.productFamilies; 4968 $deviceSelect.selectpicker('refresh'); 4969 $('.form-select-custom')[0].focus(); 4970 $loader.hide(); 4971 hasRecalled = false; 4972 } catch (error) { 4973 console.log(error); 4974 } 4975 })(); 4976 } 4977 4978 function createManufacturers() { 4979 $('.trade-in-modal').removeClass('tradein-flow-start'); 4980 validate(['manufacturer']); 4981 if (formData.manufacturer !== undefined) return; 4982 $loader.show(); 4983 $('.js-step-next').removeClass('js-active'); 4984 (async function() { 4985 try { 4986 let request = createRequest(HYLA_ATTRIBUTES_API, GET_METHOD, token); 4987 let response = await fetchHylaApi(request, createManufacturers); 4988 const $manufacturers = $('.js-manufacturers'); 4989 $manufacturers.empty(); 4990 $.each(response.manufacturers, function(index, value) { 4991 $manufacturers.append( 4992 $( 4993 '<div data-manufacturer="' + value.value + '" class="col manufacturer">' + 4994 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-1').html()), value.value]) + '" type="button" aria-label="' + value.value + (index+1) + "of" + (response.manufacturers.length) + '" class="manufacturer-checkbox">' + 4995 '<img data-gtm-asset="' + value.url + '" data-gtm-agencyid="' + HYLA_AGENCY_ID + '" src="' + value.url + '" class="manufacturer-icon"/>' + 4996 '<span class="manufacturer-check icon light-theme large-icon"><i class="success"></i></span>' + 4997 '</button>' + 4998 '</div>') 4999 ) 5000 }); 5001 hylaContentObj.manufacturers = response.manufacturers; 5002 closeBtn.focus(); 5003 document.activeElement.blur(); 5004 $loader.hide(); 5005 hasRecalled = false; 5006 } catch (error) { 5007 console.log(error); 5008 } 5009 })(); 5010 } 5011 5012 function createQuestions() { 5013 if (!validate(['confirmedModel'])) return false; 5014 if (formData.questions.length > 0) return; 5015 $('.js-step-next').removeClass('js-active'); 5016 const $questions = $('.tradein-questions .tradein-question-list'); 5017 if($questions.children().length > 0) return; 5018 $loader.show(); 5019 5020 (async function() { 5021 try { 5022 const url = `${HYLA_MODELS_PATH}/${formData.confirmedModel}${HYLA_QUESTIONS_API}` 5023 const request = createRequest(url, GET_METHOD, token); 5024 let response = await fetchHylaApi(request, createQuestions); 5025 $.each(response, function(index, value) { 5026 if (value.questionType !== 'SINGLE_SELECT') return; 5027 value.validAnswers[0].questionCode = value.code; 5028 value.validAnswers[1].questionCode = value.code; 5029 $questions.append( 5030 $('<li class="tradein-question-item">' + 5031 '<div class="tradein-question-wrap">' + 5032 '<label class="tradein-question-label">' + value.text + '</label>' + 5033 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-5').html()), value.validAnswers[0].answerText, 'popover']) + '" rel="popover" type="button" data-trigger="focus" class="popover-btn icon light-theme large-icon" data-toggle="popover" data-content="<p>' + value.helpText + '</p>"><i class="question-mark-black"></i></button>' + 5034 '</div>' + 5035 '<div class="d-flex flex-column tradein-answers-wrap">' + 5036 '<div data-name="questions" class="single-select-group">' + 5037 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-5').html()), value.validAnswers[0].answerText]) + '" class="single-select-btn" value=' + JSON.stringify(value.validAnswers[0]) + '>' + value.validAnswers[0].answerText + '</button>' + 5038 '<button data-gtm-cta="' + trimSplitJoin([removeSpecialChars($('.js-tradein-step-title-5').html()), value.validAnswers[1].answerText]) + '" class="single-select-btn" value=' + JSON.stringify(value.validAnswers[1]) + '>' + value.validAnswers[1].answerText + '</button>' + 5039 '</div>' + 5040 '</div>' + 5041 '</li>' 5042 ) 5043 ) 5044 }); 5045 hylaContentObj.questions = response; 5046 5047 $(".popover-btn").popover({ 5048 placement: 'top', 5049 html: true, 5050 trigger: 'focus', 5051 template: '<div class="tradein-popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-body"></div></div></div>' 5052 }); 5053 closeBtn.focus(); 5054 $loader.hide(); 5055 hasRecalled = false;
5056 } catch (error) { 5057 console.log(error); 5058 } 5059 })(); 5060 } 5061 5062 function validate(keys) { 5063 let valid = false; 5064 if (keys[0] === 'questions') { 5065 valid = $('.single-select-group[data-name="questions"]').length === formData.questions.length; 5066 } else { 5067 $.each(keys, function(index, value) { 5068 if(formData[value] === undefined) return valid = false; 5069 return valid = true; 5070 }); 5071 } 5072 if(valid && hasContentChangedFromLS) { 5073 $('.js-step-next, .js-step-submit').addClass('js-active').attr('aria-disabled', 'false'); 5074 } else if(!valid && hasContentChangedFromLS) { 5075 $('.js-step-next, .js-step-submit').removeClass('js-active').attr('aria-disabled', 'true'); 5076 } 5077 return valid; 5078 } 5079 5080 function trimSplitJoin(strings) { 5081 let newString = ''; 5082 for(let i = 0; i < strings.length; i++) { 5083 newString += strings[i].toLowerCase().trim().split(' ').join('_'); 5084 //add colon if not last element 5085 if (i < strings.length - 1) { 5086 newString += ':'; 5087 } 5088 } 5089 return newString; 5090 } 5091 5092 function removeSpecialChars(string) { 5093 if (string !== undefined) { 5094 return string.replace(/[`~!@#$%^*()_|+=?;:'",.<>\{\}\[\]\\\/]/gi, ''); 5095 } 5096 } 5097 5098 function isJson(str) { 5099 let json; 5100 try { 5101 json = JSON.parse(str); 5102 } catch(e) { 5103 return false; 5104 } 5105 return json; 5106 } 5107 5108 //custom form data constructor 5109 function StepsFormData(selector) { 5110 if (!selector || selector === null) { 5111 return undefined; 5112 } 5113 5114 this.deviceImg = undefined; 5115 this.questions = []; 5116 this.setData = (key, value) => { 5117 let json = false; 5118 //check if value is JSON and push to array, specific to questions array 5119 if (isNaN(parseInt(value))){ 5120 json = isJson(value); 5121 } 5122 5123 if (json) { 5124 //filter out non unique objects by questionCode 5125 this[key] = this[key].filter(( obj ) => obj.questionCode !== json.questionCode); 5126 return this[key].push(json); 5127 } 5128 5129 hasContentChangedFromLS = true; 5130 5131 return this[key] = value; 5132 }; 5133 } 5134}); 5135 5136 5137/*Helper function to get cookie value*/ 5138function getCookie(name) { 5139 var nameEQ = name + "="; 5140 var ca = document.cookie.split(';'); 5141 for (var i = 0; i < ca.length; i++) { 5142 var c = ca[i]; 5143 while (c.charAt(0) == ' ') c = c.substring(1, c.length); 5144 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); 5145 } 5146 return null; 5147} 5148 5149/*Event listener for PLP experience-fragment load in purchase flow*/ 5150$(document).on("PurchasePLPLoaded", function() { 5151 5152 /*set the selected value in sort dropdown*/ 5153 $('.sort-dropdown').each(function(index) { 5154 var dd1 = new DropDown($(this)); 5155 var selectedSortValue = $(this).find('ul.drop li.selected').html(); 5156 $('.sort-dropdown span.sort-selected').html(selectedSortValue); 5157 }); 5158 5159 /*close menu on document click*/ 5160 $(document).click(function() { 5161 $('.wrap-drop').removeClass('active'); 5162 }); 5163 5164 /*distpatch event for compare overlay on compare click*/ 5165 $('body').on("click", ".purchase-compare", function() { 5166 this.dispatchEvent(new Event('loadCompareOverlay', { 5167 'bubbles': true 5168 })); 5169 }); 5170 /*set the selected value in sort dropdown*/ 5171 var clickCount = 0; 5172 $('body').on("click", '.purchase-flow-wrapper .product-filter-container .wrap-drop.sort-dropdown', function(e) { 5173 e.stopImmediatePropagation(); 5174 if (clickCount == 0) { 5175 var dd1 = new DropDown($(this)); 5176 var selectedSortValue = $(this).find('ul.drop li.selected').html(); 5177 $('.sort-dropdown span.sort-selected').html(selectedSortValue); 5178 clickCount = clickCount + 1; 5179 $(this).click(); 5180 } 5181 }); 5182 5183 5184 5185 /*function call to set hpp data in modal*/ 5186 setHppModalData(); 5187 5188}); 5189/*On purchase listener loaded*/ 5190$(document).on("PurchasePLPListenersLoaded", function() { 5191 $(document).on("click", ".cart-wizard-heading .skipEvent, .product-listing-container .skipEvent, .purchase-flow-plp-item-loaded .skipEvent", function() { 5192 this.dispatchEvent(new Event('PuchasePLPSkipEvent', { 5193 'bubbles': true 5194 })); 5195 }); 5196 $(document).on("click", "#modalClosePdp", function() { 5197 document.dispatchEvent(new Event('PuchasePDPModalCloseEvent', { 5198 'bubbles': true 5199 })); 5200 }); 5201 attachCloseModelEventListener(); 5202}); 5203/*On Document ready*/ 5204$(document).ready(function() { 5205 setHppModalData(); 5206 attachCloseModelEventListener(); 5207 startDiagnostic(); 5208 $('.hppeligibilitychecker #not-logged-in-type .button').addClass('disabled'); 5209}); 5210/*Attach modal close event listener*/ 5211function attachCloseModelEventListener() { 5212 $(document).on("click", '.learn-more-modal .modal-body .close-modal', function() { 5213 if (document.querySelector('#checkme').getAttribute("checked") == "checked") { 5214 document.querySelector('#checkme').click(); 5215 } 5216 if (document.querySelector('.show .close') != null) { 5217 document.querySelector('.show .close').click(); 5218 } 5219 }); 5220} 5221/* function to enable the HPP submut button on selection of value form dropdown */ 5222function enableHppButtonOnDropDownSelection(element) {
5223 var esnValue =$(element).attr('data-esn'); 5224 if(esnValue) { 5225 $('.hppeligibilitychecker #not-logged-in-type .button').removeClass('disabled'); 5226 } 5227 5228} 5229 5230/*function to set hpp data in enroll now modal*/ 5231function setHppModalData() { 5232 var agree = document.getElementById('checkme'); 5233 if (agree) { 5234 agree.onchange = function() { 5235 $('#confirmBtn').toggleClass('disabled'); 5236 var accesibilityEnableLabel = ""; 5237 var accesibilityDisableLabel = ""; 5238 if (document.querySelector('#confirmBtn .confirm') != null) { 5239 accesibilityEnableLabel = document.querySelector('#confirmBtn .confirm').getAttribute("data-enable-btnmsg"); 5240 accesibilityDisableLabel = document.querySelector('#confirmBtn .confirm').getAttribute("data-disable-btnmsg"); 5241 } 5242 if ($('#confirmBtn').hasClass('disabled')) { 5243 $('#confirmBtn .confirm').attr('aria-label', accesibilityDisableLabel); 5244 } else { 5245 $('#confirmBtn .confirm').attr('aria-label', accesibilityEnableLabel); 5246 } 5247 }; 5248 } 5249 /*See Detail & TNC Modal Start*/ 5250 $('body').on("click", ".dynamic-modal-button", function() { 5251 // Get data-partnumber from parent div.hpp-plan.plan-card 5252 var partNumber = $(this).closest('div.hpp-plan.plan.card').attr('data-partnumber'); 5253 if (!$(this).hasClass("disabled")) { 5254 var modal = document.querySelector($(this).attr('data-target')); 5255 var modalAriaLabel = modal.getAttribute('data-appended-aria-text') ? $(this).html() + modal.getAttribute('data-appended-aria-text') : ''; 5256 var gtaText = $('.dynamic-modal-button').attr('data-gtm-cta'); 5257 if((partNumber && partNumber.indexOf('DPP') !== -1) && (gtaText.indexOf('Assurant_Care_see_details') !== -1)){ 5258 // Show ST Protect content in modal body 5259 var modalData = $(this).attr('data-modalval'); 5260 $('.hpp-dynamic-data').html(modalData); 5261 } 5262 else if (partNumber && partNumber.indexOf('DPP') !== -1) { 5263 // Show the .dpp-see-details-modal section in the modal body 5264 var dppSection = $('.dpp-see-details-modal').html(); 5265 $('.hpp-dynamic-data').html(dppSection); //enter see detail for dpp see details 5266 } else { 5267 var modalData = $(this).attr('data-modalval'); 5268 $('.hpp-dynamic-data').html(modalData); 5269 } 5270 if(modalAriaLabel) modal.setAttribute('aria-label', modalAriaLabel); 5271 addTabindexAccordian(modal); 5272 tabStop(modal, true); 5273 } 5274 }); 5275 5276 5277 5278 /*Enroll Now Model Open*/ 5279 $('body').on("click", ".hpp-enrollnow-button", function(event) { 5280 if (!$(this).parent().hasClass("disabled") && !$(event.target).hasClass('dynamic-modal-button')) { 5281 var $modal = $(document.querySelector($(this).attr('data-target'))); 5282 var enrollTitle = $(this).attr('data-enrolltitle'); 5283 var enrollDescription = $(this).attr('data-enrolldescription'); 5284 var enrollCondition = $(this).attr('data-enrollcondition'); 5285 let deviceCheckDescription = $(this).attr('data-devicecheckdesc'); 5286 let deviceCheckDescriptionMobile = $(this).attr('data-devicecheckdescmobile'); 5287 let deviceCheckPopupMsg = $(this).attr('data-devicecheckpopupimg'); 5288 var hppPlanName = $(this).attr('data-planname'); 5289 var productId = $(this).attr('data-productid'); 5290 var skuId = $(this).attr('data-skuid'); 5291 var serviceDays = $(this).attr('data-planservicedays'); 5292 var thumbnailimage = $(this).attr('data-thumbnailimage'); 5293 var productAssetId = $(this).attr('data-productassetid'); 5294 var productAssetAgencyId = $(this).attr('data-productassetagencyid'); 5295 var hppPlanPrice = $(this).attr('data-planprice'); 5296 var hppPartNo = $(this).attr('data-skupartnumber'); 5297 var duration = $(this).attr('data-hppduration'); 5298 var planId = $(this).attr('data-planid'); 5299 var isMonthlyPlan = $(this).attr('data-ismonthlyplan'); 5300 var hppVendorName = $(this).attr('data-vendorname'); 5301 var thumbnailimageCancelled = $(this).attr('data-thumbnailimagecancelled') 5302 $('.enroll-title').text(enrollTitle); 5303 $('.enroll-description').text(enrollDescription); 5304 $('.enroll-condition').text(enrollCondition); 5305 $('.enroll-now-confirm').attr('data-productid', productId); 5306 $('.enroll-now-confirm').attr('data-skuid', skuId); 5307 $('.enroll-now-confirm').attr('data-planname', hppPlanName); 5308 $('.enroll-now-confirm').attr('data-thumbnailimage', thumbnailimage); 5309 $('.enroll-now-confirm').attr('data-servicedays', serviceDays); 5310 $('.enroll-now-confirm').attr('data-productassetid', productAssetId); 5311 $('.enroll-now-confirm').attr('data-productassetagencyid', productAssetAgencyId); 5312 $('.enroll-now-confirm').attr('data-planprice', hppPlanPrice); 5313 $('.enroll-now-confirm').attr('data-partno', hppPartNo); 5314 $('.enroll-now-confirm').attr('data-hppduration', duration); 5315 $('.enroll-now-confirm').attr('data-planid', planId); 5316 $('.enroll-now-confirm').attr('data-ismonthlyplan', isMonthlyPlan); 5317 $('.enroll-now-confirm').attr('data-vendorname', hppVendorName); 5318 $('.enroll-now-confirm').attr('data-thumbnailimagecancelled', thumbnailimageCancelled); 5319 $('.hpp-enrollnow-button').attr('data-productid', productId); 5320 $('.hpp-enrollnow-button').attr('data-skuid', skuId); 5321 $('.hpp-enrollnow-button').attr('data-planname', hppPlanName); 5322 $('.hpp-enrollnow-button').attr('data-thumbnailimage', thumbnailimage); 5323 $('.hpp-enrollnow-button').attr('data-servicedays', serviceDays); 5324 $('.hpp-enrollnow-button').attr('data-productassetid', productAssetId); 5325 $('.hpp-enrollnow-button').attr('data-productassetagencyid', productAssetAgencyId); 5326 $('.hpp-enrollnow-button').attr('data-planprice', hppPlanPrice); 5327 $('.hpp-enrollnow-button').attr('data-partno', hppPartNo); 5328 $('.hpp-enrollnow-button').attr('data-hppduration', duration); 5329 $('.hpp-enrollnow-button').attr('data-planid', planId); 5330 $('.hpp-enrollnow-button').attr('data-ismonthlyplan', isMonthlyPlan); 5331 $('.hpp-enrollnow-button').attr('data-vendorname', hppVendorName); 5332 $('.hpp-enrollnow-button').attr('data-thumbnailimagecancelled', thumbnailimageCancelled); 5333 /* Mirror key HPP data attributes onto the device-check continue button 5334 so _setHppAddTOCartData() can build a valid HPP payload when 5335 the logged-in user clicks "Continue" after device check. */ 5336 5337 if(hppVendorName&&hppVendorName==="APPLE"){ 5338 $('.protection-device-check-modal-body').addClass('d-none'); 5339 $('.view-brochure-link').addClass('d-none'); 5340 $('.tncmodal-body').removeClass('d-none'); 5341 5342 }else if (hppPartNo && hppPartNo.indexOf('DPP') !== -1) { 5343 // Store the selected HPP plan's part number in localStorage 5344 console.log('DPP plan selected:', hppPartNo); 5345 5346 // Check flowType cookie first 5347 var flowTypeCookie = getCookie('flowType'); 5348 // ACTIVATION FLOW: dispatch VAS Purchase event and stop 5349 if (flowTypeCookie === 'activation') { 5350 console.log('FlowType is activation, dispatching hppcheckvaspurchase event'); 5351 5352 // Prevent Bootstrap modal from opening 5353 event.preventDefault(); 5354 event.stopImmediatePropagation(); 5355 5356 // Dispatch the event 5357 document.dispatchEvent(new CustomEvent('hppcheckvaspurchase', { 5358 detail: { 5359 hppPartNo: hppPartNo 5360 }, 5361 bubbles: true 5362 })); 5363 // Stop execution here - VAS API response handler will manage next steps 5364 return; 5365 } 5366 5367 // PURCHASE FLOW: device check popup (flowType is 'purchase' or not present) 5368 // If user is NOT logged in â skip device check popup, add directly to cart 5369 var isLoggedIn = document.cookie.indexOf('roToken') > -1; 5370 if (!isLoggedIn) { 5371 console.log("DPP plan: User not logged in â adding directly to cart, skipping device check"); 5372 5373 /* Prevent Bootstrap modal from showing (it was triggered by data-toggle) */ 5374 event.preventDefault(); 5375 event.stopImmediatePropagation(); 5376 5377 /* Force-close modal in case Bootstrap already started opening it */ 5378 if ($modal && $modal.length) { 5379 $modal.modal('hide'); 5380 } 5381 $('#terms-box').modal('hide'); 5382 $('.modal-backdrop').remove(); 5383 $('body').removeClass('modal-open'); 5384 5385 return; 5386 } 5387 else if(isLoggedIn && flowTypeCookie === 'purchase') { 5388 /* Logged-in user â show device check popup as normal */ 5389 $('.device-check-continue-btn').attr('data-productid', productId); 5390 $('.device-check-continue-btn').attr('data-skuid', skuId); 5391 $('.device-check-continue-btn').attr('data-planname', hppPlanName); 5392 $('.device-check-continue-btn').attr('data-thumbnailimage', thumbnailimage); 5393 $('.device-check-continue-btn').attr('data-servicedays', serviceDays); 5394 $('.device-check-continue-btn').attr('data-productassetid', productAssetId); 5395 $('.device-check-continue-btn').attr('data-productassetagencyid', productAssetAgencyId); 5396 $('.device-check-continue-btn').attr('data-planprice', hppPlanPrice); 5397 $('.device-check-continue-btn').attr('data-partno', hppPartNo); 5398 $('.device-check-continue-btn').attr('data-hppduration', duration); 5399 $('.device-check-continue-btn').attr('data-planid', planId); 5400 $('.device-check-continue-btn').attr('data-ismonthlyplan', isMonthlyPlan); 5401 $('.device-check-continue-btn').attr('data-vendorname', hppVendorName); 5402 $('.device-check-continue-btn').attr('data-thumbnailimagecancelled', thumbnailimageCancelled); 5403 $('.tncmodal-body').addClass('d-none'); 5404 $('.protection-device-check-modal-body').removeClass('d-none'); 5405 $modal.find('.device-check-enroll-title').text(enrollTitle); 5406 $modal.find('.device-check-enroll-subtitle').text(enrollDescription); 5407 $modal.find('.device-check-enroll-desc-mobile').html(deviceCheckDescriptionMobile); 5408 $modal.find('.device-check-enroll-description').html(deviceCheckDescription); 5409 $modal.find('.protection-logo-img').attr('src', deviceCheckPopupMsg); 5410 5411 } 5412 } else if(hppVendorName&&hppVendorName!="APPLE"){ 5413 $('.tncmodal-body').removeClass('d-none'); 5414 $('.protection-device-check-modal-body').addClass('d-none'); 5415 $('.view-brochure-link').removeClass('d-none'); 5416 } 5417 } 5418 }); 5419} 5420 5421 5422/**Cancel HPP Plp TnC Modal */ 5423function cancelHppTnC() { 5424 if (document.querySelector('#checkme').getAttribute("checked") == "checked") { 5425 document.querySelector('#checkme').click(); 5426 } 5427 if (document.querySelector('#terms-box .close') != null) { 5428 document.querySelector('#terms-box .close').click(); 5429 } 5430} 5431 5432/**Start Diagnostic - Opens diagnostic URL in new tab */ 5433function startDiagnostic() { 5434 $('body').on('click', '#startdiagnostic-button', function(e) { 5435 e.preventDefault(); 5436 var diagnosticUrl = $('.device-check-content').attr('data-diagnostic-url'); 5437 if (diagnosticUrl) { 5438 window.open(diagnosticUrl, '_blank'); 5439 } 5440 }); 5441} 5442 5443var hppPlanObserver = new MutationObserver(function(mutations) { 5444 var hppPlan = document.querySelector('.hpp-plan'); 5445 if (hppPlan) { 5446 var partNo= hppPlan.getAttribute("data-partnumber"); 5447 if(partNo && partNo.indexOf('DPP') !== -1){ 5448 hppPlanObserver.disconnect(); 5449 var dppSection = document.querySelector('.dpp-product-section'); 5450 var nonDppSection = document.querySelector('.non-dpp-product-section'); 5451 console.log(dppSection); 5452 if(dppSection){ 5453 dppSection.classList.remove('d-none'); 5454 nonDppSection.classList.add('d-none'); 5455 } 5456 } 5457 else{ 5458 var dppSection = document.querySelector('.dpp-product-section'); 5459 if(dppSection){ 5460 dppSection.classList.add('d-none'); 5461 } 5462 } 5463 /* Disconnect observer after finding the element to avoid unnecessary future observations */ 5464 5465 } 5466 5467}); 5468hppPlanObserver.observe(document.body, { childList: true, subtree: true }); 5469 5470/*Event listener for PLP load in activation flow*/ 5471$( document ).on("ActivationPLPLoaded", function() { 5472 /*attach event on sort dropdown after load*/ 5473 setTimeout(function() { 5474 if ($('.sort-dropdown ul li').length > 0) { 5475 $('.sort-dropdown ul li').click(function(event) { 5476 document.dispatchEvent(new CustomEvent("PLPSortDropdownFilterClicked", { 5477 "detail": { 5478 "_type": "sort-by-click", 5479 "selectedDropdown": event.currentTarget 5480 } 5481 })); 5482 }) 5483 } 5484 }, 5000); 5485 5486 /*set the selected value in sort dropdown*/ 5487 $('.sort-dropdown').each(function( index ) { 5488 var dd1 = new DropDown($(this)); 5489 var selectedSortValue = $(this).find('ul.drop li.selected').html(); 5490 $('.sort-dropdown span.sort-selected').html(selectedSortValue); 5491 }); 5492 var clickCount = 0; 5493 $('body').on("click",'.activation-flow-wrapper .product-filter-container .wrap-drop.sort-dropdown',function (e) { 5494 e.stopImmediatePropagation(); 5495 if(clickCount==0){ 5496 var dd1 = new DropDown($(this)); 5497 var selectedSortValue = $(this).find('ul.drop li.selected').html(); 5498 $('.sort-dropdown span.sort-selected').html(selectedSortValue); 5499 clickCount = clickCount+1; 5500 $(this).click(); 5501 } 5502 }); 5503 5504 /*close menu on document click*/ 5505 $(document).click(function () { 5506 $('.wrap-drop').removeClass('active'); 5507 }); 5508 5509 /*distpatch event for compare overlay on compare click*/ 5510 $('body').on("click",".purchase-compare",function(){ 5511 this.dispatchEvent(new Event('loadCompareOverlay', { 'bubbles': true })); 5512 }); 5513 5514 5515 5516 /*function call to set hpp data in modal*/ 5517 setHppModalData(); 5518}); 5519/*On activations listener loaded*/ 5520$( document ).on( "ActivationPLPListenersLoaded", function() { 5521 // Added .purchase-flow-plp-item-loaded .skipEvent for BYOP flow where _enforceProtectionPLPVisibility() shows the purchase PLP and hides the activation PLP 5522 $(document).on("click",".cart-wizard-heading .skipEvent, .activation-flow-plp-item-loaded .skipEvent, .purchase-flow-plp-item-loaded .skipEvent",function(){ 5523 this.dispatchEvent(new Event('AcivationPLPSkipEvent', { 'bubbles': true })); 5524 }); 5525 $(document).on("click","#modalClosePdp",function(){ 5526 document.dispatchEvent(new Event('ActivationPDPModalCloseEvent', { 'bubbles': true })); 5527 }); 5528 attachCloseModelEventListener(); 5529}); 5530 5531$(document).ready(function () { 5532 setHppModalData(); 5533 attachCloseModelEventListener(); 5534}); 5535 5536function attachCloseModelEventListener(){ 5537 $(document).on("click",'.learn-m
5537ore-modal .modal-body .close-modal',function(){ 5538 if(document.querySelector('#checkme').getAttribute("checked") == "checked"){ 5539 document.querySelector('#checkme').click(); 5540 } 5541 if(document.querySelector('.show .close')!=null){ 5542 document.querySelector('.show .close').click(); 5543 } 5544 }); 5545} 5546 5547/* PLP Buttons */ 5548$(".phone-selector :checkbox").on('change', function() { 5549 if ($(".refresh_plp").length === 1) { 5550 $(".phone-selector :checkbox").removeAttr("checked").parent('label').removeClass('selected'); 5551 $(".phone-selector .nav li").removeClass("selected"); 5552 $(".phone-selector :checkbox").parent('label').attr("aria-checked", "false"); 5553 $(".phone-selector .nav li").attr("aria-selected",false); 5554 $('.phone-selector .nav li').removeClass('active'); 5555 5556 $(this).parents('.phone-selector .nav li').attr("aria-selected",true); 5557 $(this).parents('.phone-selector .nav li').addClass('selected'); 5558 $(this).attr("checked", "checked").parent('label').addClass('selected'); 5559 if ($(this).parent('label').attr("aria-checked") !== undefined) { 5560 $(this).parent('label').attr("aria-checked", "true") 5561 }; 5562 5563 } else { 5564 if ($(this).attr('checked') == 'checked') { 5565 $(this).removeAttr("checked").parent('label').removeClass('selected'); 5566 if ($(this).parent('label').attr("aria-checked") !== undefined) { $(this).parent('label').attr("aria-checked", "false") }; 5567 } else { 5568 $(this).attr("checked", "checked").parent('label').addClass('selected'); 5569 if ($(this).parent('label').attr("aria-checked") !== undefined) { $(this).parent('label').attr("aria-checked", "true") }; 5570 } 5571 } 5572}); 5573 5574 5575$(".phone-selector li").on('keypress', function(event) { 5576 if ($(".refresh_plp").length === 1 && event.which == 13) { 5577 $(this).find("input").click(); 5578 $(this).find("input").trigger('change'); 5579 } 5580}); 5581 5582$(".phone-selector ul li").keypress(function(e) { 5583 if (e.which == 13) { 5584 $(this).find('label').toggleClass('selected'); 5585 } 5586}); 5587/* PLP Buttons */ 5588 5589/*Filter Modal Position*/ 5590$(".all-filter").on("click", function() { 5591 //$("#allFilterModal").modal("show"); 5592 var offset = $(this).offset(); 5593 offset.top -= 160; 5594 $('html').animate({ scrollTop: offset.top,}, 100); 5595 $('body').css("padding-right", "").removeClass('modal-open'); 5596 //$("body").append("<div class='modal-backdrop-filter fade show' style='z-index: 1210'></div>"); 5597}); 5598 5599/*Filter rating -Start*/ 5600$(".filter-rating>li").on('click', function(e) { 5601 let indexSel = $(this).attr('data-index'); 5602 $(".filter-rating>li").each(function(index) { 5603 $(this).removeClass('selected'); 5604 if (index < indexSel) { 5605 $(this).addClass('filter-rating-black'); 5606 } else { 5607 $(this).removeClass('filter-rating-black'); 5608 } 5609 }); 5610 $(this).addClass('selected'); 5611}); 5612/*Filter rating -End*/ 5613 5614/*Filter Modal Close Functioning*/ 5615$("#allFilterModal .close").on("click", function() { 5616 //$("body").find("div.modal-backdrop-filter").remove(); 5617 // options button 5618 let buttonVal = $('.all-filter-count').attr('data-permanentval'); 5619 if (buttonVal) { 5620 $('.all-filter-count').text(buttonVal); 5621 $('.filter-counter').text(buttonVal); 5622 $('.all-filter-count').parent().removeClass('disabled'); 5623 $('.all-filter-error').addClass('d-none'); 5624 } 5625 /*checkbox selector*/ 5626 let checkBoxList = $('.filter-checkbox'); 5627 5628 for (var index = 0; index < checkBoxList.length; index++) { 5629 var checkboxAnalyticsLabel = $(checkBoxList[index]).attr('data-labelanalytics'); 5630 var checkboxAnalyticsValue = ""; 5631 5632 $(checkBoxList[index]).find('li').each(function() { 5633 var checkboxVal = $(this).attr('data-value'); 5634 var value = $(this).attr('data-permanentval'); 5635 if (value != 'permanent') { 5636 if ($(this).find('.custom-checkbox .custom-control-input').attr("checked")) { 5637 $(this).find('.custom-checkbox .custom-control-input').removeAttr("checked"); 5638 $(this).find('.custom-checkbox .custom-control-input').prop("checked", false); 5639 } 5640 } else if (value == 'permanent') { 5641 if (checkboxAnalyticsValue == "") { 5642 checkboxAnalyticsValue = checkboxVal; 5643 } else { 5644 checkboxAnalyticsValue = checkboxAnalyticsValue + "~" + checkboxVal; 5645 } 5646 if (!$(this).find('.custom-checkbox .custom-control-input').attr("checked")) { 5647 $(this).find('.custom-checkbox .custom-control-input').attr("checked", "checked"); 5648 $(this).find('.custom-checkbox .custom-control-input').prop("checked", true); 5649 } 5650 } 5651 }); 5652 checkboxAnalyticsValue = checkboxAnalyticsValue.replace(/ /g, "_").toLowerCase(); 5653 checkBoxList[index].parentElement.parentElement.setAttribute("data-gtm-cta", checkboxAnalyticsLabel + checkboxAnalyticsValue); 5654 } 5655 /*rating selector*/ 5656 if ($('.filter-rating').length > 0) { 5657 let ratingPermVal = $('.filter-rating').attr("data-permanentval"); 5658 let ratingAnalyticsValue = ""; 5659 let filterRatingTextAnalytics = $('.filter-rating').attr("data-labelanalytics"); 5660 $('.filter-rating li').each(function() { 5661 let index = $(this).attr("data-index"); 5662 if (index > ratingPermVal) { 5663 $(this).removeClass('filter-rating-green'); 5664 $(this).removeClass('filter-rating-black'); 5665 $(this).removeClass('selected'); 5666 } else if (index < ratingPermVal) { 5667 5668 $(this).addClass('filter-rating-green'); 5669 $(this).addClass('filter-rating-black'); 5670 $(this).removeClass('selected'); 5671 } else if (index === ratingPermVal) { 5672 $(this).addClass('filter-rating-green'); 5673 $(this).addClass('filter-rating-black'); 5674 $(this).addClass('selected'); 5675 ratingAnalyticsValue = index; 5676 } 5677 }); 5678 $('.filter-rating')[0].parentElement.parentElement.setAttribute("data-gtm-cta", filterRatingTextAnalytics + ratingAnalyticsValue); 5679 } 5680 /*range Selector*/ 5681 if ($('.range-slider').length > 0) { 5682 var rangePermVal = $('.range-slider').attr("data-permanentval"); 5683 var rangeAnalyticsValue = ""; 5684 var filterRangeTextAnalytics = $('.range-slider').attr("data-labelanalytics"); 5685 if (rangePermVal) { 5686 let sliderType = $('.slider').attr("data-type"); 5687 let minVal = rangePermVal.split(',')[0]; 5688 let maxVal = rangePermVal.split(',')[1]; 5689 rangeAnalyticsValue = minVal + "-" + maxVal; 5690 let $sliderReset = $(".slider"); 5691 $sliderReset.slider("values", 0, minVal); 5692 $sliderReset.slider("values", 1, maxVal); 5693 if (sliderType === "price") { 5694 $('.tooltip-min').text("$" + minVal); 5695 $('.tooltip-max').text("$" + maxVal); 5696 } 5697 if (sliderType === "data") { 5698 let maxRange = $('.slider').attr("data-maxrange"); 5699 let showUnlimited = $('.slider').attr('data-showUnlimited'); 5700 let unlimitedLabel = $('.slider').attr('data-unlimitedlabel'); 5701 var minDataUnit = maxDataUnit = "MB"; 5702 var minRangeDsp = minVal; 5703 var maxRangeDsp = maxVal; 5704 if (minVal >= 1024) { 5705 minRangeDsp = (minVal / 1024).toFixed(1); 5706 minDataUnit = "GB"; 5707 } 5708 $(".tooltip-min").text(minRangeDsp + " " + minDataUnit).attr('data-minVal', minVal - 1); 5709 if (showUnlimited == "true" && maxVal == maxRange) { 5710 $(".tooltip-max").text(unlimitedLabel).attr('data-maxVal', unlimitedLabel); 5711 } else { 5712 if (maxVal >= 1024) { 5713 maxRangeDsp = (maxVal / 1024).toFixed(1); 5714 maxDataUnit = "GB"; 5715 } 5716 $(".tooltip-max").text(maxRangeDsp + " " + maxDataUnit).attr('data-maxVal', maxVal + 1); 5717 } 5718 } 5719 if (sliderType === "text") { 5720 $('.tooltip-min').text(minVal); 5721 $('.tooltip-max').text(maxVal); 5722 } 5723 if (sliderType === "talk") { 5724 const minutes = $('.product-filter-container').getAttribute('data-lblminutes'); 5725 5726 $('.tooltip-min').text(minVal + minutes ); 5727 $('.tooltip-max').text(maxVal + minutes ); 5728 } 5729 5730 var sliderCheckboxAnalyticsValue = ""; 5731 $('.slider-checkboxes li').each(function() { 5732 5733 let value = $(this).attr('data-permanentval'); 5734 let checkboxMin = $(this).attr('data-checkboxmin'); 5735 let checkboxMax = $(this).attr('data-checkboxmax'); 5736 if (value != 'permanent') { 5737 if ($(this).find('.custom-checkbox .custom-control-input').attr("checked")) { 5738 $(this).find('.custom-checkbox .custom-control-input').removeAttr("checked"); 5739 $(this).find('.custom-checkbox .custom-control-input').prop("checked", false); 5740 } 5741 } else if (value == 'permanent') { 5742 if (sliderCheckboxAnalyticsValue == "") { 5743 sliderCheckboxAnalyticsValue = checkboxMin + "-" + checkboxMax; 5744 } else { 5745 sliderCheckboxAnalyticsValue = sliderCheckboxAnalyticsValue + "~" + checkboxMin + "-" + checkboxMax; 5746 } 5747 if (!$(this).find('.custom-checkbox .custom-control-input').attr("checked")) { 5748 $(this).find('.custom-checkbox .custom-control-input').attr("checked", "checked"); 5749 $(this).find('.custom-checkbox .custom-control-input').prop("checked", true); 5750 } 5751 5752 } 5753 }); 5754 5755 if (sliderCheckboxAnalyticsValue != "") { 5756 $('.range-slider')[0].parentElement.parentElement.setAttribute("data-gtm-cta", filterRangeTextAnalytics + sliderCheckboxAnalyticsValue); 5757 } else { 5758 $('.range-slider')[0].parentElement.parentElement.setAttribute("data-gtm-cta", filterRangeTextAnalytics + rangeAnalyticsValue); 5759 } 5760 } 5761 } 5762}); 5763/*Filter modal Close functioning*/ 5764 5765/*Filter modal button functioning*/ 5766$("#allFilterModal .all-filter-count").on("click", function() { 5767 //$("body").find("div.modal-backdrop-filter").remove();
5768 let clearfilter = document.querySelector('.clear-filter-accessibility').innerHTML; 5769 let badgeHtml = ' <div class="badges" data-id="{{id}}" data-type="{{type}}"><span class="badge-title caption-two">{{value}}</span><span role="button" tabindex="0" aria-label="{{clearfilter}} {{filtername}}" class="icon light-theme small-icon"><i class="clear"></i></span></div>'; 5770 document.querySelector('.filter-badges').innerHTML = ""; 5771 let totalCount = 0; 5772 /*checkboxes*/ 5773 let filterCheckboxList = $(".filter-checkbox"); 5774 $(".filter-checkbox").each(function(index) { 5775 let viewType = $(this).attr("data-selctedcheckboxview"); 5776 let label = $(this).attr("data-label"); 5777 let checkboxId = $(this).attr("id"); 5778 let count = ""; 5779 let checkboxList = filterCheckboxList[index].querySelectorAll('li'); 5780 for (let j = 0; j < checkboxList.length; j++) { 5781 5782 if (checkboxList[j].querySelector('input').checked) { 5783 let id = checkboxList[j].querySelector('input').id; 5784 let selectedval = checkboxList[j].querySelector('p').innerText; 5785 checkboxList[j].setAttribute('data-permanentVal', 'permanent'); 5786 if (viewType === "showseperate") { 5787 totalCount = totalCount + 1; 5788 let badge = badgeHtml.replaceAll("{{value}}", selectedval).replace("{{id}}", id).replace("{{type}}", "checkbox").replaceAll("{{clearfilter}}", clearfilter).replaceAll("{{filtername}}", selectedval); 5789 document.querySelector('.filter-badges').insertAdjacentHTML('beforeend', badge); 5790 } 5791 count++; 5792 } else { 5793 checkboxList[j].removeAttribute('data-permanentVal'); 5794 } 5795 } 5796 if (viewType === "showcount") { 5797 if (count != "") { 5798 totalCount = totalCount + 1; 5799 let badge = badgeHtml.replaceAll("{{value}}", label + " (" + count + ")").replace("{{id}}", checkboxId).replace("{{type}}", "checkboxlist").replaceAll("{{clearfilter}}", clearfilter).replaceAll("{{filtername}}", label + " (" + count + ")"); 5800 document.querySelector('.filter-badges').insertAdjacentHTML('beforeend', badge); 5801 } 5802 } 5803 5804 }); 5805 5806 /*range selector*/ 5807 let rangeSelector = $('.range-slider'); 5808 let labelRange = rangeSelector.attr("data-label"); 5809 let sliderType = $('.slider').attr("data-type"); 5810 if ($('.slider').hasClass("selectedRange")) { 5811 let rangeMin = rangeSelector.find('.tooltip-min').attr("data-minval"); 5812 let rangeMax = rangeSelector.find('.tooltip-max').attr("data-maxval"); 5813 let rangeMinLabel = rangeSelector.find('.tooltip-min').text(); 5814 let rangeMaxLabel = rangeSelector.find('.tooltip-max').text(); 5815 totalCount = totalCount + 1; 5816 let rangeBadge = badgeHtml.replaceAll("{{value}}", labelRange + " (" + rangeMinLabel + "-" + rangeMaxLabel + ")").replace("{{id}}", labelRange).replace("{{type}}", "rangeslider").replaceAll("{{clearfilter}}", clearfilter).replaceAll("{{filtername}}", labelRange + " (" + rangeMinLabel + "-" + rangeMaxLabel + ")"); 5817 document.querySelector('.filter-badges').insertAdjacentHTML('beforeend', rangeBadge); 5818 if (sliderType === "data" || sliderType === "talk" || sliderType === "text") { 5819 rangeMin = +rangeMin + 1; 5820 rangeMax = rangeMax - 1; 5821 rangeSelector.attr('data-permanentVal', rangeMin + "," + rangeMax); 5822 } else { 5823 rangeSelector.attr('data-permanentVal', rangeMin + "," + rangeMax); 5824 } 5825 } else { 5826 rangeSelector.attr('data-permanentVal', $('.slider').attr("data-minrange") + "," + $('.slider').attr("data-maxrange")); 5827 } 5828 5829 let sliderCheckboxes = $('.slider-checkboxes li'); 5830 for (let s = 0; s < sliderCheckboxes.length; s++) { 5831 5832 if (sliderCheckboxes[s].querySelector('input').checked) { 5833 let id = sliderCheckboxes[s].querySelector('input').id; 5834 let selectedval = sliderCheckboxes[s].querySelector('p').innerText; 5835 sliderCheckboxes[s].setAttribute('data-permanentVal', 'permanent'); 5836 labelRange = document.querySelector('.range-slider').getAttribute('data-label'); 5837 totalCount = totalCount + 1;
5838 let badgeVal = labelRange + " (" + selectedval + ")"; 5839 let badge = badgeHtml.replaceAll("{{value}}", badgeVal).replace("{{id}}", id).replace("{{type}}", "checkbox").replaceAll("{{clearfilter}}", clearfilter).replaceAll("{{filtername}}", badgeVal); 5840 document.querySelector('.filter-badges').insertAdjacentHTML('beforeend', badge); 5841 5842 } else { 5843 sliderCheckboxes[s].removeAttribute('data-permanentVal'); 5844 } 5845 } 5846 5847 /* rating selector*/ 5848 let ratingSelector = $('.filter-rating li.selected'); 5849 let labelRating = $('.filter-rating').attr("data-label"); 5850 let labelRatingSelected = $('.filter-rating').attr("data-ratinglabel"); 5851 let labelRatingMaxSelected = $('.filter-rating').attr("data-maxratinglabel"); 5852 let ratingId = $('.filter-rating').attr("id"); 5853 if (ratingSelector.length > 0) { 5854 totalCount = totalCount + 1; 5855 let ratingValue = $('.filter-rating li.selected').attr('data-index'); 5856 let ratingBadge = ""; 5857 if (ratingValue === $('.filter-rating li').length) { 5858 ratingBadge = badgeHtml.replaceAll("{{value}}", labelRating + " ( " + ratingValue + " " + labelRatingMaxSelected + " )").replace("{{id}}", ratingId).replace("{{type}}", "ratingselector").replaceAll("{{clearfilter}}", clearfilter).replaceAll("{{filtername}}", labelRating + " ( " + ratingValue + " " + labelRatingMaxSelected + " )"); 5859 } else { 5860 ratingBadge = badgeHtml.replaceAll("{{value}}", labelRating + " ( " + ratingValue + " " + labelRatingSelected + " )").replace("{{id}}", ratingId).replace("{{type}}", "ratingselector").replaceAll("{{clearfilter}}", clearfilter).replaceAll("{{filtername}}", labelRating + " ( " + ratingValue + " " + labelRatingMaxSelected + " )"); 5861 } 5862 document.querySelector('.filter-badges').insertAdjacentHTML('beforeend', ratingBadge); 5863 $('.filter-rating').attr('data-permanentVal', ratingValue); 5864 5865 } else { 5866 $('.filter-rating').attr('data-permanentVal', "0"); 5867 } 5868 /*options button*/ 5869 $('.mobile-filter-count').text("(" + totalCount + ")"); 5870 let optionButton = $('.all-filter-count').text(); 5871 $('.all-filter-count').attr('data-permanentVal', optionButton); 5872}); 5873/*Filter modal button functioning*/ 5874 5875/*Filter Badges Start*/ 5876$('body').on("click", ".filter-badges span.icon", function() { 5877 let id = $(this).parent('.badges').attr('data-id'); 5878 let type = $(this).parent('.badges').attr('data-type'); 5879 5880 if (type === 'checkbox') { 5881 $('.filters-container').find('#' + id).removeAttr("checked"); 5882 $('.filters-container').find('#' + id).parent().parent().removeAttr("data-permanentval"); 5883 } 5884 if (type === 'checkboxlist') { 5885 5886 let checkboxLi = $('.filters-container').find('#' + id).find('li'); 5887 if (checkboxLi.length > 0) { 5888 checkboxLi.each(function() { 5889 $(this).removeAttr("data-permanentval"); 5890 $(this).find('.custom-checkbox .custom-control-input').removeAttr("checked"); 5891 }); 5892 } 5893 } 5894 if (type === 'rangeslider') { 5895 $(".slider").each(function(){ 5896 let sliderType = $(this).attr("data-type"); 5897 let minVal = $(this).attr("data-minrange"); 5898 let maxVal = $(this).attr("data-maxrange"); 5899 var $sliderReset = $(this); 5900 $(".range-slider").attr('data-permanentVal', minVal + "," + maxVal); 5901 $(this).removeClass("selectedRange"); 5902 $sliderReset.slider("values", 0, minVal); 5903 $sliderReset.slider("values", 1, maxVal); 5904 $(this).find('.tooltip-min').text($('.start-price').html()); 5905 $(this).find('.tooltip-max').text($('.end-price').html()); 5906 }); 5907 } 5908 if (type === 'ratingselector') { 5909 let ratingLi = $('.filters-container').find('#' + id).find('li'); 5910 $('.filter-rating').attr('data-permanentVal', "0"); 5911 if (ratingLi.length > 0) { 5912 ratingLi.each(function() { 5913 5914 $(this).removeClass('filter-rating-green'); 5915 $(this).removeClass('filter-rating-black'); 5916 $(this).removeClass('selected'); 5917 5918 }); 5919 } 5920 } 5921 /*custom event*/ 5922 this.dispatchEvent(new Event('closeBadge', { 5923 'bubbles': true 5924 })); 5925 $(".all-filter-count").removeAttr("data-permanentval"); 5926 $(this).parent('.badges').remove(); 5927 $(".toal-count").focus(); 5928}); 5929/*Filter Badges End*/ 5930 5931/* To display smartpay preapproval banner */ 5932 5933$("#sp-preapproval-banner").attr("style", "display:none"); 5934$("#sp-preapproval-banner-pdp").attr("style", "display:none"); 5935$("#overview").attr("banner-visible","false"); 5936$(window).load(function () { 5937 var preApprovalValue = getCookieCommon("preApproval"); 5938 if (preApprovalValue) { 5939 $(".cmp-experiencefragment--paypal-banner-plp-xf").attr("style", "display:none"); 5940 $("#deals-monthly_payment_plan") && $("#deals-monthly_payment_plan").click(); 5941 $("#monthly_payment_plan-monthly_payment_plan") && $("#monthly_payment_plan-monthly_payment_plan").click(); 5942 $("#plan_de_pago_mensual-plan_de_pago_mensual") && $("#plan_de_pago_mensual-plan_de_pago_mensual").click(); 5943 $("#ofertas-plan_de_pago_mensual") && $("#ofertas-plan_de_pago_mensual").click(); 5944 $(".all-filter-count") && $(".all-filter-count").click(); 5945 $('[value="emi"]') && $('[value="emi"]').click(); 5946 } 5947}); 5948 5949/* To switch button on smartpay preapproval banner */ 5950$(document).on("click","#finance-phn-btn .btn", function(){ 5951 $("#deals-monthly_payment_plan") && $("#deals-monthly_payment_plan").click(); 5952 $("#ofertas-plan_de_pago_mensual") && $("#ofertas-plan_de_pago_mensual").click(); 5953 $("#monthly_payment_plan-monthly_payment_plan") && $("#monthly_payment_plan-monthly_payment_plan").click(); 5954 $("#plan_de_pago_mensual-plan_de_pago_mensual") && $("#plan_de_pago_mensual-plan_de_pago_mensual").click(); 5955 $(".all-filter-count") && $(".all-filter-count").click(); 5956 $(this).hide(); 5957}); 5958 5959$(document).on("click","#deals-monthly_payment_plan, #ofertas-plan_de_pago_mensual, #monthly_payment_plan-monthly_payment_plan, #plan_de_pago_mensual-plan_de_pago_mensual", function(){
5960 if($("#deals-monthly_payment_plan").prop('checked') || $("#ofertas-plan_de_pago_mensual").prop('checked') || $("#monthly_payment_plan-monthly_payment_plan").prop('checked') || $("#plan_de_pago_mensual-plan_de_pago_mensual").prop('checked')){ 5961 $("#finance-phn-btn .btn").hide(); 5962 }else { 5963 $("#finance-phn-btn .btn").show(); 5964 } 5965}); 5966 5967function replaceAsLowAs(scriptValue){ 5968 $("p").each(function(){ 5969 var html= $(this).html(); 5970 if(html.indexOf("As low as")>=0){ 5971 $(this).html(html.replace("As low as",scriptValue)); 5972 } else if(html.indexOf("Desde solo")>=0) { 5973 $(this).html(html.replace("Desde solo",scriptValue)); 5974 } else if(html.indexOf("As Low")>=0) { 5975 $(this).html(html.replace("As Low",scriptValue)); 5976 } 5977 }) 5978} 5979/** 5980 * This function will display the alert message for Free Phones when user select the Ineligible plan from Shop Plan Journey 5981 * 5982 */ 5983async function freePhoneAlert() { 5984 let buttonText = await getScriptingValueCommon('_BTN_OK'); 5985 let modalDataObj = { 5986 heading: await getScriptingValueCommon('_ERR_FREE_PHONE_INELIGIBLE_PLAN_TITLE'), 5987 summary: await getScriptingValueCommon('_ERR_FREE_PHONE_INELIGIBLE_PLAN_BODY'), 5988 firstCtaLabel: buttonText, 5989 firstCtaEvent: 'document.dispatchEvent(new CustomEvent("openPDPModal",{"detail": {}}))', 5990 firstCtaLink: ' ', 5991 firstCtaAriaLabel: buttonText, 5992 firstCtaGtmText: buttonText, 5993 preventClose: "true" 5994 } 5995 $('#purchase-modal-box').modal('hide'); 5996 document.dispatchEvent(new CustomEvent("ShowGenericPopup", { 5997 'bubbles': true, 5998 'detail': { 5999 "modalDataObj": modalDataObj 6000 } 6001 })); 6002} 6003 6004/** 6005 * This function is use to enable the message for portin/veriff disclaimer on PDP if verification screen is coming in purchase flow journey 6006 * @param {*} element 6007 */ 6008function setPortinDisclaimer(element) { 6009 const showportinflow = element.querySelector('#portInVerification')?.dataset?.showportinflow; 6010 if (showportinflow === TRUE_FLAG) { 6011 if (element.querySelector('#portInVerification-phone #portinverifysuccess')) 6012 element.querySelector('#portInVerification-phone #portinverifysuccess').style.display = 'block'; 6013 if (element.querySelector('#portInVerification .portIn-disclosure2')) 6014 element.querySelector("#portInVerification .portIn-disclosure2").style.display = 'none'; 6015 element.querySelector("#portInAddCartBtn")?.classList.remove("disabled"); 6016 if (document.querySelector('.purchase-modal-box-footer .primary-btn')) { 6017 document.querySelector('.purchase-modal-box-footer .primary-btn').classList.remove('disabled'); 6018 } 6019 window.portInAddToCartBtnDisabled = false; 6020 if (element.querySelector("#portInAddCartBtn .addToCartBtn")) 6021 element.querySelector("#portInAddCartBtn .addToCartBtn").setAttribute('aria-label', element.querySelector("#portInAddCartBtn .addToCartBtn").dataset.addtocarttext); 6022 } 6023} 6024 6025/** 6026 * This function will toggle the option if user choose the Free payment option from Phone PDP Page 6027 * * @params {STRING} - {@paymentType - payment type option} 6028 */ 6029async function setFreePhoneData(paymentType) { 6030 let element = document.querySelector('.phonedetail-price-container'); 6031 element.querySelector('#addtocart .pp-disclaimer')?.classList.remove("pt-20"); 6032 if (paymentType === LBL_FREE_OPTION) { 6033 var offerType = $(".color-swatch .selected").attr("data-offertype"); 6034 clearRadio('.zipapi-config .payment-type .custom-control-input'); 6035 this.setClawBackInstructions(element,'.clawback-footnote',offerType,document.querySelector(lbl_dot_section_api_container)?.dataset?.enableveriffidentification,TRUE_FLAG); 6036 let hideVeriff = document.querySelector(".section-api-container")?.dataset.migrateverifftocart; 6037 6038 if(hideVeriff === 'true' && (offerType === lbl_offer_port_in || offerType === lbl_offer_veriff)) { 6039 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6040 document.querySelector("#portInAddCartBtn")?.classList.remove("disabled"); 6041 window.portInAddToCartBtnDisabled = false;
6042 6043 //persist offer type to make add to cart call 6044 sessionStorage.setItem("great-price-offer-type",document.querySelector(".selected.imageChange")?.dataset?.offertype); 6045 6046 //if twp section is visible, hide it here 6047 document.querySelector("#twp-plan-details")?.classList?.add("d-none"); 6048 document.querySelector(".legal-disclosure.pb-30.text-left.cart-footnote")?.classList?.add("d-none"); 6049 document.querySelector("#addtocart")?.classList?.add("d-none"); 6050 element.querySelector('#portInVerification')?.classList?.remove("d-none"); 6051 6052 } else if (hideVeriff !== 'true' && (offerType === lbl_offer_port_in || offerType === lbl_offer_veriff)) { 6053 element.querySelector('#addtocart').classList.add("d-none"); 6054 element.querySelector('#portInVerification')?.classList.remove("d-none"); 6055 element.querySelector('#portInVerification-phone')?.classList.remove("d-none"); 6056 this.setPortinDisclaimer(element); 6057 resetPortIn(); 6058 } else if (offerType === lbl_offer_activation) { 6059 element.querySelector('#addtocart').classList.remove("d-none"); 6060 element.querySelector('#portInVerification')?.classList.add("d-none"); 6061 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6062 element.querySelector('#addtocart .zipapi-config .choice-card.upgrade')?.classList.add("d-none"); 6063 element.querySelector('#addtocart .zipapi-config .upgradeNotEligible')?.classList.remove("d-none"); 6064 element.querySelector('#addtocart .paypal-container')?.classList.remove("d-none"); 6065 element.querySelector('#addtocart #cart-option-counter')?.classList.remove("d-none"); 6066 element.querySelector('#addtocart .payment-type-heading')?.classList.remove("d-none"); 6067 element.querySelector('#addtocart .cart-footnote')?.classList.remove("d-none"); 6068 element.querySelector('#addtocart .choice-cards')?.classList.remove("d-none"); 6069 var addToCartElements = $('#addtocart .zipapi-config'); 6070 if (addToCartElements != null && addToCartElements.length > 0) { 6071 addToCartElements[0]?.classList.remove("disabledPageContent"); 6072 setAddToCartTabIndex(); 6073 } 6074 } 6075 6076 } else { 6077 element.querySelector('#addtocart').classList.remove("d-none"); 6078 element.querySelector('#portInVerification')?.classList.add("d-none"); 6079 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6080 element.querySelector('#addtocart .zipapi-config .choice-card.upgrade')?.classList.remove("d-none"); 6081 element.querySelector('#addtocart .zipapi-config .upgradeNotEligible')?.classList.add("d-none"); 6082 element.querySelector('#addtocart .paypal-container')?.classList.remove("d-none"); 6083 element.querySelector('#addtocart .payment-type-heading')?.classList.remove("d-none"); 6084 element.querySelector('#addtocart .cart-footnote')?.classList.remove("d-none"); 6085 if(document.querySelector('.section-api-container')?.dataset?.brand?.toUpperCase() !== 'TOTAL_WIRELESS') { 6086 element.querySelector('#addtocart .choice-cards')?.classList.remove("d-none"); 6087 element.querySelector('#addtocart #cart-option-counter')?.classList.remove("d-none"); 6088 } 6089 var addToCartElements = $('#addtocart .zipapi-config'); 6090 if (addToCartElements != null && addToCartElements.length > 0) { 6091 addToCartElements[0]?.classList.remove("disabledPageContent"); 6092 setAddToCartTabIndex(); 6093 } 6094 6095 element.querySelector("#addtocart .clawback-footnote")?.classList.add("d-none"); 6096 } 6097 6098 let enableDcotPromoOffers = document.querySelector('.section-api-container')?.dataset?.enabledcotpromooffers; 6099 const dcotModelName = document.querySelector(".phonedetail-price-container")?.dataset.dcotmodelname; 6100 const enabledcotpaymentoptionposition = document.querySelector(".phonedetail-price-container")?.dataset.enabledcotpaymentoptionposition; 6101 6102 if(enableDcotPromoOffers && dcotModelName && enabledcotpaymentoptionposition && 6103 enabledcotpaymentoptionposition == "true") { 6104 if($('.payment-option-ex .custom-control-input:checked').val() == "full-price"){ 6105 element.querySelector(".dcot-full-price-promo.dcot-full-price-promo-payment-section")?.classList.remove("d-none"); 6106 element.querySelector(".dcot-full-price-promo.dcot-full-price-promo-payment-section .offer-details-link")?.classList.remove("d-none"); 6107 } else { 6108 element.querySelector(".dcot-full-price-promo.dcot-full-price-promo-payment-section")?.classList.add("d-none"); 6109 } 6110 } 6111 6112} 6113/** 6114 * Function to unchecked the radio button 6115 * @params {STRING} - {@elementClass - element class name 6116 * } 6117 **/ 6118function clearRadio(elementClass) { 6119 let radio = document.querySelectorAll(elementClass); 6120 for (let index = 0; index < radio.length; index++) { 6121 radio[index].checked = false;
6122 radio[index]?.closest('.choice-card')?.classList.remove("selected"); 6123 var custType = document.querySelector(elementClass)?.closest('input')?.value; 6124 if (custType != 'upgrade' && document.querySelector('#phoneNo')) { 6125 document.querySelector('#phoneNo').setAttribute('tabindex', '-1'); 6126 document.querySelector('#phoneNo').value = ''; 6127 } 6128 } 6129} 6130/** 6131 * Function to set the promotional offer Labels 6132 * @params {STRING,INT} - {@element - Element 6133 * @offertype - Type of promotional offer 6134 * @elemntClass - element Class 6135 * @label - label 6136 * } 6137 **/ 6138function setOfferLabels(element,elemntClass,label,offertype,flag, _setDynamicPlansLabels){ 6139 6140 if(label && label.includes('|')){ 6141 let plantypes = (document.querySelector('.promooffer-subheading')?.dataset?.planlabel) ? document.querySelector('.promooffer-subheading')?.dataset?.planlabel : ''; 6142 if (element.querySelector(elemntClass)) { 6143 if (element.querySelector(elemntClass) && label && (offertype == lbl_offer_port_in || offertype == lbl_offer_activation || offertype == lbl_offer_veriff)) { 6144 if (label.split('|').length > 1) { 6145 if(label.split('|').length > 2){ 6146 if ((offertype == lbl_offer_port_in ) && !flag) { 6147 element.querySelector(elemntClass).innerHTML = label.split('|')[0]; 6148 6149 } else if ((offertype == lbl_offer_activation) && !flag) { 6150 element.querySelector(elemntClass).innerHTML = label.split('|')[1]; 6151 6152 } else if ((offertype == lbl_offer_veriff) && !flag) { 6153 element.querySelector(elemntClass).innerHTML = label.split('|')[2]; 6154 } 6155 } else { 6156 6157 let price = element.querySelector('.colorImageSwitch .imageChange.selected')?.dataset.tabprice?.toLowerCase(); 6158 6159 if(flag && price==="free") 6160 element.querySelector(elemntClass).innerHTML = label.split('|')[0]; 6161 else 6162 element.querySelector(elemntClass).innerHTML = label.split('|')[1]; 6163 } 6164 } else 6165 element.querySelector(elemntClass).innerHTML = DOMPurify.sanitize(label); 6166 6167 } else { 6168 element.querySelector(elemntClass).innerHTML = ""; 6169 } 6170 6171 let text = element.querySelector(elemntClass).innerHTML; 6172 if(_setDynamicPlansLabels) { 6173 const element = document.querySelector(".phonedetail-price-container"); 6174 const orLabel = element?.dataset.orlabel; 6175 const higherlabel = element?.dataset.higherlabel; 6176 let updatedText = _setDynamicPlansLabels(text,null,orLabel, higherlabel, plantypes); 6177 element.querySelector(elemntClass).innerHTML = DOMPurify.sanitize(updatedText); 6178 } 6179 } 6180 } 6181} 6182/** 6183 * Function to set the Clawback instructions for promotional devices 6184 * @params {STRING,INT} - {@element - Element 6185 * @offertype - Type of promotional offer 6186 * @elemntClass - element Class 6187 * @label - label 6188 * } 6189 **/ 6190async function setClawBackInstructions(element,elemntClass,offertype,enableVeriffIdentification,optionChangeFlag){ 6191 let optionSelected= element.querySelector(".payment-option .choice-card.promo-offer")?.classList?.contains("selected"); 6192 var enableClawBackInstr = document.querySelector(lbl_dot_section_api_container)?.dataset?.enableclawbackinstr; 6193 var enableCBIForDiscount = document.querySelector(lbl_dot_section_api_container)?.dataset?.enablecbifordiscount; 6194 var clawBackInstrForOffers= document.querySelector(lbl_dot_section_api_container)?.dataset?.clawbackinstrforoffers; 6195 if(enableClawBackInstr === TRUE_FLAG && clawBackInstrForOffers.includes(offertype)){ 6196 let price = element.querySelector('.colorImageSwitch .imageChange.selected')?.dataset.tabprice?.toLowerCase();
6197 let clawBackFlag = FALSE_FLAG; 6198 let freeLabel = document.querySelectorAll(".tabprice-free")[0]?.innerText?.toLowerCase(); 6199 if(enableCBIForDiscount === TRUE_FLAG || price=== freeLabel){ 6200 clawBackFlag = TRUE_FLAG; 6201 } 6202 if(clawBackFlag === TRUE_FLAG){ 6203 var elementName,cfLabel,footNoteEle,cfVal; 6204 if((offertype == lbl_offer_port_in ) ){ 6205 elementName= ".port-in-footnote "+ elemntClass; 6206 footNoteEle = elementName +" .footnote"; 6207 cfLabel = "_LBL_CLAWBACK_INSTRUCTIONS_PORT_IN_OFFER"; 6208 }else if((offertype == lbl_offer_veriff && enableVeriffIdentification === TRUE_FLAG)){ 6209 elementName= ".veriff-footnote "+ elemntClass; 6210 footNoteEle = elementName +" .footnote"; 6211 cfLabel = "_LBL_CLAWBACK_INSTRUCTIONS_VERIFF_OFFER"; 6212 }else if((offertype == lbl_offer_activation && (optionSelected || optionSelected===TRUE_FLAG))){ 6213 elementName= "#addtocart "+ elemntClass; 6214 footNoteEle = elementName; 6215 cfLabel = "_LBL_CLAWBACK_INSTRUCTIONS_ACTIVATION_OFFER"; 6216 } 6217 cfVal = DOMPurify.sanitize(await getScriptingValueCommon(cfLabel)) 6218 if(element.querySelector(footNoteEle))element.querySelector(footNoteEle).innerHTML=cfVal; 6219 element.querySelector(elementName)?.classList.remove("d-none"); 6220 6221 if(optionChangeFlag=== FALSE_FLAG && element.querySelector(".payment-option .offer-details-link")){ 6222 let offerLink= document.querySelector(element.querySelector(".payment-option .offer-details-link").getAttribute("data-target")); 6223 if(offerLink){ 6224 let ultag = offerLink.getElementsByClassName('dynamic-desc')[0]?.querySelector("ul") 6225 const li = document.createElement('li'); 6226 li.innerHTML = cfVal; 6227 ultag?.appendChild(li); 6228 } 6229 } 6230 } 6231 } 6232} 6233 6234 6235function setDynamicPromoLabels(promoPlanPriceListItems, orLabel, orHigherLabel, _setDynamicPlansLabels, promoScriptText, element) { 6236 6237 let dcotPromoMessage; 6238 if($(".dcot-promo-subheading").length > 0){ 6239 dcotPromoMessage = $(".dcot-promo-subheading").html(); 6240 } else if(promoScriptText){ 6241 dcotPromoMessage = promoScriptText; 6242 } 6243 let defaultModelName = $('.product-name').length > 0 ? $('.product-name').text() : ""; 6244 const dcotModelName = element?.dataset.dcotmodelname ? element?.dataset.dcotmodelname : defaultModelName; 6245 const dcotMonthlyDisc = element?.dataset.dcotmonthlydisc; 6246 const dcotOfferEndDt = element?.dataset.dcotofferenddt; 6247 const dcotPaidAmt = element?.dataset.dcotpaidamt; 6248 const dcotTotalMonthText = element?.dataset.dcottotalmonthtext; 6249 const dcotSaving = element?.dataset.dcotsaving; 6250 const enabledcotpaymentoptionposition = element.dataset.enabledcotpaymentoptionposition ? element.dataset.enabledcotpaymentoptionposition : "false"; 6251 6252 if (dcotPromoMessage) { 6253 dcotPromoMessage = dcotPromoMessage.replace(/{{monthlyDisc}}/g, dcotMonthlyDisc).replace(/{{totalMonths}}/g, dcotTotalMonthText).replace(/{{offerEndDate}}/g, dcotOfferEndDt).replace(/{{saving}}/g, dcotSaving).replace(/{{paidAmt}}/g, dcotPaidAmt).replace(/{{phone-name}}/g, dcotModelName); 6254 dcotPromoMessage = _setDynamicPlansLabels(dcotPromoMessage,promoPlanPriceListItems,orLabel, orHigherLabel,) 6255 dcotPromoMessage = updateDcotDynamicLabels(dcotPromoMessage); 6256 let dcotPromoMessagehtml = '<div class="dcot-promobanner"><span class="pdp-dcot-promo-text-icon"></span><span class="promo-msg bold">'+dcotPromoMessage +"</span></div>"; 6257 $(".promooffer-subheading").html(dcotPromoMessagehtml); 6258 let targetEle = document.querySelector('.promooffer-subheading .promo-msg p') ? '.promooffer-subheading .promo-msg p' : '.promooffer-subheading .promo-msg' 6259 this.setOfferDetailLink(element,dcotPromoMessage,targetEle," .dcot-offer-details-link"); 6260 6261 if($(".promooffer-subheading-mob div").length > 0){ 6262 $(".promooffer-subheading-mob div").html(dcotPromoMessagehtml); 6263 let targetElemob = document.querySelector('.promooffer-subheading-mob .promo-msg p') ? '.promooffer-subheading-mob .promo-msg p' : '.promooffer-subheading-mob .promo-msg' 6264 6265 this.setOfferDetailLink(element,dcotPromoMessage, targetElemob, ".dcot-offer-details-link"); 6266 } 6267 } 6268 if($(".dcot-promo-offer-data .offer-desc").length > 0){ 6269 let dynamicTitleBody = $(".dcot-promo-offer-data .offer-desc").html(); 6270 dynamicTitleBody = dynamicTitleBody.replace(/{{monthlyDisc}}/g, dcotMonthlyDisc).replace(/{{totalMonths}}/g, dcotTotalMonthText).replace(/{{offerEndDate}}/g, dcotOfferEndDt).replace(/{{saving}}/g, dcotSaving).replace(/{{paidAmt}}/g, dcotPaidAmt).replace(/{{phone-name}}/g, dcotModelName); 6271 dynamicTitleBody && $("#dcot-offer-box .modal-body .dynamic-desc").html(dynamicTitleBody); 6272 } 6273 if($(".dcot-promo-offer-data .offer-heading").length > 0){ 6274 let dynamicModelTitle = $(".dcot-promo-offer-data .offer-heading").html(); 6275 dynamicModelTitle = dynamicModelTitle.replace(/{{monthlyDisc}}/g, dcotMonthlyDisc).replace(/{{totalMonths}}/g, dcotTotalMonthText).replace(/{{offerEndDate}}/g, dcotOfferEndDt).replace(/{{saving}}/g, dcotSaving).replace(/{{paidAmt}}/g, dcotPaidAmt).replace(/{{phone-name}}/g, dcotModelName); 6276 dynamicModelTitle && $("#dcot-offer-box .modal-body .dynamic-title").html(dynamicModelTitle); 6277 } 6278 6279 6280 if ($("#dcot-offer-box .modal-body .dynamic-desc").length > 0) { 6281 let dcotOfferDetailBodyHtml = $("#dcot-offer-box .modal-body .dynamic-desc").html(); 6282 6283 dcotOfferDetailBodyHtml = dcotOfferDetailBodyHtml.replace(/{{monthlyDisc}}/g, dcotMonthlyDisc).replace(/{{totalMonths}}/g, dcotTotalMonthText).replace(/{{offerEndDate}}/g, dcotOfferEndDt).replace(/{{saving}}/g, dcotSaving).replace(/{{paidAmt}}/g, dcotPaidAmt).replace(/{{phone-name}}/g, dcotModelName); 6284 dcotOfferDetailBodyHtml = _setDynamicPlansLabels(dcotOfferDetailBodyHtml,promoPlanPriceListItems,orLabel, orHigherLabel); 6285 dcotOfferDetailBodyHtml = updateDcotDynamicLabels(dcotOfferDetailBodyHtml); 6286 $("#dcot-offer-box .modal-body .dynamic-desc").html(dcotOfferDetailBodyHtml); 6287 if($('#dcot-offer-box .button a.btn').length > 0){ 6288 $('#dcot-offer-box .button a.btn').attr('data-dismiss', "modal"); 6289 } 6290 } 6291 6292 6293 if ($(".dcot-full-price-promo")) { 6294 let dcotFullpriceOfferHtml = $(".dcot-full-price-promo").html(); 6295 dcotFullpriceOfferHtml = dcotFullpriceOfferHtml.replace(/{{monthlyDisc}}/g, dcotMonthlyDisc).replace(/{{totalMonths}}/g, dcotTotalMonthText).replace(/{{offerEndDate}}/g, dcotOfferEndDt).replace(/{{saving}}/g, dcotSaving).replace(/{{paidAmt}}/g, dcotPaidAmt).replace(/{{phone-name}}/g, dcotModelName); 6296 dcotFullpriceOfferHtml = _setDynamicPlansLabels(dcotFullpriceOfferHtml,promoPlanPriceListItems,orLabel, orHigherLabel); 6297 dcotFullpriceOfferHtml = updateDcotDynamicLabels(dcotFullpriceOfferHtml); 6298 $(".dcot-full-price-promo").html(dcotFullpriceOfferHtml); 6299 window.setOfferDetailLink(element,dcotFullpriceOfferHtml,'.dcot-full-price-promo.promo-detail-price .dcot-fullprice-promo-text'," .dcot-offer-details-link"); 6300 } 6301 let enableDcotPromoOffers = document.querySelector('.section-api-container')?.dataset?.enabledcotpromooffers; 6302 6303 if(enableDcotPromoOffers && dcotModelName) { 6304 $('.dcot-promo-subheading')?.addClass('dcot-promobanner'); 6305 $('.dcot-promo-subheading-mob')?.addClass('dcot-promo-banner-mob'); 6306 6307 if(enabledcotpaymentoptionposition == "true"){ 6308 $(".dcot-full-price-promo.promo-detail-price")?.addClass("d-none"); 6309 } else { 6310 $(".dcot-full-price-promo.dcot-full-price-promo-payment-section")?.addClass("d-none"); 6311 $(".dcot-full-price-promo.promo-detail-price")?.removeClass("d-none"); 6312 $(".dcot-full-price-promo.promo-detail-price .offer-details-link")?.removeClass("d-none"); 6313 $(".dcot-full-price-promo.promo-detail-price .offer-details-link")?.attr("aria-hidden", "false"); 6314 } 6315 6316 } 6317 6318 let dynamicTitleHeader = $("#dcot-offer-box .modal-body .dynamic-title")?.html(); 6319 if(dynamicTitleHeader && dynamicTitleHeader == ''){ 6320 dynamicTitleHeader = $("#dcot-offer-box .modal-body .dynamic-title")?.html(); 6321 } 6322 if(dynamicTitleHeader) { 6323 if(enableDcotPromoOffers && dcotModelName) { 6324 dynamicTitleHeader = dynamicTitleHeader.replace(/{{monthlyDisc}}/g, dcotMonthlyDisc).replace(/{{totalMonths}}/g, dcotTotalMonthText).replace(/{{offerEndDate}}/g, dcotOfferEndDt).replace(/{{saving}}/g, dcotSaving).replace(/{{paidAmt}}/g, dcotPaidAmt).replace(/{{phone-name}}/g, dcotModelName); 6325 } 6326 setTimeout(()=>{ 6327 $("#dcot-offer-box .modal-body .dynamic-title").html(dynamicTitleHeader); 6328 },10); 6329 } 6330} 6331 6332function updateDcotDynamicLabels(promoText,dcotautorefillflag, dcotactivatenewline,dcotupgrade){ 6333 6334 const element = document.querySelector(".phonedetail-price-container"); 6335 if(promoText) { 6336 if(element) { 6337 dcotautorefillflag = element.dataset.dcotautorefillflag ? element.dataset.dcotautorefillflag : ""; 6338 dcotactivatenewline = element.dataset.dcotactivatenewline ? element.dataset.dcotactivatenewline : ""; 6339 dcotupgrade = element.dataset.dcotupgrade ? element.dataset.dcotupgrade : ""; 6340 } 6341 6342 if(dcotautorefillflag && dcotautorefillflag == 'true') { 6343 promoText = promoText.replace(/{{autopay-st}}/g,"").replace(/{{autopay-end}}/g, ""); 6344 } else { 6345 promoText = removeTextBetweenWords(promoText, "{{autopay-st}}", "{{autopay-end}}") 6346 } 6347 6348 if(dcotactivatenewline && dcotactivatenewline == 'true' && dcotupgrade && dcotupgrade == 'true') { 6349 promoText = promoText.replace(/{{newline-st}}/g,"").replace(/{{newline-end}}/g, ""); 6350 promoText = promoText.replace(/{{upg-st}}/g,"").replace(/{{upg-end}}/g, ""); 6351 promoText = promoText.replace(/{{newlineand-st}}/g,"").replace(/{{newlineand-end}}/g, ""); 6352 } else if(!(dcotactivatenewline && dcotactivatenewline == 'true') && dcotupgrade && dcotupgrade == 'true'){ 6353 promoText = removeTextBetweenWords(promoText, "{{newline-st}}", "{{newline-end}}"); 6354 promoText = promoText.replace(/{{upg-st}}/g,"").replace(/{{upg-end}}/g, ""); 6355 } else if(dcotactivatenewline && dcotactivatenewline == 'true' && !(dcotupgrade && dcotupgrade == 'true')){ 6356 promoText = removeTextBetweenWords(promoText, "{{newlineand-st}}", "{{newlineand-end}}"); 6357 promoText = promoText.replace(/{{newline-st}}/g,"").replace(/{{newline-end}}/g, ""); 6358 promoText = removeTextBetweenWords(promoText, "{{upg-st}}", "{{upg-end}}"); 6359 } else { 6360 promoText = removeTextBetweenWords(promoText, "{{upg-st}}", "{{upg-end}}"); 6361 promoText = removeTextBetweenWords(promoText, "{{newline-st}}", "{{newline-end}}"); 6362 } 6363 } 6364 6365 return promoText 6366} 6367 6368function removeTextBetweenWords(fullText, startText, endText){ 6369 if(fullText && fullText.includes(startText) && fullText.includes(endText)){ 6370 const startIndex = fullText.indexOf(startText); 6371 const endIndex = fullText.indexOf(endText)+endText.length; 6372 let returnString = fullText.slice(0, startIndex)+ fullText.slice(endIndex); 6373 if(returnString.indexOf(startText) != -1 && returnString.indexOf(endText) != -1){ 6374 return removeTextBetweenWords(returnString, startText, endText) 6375 } 6376 return returnString; 6377 } else { 6378 return fullText; 6379 } 6380 6381} 6382 6383/** 6384 * Function to set the offer labels on images dynamically 6385 * @params {STRING,STRING} - {@element - Element 6386 * @label - label 6387 * } 6388 **/ 6389function setImageBadge(element,label){ 6390 if(element.querySelector("#phoneThumbnailImage li") && element.querySelector("#phoneThumbnailImage li").classList.contains('active')){ 6391 $('#phoneImageCarousel .carousel-item.active').append("<div class='offer-price-img-badge d-none'>"+label+"</div>"); 6392 }else 6393 { 6394 let childNode = element.querySelector(".offer-price-img-badge"); 6395 if(childNode)element.querySelector("#phoneImageCarousel .carousel-item")?.removeChild(childNode); 6396 } 6397} 6398/** 6399 * Function to set the offer labels on images dynamically 6400 * @params {STRING,STRING} - {@element - Element 6401 * @offertype - Type of promotional offer 6402 * } 6403 **/ 6404async function setOfferLabelOnImage(element,offertype){ 6405 let price = element.querySelector('.colorImageSwitch .imageChange.selected')?.dataset.tabprice?.toLowerCase(); 6406 let label; 6407 let freeLabel = document.querySelectorAll(".tabprice-free")[0]?.innerText?.toLowerCase(); 6408 if( price=== freeLabel ) 6409 label = await getScriptingValueCommon('_LBL_FREE_PRICE_OFFER_IMAGE_BADGE'); 6410 else 6411 label = await getScriptingValueCommon('_LBL_GREAT_PRICE_OFFER_IMAGE_BADGE'); 6412 6413 this.setImageBadge(element,label); 6414 let offerLabel = DOMPurify.sanitize(await getScriptingValueCommon(offertype+'_PHONE_SUB_HEADING')); 6415 let promoSubHeading = document.querySelector('.promooffer-subheading'); 6416 if(promoSubHeading && promoSubHeading.getAttribute("data-promolabel")){ 6417 offerLabel = promoSubHeading.getAttribute("data-promolabel"); 6418 } 6419 6420 let offerTypeVal = ""; 6421 if(offertype == lbl_offer_veriff ) { 6422 offerTypeVal = 'veriff'; 6423 } else if(offertype == lbl_offer_activation ) { 6424 offerTypeVal = "activation"; 6425 } else if(offertype == lbl_offer_port_in ) { 6426 offerTypeVal = "port-in"; 6427 } 6428 6429// if(document.querySelector('.promooffer-subheading div') && offerLabel && !document.querySelector('.promooffer-subheading .promo-msg')){ 6430 if(document.querySelector('.promooffer-subheading') && offerLabel ){ 6431 document.querySelector('.promooffer-subheading').innerHTML = '<span class="promo-msg bold">'+offerLabel+'</span>'; 6432 let targetele = document.querySelector('.promooffer-subheading .promo-msg p')? '.promooffer-subheading .promo-msg p' : '.promooffer-subheading .promo-msg'; 6433 this.setOfferDetailLink(element,document.querySelector('.promooffer-subheading .promo-msg')?.innerHTML,targetele," .offer-details-link"); 6434 if(offerTypeVal !== ""){ 6435 document.querySelector('.promooffer-subheading .promo-msg .offer-details-link')?.setAttribute('data-target', '#'+offerTypeVal+'-offer-box'); 6436 } 6437 6438 } 6439// if(document.querySelector('.promooffer-subheading-mob') && offerLabel && !document.querySelector('.promooffer-subheading-mob .promo-msg')){ 6440 if(document.querySelector('.promooffer-subheading-mob') && offerLabel ){ 6441 document.querySelector('.promooffer-subheading-mob').innerHTML = '<span class="promo-msg bold">'+offerLabel+'</span>'; 6442 let targetele = document.querySelector('.promooffer-subheading-mob .promo-msg p')? '.promooffer-subheading-mob .promo-msg p' : '.promooffer-subheading-mob .promo-msg'; 6443 this.setOfferDetailLink(element,document.querySelector('.promooffer-subheading-mob .promo-msg')?.innerHTML,targetele," .offer-details-link"); 6444 if(offerTypeVal !== ""){ 6445 document.querySelector('.promooffer-subheading-mob .promo-msg .offer-details-link')?.setAttribute('data-target', '#'+offerTypeVal+'-offer-box'); 6446 } 6447 } 6448} 6449/** 6450 * Function to add offer detail link dynamically in promo Label 6451 * @params {STRING,INT} - {@element - element 6452 * @offerLabel - promotional label 6453 * @targetElement - Target element 6454 * } 6455 **/ 6456async function setOfferDetailLink(element,offerLabel,targetElement,targetElementClass){ 6457 6458 if(offerLabel && offerLabel.includes("{{offerdetail}}") && element.querySelector(targetElement)){ 6459 let new_element = element.querySelector('.payment-option '+targetElementClass)?.cloneNode(true); 6460 if(new_element) element.querySelectorAll(targetElement).forEach(updateElement => {updateElement.appendChild(new_element); }); 6461 6462 let newContent= element.querySelector(targetElement).innerHTML.replace(/{{offerdetail}}/g,""); 6463 ele
6463ment.querySelectorAll(targetElement).forEach(updateElement => {updateElement.innerHTML = newContent; }); 6464 let seeOfferLabel = await getScriptingValueCommon('_LBL_SEE_OFFER_DETAILS'); 6465 if(seeOfferLabel && seeOfferLabel !='_LBL_SEE_OFFER_DETAILS' && element.querySelector(targetElement+' '+targetElementClass)){ 6466 element.querySelectorAll(targetElement+' '+targetElementClass).forEach(updateElement => { updateElement.innerHTML = seeOfferLabel; }); 6467 element.querySelector(targetElement+' '+targetElementClass)?.setAttribute("tabindex", "0"); 6468 element.querySelector(targetElement+' '+targetElementClass)?.removeAttribute("aria-hidden"); 6469 } 6470 } 6471} 6472 6473/** 6474 * Function to check if promotion available for product then enable the Free Payment option 6475 * @params {STRING,INT} - {@showsmartpay - showsmartpay flag 6476 * @offertype - Type of promotional offer 6477 * @stockStatus - stock status 6478 * @element - element 6479 * @isColorSelection - method call when clicked on color 6480 * } 6481 **/ 6482var enableFreePaymentOption = async (showsmartpay, offertype, stockStatus, element, isColorSelection, _setDynamicPlansLabels) => { 6483 var prefixlabel = element.querySelector(".choice-card.promo-offer .prefixlabel")?.dataset.prefixlabel; 6484 var optionlabel = element.querySelector(".choice-card.promo-offer .optionlabel")?.dataset.optionlabel; 6485 var summarylabel = element.querySelector(".choice-card.promo-offer .summarylabel")?.dataset.summarylabel; 6486 var suffixLabel = element.querySelector(".choice-card.promo-offer .po-suffix")?.dataset.suffixlalel; 6487 var enableVeriffIdentification = document.querySelector(lbl_dot_section_api_container)?.dataset?.enableveriffidentification; 6488 const stepNo = 'step_no'; 6489 let stepArray = [STEP_AVAILABLE_COLOR_CONTAINER]; 6490 if (showsmartpay === 'true' || (offertype == lbl_offer_activation || offertype == lbl_offer_veriff || offertype == lbl_offer_port_in ) ) 6491 stepArray.push(STEP_PAYMENT_OPTION); 6492 if (offertype == lbl_offer_port_in || offertype == lbl_offer_veriff) 6493 stepArray.push(STEP_PORT_IN_ADD_TO_CART); 6494 else 6495 stepArray.push(STEP_ADD_TO_CART); 6496 if(document.getElementById("upgrade-verify-code-block") && document.getElementById("upgradeFlagValue")?.value==="true") 6497 stepArray.push("verifyCode"); 6498 await setStepNo(stepArray, stepNo); 6499 this.setOfferLabels(element,".choice-card.promo-offer .optionlabel",optionlabel,offertype,true, _setDynamicPlansLabels); 6500 this.setOfferLabels(element,".choice-card.promo-offer .summarylabel",summarylabel,offertype,false, _setDynamicPlansLabels); 6501 this.setOfferLabels(element,".choice-card.promo-offer .po-suffix",suffixLabel,offertype,false, _setDynamicPlansLabels); 6502 if (element.querySelector(".choice-card.promo-offer .prefixlabel") ) { 6503 if (element.querySelector(".choice-card.promo-offer .prefixlabel") && prefixlabel && element.querySelector(".offer-details-link") && (offertype == lbl_offer_port_in || offertype == lbl_offer_activation || offertype == lbl_offer_veriff)) { 6504 if (offertype == lbl_offer_port_in) { 6505 if(element.querySelector(".choice-card.promo-offer .prefixlabel-acc")) 6506 element.querySelector(".choice-card.promo-offer .prefixlabel-acc").innerHTML = prefixlabel.split('|')[0]; 6507 element.querySelector(".choice-card.promo-offer .prefixlabel").innerHTML = prefixlabel.split('|')[0]; 6508 element.querySelector(".offer-details-link").setAttribute("data-target", element.querySelector(".offer-details-link")?.dataset.portinlink); 6509 }else if (offertype == lbl_offer_veriff) { 6510 if(element.querySelector(".choice-card.promo-offer .prefixlabel-acc")) 6511 element.querySelector(".choice-card.promo-offer .prefixlabel-acc").innerHTML = prefixlabel.split('|')[2]; 6512 element.querySelector(".choice-card.promo-offer .prefixlabel").innerHTML = prefixlabel.split('|')[2]; 6513 element.querySelector(".offer-details-link").setAttribute("data-target", element.querySelector(".offer-details-link")?.dataset.verifflink); 6514 } 6515 else { 6516 if(element.querySelector(".choice-card.promo-offer .prefixlabel-acc")) 6517 element.querySelector(".choice-card.promo-offer .prefixlabel-acc").innerHTML = prefixlabel.split('|')[1]; 6518 element.querySelector(".choice-card.promo-offer .prefixlabel").innerHTML = prefixlabel.split('|')[1]; 6519 element.querySelector(".offer-details-link").setAttribute("data-target", element.querySelector(".offer-details-link")?.dataset.activationlink); 6520 } 6521 if(element.querySelector(".choice-card.promo-offer .
6521summary-acc") && element.querySelector(".choice-card.promo-offer .summarylabel")) 6522 element.querySelector(".choice-card.promo-offer .summary-acc").innerHTML = element.querySelector(".choice-card.promo-offer .summarylabel").innerHTML; 6523 6524 } else { 6525 if(element.querySelector(".choice-card.promo-offer .prefixlabel-acc")) 6526 element.querySelector(".choice-card.promo-offer .prefixlabel-acc").innerHTML = ""; 6527 if(element.querySelector(".choice-card.promo-offer .summary-acc")) 6528 element.querySelector(".choice-card.promo-offer .summary-acc").innerHTML=""; 6529 element.querySelector(".choice-card.promo-offer .prefixlabel").innerHTML = ""; 6530 } 6531 } 6532 6533 if((offertype == lbl_offer_veriff && enableVeriffIdentification ==='true')){ 6534 let portinverifysuccess = document.getElementById("portinverifysuccess"); 6535 let headingText = portinverifysuccess?.dataset.hedingtext; 6536 let descriptionText = portinverifysuccess?.dataset.descriptiontext; 6537 6538 if(headingText && descriptionText){ 6539 if(portinverifysuccess.querySelector('.promo-heading')) 6540 portinverifysuccess.querySelector('.promo-heading').innerHTML = headingText; 6541 if(portinverifysuccess.querySelector('.promo-desc')){ 6542 portinverifysuccess.querySelector('.promo-desc').innerHTML = descriptionText; 6543 portinverifysuccess.querySelector('.promo-alert')?.setAttribute("aria-label",(headingText+" "+portinverifysuccess.querySelector('.promo-desc').innerText)) 6544 } 6545 } 6546 portinverifysuccess.querySelector('.port-in-footnote')?.classList.add("d-none"); 6547 portinverifysuccess.querySelector('.veriff-footnote')?.classList.remove("d-none"); 6548 6549 let loggedInFN = portinverifysuccess.querySelector('.veriff-footnote .footnote-data .fn-li')?.innerHTML; 6550 let notLoggedInFN = portinverifysuccess.querySelector('.veriff-footnote .footnote-data .fn-nl')?.innerHTML; 6551 let loggedInVerifiedFN = portinverifysuccess.querySelector('.veriff-footnote .footnote-data .fn-lv')?.innerHTML; 6552 let isUserLoggedIn = await checkUserLoggedInCommon(); 6553 if(isUserLoggedIn){ 6554 let veriffStatus = window.decryptStringCommon(window.getCookieCommon(COOKIE_VERIFF_STATUS)); 6555 let veriffPurStatus = window.decryptStringCommon(window.getCookieCommon(COOKIE_VERIFF_PURCHASE_STATUS)); 6556 if (veriffPurStatus && veriffPurStatus.indexOf("|") > -1){ 6557 let veriffPurchaseStatus = veriffPurStatus.split("|")[0]; 6558 6559 if(veriffStatus===VERIFF_STATUS_APPROVED && veriffPurchaseStatus != VERIFF_STATUS_LIMIT_EXCEEDED){ 6560 portinverifysuccess.querySelector('.veriff-footnote .cart-footnote .footnote-dynamic').innerHTML = DOMPurify.sanitize(loggedInVerifiedFN); 6561 } 6562 else 6563 portinverifysuccess.querySelector('.veriff-footnote .cart-footnote .footnote-dynamic').innerHTML = DOMPurify.sanitize(loggedInFN); 6564 } 6565 }else if(portinverifysuccess.querySelector('.veriff-footnote .cart-footnote .footnote-dynamic')){ 6566 portinverifysuccess.querySelector('.veriff-footnote .cart-footnote .footnote-dynamic').innerHTML = notLoggedInFN; 6567 } 6568 } 6569 this.setClawBackInstructions(element,'.clawback-footnote',offertype,enableVeriffIdentification,FALSE_FLAG); 6570 if(offertype == lbl_offer_port_in || offertype == lbl_offer_activation || offertype == lbl_offer_veriff) 6571 this.setOfferLabelOnImage(element,offertype); 6572 let hidedropDown = 'false'; 6573 if(element.querySelector('.other-options-accordion')) 6574 hidedropDown=element.querySelector('.other-options-accordion').getAttribute("data-hidepodropdown"); 6575 if(element.querySelector('.payment-type .choice-card.selected input')?.value==="upgrade" && (offertype == lbl_offer_port_in || offertype == lbl_offer_activation || (offertype == lbl_offer_veriff && enableVeriffIdentification ==='true')) ){ 6576 //added below code to handle the upgrade Scenario for promotional offers 6577 element.querySelector('.payment-option-ex')?.classList.remove("d-none"); 6578 if ($('.payment-option-ex .custom-control-input:checked').val() === 'promo=offer' && isColorSelection) clearRadio('.payment-option-ex .custom-control-input'); 6579 }else if (showsmartpay == 'true' && (offertype == lbl_offer_port_in || offertype == lbl_offer_activation || (offertype == lbl_offer_veriff && enableVeriffIdentification ==='true'))) { 6580 //hide other payment options accordion, if smart pay is not there 6581 element.querySelector('.promoofferdisable')?.classList.remove("d-none"); 6582 if(hidedropDown != 'true'){ 6583 element.querySelector('.other-options-accordion')?.classList.remove("d-none"); 6584 if (!(document.querySelector('.payment-option .choice-card.full-price .custom-control-input')?.checked || document.querySelector('.payment-option .choice-card.emi .custom-control-input')?.checked)) { 6585 element.querySelector('.other-payment-options-container')?.classList.add("collapse"); 6586 } 6587 } 6588 element.querySelector('#addtocart')?.classList.add("d-none"); 6589 element.querySelector('#portInVerification')?.classList.remove("d-none"); 6590 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6591 if (isColorSelection) { 6592 setEnablePaymentOptionsElement(); 6593 element.querySelector(".choice-card.promo-offer")?.classList.remove("d-none"); 6594 clearRadio('.payment-option-ex .custom-control-input'); 6595 } 6596 element.querySelector('#addtocart .pp-disclaimer')?.classList.add("pt-20"); 6597 element.querySelector('.offer-details-link ')?.classList.remove("d-none"); 6598 element.querySelector('.offer-details-link ')?.setAttribute("tabindex", "0"); 6599 element.querySelector('.offer-details-link ')?.setAttribute("aria-hidden", "false"); 6600 } else if (showsmartpay == 'true' && (offertype == "" || offertype == undefined || offertype == null || (offertype == lbl_offer_veriff && enableVeriffIdentification !='true'))) { 6601 //hide other payment options accordion, if smart pay is not there 6602 element.querySelector('.promoofferdisable')?.classList.add("d-none"); 6603 if(hidedropDown != 'true'){ 6604 element.querySelector('.other-options-accordion')?.classList.add("d-none"); 6605 element.querySelector('.other-payment-options-container')?.classList.remove("collapse"); 6606 } 6607 element.querySelector('#addtocart')?.classList.remove("d-none"); 6608 element.querySelector('#portInVerification')?.classList.add("d-none"); 6609 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6610 element.querySelector(".choice-card.promo-offer")?.classList.add("d-none"); 6611 if (stockStatus && stockStatus.toLowerCase() != UNAVAILABLE) 6612 setEnablePaymentOptionsElement(); 6613 element.querySelector('.offer-details-link ')?.classList.add("d-none"); 6614 element.querySelector('.offer-details-link ')?.setAttribute("tabindex", "-1"); 6615 element.querySelector('.offer-details-link ')?.setAttribute("aria-hidden", "true"); 6616 if ($('.payment-option-ex .custom-control-input:checked').val() === 'promo=offer' && isColorSelection) clearRadio('.payment-option-ex .custom-control-input'); 6617 } else if (showsmartpay == 'false' && (offertype == lbl_offer_port_in || offertype == lbl_offer_activation || (offertype == lbl_offer_veriff && enableVeriffIdentification ==='true'))) { 6618 element.querySelector('.payment-option-ex')?.classList.remove("d-none"); 6619 setEnablePaymentOptionsElement();
6620 document.querySelector("#twp-protection-plan-banner")?.classList?.add("d-none"); 6621 //hide other payment options accordion, if smart pay is not there 6622 element.querySelector('.promoofferdisable')?.classList.remove("d-none"); 6623 if(hidedropDown != 'true'){ 6624 element.querySelector('.other-options-accordion')?.classList.add("d-none"); 6625 element.querySelector('.other-payment-options-container')?.classList.remove("collapse"); 6626 } 6627 if (offertype == lbl_offer_port_in || offertype == lbl_offer_veriff) { 6628 element.querySelector('#addtocart')?.classList.add("d-none"); 6629 element.querySelector('#portInVerification')?.classList.remove("d-none"); 6630 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6631 } 6632 if (offertype == lbl_offer_activation) { 6633 element.querySelector('#addtocart')?.classList.remove("d-none"); 6634 element.querySelector('#portInVerification')?.classList.add("d-none"); 6635 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6636 element.querySelector('#addtocart .paypal-container')?.classList.add("d-none"); 6637 element.querySelector('#addtocart #cart-option-counter')?.classList.add("d-none"); 6638 element.querySelector('#addtocart .payment-type-heading')?.classList.add("d-none"); 6639 element.querySelector('#addtocart .cart-footnote')?.classList.add("d-none"); 6640 element.querySelector('#addtocart .choice-cards')?.classList.add("d-none"); 6641 } 6642 element.querySelector(".choice-card.promo-offer")?.classList.remove("d-none"); 6643 6644 if (element.querySelector('#paymentOption').classList.contains("disabledPageContent")) { 6645 element.querySelector('#paymentOption')?.classList.remove("disabledPageContent"); 6646 setEnablePaymentOptionsElement(); 6647 } 6648 element.querySelector(".choice-card.emi")?.classList.add("d-none"); 6649 element.querySelector('.smart-pay-link')?.classList.add("d-none"); 6650 element.querySelector('.smart-pay-link')?.setAttribute("tabindex", "-1"); 6651 element.querySelector('.smart-pay-link')?.setAttribute("aria-hidden", "true"); 6652 if (isColorSelection) clearRadio('.payment-option-ex .custom-control-input'); 6653 element.querySelector('#addtocart .pp-disclaimer')?.classList.add("pt-20"); 6654 element.querySelector('.offer-details-link ')?.classList.remove("d-none"); 6655 element.querySelector('.offer-details-link ')?.setAttribute("tabindex", "0"); 6656 element.querySelector('.offer-details-link ')?.setAttribute("aria-hidden", "false"); 6657 6658 /* Disable the Select button in PDP Overlay */ 6659 if(document.querySelector('.purchase-modal-box-footer .primary-btn') && !document.querySelector('.payment-option .custom-control-input:checked ~ .custom-control-label') 6660 && document.querySelector('.colorImageSwitch .imageChange.selected') 6661 && (document.querySelector('.colorImageSwitch .imageChange.selected').dataset.offertype === lbl_offer_veriff || document.querySelector('.colorImageSwitch .imageChange.selected').dataset.offertype === lbl_offer_port_in || document.querySelector('.colorImageSwitch .imageChange.selected').dataset.offertype === lbl_offer_activation)){ 6662 document.querySelector('.purchase-modal-box-footer .primary-btn').classList.add('disabled'); 6663 const disabledLabel = document.querySelector('.purchase-modal-box-footer .primary-btn a').getAttribute('data-add-cart-accessible'); 6664 document.querySelector('.purchase-modal-box-footer .primary-btn a').setAttribute("aria-label", disabledLabel); 6665 if(document.querySelector('div#paymentOption') && document.querySelector('div#paymentOption').classList.contains("disabledPageContent")) { 6666 document.querySelector('div#paymentOption').classList.remove("disabledPageContent"); 6667 } 6668 } 6669 6670 } else if (showsmartpay == 'false' && (offertype == "" || offertype == undefined || offertype == null || (offertype == lbl_offer_veriff && enableVeriffIdentification !='true'))) { 6671 //hide other payment options accordion, if smart pay is not there 6672 element.querySelector('.payment-option-ex')?.classList.add("d-none"); 6673 element.querySelector('.promoofferdisable')?.classList.add("d-none"); 6674 if(hidedropDown != 'true'){ 6675 element.querySelector('.other-options-accordion')?.classList.add("d-none"); 6676 element.querySelector('.other-payment-options-container')?.classList.remove("collapse"); 6677 } 6678 element.querySelector('#addtocart')?.classList.remove("d-none"); 6679 element.querySelector('#portInVerification')?.classList.add("d-none"); 6680 element.querySelector('#portInVerification-phone')?.classList.add("d-none"); 6681 if (!element.querySelector('#paymentOption')?.classList.contains("disabledPageContent")) { 6682 element.querySelector('#paymentOption')?.classList.add("disabledPageContent"); 6683 setDisabledPaymentOptionsElement(); 6684 } 6685 element.querySelector(".choice-card.emi")?.classList.add("d-none"); 6686 element.querySelector('.smart-pay-link')?.classList.add("d-none"); 6687 element.querySelector('.smart-pay-link')?.setAttribute("tabindex", "-1"); 6688 element.querySelector('.smart-pay-link')?.setAttribute("aria-hidden", "true"); 6689 element.querySelector('.offer-details-link ')?.classList.add("d-none"); 6690 element.querySelector('.offer-details-link ')?.setAttribute("tabindex", "-1"); 6691 element.querySelector('.offer-details-link ')?.setAttribute("aria-hidden", "true"); 6692 var colorSelectedElement = element.querySelector('.color-swatch .selected'); 6693 if (colorSelectedElement != null && colorSelectedElement != undefined) { 6694 if (element.querySelector('#addtocart .zipapi-config')?.classList.contains("disabledPageContent")) { 6695 element.querySelector('#addtocart .zipapi-config')?.classList.remove("disabledPageContent"); 6696 setEnableAddToCartElement(); 6697 } 6698 } 6699 } 6700 6701 if (stockStatus && stockStatus.toLowerCase() === UNAVAILABLE) { 6702 element.querySelector('#paymentOption').classList.add("disabledPageContent"); 6703 setDisabledPaymentOptionsElement(); 6704 element.querySelector('.zipapi-config').classList.add("disabledPageContent"); 6705 setDisabledAddToCartElement(); 6706 } 6707 if(window.getCookieCommon(COOKIE_VERIFF_DATA) && (offertype == lbl_offer_veriff && enableVeriffIdentification ==='true') && document.querySelector('.other-options-accordion')){ 6708 window.deleteCookieCommon(COOKIE_VERIFF_DATA); 6709 if(!document.querySelector('.other-options-accordion').classList.contains("d-none")) document.querySelector('.other-payment-options-container-toggle').click();; 6710 } 6711 if((offertype === lbl_offer_veriff && enableVeriffIdentification ==='true')|| offertype == lbl_offer_activation || offertype == lbl_offer_port_in ) 6712 this.disableFreePromoOption(element,offertype,enableVeriffIdentification); 6713 6714} 6715/** 6716 * This function will disable the free option if user chosen the $30 or $40 plan in shop plan journey 6717 * * @params {STRING} - {@element - Element} 6718 */ 6719async function disableFreePromoOption(element){ 6720 /* Disable the Free option in PDP Overlay */ 6721 let planLSData = window.localStorage.getItem("plan"); 6722 if(document.querySelector('#purchase-modal-box') && planLSData){ 6723 let planLS = JSON.parse(planLSData); 6724 let planLSDetails = Array.isArray(planLS) ? planLS[0] : planLS; 6725 let freeOptHideflag = true; 6726 if (planLSDetails) { 6727 let skuId = document.querySelector('.colorImageSwitch .imageChange.selected')?.dataset.promoplanids; 6728 const skuIdarray = skuId ? skuId.split(",") : []; 6729 if (skuIdarray.includes(planLSDetails.skuPartNo)) { 6730 freeOptHideflag = false;
6731 } 6732 } 6733 if (planLSDetails && freeOptHideflag) { 6734 var poElements = element.querySelectorAll('.payment-option.choice-cards .choice-card.promo-offer .custom-control-input') 6735 for (let index = 0; index < poElements.length; index++) { 6736 poElements[index].setAttribute("tabindex","-1"); 6737 poElements[index].setAttribute("aria-hidden","true"); 6738 poElements[index].setAttribute("disabled",""); 6739 } 6740 element.querySelector(".payment-option.choice-cards .choice-card.promo-offer")?.classList.add("disabledRadioContent"); 6741 if(!element.querySelector('.other-options-accordion')?.classList.contains("d-none")) 6742 element.querySelector('.other-payment-options-container-toggle')?.click(); 6743 element.querySelector(".payment-option.choice-cards .promo-plan-ineligible")?.classList.remove("d-none"); 6744 let promoPlanLink = element.querySelector(".payment-option.choice-cards .promo-plan-ineligible a"); 6745 if( promoPlanLink){ 6746 promoPlanLink.removeAttribute("tabindex"); 6747 promoPlanLink.removeAttribute("aria-hidden"); 6748 promoPlanLink.removeAttribute("disabled"); 6749 } 6750 }else{ 6751 element.querySelector(".payment-option.choice-cards .choice-card.promo-offer")?.classList.remove("disabledRadioContent"); 6752 var poElements = element.querySelectorAll('.payment-option.choice-cards .choice-card.promo-offer .custom-control-input') 6753 for (let index = 0; index < poElements.length; index++) { 6754 poElements[index].removeAttribute("tabindex"); 6755 poElements[index].removeAttribute("aria-hidden"); 6756 poElements[index].removeAttribute("disabled"); 6757 } 6758 } 6759 } 6760} 6761 6762/** 6763* Function to set the disabled the payment options radio buttons in case of stock not available 6764* } 6765**/ 6766function setDisabledPaymentOptionsElement() { 6767 var paymentOptionElements = document.querySelectorAll('#paymentOption .choice-cards .choice-card .custom-control-input') 6768 for (let index = 0; index < paymentOptionElements.length; index++) { 6769 paymentOptionElements[index].setAttribute("tabindex", "-1"); 6770 paymentOptionElements[index].setAttribute("aria-hidden", "true"); 6771 paymentOptionElements[index].setAttribute("disabled", ""); 6772 } 6773 document.querySelector('#paymentOption .choice-cards .smart-pay-link')?.setAttribute("tabindex", "-1"); 6774 document.querySelector('#paymentOption .choice-cards .smart-pay-link')?.setAttribute("aria-hidden", "true"); 6775} 6776/** 6777* Function to set the disabled the add to cart radio buttons in case of stock not available 6778* } 6779**/ 6780function setDisabledAddToCartElement() { 6781 var addToCartInputElements = document.querySelectorAll('#addtocart .zipapi-config .choice-cards .choice-card .custom-control-input') 6782 for (let index = 0; index < addToCartInputElements.length; index++) { 6783 addToCartInputElements[index].setAttribute("tabindex", "-1"); 6784 addToCartInputElements[index].setAttribute("aria-hidden", "true"); 6785 addToCartInputElements[index].setAttribute("disabled", ""); 6786 } 6787 document.querySelector('#addtocart .zipapi-config .legal-disclosure .legal')?.setAttribute("aria-hidden", "true"); 6788} 6789/** 6790* Function to set the enable the add to cart radio buttons in case of stock available 6791* } 6792**/ 6793function setEnableAddToCartElement() { 6794 var addToCartInputElements = document.querySelectorAll('#addtocart .zipapi-config .choice-cards .choice-card .custom-control-input') 6795 for (let index = 0; index < addToCartInputElements.length; index++) { 6796 addToCartInputElements[index].removeAttribute("tabindex"); 6797 addToCartInputElements[index].removeAttribute("aria-hidden"); 6798 addToCartInputElements[index].removeAttribute("disabled"); 6799 } 6800 document.querySelector('#phoneNo')?.removeAttribute("tabindex"); 6801 document.querySelector('#addtocart .zipapi-config .legal-disclosure .legal')?.removeAttribute("aria-hidden"); 6802} 6803 6804/** 6805* Function to set the enable the Payment options radio buttons in case of stock available 6806* } 6807**/ 6808function setEnablePaymentOptionsElement() { 6809 var paymentOptionElements = document.querySelectorAll('#paymentOption .choice-cards .choice-card .custom-control-input') 6810 for (let index = 0; index < paymentOptionElements.length; index++) { 6811 paymentOptionElements[index].removeAttribute("tabindex"); 6812 paymentOptionElements[index].removeAttribute("aria-hidden"); 6813 paymentOptionElements[index].removeAttribute("disabled"); 6814 } 6815 document.querySelector('#paymentOption .choice-cards .smart-pay-link')?.removeAttribute("aria-hidden"); 6816 document.querySelector('#paymentOption .choice-cards .smart-pay-link')?.removeAttribute("tabindex"); 6817} 6818 6819 6820/**
6821 * Function to set Step numbers for PDP pages. Array must be unique IDs and/or ClassNames. 6822 * @param {*String_Array} - parentDivArray 6823 * @param {*String} - stepClassName 6824 */ 6825var setStepNo = async (parentDivArray, stepClassName) => { 6826 if (parentDivArray && Array.isArray(parentDivArray) && stepClassName) { 6827 const len = parentDivArray.length; 6828 if (len && len > 1) { 6829 let newHtml = await getScriptingValueCommon('_LBL_STEP_OF_TOTAL'); 6830 parentDivArray.map((div, i) => { 6831 let newDiv = document.querySelector(`#${div}`) ? 6832 document.querySelector(`#${div} .${stepClassName}`) : 6833 document.querySelector(`.${div} .${stepClassName}`); 6834 if (newDiv && newHtml) { 6835 newDiv.innerHTML = DOMPurify.sanitize(newHtml.replace("{{index}}", i + 1).replace("{{total}}", len)); 6836 } 6837 }) 6838 } 6839 } 6840} 6841 6842 6843/** 6844* Function to reset the port in section if user switches payment option or checking with another number 6845* } 6846**/ 6847function resetPortIn(){ 6848 let portInPhoneNo = document.getElementById("portInPhoneNo"); 6849 let portinverifysuccess = document.getElementById("portinverifysuccess"); 6850 let portinverifyerror = document.getElementById("portinverifyerror"); 6851 let portInPhoneNoBtn = document.querySelector(".portInPhoneNoBtn"); 6852 let portinverifiycode = document.getElementById("portinverifiycode"); 6853 let portInFootNote = document.querySelector(".portIn-disclosure2"); 6854 let portInVerifyCodeInput = document.querySelector("#portInVerificationCode"); 6855 let portInFailureMsg = document.getElementById("port-in-failure-msg"); 6856 let portInResendOtpError = document.getElementById("resend-otp-error-section"); 6857 document.getElementById("portInVerification-phone")?.classList?.remove("portin-success-container"); 6858 if(portInPhoneNo){ 6859 portInPhoneNo.value=""; 6860 portInVerifyCodeInput.value=""; 6861 portInPhoneNo.dispatchEvent(new KeyboardEvent('keyup', {'key': ''})); 6862 portInVerifyCodeInput.dispatchEvent(new KeyboardEvent('keyup', {'key': ''})); 6863 portInVerifyCodeInput?.classList.remove("success"); 6864 portInVerifyCodeInput?.classList.remove("error"); 6865 document.querySelector(".verification-code-error")?.classList?.add("d-none"); 6866 document.querySelector(".verification-code-error .error-text").innerHTML=""; 6867 portInResendOtpError.style.display='none'; 6868 $("#btnPortInVerifyCodeIdentity").attr("disabled",true); 6869 document.querySelector("#phonumber-block").classList=""; 6870 document.querySelector(".resend-port-in-section").style.display='block'; 6871 portinverifiycode.style.display='none'; 6872 portinverifysuccess.style.display='none'; 6873 portinverifyerror.style.display='none'; 6874 if(portInFailureMsg)portInFailureMsg.style.display='none'; 6875 if(portInFootNote)portInFootNote.style.display='block'; 6876 document.getElementById("portIn-number-validate").style.display='block'; 6877 if (portInPhoneNoBtn.style.display==='none') { 6878 portInPhoneNoBtn.style.display='block'; 6879 portInPhoneNoBtn.setAttribute("disabled", false); 6880 } else { 6881 portInPhoneNoBtn.style.display='block' 6882 } 6883 document.getElementById("portInAddCartBtn")?.classList.add("disabled"); 6884 if (document.querySelector('.purchase-modal-box-footer .primary-btn')) { 6885 document.querySelector('.purchase-modal-box-footer .primary-btn').classList.add('disabled'); 6886 } 6887 } 6888} 6889 6890 6891/** 6892 * This function is used to validate verification code. 6893 * @param {String} {@value value of the item} 6894 * @param {String} {@element element of the item} 6895 * @param {String} {@btnElement button which needs to hide/show} 6896 * @returns {*|Null} 6897 **/ 6898function validatePortInVerificationCode(value, element, btnElement) { 6899 if (value && value.length >5) { 6900 $(element).addClass("success"); 6901 $(btnElement).removeClass('disabled'); 6902 $("#btnPortInVerifyCodeIdentity").attr("disabled",false); 6903 } else { 6904 $(element).removeClass("success"); 6905 $(btnElement).addClass('disabled'); 6906 $("#btnPortInVerifyCodeIdentity").attr("disabled",true); 6907 } 6908} 6909 6910/** 6911 * This function is used to set local storage for ineligible plan purchase for store1. 6912 **/ 6913function setLocalStorageForPromo(event) { 6914 const currentProduct = localStorage.getItem("currentProduct"); 6915 const phoneType = localStorage.getItem("phoneType"); 6916 const autoRefillSelectedStatus = localStorage.getItem("autoRefillSelectedStatus"); 6917 let selected = document.querySelector('.colorImageSwitch .imageChange.selected'); 6918 const skuId = selected.dataset.productid; 6919 localStorage.setItem("prevValuesForPromo", JSON.stringify({ currentProduct, phoneType, autoRefillSelectedStatus, skuId })); 6920 const href = event.target.getAttribute("data-href"); 6921 window.location.href = href + "?promo_ip=true"; 6922} 6923$(document).ready(function() { 6924 var skinnyElement = document.getElementById("skinny-data"); 6925 var deviceDetailSkinnyElement = document.getElementById("device-skinny-data"); 6926 if (skinnyElement) { 6927 6928 var skinnyData = localStorage.getItem("skinnyBanner"); 6929 if (skinnyData) { 6930 var skinnyObj = JSON.parse(skinnyData); 6931 var enableSkinnyBanner = skinnyObj.enableSkinnyBanner; 6932 if (enableSkinnyBanner && enableSkinnyBanner === 'true') { 6933 if (deviceDetailSkinnyElement) { 6934 deviceDetailSkinnyElement.remove(); 6935 } 6936 var bannerText = DOMPurify.sanitize(skinnyObj.bannerText); 6937 var modalText = DOMPurify.sanitize(skinnyObj.modalText); 6938 var modalLink = DOMPurify.sanitize(skinnyObj.modalLink); 6939 var ctaText = DOMPurify.sanitize(skinnyObj.ctaText); 6940 var modalId = skinnyObj.modalId; 6941 var enableModal = skinnyObj.enableModal; 6942 var simKitPage = skinnyObj.simKitPage; 6943 var bgColor = skinnyElement.dataset.bgcolor; 6944 var showSkinnybannerOnCart = skinnyElement.dataset.showskinnybanneroncart;
6945 var compModalMsg = skinnyElement.dataset.compmodal; 6946 var compCtaText = skinnyElement.dataset.compctatext; 6947 var compLink = skinnyElement.dataset.complink; 6948 var pagestodisplay = skinnyElement.dataset.pagestodisplay; 6949 var addedToCart = skinnyObj.addedToCart ? skinnyObj.addedToCart : "false"; 6950 var tempSkinnyObj = { 6951 ...skinnyObj, 6952 bgColor: bgColor, 6953 showSkinnybannerOnCart: showSkinnybannerOnCart, 6954 addedToCart: addedToCart 6955 }; 6956 localStorage.setItem("skinnyBanner", JSON.stringify(tempSkinnyObj)); 6957 if (localStorage.getItem("priceType")) { 6958 var priceType = localStorage.getItem("priceType"); 6959 } 6960 if (localStorage.getItem("skinnyPromo")) { 6961 var skinnyPromo = localStorage.getItem("skinnyPromo"); 6962 var skinnyPromoObj = JSON.parse(skinnyPromo); 6963 var promoLabel = skinnyPromoObj.promoLabel; 6964 var modalDesc = skinnyPromoObj.modalDesc; 6965 } 6966 if (document.getElementById("seeDetailModalLink")) { 6967 var seeDetailModalLink = document.getElementById("seeDetailModalLink"); 6968 } 6969 if (document.getElementById("seeDetailLink")) { 6970 var seeDetailLink = document.getElementById("seeDetailLink"); 6971 } 6972 if (enableModal && enableModal !== 'true' && seeDetailModalLink && seeDetailLink) { 6973 seeDetailModalLink.remove(); 6974 seeDetailLink.href = DOMPurify.sanitize(modalLink); 6975 } else if (enableModal && enableModal === 'true' && seeDetailLink) { 6976 seeDetailLink.remove(); 6977 } 6978 if (seeDetailLink && (!modalText || modalText.trim().length === 0 || modalText === 'keep_empty')) { 6979 seeDetailLink.remove(); 6980 seeDetailModalLink.remove(); 6981 } 6982 var pathLastselector = window.location.pathname.split('.').slice(-1)[0]; 6983 if (pathLastselector !== 'html') { 6984 var purchaseStep = window.location.pathname.split('.').slice(-1)[0]; 6985 } else { 6986 purchaseStep = window.location.pathname.split('.').slice(-2)[0]; 6987 } 6988 var tabletPath = window.location.pathname; 6989 if (pagestodisplay && pagestodisplay.includes(purchaseStep)) { 6990 if (bannerText && bannerText !== 'keep_empty') { 6991 document.querySelector(".cmp-skinnybanner__text-message").innerHTML = DOMPurify.sanitize(bannerText.replace('<p>','').replace('</p>','').replace('<br>','')); 6992 } else if (promoLabel && modalDesc) { 6993 document.querySelector(".cmp-skinnybanner__text-message").innerHTML = DOMPurify.sanitize(promoLabel.replace('<p>','').replace('</p>','').replace('<br>','')); 6994 } else if (skinnyElement) { 6995 skinnyElement.remove(); 6996 } 6997 if (ctaText && ctaText !== 'keep_empty') { 6998 document.querySelector(".cmp-skinnybanner__modal-ctatext").innerHTML = DOMPurify.sanitize(ctaText); 6999 } else if (compCtaText) { 7000 document.querySelector(".cmp-skinnybanner__modal-ctatext").innerHTML = DOMPurify.sanitize(compCtaText); 7001 } 7002 if (modalText && modalText !== 'keep_empty') { 7003 document.querySelector(".cmp-skinnybanner__modal-message").innerHTML = DOMPurify.sanitize(modalText); 7004 } else if (modalDesc && promoLabel) { 7005 document.querySelector(".skinny-modal-content").innerHTML = DOMPurify.sanitize(modalDesc); 7006 } else if (compModalMsg) { 7007 document.querySelector(".cmp-skinnybanner__modal-message").innerHTML = DOMPurify.sanitize(compModalMsg); 7008 } 7009 if (modalLink && modalLink !== 'keep_empty' && document.querySelector(".cmp-skinnybanner__modal-link")) { 7010 document.querySelector(".cmp-skinnybanner__modal-link").innerHTML = DOMPurify.sanitize(modalLink); 7011 } else if (compLink && document.querySelector(".cmp-skinnybanner__modal-link")) { 7012 document.querySelector(".cmp-skinnybanner__modal-link").innerHTML = DOMPurify.sanitize(compLink); 7013 } 7014 } else if (pagestodisplay && pagestodisplay.includes(purchaseStep) && simKitPage) { 7015 if (bannerText && bannerText !== 'keep_empty') { 7016 document.querySelector(".cmp-skinnybanner__text-message").innerHTML = DOMPurify.sanitize(bannerText.replace('<p>','').replace('</p>','').replace('<br>','')); 7017 } else if (skinnyElement) { 7018 skinnyElement.remove(); 7019 } 7020 if (ctaText && ctaText !== 'keep_empty') { 7021 document.querySelector(".cmp-skinnybanner__modal-ctatext").innerHTML = DOMPurify.sanitize(ctaText); 7022 } 7023 if (modalText && modalText !== 'keep_empty') { 7024 document.querySelector(".cmp-skinnybanner__modal-message").innerHTML = DOMPurify.sanitize(modalText); 7025 } 7026 if (modalLink && modalLink !== 'keep_empty' && document.querySelector(".cmp-skinnybanner__modal-link")) { 7027 document.querySelector(".cmp-skinnybanner__modal-link").innerHTML = DOMPurify.sanitize(modalLink); 7028 } 7029 } else if (pagestodisplay && pagestodisplay.includes(purchaseStep) && tabletPath.includes('tablets')) { 7030 if (bannerText && bannerText !== 'keep_empty') { 7031 document.querySelector(".cmp-skinnybanner__text-message").innerHTML = bannerText.replace('<p>','').replace('</p>','').replace('<br>',''); 7032 } else if (skinnyElement) { 7033 skinnyElement.remove(); 7034 } 7035 if (ctaText && ctaText !== 'keep_empty') { 7036 document.querySelector(".cmp-skinnybanner__modal-ctatext").innerHTML = ctaText; 7037 } 7038 if (modalText && modalText !== 'keep_empty') { 7039 document.querySelector(".cmp-skinnybanner__modal-message").innerHTML = modalText; 7040 } 7041 if (modalLink && modalLink !== 'keep_empty') { 7042 document.querySelector(".cmp-skinnybanner__modal-link").innerHTML = modalLink; 7043 } 7044 } else if (skinnyElement) { 7045 skinnyElement.remove(); 7046 } 7047 7048 } else { 7049 skinnyElement.remove(); 7050 } 7051 } else { 7052 skinnyElement.remove(); 7053 } 7054 } 7055 7056 let simSkinnyData = localStorage.getItem("simKitSkinnyBanner"); 7057 let skinnyBannerData = localStorage.getItem("skinnyBanner"); 7058 let brandType = document.querySelector(".section-api-container")?.dataset.brand; 7059 if (simSkinnyData) { 7060 var simSkinnyObj = JSON.parse(simSkinnyData); 7061 let activationEnableSkinnyBanner = simSkinnyObj.enableSkinnyBanner; 7062 let activationSkinnyPromoText = simSkinnyObj.bannerText; 7063 let activationSkinnyModalText = simSkinnyObj.modalText; 7064 let activationSkinnyModalLink = simSkinnyObj.modalLink; 7065 let activationSkinnyCtaText = simSkinnyObj.ctaText; 7066 let activationEnableSkinnyModal = simSkinnyObj.enableModal; 7067 let activationSkinnyBannerColor = simSkinnyObj.bgColor; 7068 let colorElement = document.querySelector(".byop-cmp-skinnybanner"); 7069 7070 if (document.getElementById("seeDetailModalLink") !== 'undefined' && document.getElementById("seeDetailModalLink") !== null) { 7071 var seeDetailModalLink = document.getElementById("seeDetailModalLink"); 7072 } 7073 if (document.getElementById("seeDetailLink") !== 'undefined' && document.getElementById("seeDetailLink") !== null) { 7074 var seeDetailLink = document.getElementById("seeDetailLink"); 7075 } 7076 if (typeof activationEnableSkinnyModal !== 'undefined' && activationEnableSkinnyModal !== 'true' && typeof seeDetailModalLink !== 'undefined' && typeof seeDetailLink !== 'undefined') { 7077 seeDetailModalLink.remove(); 7078 seeDetailLink.href = DOMPurify.sanitize(activationSkinnyModalLink); 7079 } else if (typeof activationEnableSkinnyModal !== 'undefined' && activationEnableSkinnyModal === 'true' && typeof seeDetailLink !== 'undefined') { 7080 seeDetailLink.remove(); 7081 } 7082 if (typeof activationEnableSkinnyBanner !== 'undefined' && activationEnableSkinnyBanner !== null && activationEnableSkinnyBanner === 'true') { 7083 if (typeof activationSkinnyPromoText !== 'undefined' && activationSkinnyPromoText !== null) { 7084 const skinnyBannerMessageElement = document.querySelector(".cmp-byop-skinnybanner__text-message"); 7085 if (skinnyBannerMessageElement) { 7086 skinnyBannerMessageElement.innerHTML = DOMPurify.sanitize(activationSkinnyPromoText.replace('<p>','').replace('</p>','').replace('<br>','')); 7087 } 7088 if (colorElement !== undefined && colorElement !== null && activationSkinnyBannerColor !== undefined && activationSkinnyBannerColor !== null) { 7089 colorElement.style.backgroundColor = activationSkinnyBannerColor; 7090 } else if (colorElement !== undefined && colorElement !== null) { 7091 colorElement.style.backgroundColor = '#E5F2FC'; 7092 } 7093 } 7094 } else if (colorElement != 'undefined' && colorElement != null) { 7095 colorElement.style.display = 'none'; 7096 } 7097 if (typeof activationSkinnyModalText !== 'undefined' && activationSkinnyModalText !== null) { 7098 if (document.querySelector(".cmp-byop-skinnybanner__modal-message")) { 7099 document.querySelector(".cmp-byop-skinnybanner__modal-message").innerHTML = DOMPurify.sanitize(activationSkinnyModalText); 7100 } 7101 } 7102 if (typeof activationSkinnyCtaText !== 'undefined' && activationSkinnyCtaText !== null) { 7103 if (document.querySelector(".cmp-byop-skinnybanner__cta-text")) { 7104 document.querySelector(".cmp-byop-skinnybanner__cta-text").innerHTML = DOMPurify.sanitize(activationSkinnyCtaText); 7105 } 7106 } 7107 } 7108 if (skinnyBannerData && brandType === "TRACFONE") { 7109 var simSkinnyObj = JSON.parse(skinnyBannerData); 7110 let activationEnableSkinnyBanner = simSkinnyObj.enableSkinnyBanner; 7111 let activationSkinnyPromoText = simSkinnyObj.bannerText; 7112 let activationSkinnyModalText = simSkinnyObj.modalText; 7113 let activationSkinnyModalLink = simSkinnyObj.modalLink; 7114 let activationSkinnyCtaText = simSkinnyObj.ctaText; 7115 let activationEnableSkinnyModal = simSkinnyObj.enableModal; 7116 let activationSkinnyBannerColor = simSkinnyObj.bgColor; 7117 let colorElement = document.querySelector(".byop-cmp-skinnybanner"); 7118 window.localStorage.setItem("simKitSkinnyBanner", skinnyBannerData); 7119 7120 $(document).on("click",".choice-card input[name='addToYourCartOption']", function () { 7121 let simSkinnyData = localStorage.getItem("simKitSkinnyBanner"); 7122 if (simSkinnyData) { 7123 window.localStorage.setItem("skinnyBanner", simSkinnyData); 7124 localStorage.removeItem("simKitSkinnyBanner"); 7125 } 7126 }); 7127 7128 if (document.getElementById("seeDetailModalLink") !== 'undefined' && document.getElementById("seeDetailModalLink") !== null) { 7129 var seeDetailModalLink = document.getElementById("seeDetailModalLink"); 7130 } 7131 if (document.getElementById("seeDetailLink") !== 'undefined' && document.getElementById("seeDetailLink") !== null) { 7132 var seeDetailLink = document.getElementById("seeDetailLink"); 7133 } 7134 if (typeof activationEnableSkinnyModal !== 'undefined' && activationEnableSkinnyModal !== 'true' && typeof seeDetailModalLink !== 'undefined' && typeof seeDetailLink !== 'undefined') { 7135 seeDetailModalLink.remove(); 7136 seeDetailLink.href = DOMPurify.sanitize(activationSkinnyModalLink); 7137 } else if (typeof activationEnableSkinnyModal !== 'undefined' && activationEnableSkinnyModal === 'true' && typeof seeDetailLink !== 'undefined') { 7138 seeDetailLink.remove(); 7139 } 7140 if (typeof activationEnableSkinnyBanner !== 'undefined' && activationEnableSkinnyBanner !== null && activationEnableSkinnyBanner === 'true') { 7141 if (typeof activationSkinnyPromoText !== 'undefined' && activationSkinnyPromoText !== null) { 7142 const skinnyBannerMessageElement = document.querySelector(".cmp-byop-skinnybanner__text-message"); 7143 if (skinnyBannerMessageElement) { 7144 skinnyBannerMessageElement.innerHTML = DOMPurify.sanitize(activationSkinnyPromoText.replace('<p>','').replace('</p>','').replace('<br>','')); 7145 } 7146 if (colorElement !== undefined && colorElement != null && activationSkinnyBannerColor !== undefined && activationSkinnyBannerColor !== null) { 7147 colorElement.style.backgroundColor = activationSkinnyBannerColor; 7148 } else if (colorElement !== undefined && colorElement !== null) { 7149 colorElement.style.backgroundColor = '#E5F2FC'; 7150 } 7151 } 7152 } else if (colorElement !== undefined && colorElement != null) { 7153 colorElement.style.display = 'none'; 7154 } 7155 if (typeof activationSkinnyModalText !== 'undefined' && activationSkinnyModalText !== null) { 7156 if (document.querySelector(".cmp-byop-skinnybanner__modal-message")) { 7157 document.querySelector(".cmp-byop-skinnybanner__modal-message").innerHTML = DOMPurify.sanitize(activationSkinnyModalText); 7158 } 7159 } 7160 if (typeof activationSkinnyCtaText !== 'undefined' && activationSkinnyCtaText !== null) { 7161 if (document.querySelector(".cmp-byop-skinnybanner__cta-text")) { 7162 document.querySelector(".cmp-byop-skinnybanner__cta-text").innerHTML = DOMPurify.sanitize(activationSkinnyCtaText); 7163 } 7164 } 7165 } else { 7166 const deviceSkinny = document.querySelector('.cmp-skinnybanner__text-message > p'); 7167 let deviceSkinnyText = ''; 7168 if (deviceSkinny) {
7169 for(const node of deviceSkinny.childNodes) { 7170 if(node.nodeType === Node.TEXT_NODE) { 7171 deviceSkinnyText += node.textContent.trim(); 7172 } 7173 } 7174 if (!deviceSkinnyText) { 7175 let mainSkinnyBanner = document.querySelector(".cmp-skinnybanner--main"); 7176 if (mainSkinnyBanner != 'undefined' && mainSkinnyBanner != null) { 7177 mainSkinnyBanner.style.display = 'none'; 7178 } 7179 } 7180 } else if (skinnyBannerData) { 7181 let skinnyObj = JSON.parse(skinnyBannerData); 7182 var enableSkinnyBanner = skinnyObj.enableSkinnyBanner; 7183 let mainSkinnyBanner = document.querySelector(".cmp-skinnybanner--main"); 7184 if (!enableSkinnyBanner && mainSkinnyBanner != 'undefined' && mainSkinnyBanner != null) { 7185 mainSkinnyBanner.style.display = 'none'; 7186 } 7187 } else { 7188 let mainSkinnyBanner = document.querySelector(".cmp-skinnybanner--main"); 7189 if (mainSkinnyBanner != 'undefined' && mainSkinnyBanner != null) { 7190 mainSkinnyBanner.style.display = 'none'; 7191 } 7192 } 7193 } 7194 7195 let byopSimKit = document.querySelector(".section-api-container"); 7196 let skinnyBanner = document.querySelector(".skinnybanner"); 7197 if (brandType === "STRAIGHT_TALK" || brandType === "TRACFONE") { 7198 var pagePath = window.location.pathname; 7199 if(pagePath.includes("activate") || pagePath.includes("purchase")) { 7200 if (skinnyBannerData) { 7201 let skinnyObj = JSON.parse(skinnyBannerData); 7202 var bannerText = skinnyObj.bannerText; 7203 if (!bannerText && skinnyBanner != 'undefined' && skinnyBanner != null) { 7204 skinnyBanner.style.display = 'none'; 7205 } else { 7206 document.querySelector(".skinnybanner")?.style.setProperty("background-color", "#ffff"); 7207 document.querySelector(".skinnybanner")?.style.setProperty("padding-top", "16px"); 7208 } 7209 } else if (skinnyBanner) { 7210 skinnyBanner.style.display = 'none'; 7211 } 7212 } 7213 if (pagePath.includes('byop-simkit')) { 7214 let byopSimKitEnableSkinnyBanner = byopSimKit.dataset.enableskinnybanner; 7215 let byopSimKitSkinnyPromoText = byopSimKit.dataset.skinnybannerpromotext; 7216 let byopSimKitSkinnyModalText = byopSimKit.dataset.skinnybannerpromomodaltext; 7217 let byopSimKitSkinnyModalLink = byopSimKit.dataset.skinnybannermodallink; 7218 let byopSimKitSkinnyCtaText = byopSimKit.dataset.skinnybannerctatext; 7219 let byopSimKitEnableSkinnyModal = byopSimKit.dataset.enableskinnymodal; 7220 let byopSimKitSkinnyBannerColor = byopSimKit.dataset.skinnybannercolor ? activationElement.dataset.skinnybannercolor : '#E5F2FC';; 7221 let byopSimKitShowSkinnyBannerOnCart = byopSimKit.dataset.showskinnybanneroncart; 7222 let colorElement = document.querySelector(".byop-cmp-skinnybanner"); 7223 7224 if (document.getElementById("seeDetailModalLink") !== 'undefined' && document.getElementById("seeDetailModalLink") !== null) { 7225 var seeDetailModalLink = document.getElementById("seeDetailModalLink"); 7226 } 7227 if (document.getElementById("seeDetailLink") !== 'undefined' && document.getElementById("seeDetailLink") !== null) { 7228 var seeDetailLink = document.getElementById("seeDetailLink"); 7229 } 7230 7231 if (typeof byopSimKitEnableSkinnyModal !== 'undefined' && byopSimKitEnableSkinnyModal !== 'true' && typeof seeDetailModalLink !== 'undefined' && typeof seeDetailLink !== 'undefined') { 7232 seeDetailModalLink.remove(); 7233 seeDetailLink.href = byopSimKitSkinnyModalLink; 7234 } else if (typeof byopSimKitEnableSkinnyModal !== 'undefined' && byopSimKitEnableSkinnyModal === 'true' && typeof seeDetailLink !== 'undefined') { 7235 seeDetailLink.remove(); 7236 } 7237 if (typeof byopSimKitEnableSkinnyBanner !== 'undefined' && byopSimKitEnableSkinnyBanner !== null && byopSimKitEnableSkinnyBanner === 'true') { 7238 if (typeof byopSimKitSkinnyPromoText !== 'undefined' && byopSimKitSkinnyPromoText !== null) { 7239 if (document.querySelector(".cmp-byop-skinnybanner__text-message")) { 7240 const cleanedText = byopSimKitSkinnyPromoText.replace(/<p>/gi, '').replace(/<\/p>/gi, '').replace(/<br\s*\/?>/gi, ''); 7241 document.querySelector(".cmp-byop-skinnybanner__text-message").innerHTML = cleanedText; 7242 } 7243 if (colorElement != 'undefined' && colorElement != null && byopSimKitSkinnyBannerColor != 'undefined' && byopSimKitSkinnyBannerColor != null) { 7244 colorElement.style.backgroundColor = byopSimKitSkinnyBannerColor; 7245 } 7246 } 7247 } 7248 7249 if (typeof byopSimKitSkinnyModalText !== 'undefined' && byopSimKitSkinnyModalText !== null) { 7250 if (document.querySelector(".cmp-byop-skinnybanner__modal-message")) { 7251 const modalText = byopSimKitSkinnyModalText.replace(/<p>/gi, '').replace(/<\/p>/gi, '').replace(/<br\s*\/?>/gi, ''); 7252 document.querySelector(".cmp-byop-skinnybanner__modal-message").innerHTML = modalText; 7253 } 7254 7255 } 7256 if (typeof byopSimKitSkinnyCtaText !== 'undefined' && byopSimKitSkinnyCtaText !== null) { 7257 if (document.querySelector(".cmp-byop-skinnybanner__cta-text")) { 7258 const ctaText = byopSimKitSkinnyCtaText.replace(/<p>/gi, '').replace(/<\/p>/gi, '').replace(/<br\s*\/?>/gi, ''); 7259 document.querySelector(".cmp-byop-skinnybanner__cta-text").innerHTML = ctaText; 7260 } 7261 } 7262 7263 let byopSimKitBannerObj = {}; 7264 if (byopSimKitEnableSkinnyBanner) { 7265 byopSimKitBannerObj.bannerText = byopSimKitSkinnyPromoText; 7266 byopSimKitBannerObj.modalText = byopSimKitSkinnyModalText; 7267 byopSimKitBannerObj.modalLink = byopSimKitSkinnyModalLink; 7268 byopSimKitBannerObj.ctaText = byopSimKitSkinnyCtaText; 7269 byopSimKitBannerObj.enableSkinnyBanner = byopSimKitEnableSkinnyBanner; 7270 byopSimKitBannerObj.enableModal = byopSimKitEnableSkinnyModal; 7271 byopSimKitBannerObj.bgColor = byopSimKitSkinnyBannerColor; 7272 byopSimKitBannerObj.addedToCart = "true"; 7273 byopSimKitBannerObj.showSkinnybannerOnCart = byopSimKitShowSkinnyBannerOnCart; 7274 window.localStorage.setItem("skinnyBanner", JSON.stringify(byopSimKitBannerObj)); 7275 } 7276 } 7277 } 7278 $(document).on("click", "div.cmp-skinnybanner__text-message a.add-role-btn", function() { 7279 const skinnyModalPopupClose = document.getElementById("skinnyModalPopupClose"); 7280 skinnyModalPopupClose?.addEventListener("click", function(e) { 7281 e.stopPropagation(); 7282 $("#skinny-modal").modal("hide"); 7283 }); 7284 }); 7285 (function enforceEmptyJourneySkinnyBannerRemoval() { 7286 var pathLower = window.location.pathname.toLowerCase(); 7287 7288 // Cart / checkout are React-driven (overrideSkinnyBannerPromoText) â never touch here 7289 var isCartPage = pathLower.includes("cart") || pathLower.includes("checkout"); 7290 if (isCartPage) { 7291 return; 7292 } 7293 7294 // Do NOT interfere with SIM-kit / BYOP / activation banner flows (separate LS keys) 7295 if (pathLower.includes("byop-simkit") || pathLower.includes("activate") 7296 || localStorage.getItem("simKitSkinnyBanner")) { 7297 return; 7298 } 7299 // Only enforce on phone/plan purchase journey pages 7300 if (!pathLower.includes("purchase")) { 7301 return; 7302 } 7303 7304 // SOURCE OF TRUTH: decide from localStorage bannerText, not rendered DOM text. 7305 // This is available immediately, regardless of when the banner node renders. 7306 function isBannerTextEmpty() { 7307 try { 7308 var raw = localStorage.getItem("skinnyBanner"); 7309 if (!raw) { 7310 return true; // no config => nothing to show on journey 7311 } 7312 var obj = JSON.parse(raw); 7313 7314 // If banner not enabled, journey should not render it 7315 if (!obj || obj.enableSkinnyBanner !== "true") { 7316 return true; 7317 } 7318 7319 var text = (obj.bannerText || "") 7320 .replace(/<p>/gi, "") 7321 .replace(/<\/p>/gi, "") 7322 .replace(/<br\s*\/?>/gi, "") 7323 .replace(/ /gi, " ") 7324 .replace(/\u00a0/g, " ") 7325 .replace(/\s+/g, " ") 7326 .trim(); 7327 7328 return !text || text.length === 0 || text === "keep_empty"; 7329 } catch (e) { 7330 return true; // on parse error, fail safe -> hide 7331 } 7332 } 7333 7334 function removeEmptyBanner() { 7335 if (!isBannerTextEmpty()) { 7336 return false; // valid text -> leave banner visible 7337 } 7338 var mainWrapper = document.querySelector(".cmp-skinnybanner--main"); 7339 if (mainWrapper) { 7340 mainWrapper.style.display = 'none'; // hides wrapper + background container 7341 return true; 7342 } 7343 return false; // node not present yet 7344 } 7345 7346 // 1) Try immediately (covers PDP where node already exists) 7347 if (removeEmptyBanner()) { 7348 return; 7349 } 7350 7351 // 2) If bannerText is valid, no need to observe â exit 7352 if (!isBannerTextEmpty()) { 7353 return; 7354 } 7355 7356 // 3) Node not yet rendered (journey pages). Observe DOM until it appears, then remove. 7357 var observer = new MutationObserver(function() { 7358 if (removeEmptyBanner()) { 7359 observer.disconnect(); 7360 } 7361 }); 7362 observer.observe(document.body, { childList: true, subtree: true }); 7363 7364 // 4) Safety timeouts (in case observer misses / SPA hydration) 7365 var attempts = 0; 7366 var poll = setInterval(function() { 7367 attempts++; 7368 if (removeEmptyBanner() || attempts >= 20) { // ~5s max at 250ms 7369 clearInterval(poll); 7370 observer.disconnect(); 7371 } 7372 }, 250); 7373 7374 // 5) Final guard on full load 7375 window.addEventListener("load", function() { 7376 removeEmptyBanner(); 7377 }); 7378 })(); 7379});
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.