1if (sessionStorage.getItem("mastiffdebug") === null) { 2 const onProd = window.location && window.location.hostname === "support.hp.com"; 3 sessionStorage.setItem("mastiffdebug", "false"); 4 sessionStorage.setItem("mastifflog", "false"); 5} 6 7function isMastiffDebug() { 8 return sessionStorage.getItem("mastiffdebug") === "true"; 9} 10 11function getMastiffUrl() { 12 return isMastiffDebug() 13 ? "https://mastiff-itg.ext.hp.com/gw/hpit/cs/mastiff.itg/1.0/MastiffService-1/getOffer" 14 : "https://mastiff.ext.hp.com/gw/hpit/cs/mastiff/1.0/MastiffService-1/getOffer"; 15} 16 17var PAGE_CONFIG = { 18 warrantyresult_falcon: { 19 offerLocations: "primary,shop1,shop2,shop3,secondary", 20 positions: { 21 primary: { 22 placeholderSelector: "#warranty_spos_template3, #warranty_spos_template3_mobile", 23 containerSelector: "#mastiff-check-warranty-primary-offer" 24 }, 25 secondary: { 26 placeholderSelector: "#warranty_spos_template4", 27 containerSelector: "#mastiff-check-warranty-secondary-offers" 28 }, 29 shop1: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" }, 30 shop2: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" }, 31 shop3: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" } 32 } 33 }, 34 pdp_falcon: { 35 offerLocations: "primary,shop1,shop2,shop3,secondary", 36 positions: { 37 primary: { placeholderSelector: "#pdp_spos_template1, #pdp_spos_template1_mobile" }, 38 secondary: { placeholderSelector: "#pdp_spos_template4" }, 39 shop1: { placeholderSelector: "#pdp_spos_shoptab_template2", containerSelector: ".shop" }, 40 shop2: { placeholderSelector: "#pdp_spos_shoptab_template2", containerSelector: ".shop" }, 41 shop3: { placeholderSelector: "#pdp_spos_shoptab_template2", containerSelector: ".shop" } 42 } 43 }, 44 warrantyresult_falcon: { 45 offerLocations: "primary,shop1,shop2,shop3,secondary", 46 positions: { 47 primary: { 48 placeholderSelector: "#warranty_spos_template3, #warranty_spos_template3_mobile", 49 containerSelector: "#mastiff-check-warranty-primary-offer" 50 }, 51 secondary: { 52 placeholderSelector: "#warranty_spos_template4", 53 containerSelector: "#mastiff-check-warranty-secondary-offers" 54 }, 55 shop1: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" }, 56 shop2: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" }, 57 shop3: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" } 58 } 59 }, 60 drivers_closure: { 61 offerLocations: "primary", 62 positions: { primary: { placeholderSelector: "#mastiff-diag-banner" } } 63 }, 64 drivers_details: { 65 offerLocations: "primary,secondary", 66 positions: { 67 primary: { placeholderSelector: "#swd_spos_template6" }, 68 secondary: { placeholderSelector: "#mastiff-diag-banner" } 69 } 70 }, 71 document: { 72 offerLocations: "primary", 73 positions: { primary: { placeholderSelector: "#opt-mastiff-doc" } } 74 }, 75 contact: { 76 offerLocations: "primary,secondary", 77 positions: { 78 primary: { placeholderSelector: "#contact_option_mastiff_tile_template" }, 79 secondary: { placeholderSelector: "#contact_resource_mastiff_template" }, 80 phone: { placeholderSelector: "#phone_fee_mastiff_tile_template" } 81 } 82 }, 83 "contact-solution": { 84 // New Contact Solution pages expect a single primary placement only 85 offerLocations: "primary", 86 positions: { 87 primary: { placeholderSelector: "#mastiff-pfw-contact-solutions" } 88 } 89 }, 90 "contact-hp": { 91 offerLocations: "primary,secondary", 92 positions: { 93 primary: { placeholderSelector: "#co_spos_template5" }, 94 secondary: { placeholderSelector: "#contact_resource_mastiff_template" } 95 } 96 }, 97 contact_closure: { 98 offerLocations: "primary,secondary", 99 positions: { 100 primary: { placeholderSelector: ".mastiff_template_container" }, 101 secondary: { placeholderSelector: "#contact-summary-warranty-mastiff" } 102 } 103 }, 104 "printer-setup": { 105 offerLocations: "primary,shop1,shop2,shop3,secondary", 106 positions: { 107 primary: { placeholderSelector: "#opt-mastiff-setup" }, 108 secondary: { placeholderSelector: "#mastiffoffers" }, 109 shop1: { placeholderSelector: "#mastiffoffers" }, 110 shop2: { placeholderSelector: "#mastiffoffers" }, 111 shop3: { placeholderSelector: "#mastiffoffers" } 112 } 113 }, 114 repair: { 115 offerLocations: "primary", 116 positions: { primary: { placeholderSelector: "#mastiffoffers" } } 117 }, 118 "hardware-diagnostics": { 119 offerLocations: "primary", 120 positions: { primary: { placeholderSelector: "#mastiffoffers" } } 121 }, 122 service: { 123 offerLocations: "secondary", 124 positions: { 125 secondary: { placeholderSelector: "#mastiff_SDP_sticky_banner", containerSelector: "#sdp-mastiff
125-banner-container" } 126 } 127 }, 128 home: { 129 offerLocations: "primary", 130 positions: { primary: { placeholderSelector: ".mastiff_template_container" } } 131 }, 132 home_printer: { 133 offerLocations: "primary", 134 positions: { primary: { placeholderSelector: ".mastiff_template_container" } } 135 }, 136 home_computer: { 137 offerLocations: "primary", 138 positions: { primary: { placeholderSelector: ".mastiff_template_container" } } 139 }, 140 dashboard: { 141 offerLocations: "carousel", 142 positions: { 143 primary: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" }, 144 secondary: { placeholderSelector: "#mastiffoffers" }, 145 shop1: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" }, 146 shop2: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" }, 147 shop3: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" } 148 } 149 }, 150 "help-printer": { 151 offerLocations: "primary,secondary", 152 positions: { 153 primary: { placeholderSelector: "#mastiff-diag-banner" }, 154 secondary: { placeholderSelector: "#mastiff_diag_sticky_banner", containerSelector: "#diag-mastiff-banner-container" } 155 } 156 }, 157 "help-computer": { 158 offerLocations: "primary,shop1,secondary", 159 positions: { 160 primary: { placeholderSelector: "#mastiff-diag-banner" }, 161 secondary: { placeholderSelector: "#mastiff_diag_sticky_banner", containerSelector: "#diag-mastiff-banner-container" }, 162 shop1: { placeholderSelector: "#mastiff-partstore" } 163 } 164 }, 165 "help-windows": { 166 offerLocations: "secondary", 167 positions: { 168 secondary: { placeholderSelector: "#mastiff-sticky-banner", containerSelector: "#mastiff-sticky-banner" } 169 } 170 }, 171 default: { 172 offerLocations: "primary,shop1,shop2,shop3,secondary", 173 positions: { 174 primary: { placeholderSelector: "#mastiffoffers" }, 175 secondary: { placeholderSelector: "#mastiffoffers" }, 176 shop1: { placeholderSelector: "#mastiffoffers" }, 177 shop2: { placeholderSelector: "#mastiffoffers" }, 178 shop3: { placeholderSelector: "#mastiffoffers" } 179 } 180 } 181}; 182 183 184var PAGE_OFFER_MAP = [ 185 { 186 pages: ["home", "home_printer", "home_computer"], 187 positions: { 188 primary: { 189 // fn: "showCarouselBanner", 190 placeholder: ".mastiff_template_container", 191 insert: "html", 192 required: ["html", "imageURL", "primaryText1", "primaryButtonText", "storeURL"], 193 replacements: { 194 "%LargeBannerImgPlaceholder%": "imageURL", 195 "%LargeBannerTitleplaceholder%": "primaryText1", 196 "%LargeBannerDescriptionplaceholder%": "primaryText2", 197 "%LargeBannerCTAplaceholder%": "primaryButtonText" 198 }, 199 hide: "none" 200 } 201 } 202 }, 203 { 204 page: "contact_closure", 205 positions: { 206 primary: { 207 // fn: "showCarouselBanner", 208 placeholder: ".mastiff_template_container", 209 insert: "html", 210 required: ["html", "imageURL", "primaryText1", "primaryButtonText", "storeURL"], 211 replacements: { 212 "%LargeBannerImgPlaceholder%": "imageURL", 213 "%LargeBannerTitleplaceholder%": "primaryText1", 214 "%LargeBannerDescriptionplaceholder%": "primaryText2", 215 "%LargeBannerCTAplaceholder%": "primaryButtonText" 216 }, 217 hide: "none" 218 }, 219 secondary: { 220 // fn: "showContactSummaryOffer", 221 placeholder: "#contact-summary-warranty-mastiff", 222 insert: "append", 223 required: ["html", "primaryButtonText", "storeURL"], 224 replacements: { 225 "%simpleLinkTemplateCTAplaceholder%": "primaryButtonText", 226 "%simpleLinkTemplateURL%": "storeURL", 227 "%simpleLinkTemplateId%": "divId" 228 }, 229 hide: "$(\"#contact-summary-warranty-mastiff\").hide()" 230 } 231 } 232 }, 233 { 234 page: "drivers_details", 235 positions: { 236 detailsCategory: { 237 // fn: "showSwdViewInStoreOffer", 238 placeholder: "#mastiff_view_in_store_SWD", 239 insert: "html", 240 required: ["html", "primaryButtonText", "storeURL"], 241 replacements: { 242 "%simpleLinkTemplateImgURL%": "imageURL", 243 "%simpleLinkTemplateCTAplaceholder%": "primaryButtonText", 244 "%simpleLinkTemplateId%": "divId" 245 }, 246 hide: "none" 247 }, 248 primary: { 249 // fn: "showDriverDetailsOffer", 250 placeholder: "#driversPageMastiffBannerTop", 251 insert: "html", 252 required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"], 253 replacements: { 254 "%DriverTileOfferImgURLPlaceholder%": "imageURL", 255 "%DriverTileOfferTitlePlaceholder%": "primaryText1", 256 "%DriverTileOfferDescriptionPlaceholder%": "primaryText2", 257 "%DriverTileOfferCTAPlaceholder%": "primaryButtonText", 258 "%DriverTileOfferId%": "divId", 259 "%secondaryContactHPOfferIdPlaceholder%": "divId" 260 }, 261 hide: "none" 262 }, 263 secondary: { 264 // fn: "showDriverDetailsOffer", 265 placeholder: "#driversPageMastiffBannerBot", 266 insert: "html", 267 required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"], 268 replacements: { 269 "%DriverTileOfferImgURLPlaceholder%": "imageURL", 270 "%DriverTileOfferTitlePlaceholder%": "primaryText1", 271 "%DriverTileOfferDescriptionPlaceholder%": "primaryText2", 272 "%DriverTileOfferCTAPlaceholder%": "primaryButtonText", 273 "%DriverTileOfferId%": "divId", 274 "%secondaryContactHPOfferIdPlaceholder%": "divId" 275 }, 276 hide: "none" 277 }, 278 shop1: { 279 placeholder: "#", 280 insert: "html", 281 required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"], 282 replacements: { 283 "%DriverTileOfferImgURLPlaceholder%": "imageURL", 284 "%DriverTileOfferTitlePlaceholder%": "primaryText1", 285 "%DriverTileOfferDescriptionPlaceholder%": "primaryText2", 286 "%DriverTileOfferCTAPlaceholder%": "primaryButtonText", 287 "%DriverTileOfferId%": "divId", 288 "%secondaryContactHPOfferIdPlaceholder%": "divId" 289 }, 290 hide: "none" 291 } 292 } 293 }, 294 { 295 page: "drivers_closure", 296 positions: { 297 primary: { 298 // fn: "showDriverClosurePrimaryOffer", 299 placeholder: "#swdClosurePageMastiffBanner", 300 insert: "html", 301 required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"], 302 replacements: { 303 "%DriverTileOfferImgURLPlaceholder%": "imageURL", 304 "%DriverTileOfferTitlePlaceholder%": "primaryText1", 305 "%DriverTileOfferDescriptionPlaceholder%": "primaryText2", 306 "%DriverTileOfferCTAPlaceholder%": "primaryButtonText", 307 "%DriverTileOfferId%": "divId" 308 }, 309 hide: "none" 310 } 311 } 312 }, 313 { 314 page: "service", 315 positions: { 316 secondary: { 317 // fn: "showStickyBannerSecondaryOffer",
318 container: "#sdp-mastiff-banner-container", 319 placeholder: "#mastiff_SDP_sticky_banner", 320 insert: "html", 321 required: ["html", "primaryText1", "primaryButtonText", "storeURL"], 322 replacements: { 323 "{title}": "primaryText1", 324 "{cta}": "primaryButtonText", 325 "%stickyFooterOfferId%": "divId" 326 }, 327 hide: "hideContainer('#sdp-mastiff-banner-container','hide')" 328 } 329 } 330 }, 331 { 332 pages: ["repair", "hardware-diagnostics"], 333 positions: { 334 "1r4ccontainer": { 335 // fn: "showHelpPageOffer", 336 placeholder: "#mastiff-offer-content", 337 insert: "html", 338 required: ["html", "primaryText1"], 339 replacements: { 340 "{title}": "primaryText1", 341 "{description}": "primaryText2", 342 "%divId%": "divId" 343 }, 344 hide: "none" 345 }, 346 "1r4cTile": { 347 // fn: "showHelpPageOffer", 348 placeholder: "#DiagsRepairsDSPOSOffersContainer", 349 insert: "append", 350 required: ["html", "imageURL", "primaryText1", "primaryText2", "primaryButtonText", "storeURL"], 351 replacements: { 352 "%falconContactHPImgURLPlaceholder%": "imageURL", 353 "%falconContactHPOfferTitlePlaceholder%": "primaryText1", 354 "%falconContactHPOfferDescriptionPlaceholder%": "primaryText2", 355 "%falconContactHPOfferCTAPlaceholder%": "primaryButtonText", 356 "%falconContactHPOfferIdPlaceholder%": "divId" 357 }, 358 hide: "none" 359 } 360 } 361 }, 362 { 363 pages: ["help-computer", "help-printer"], 364 positions: { 365 primary: { 366 // fn: "showHelpPrimaryOffer", 367 placeholder: "#mastiff-diag-banner", 368 insert: "html", 369 required: ["html", "storeURL", "primaryButtonText", "primaryText1", "primaryText2", "imageURL"], 370 replacements: { 371 "%imageurlPlaceholder%": "imageURL", 372 "%titlePlaceholder%": "primaryText1", 373 "%descriptionPlaceholder%": "primaryText2", 374 "%ctaPlaceholder%": "primaryButtonText", 375 "%PrimaryDiagnosticsTabsTileOfferIdPlaceholder%": "divId" 376 }, 377 hide: "hideContainer('#mastiff-diag-banner','hidden')" 378 }, 379 secondary: { 380 // fn: "showStickyBannerSecondaryOffer", 381 container: "#diag-mastiff-banner-container", 382 placeholder: "#mastiff_diag_sticky_banner", 383 insert: "html", 384 required: ["html", "primaryText1", "primaryButtonText", "storeURL"], 385 replacements: { 386 "{title}": "primaryText1", 387 "{cta}": "primaryButtonText", 388 "%stickyFooterOfferId%": "divId" 389 }, 390 hide: "hideContainer('#diag-mastiff-banner-container','hide')" 391 }, 392 shop1: { 393 placeholder: "#mastiff-partstore", 394 insert: "html", 395 required: ["html", "storeURL", "primaryButtonText"], 396 replacements: { 397 "%simpleLinkTemplateCTAplaceholder%": "primaryButtonText", 398 "%simpleLinkTemplateURL%": "storeURL", 399 "%PromoTileId%": "divId" 400 }, 401 hide: "hideContainer('#mastiff-partstore','hidden')" 402 }, 403 owDiagsContainer: { 404 placeholder: ".warranty-container", //.warranty-container 405 insert: "html", 406 required: ["html", "primaryText1"], 407 replacements: { 408 "{title}": "primaryText1" 409 }, 410 hide: "hideContainer('.warranty-container','hidden')" 411 }, 412 owDiags: { 413 placeholder: ".warranty-container .DiagsOOWSectionOffers", 414 insert: "append", 415 required: ["html", "storeURL", "primaryButtonText"], 416 replacements: { 417 "{cta}": "primaryButtonText", 418 "{imageurl}": "imageURL", 419 "%simpleLinkTemplateId%": "divId" 420 }, 421 hide: "none" 422 } 423 } 424 }, 425 { 426 page: "document", 427 positions: { 428 primary: { 429 // fn: "showDocumentOffer", 430 placeholder: "#opt-mastiff-doc", 431 insert: "append", 432 required: ["html", "imageURL", "primaryText1", "primaryButtonText", "storeURL"], 433 replacements: { 434 "%offerimageURLPlaceholder%": "imageURL", 435 "%offerprimaryText1PlaceHolder%": "primaryText1", 436 "%offerprimaryText2PlaceHolder%": "primaryText2", 437 "%offerprimaryButtonTextPlaceHolder%": "primaryButtonText" 438 }, 439 hide: "none" 440 } 441 } 442 }, 443 { 444 page: "pdp_falcon", 445 positions: { 446 wtywidget: { 447 // fn: "", 448 placeholder: "#mastiff-extend-wty-pdp", 449 insert: "html", 450 required: ["html", "primaryButtonText", "storeURL"], 451 replacements: { 452 "{imageurl}": "imageURL", 453 "{cta}": "primaryButtonText", 454 "%simpleLinkTemplateId%": "divId" 455 }, 456 hide: "none", 457 templateReference: "swTemplate3" 458 } 459 } 460 }, 461 { 462 page: "help-windows", 463 positions: { 464 secondary: { 465 container: "#mastiff-sticky-banner", 466 placeholder: "#mastiff-sticky-banner", 467 insert: "html", 468 required: ["html", "primaryText1", "primaryButtonText", "storeURL"], 469 replacements: { 470 "{title}": "primaryText1", 471 "{cta}": "primaryButtonText", 472 "%stickyFooterOfferId%": "divId" 473 }, 474 hide: "hideContainer('#mastiff-sticky-banner','hide')" 475 } 476 } 477 }, 478 { 479 page: "contact-landing", 480 positions: { 481 "1r3ccontainer": { 482 placeholder: "#mastiff-quicklink-section", 483 insert: "html", 484 required: ["html", "primaryText1"], 485 replacements: { 486 "{title}": "primaryText1", 487 "{description}": "primaryText2", 488 "%divId%": "divId" 489 }, 490 hide: "none" 491 }, 492 "1r3cTile": { 493 placeholder: "#contactEntryOffersContainer", 494 insert: "append", 495 required: ["html", "imageURL", "primaryText1", "primaryText2", "primaryButtonText", "storeURL"], 496 replacements: { 497 "%OWEntryOfferImgURLPlaceholder%": "imageURL", 498 "%OWEntryOfferTitlePlaceholder%": "primaryText1", 499 "%OWEntryOfferDescriptionPlaceholder%": "primaryText2", 500 "%OWEntryOfferCTAPlaceholder%": "primaryButtonText", 501 "%falconContactHPOfferIdPlaceholder%": "divId" 502 }, 503 hide: "none" 504 } 505 } 506 }, 507]; 508 509var offerResults = null; 510var accessoriesOfferResults = null; 511 512var reqObj = {}; 513 514var pgName = pageName(); 515 516var LeadOfferIndex = 1; 517var enableDashTile = false; 518 519var intentBasedLocationEmpty = true; 520var enablePromoTab = false; 521var enablepdpCarousel = false; 522var samePage = false; 523var deviceInfo = null; 524 525var intentPDPCategories = ["setup-user-guides", "tools-dignostics", "warranty-repair", "security-viruses", "ink-paper", "troubleshooting"]; 526 527var promoTab = "<div id=\"promoContainer\"> <style> #promoContainer { border-top: 1px solid #dbdbdb; } .promoTitle { font-family: Forma DJR Micro; font-size: 24px; font-weight: 400; line-height: 32px; margin-top: 20px; } .promoOffers { margin-top: 26px; margin-bottom: 50px; display: flex; } @media screen and (min-width: 601px) and (max-width: 1158px) { .promoOffers { flex-direction: column; align-items: center; } .promoTiles { margin-top: 10px; } } @media screen and (max-width: 600px) { .promoOffers { flex-direction: column; align-items: center; margin-bottom: 30px; } .promoTitle { font-size: 14px !important; line-height: 20px !important; margin-top: 20px !important; } } </style> <h2 class=\"promoTitle\">Promotions & deals</h2> <div class=\"promoOffers\"> <div class=\"promoTiles\"> <div class=\"promoPrimaryTile\"></div> <div class=\"promoSecondaryTile\"></div> </div> </div> </div>"; 528 529var promoShopOfferSliderDiv = "<div class=\"promoCarousel\"> <style> .promoCarousel { margin-right: 30px; margin-bottom: 30px; border-radius: 16px; background: #FFFFFF; box-shadow: 0 1px 4px 1px #21212133; position: relative; } .promoCarousel #navigation { position: absolute; display: flex; right: 15.57px; bottom: -20px; padding: 0px 10px; align-items: center; height: 56px; border-radius: 16px; background: #FFFFFF; box-shadow: 0 1px 4px 1px #21212133; } .promoCarousel .elipse { background: #0278AB; border-radius: 50%; cursor: pointer; margin: 0px 8px 0px 8px; width: 30px; height: 30px; position: relative; } .disabledElipse { background: #ADADAD; border-radius: 50%; margin: 0px 8px 0px 8px; width: 30px; height: 30px; position: relative; } .disabledElipse:focus { box-shadow: none} .promoCarousel .elipse:hover { transition: 0.1s; background: #035C84; } .promoCarousel .elipse:active { transform: scale(0.9); } .promoCarousel .arrow { color: #FFF; width: 7.5px; height: 7.5px; position: absolute; top: 10.5px; } .promoCarousel .left { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(45deg); left: 12px; } .promoCarousel .right { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(-135deg); right: 12px; } @media screen and (min-width: 601px) and (max-width: 1158px) { .promoCarousel { margin-right: 0px; } } @media screen and (max-width: 600px) { .promoCarousel { margin-right: 0px; margin-bottom: 56px; height: initial; } .promoCarousel #navigation { right: -5px; } } </style> <div id=navigation> <a tabindex=0 class=elipse id=SPOS_navLeft onclick=\"nextSlide(-1)\"> <div class=\"arrow left\"></div> </a> <a tabindex=0 class=elipse id=SPOS_navRight onclick=\"nextSlide(1)\"> <div class=\"arrow right\"></div> </a> </div> </div>"; 530var wtyShopOfferSliderDiv = "<div class=\"WRSecondarySlidercontainer\"> <style> #sposhrTag {position: relative; top: 35px; margin-bottom: 35px;} .WRSecondarySlidercontainer { min-height: 99px; display: flex; flex-direction: column; border-radius: 10px; } #navigation { display: flex; margin-left: 15.08px; order: 1; height: 0px; } .elipse { background: #FFF; border-radius: 50%; cursor: pointer; margin: 0px 7px 0px 7px; width: 40px; height: 40px; box-shadow: 0px 0px 10px 2px rgb(0 0 0 / 10%); position: relative; } .elipse:hover { transition: 0.1s; background: #165DBA; } .elipse:focus { transition: 0.1s; background: #165DBA; } .elipse:hover .arrow { color: #FFF; transition: 0.1s; } .elipse:focus .arrow { color: #FFF; transition: 0.1s; } .elipse:active { transform: scale(0.9); } .arrow { color: #165DBA; width: 10px; height: 10px; position: absolute; top: 14px; } .left { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(45deg); left: 16px; } .right { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(-135deg); right: 16px; } @media screen and (max-width: 600px) { #navigation { margin-left: 17.08px; height: 30px; } .elipse{ top: 28.6px; } } </style> <div id=\"navigation\"> <a tabindex=\"0\" class=\"elipse\" id=\"navLeft\" onclick=\"nextSlide(-1)\"> <div class=\"arrow left\"></div> </a> <a tabindex=\"0\" class=\"elipse\" id=\"navRight\" onclick=\"nextSlide(1)\"> <div class=\"arrow right\"></div> </a> </div> </div> <hr id=\"sposhrTag\" >";
531//var dashboardSliderDiv = ` <div class="dashboardSlidercontainer"> <style type="text/css"> .dashboardSlidercontainer .DashTempshowSlide { display: none; } .dashboardSlidercontainer { height: 242px; display: flex; justify-content: center; text-align: center; position: relative; } /* Navigation bar styles scoped to .dashboardSlidercontainer */ .dashboardSlidercontainer .dashboard-navigation { position: absolute; left: 0; right: 0; bottom: 10px; width: 100%; display: flex; justify-content: center; align-items: center; z-index: 1; gap: 20px; } .dashboardSlidercontainer .left-elipse, .dashboardSlidercontainer .right-elipse { border-radius: 50%; cursor: pointer; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; background: transparent; border: none; position: static; } .dashboardSlidercontainer .left, .dashboardSlidercontainer .right { width: 12px; height: 12px; box-shadow: -1px 1px 0 #0171AD; position: static; background: none; border: none; } .dashboardSlidercontainer .left { transform: rotate(45deg); } .dashboardSlidercontainer .right { transform: rotate(-135deg); } .dashboardSlidercontainer .nav-bullets { display: flex; gap: 8px; justify-content: center; align-items: center; } .dashboardSlidercontainer .nav-bulvar { width: 14px; height: 14px; border-radius: 50%; background: #D0CCCC; display: inline-block; cursor: pointer; transition: background 0.2s; } .dashboardSlidercontainer .nav-bullet-active { background: #0171AD; } .dashboardSlidercontainer .DashTempfade { animation-name: fade; animation-duration: 1.5s; z-index: 0; } @keyframes fade { from { opacity: .4; } to { opacity: 1; } } </style> <div class="dashboard-navigation"> <div class="left-elipse" onclick="nextSlide(-1)"> <div class="left"></div> </div> <div class="nav-bullets" id="nav-bullets"></div> <div class="right-elipse" onclick="nextSlide(1);"> <div class="right"></div> </div> </div> </div> `; 532var dashboardSliderDiv = `<div class="dashboardSlidercontainer"> <style type="text/css"> .DashTempshowSlide { display: none } .dashboardSlidercontainer { width: 100%; height: 242px; display: flex; justify-content: center; text-align: center; } .active { background-color: #717171; } .DashTempfade { -webkit-animation-name: fade; -webkit-animation-duration: 1.5s; animation-name: fade; animation-duration: 1.5s; } @-webkit-keyframes fade { from { opacity: .4 } to { opacity: 1 } } @keyframes fade { from { opacity: .4 } to { opacity: 1 } } #navigation { position: absolute; display: inline-flex; bottom: 19px; text-align: center; line-height: 0; display: flex; order: 1; height: 0px; } #nav-bullets {pointer-events: none; position: absolute; left: 0; right: 0; gap: 5px; margin: auto; bottom: 86px; display: flex; justify-content: center;} .nav-bullet { border-radius: 100%; width: 4px; height: 4px; opacity: 1; border: 1px solid #e3e0e0; } .nav-bullet-active { border-radius: 3px; width: 13px; background: #e3e0e0 0% 0% no-repeat padding-box; } .elipse { background: #FFF; border-radius: 50%; cursor: pointer; margin: 0px 7px 0px 7px; width: 40px; height: 40px; box-shadow: 0px 0px 10px 2px rgb(0 0 0 / 10%); position: relative; } .elipse:hover { transition: 0.1s; background: #0096d6; } .elipse:focus { transition: 0.1s; background: #0096d6; } .elipse:hover .arrow { color: #FFF; transition: 0.1s; } .elipse:focus .arrow { color: #FFF; transition: 0.1s; } .elipse:active { transform: scale(0.9); } .arrow { color: #0096d6; width: 10px; height: 10px; position: absolute; top: 14px; } .left { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(45deg); left: 16px; } .right { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(-135deg); right: 16px; } @media screen and (max-width: 600px) { .elipse { top: 28.6px; }} </style> <div id="navigation"> <a tabindex="0" class="elipse" id="navLeft" onclick="nextSlide(-1)"> <div class="arrow left"></div> </a> <div id="nav-bullets"> </div> <a tabindex="0" class="elipse" id="navRight" onclick="nextSlide(1)"> <div class="arrow right"></div> </a> </div> </div>`; 533 534async function standardRenderOffer(pageName, position, offerElement, targetPlaceholder, displayOnRender = true, addUrl = true) { 535 var divId = ""; 536 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 537 538 var LeadOffer = {}; 539 LeadOffer.OfferID = divId; 540 //var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 541 LeadOffer.OfferClicked = "no"; 542 LeadOffer.offerShown = "no"; 543 544 const mapEntry = PAGE_OFFER_MAP.find(cfg => (cfg.page && cfg.page === pageName) || (cfg.pages && cfg.pages.includes(pageName))); 545 if (!mapEntry) { 546 LeadOffer.errorData = "No offer configuration found for page: " + pageName; 547 logToGlobalDataLayer(LeadOffer); 548 logInfo("No offer configuration found for page: " + pageName); 549 return Promise.resolve(); 550 } 551 552 const posCfg = mapEntry.positions[position]; 553 if (!posCfg) { 554 LeadOffer.errorData = "No offer configuration found for position: " + position + " on page: " + pageName; 555 logToGlobalDataLayer(LeadOffer); 556 logInfo("No offer configuration found for position: " + position + " on page: " + pageName); 557 return Promise.resolve(); 558 } 559 560 LeadOffer.SPOStemplate = posCfg.templateReference || ""; 561 562 const placeholder = targetPlaceholder || posCfg.placeholder; 563 const insert = posCfg.insert || "html"; 564 const required = posCfg.required || []; 565 const replacements = posCfg.replacements || {}; 566 const hideAction = posCfg.hide; 567 568 return waitForElement(placeholder, "", 5000).then(function () { 569 const missing = required.some(field => !isDefined(offerElement[field])); 570 if (!missing) { 571 var canInsert = (insert === "append" || insert === "prepe
571nd") || isContainerEmpty(placeholder); 572 if (canInsert) { 573 var html = offerElement.html; 574 Object.entries(replacements).forEach(([token, key]) => { 575 var val = (key === "divId") ? divId : offerElement[key]; 576 html = html.replace(new RegExp(token, 'g'), val); 577 }); 578 579 if (insert === "append") { 580 $(placeholder).append(html); 581 } else if (insert === "prepend") { 582 $(placeholder).prepend(html); 583 } else { 584 $(placeholder).html(html); 585 } 586 587 if (displayOnRender) $(placeholder).removeClass("hidden").removeClass("hide").show(); 588 589 allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency); 590 applyAccessibilityAttributes(divId, offerElement); 591 if (addUrl) addUrlAndClickEvent(divId, offerElement); 592 LeadOffer.offerShown = "yes"; 593 logInfo(pageName + " offer HTML inserted", offerElement); 594 return true; 595 } else { 596 LeadOffer.errorData = pageName + " " + position + " Offer Location is not empty"; 597 LeadOffer.offerShown = "no"; 598 } 599 logToGlobalDataLayer(LeadOffer); 600 return false; 601 } else { 602 logInfo(pageName + " offer content not available"); 603 LeadOffer.errorData = "No Content Available"; 604 LeadOffer.offerShown = "no"; 605 logToGlobalDataLayer(LeadOffer); 606 return false; 607 } 608 }).finally(() => { 609 if (hideAction && hideAction !== "none") { 610 try { 611 eval(hideAction); 612 } catch (e) { 613 logInfo("Hide action failed", e); 614 } 615 } 616 }); 617} 618 619var offerNameForDecline = ""; 620 621// ---------------- request payload builders 622// Builds the Sage/Sierra context value expected by Mastiff from supported URL parameters. 623function buildAdditionalUserData(queryParams) { 624 const allowedFields = [ 625 "channel", 626 "intent", 627 "subscription", 628 "resolved", 629 "offerpromoted" 630 ]; 631 632 return allowedFields 633 .filter(field => isDefined(queryParams[field])) 634 .map(field => `${field}:${queryParams[field]}`) 635 .join("|"); 636} 637 638// BUILDERS: Dashboard payload builders 639function buildUserForDashboard(pgName) { 640 const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {}; 641 return { 642 callerId: "supportweb", 643 sessionId: g.sessionId || "", 644 pageId: pgName, 645 HPID: "", 646 intent: "", 647 locale: g.Locale || "", 648 countryCode: g.CountryCode || "", 649 language: g.LanguageCode || "", 650 deviceType: "", 651 activeHealth: "", 652 isNewCustomer: "", 653 emailOffers: "", 654 gender: "", 655 smartFriend: "", 656 customerType: "", 657 documentId: "" 658 }; 659} 660 661function pickDashboardDevice() { 662 const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {}; 663 const list = g?.Dashboard?.Products || []; 664 const n = g?.Dashboard?.NoOfDevices || list.length || 0; 665 var match = null; 666 for (var i = 0; i < n; i++) { 667 const d = list[i]; 668 if (!d) continue; 669 if (d.productLine == g?.Product?.productLineCode && 670 d.productName == g?.Product?.productName && 671 d.productNameOID == g?.Product?.productOID) { 672 match = d; break; 673 } 674 } 675 676 // try to match serial and model number if no match found yet 677 if (!isDefined(match)) { 678 waitForElement('#serial-number', '', 5000) 679 waitForElement('#model-number', '', 5000) 680 const sn = $('#serial-number').text() || $('#serial-number').val() || ""; 681 const mn = $('#model-number').text() || $('#model-number').val() || ""; 682 match = list.find(d => d.serialNumber == sn && d.productNumber == mn); 683 } 684 return match || {}; 685} 686 687function buildProductForDashboard() { 688 const d = pickDashboardDevice(); 689 var modelNumber = d.productNumber || ""; 690 if (modelNumber && modelNumber.indexOf("#") > 0) { 691 modelNumber = modelNumber.substring(0, modelNumber.length - 4); 692 } 693 return { 694 modelNumber, 695 serialNumber: d.serialNumber || "", 696 partNumber: "", 697 productRegion: "", 698 productEndOfLifeCycle: "", 699 productEndOfSupportCycle: "", 700 productType: "", 701 productLine: d.productLine || "", 702 productSegment: "", 703 productCategory: "", 704 productSubCategory: "", 705 productSeries: d.productSeriesName || "", 706 productSeriesOid: d.productSeriesOID || "", 707 productSupportCategoryName: d.productName || "", 708 productName: d.productName || "", 709 productNameOid: d.productNameOID || "", 710 productReleasedate: "", 711 platform: `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}` || "", 712 includeHTML: "", 713 carePackEligible: "", 714 currentActiveCarePack: "", 715 instantInkEligible: "", 716 instantInkCapability: "", 717 inkLevel: "", 718 instantInkSubscriptionStatus: "", 719 loi: "" 720 }; 721} 722 723// COMMON payload builders 724function buildUserCommon(pgName, segments, queryParams) { 725 const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {}; 726 const user = {
727 callerId: "supportweb", 728 sessionId: g.sessionId || "", 729 pageId: pgName, 730 HPID: "", 731 intent: "", 732 locale: g.Locale || "", 733 countryCode: g.CountryCode || "", 734 language: g.LanguageCode || "", 735 deviceType: "", 736 activeHealth: "", 737 isNewCustomer: !samePage, 738 emailOffers: "", 739 gender: "", 740 smartFriend: "", 741 customerType: g?.Product?.audienceType || "", 742 documentId: (g?.Document?.documentID) || "", 743 additionalUserData: buildAdditionalUserData(queryParams) 744 }; 745 746 const locSeg = segments[3] || ""; 747 if (!isDefined(user.countryCode) && locSeg.length >= 2) user.countryCode = locSeg.substring(0, 2); 748 if (!isDefined(user.language) && locSeg.length >= 5) user.language = locSeg.substring(3); 749 if (!isDefined(user.locale)) user.locale = locSeg; 750 751 if (pgName === "pdp_falcon") { 752 user.intent = segments[5] || ""; 753 } else if (pgName === "help-computer" || pgName === "help-printer") { 754 user.intent = (segments[6] ? segments[6].split("?")[0] : ""); 755 } else if (pgName === "contact-solution") { 756 // Intent for contact-solution pages comes from segment index 6 (exclude query string) 757 user.intent = (segments[6] ? segments[6].split("?")[0] : "") + "_" + (segments[7] ? segments[7].split("?")[0] : ""); 758 } else if (pgName === "help-windows") { 759 user.intent = (segments[5] ? segments[5].split("?")[0] : ""); 760 } 761 762 if (!isDefined(user.documentId)) { 763 if (segments[4] == "document") user.documentId = segments[5] || ""; 764 else if (segments[7] == "document") user.documentId = segments[8] || ""; 765 else if (segments[9] == "document") user.documentId = segments[10] || ""; 766 } 767 768 return user; 769} 770 771function buildWarrantyCommon(serialNumber) { 772 const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {}; 773 var w = { 774 warrantyState: "", 775 warrantyStatus: "", 776 warrantyStatusDetail: "", 777 warrantyStatusCode: "", 778 warrantyCaption: "", 779 warrantyStartdate: "", 780 warrantyEnddate: "", 781 warrantyRemainingDays: "", 782 warrantyTypeCode: "", 783 warrantyProductTypeCode: "", 784 warrantyCoveragePeriod: "" 785 }; 786 787 if (serialNumber === g?.EntitlementResults?.serialNumber) { 788 w = { 789 warrantyState: g?.EntitlementResults?.EntResults || "", 790 warrantyStatus: "", 791 warrantyStatusDetail: "", 792 warrantyStatusCode: "", 793 warrantyCaption: "", 794 warrantyStartdate: g?.EntitlementResults?.serviceObligationLineItemStartDate || "", 795 warrantyEnddate: g?.EntitlementResults?.serviceObligationLineItemEndDate || "", 796 warrantyRemainingDays: g?.EntitlementResults?.serviceObligationLineItemRemainingDays || "", 797 warrantyTypeCode: g?.EntitlementResults?.serviceObligationTypeCode || "", 798 warrantyProductTypeCode: g?.EntitlementResults?.serviceProductTypeCode || "", 799 warrantyCoveragePeriod: g?.EntitlementResults?.tierServiceObligationLineItemPeriodInMonths || "" 800 }; 801 802 if (!isDefined(w.warrantyState)) { 803 const el = document.getElementById("warrantyStatus"); 804 if (el) w.warrantyState = $("#warrantyStatus").val() || ""; 805 } 806 } 807 808 return w; 809} 810 811function buildProductCommon(pgName, segments, queryParams) { 812 const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {}; 813 const p = { 814 modelNumber: null, 815 serialNumber: null, 816 partNumber: "", 817 productRegion: "", 818 productEndOfLifeCycle: "", 819 productEndOfSupportCycle: "", 820 productType: "", 821 productLine: g?.Product?.productLineCode || "", 822 productSegment: "", 823 productCategory: "", 824 productSubCategory: "", 825 productSeries: g?.Product?.seriesName || "", 826 productSeriesOid: g?.Product?.seriesOid || "", 827 productSupportCategoryName: g?.Product?.supportCategoryName || "", 828 productName: g?.Product?.supportNameName || "",
829 productNameOid: g?.Product?.supportNameOid || "", 830 productReleasedate: g?.Product?.webReleaseDate || "", 831 platform: `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}` || "", 832 includeHTML: "", 833 carePackEligible: "", 834 currentActiveCarePack: "", 835 instantInkEligible: "", 836 instantInkCapability: "", 837 inkLevel: "", 838 instantInkSubscriptionStatus: "", 839 loi: "" 840 }; 841 842 //From DOM Elements 843 const getVal = id => (document.getElementById(id) ? $("#" + id).val() : ""); 844 if (!isDefined(p.modelNumber)) p.modelNumber = getVal("skuFromSession") || null; 845 if (!isDefined(p.serialNumber)) p.serialNumber = getVal("detectedSerialNo") || null; 846 if (!isDefined(p.serialNumber)) p.serialNumber = getVal("serialNumberFromSession") || null; 847 if (!isDefined(p.productSeries)) p.productSeries = getVal("seriesName") || p.productSeries; 848 if (!isDefined(p.productSeriesOid)) p.productSeriesOid = getVal("productSeriesId") || p.productSeriesOid; 849 850 // From URL 851 // productSeries 852 const setSeriesFromSeg = (idx) => { 853 if (!isDefined(p.productSeries) && isDefined(segments[idx])) 854 p.productSeries = segments[idx].replace(/-/g, " "); 855 }; 856 857 if (pgName === "drivers_closure") setSeriesFromSeg(7); 858 else if (pgName === "drivers_details") setSeriesFromSeg(6); 859 else if (pgName === "drivers_closure") setSeriesFromSeg(7); 860 else if (pgName === "contact") setSeriesFromSeg(6); 861 else if (pgName === "pdp_falcon") setSeriesFromSeg(6); 862 else if (segments[4] !== "document" && segments[4] !== "help") setSeriesFromSeg(5); 863 864 // productSeriesOid 865 const setSeriesOidFromSeg = (idx) => { 866 if (!isDefined(p.productSeriesOid) && isDefined(segments[idx])) 867 p.productSeriesOid = segments[idx].replace(/-/g, " "); 868 }; 869 870 if (pgName === "drivers_closure") setSeriesOidFromSeg(8); 871 else if (pgName === "contact") setSeriesOidFromSeg(7); 872 else if (pgName === "contact-solution") setSeriesOidFromSeg(1); // empty 873 else if (segments[4] !== "document" && segments[4] !== "help") setSeriesOidFromSeg(6); 874 875 // productNameOid 876 if (!isDefined(p.productNameOid)) { 877 var stringToBeParsed = ""; 878 879 // if (pgName === "pdp_falcon" && isDefined(segments[6])) { 880 // stringToBeParsed = segments.includes("model") 881 // ? segments[segments.indexOf("model") + 1] 882 // : (/^\d+$/.test(segments[6]) || segments[6].includes("?")) ? segments[6] 883 // : (/^\d+$/.test(segments[7]) || segments[7]?.includes("?")) ? segments[7] 884 // : ""; 885 // } else 886 if (pgName === "drivers_details" && isDefined(segments[7])) { 887 stringToBeParsed = segments[7]; 888 } else if (pgName === "drivers_closure") { 889 if (isDefined(segments[8])) { 890 stringToBeParsed = segments.includes("model") 891 ? segments[segments.indexOf("model") + 1] 892 : (/^\d+$/.test(segments[8]) || segments[8].includes("?")) ? segments[8] 893 : (/^\d+$/.test(segments[10]) || segments[10]?.includes("?")) ? segments[10] 894 : ""; 895 } 896 } else if (pgName === "contact") { 897 stringToBeParsed = isDefined(segments[9]) ? segments[9] : ""; 898 } 899 900 // fallback logic 901 if (!stringToBeParsed) { 902 if (pgName === "drivers_closure") { 903 stringToBeParsed = isDefined(segments[10]) ? segments[10] : ""; 904 } else if (pgName === "contact") { 905 stringToBeParsed = isDefined(segments[9]) ? segments[9] : ""; 906 } else if (pgName === "document" && segments[7] === "model") { 907 stringToBeParsed = isDefined(segments[8]) ? segments[8] : ""; 908 } else if (typeof segments[8] !== "undefined") { 909 stringToBeParsed = isDefined(segments[8]) ? segments[8] : ""; 910 } else {
911 stringToBeParsed = isDefined(segments[8]) ? segments[8] : ""; 912 } 913 } 914 915 if (stringToBeParsed) { 916 p.productNameOid = stringToBeParsed.includes("?") 917 ? stringToBeParsed.substring(0, stringToBeParsed.indexOf("?")) 918 : stringToBeParsed.replace(/-/g, " "); 919 } 920 } 921 922 923 if (isDefined(stringToBeParsed)) { 924 p.productNameOid = stringToBeParsed.includes("?") 925 ? stringToBeParsed.substring(0, stringToBeParsed.indexOf("?")) 926 : stringToBeParsed.replace(/-/g, " "); 927 } 928 //FORCED and TO BE VERIFIED reset for help-computer page 929 if (pgName === "help-computer" && isDefined(p.productNameOid)) { 930 p.productNameOid = ""; 931 } 932 933 //From Query Params 934 if (!isDefined(p.modelNumber) && isDefined(queryParams["sku"])) p.modelNumber = queryParams["sku"]; 935 if (!isDefined(p.serialNumber) && isDefined(queryParams["serialnumber"])) p.serialNumber = queryParams["serialnumber"]; 936 937 if (!isDefined(p.modelNumber)) { 938 p.modelNumber = g?.Product?.productNumber || ""; 939 if (p.modelNumber && p.modelNumber.indexOf("#") > 0) { 940 p.modelNumber = p.modelNumber.substring(0, p.modelNumber.length - 4); 941 } 942 } 943 if (!isDefined(p.serialNumber)) { 944 p.serialNumber = g?.Product?.serialNumber || ""; 945 } 946 947 p.productName = strOrEmpty(p.productName); 948 p.productNameOid = strOrEmpty(p.productNameOid); 949 p.modelNumber = strOrEmpty(p.modelNumber); 950 p.serialNumber = strOrEmpty(p.serialNumber); 951 p.productSeries = strOrEmpty(p.productSeries); 952 p.productSeriesOid = strOrEmpty(p.productSeriesOid); 953 return p; 954} 955 956// utility to ensure sessionId is set 957function ensureSessionId(reqObj, user) { 958 if (isDefined(user.sessionId)) return; 959 var mastiffSessionId = ""; 960 try { 961 if (typeof localStorage === "undefined" || localStorage == null) { 962 mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10); 963 } else { 964 mastiffSessionId = localStorage.getItem("MastiffSessionId"); 965 if (!isDefined(mastiffSessionId)) { 966 mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10); 967 localStorage.setItem("MastiffSessionId", mastiffSessionId); 968 } 969 } 970 } catch (e) { 971 mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10); 972 } 973 user.sessionId = mastiffSessionId; 974} 975 976// core request builder code 977function buildRequestPayload() { 978 const { segments, queryParams } = normalizeUrl(); 979 const reqObj = {}; 980 reqObj.requestId = createReqId(); 981 reqObj.offerLocations = (PAGE_CONFIG[pgName] || PAGE_CONFIG.default).offerLocations; 982 // Force single primary location for contact-solution pages regardless of default logic 983 if (pgName === "contact-solution") { 984 reqObj.offerLocations = "primary"; 985 } 986 reqObj.offerName = ""; 987 reqObj.acceptanceLevel = ""; 988 989 if (pgName === "dashboard") { 990 const user = buildUserForDashboard(pgName); 991 const product = buildProductForDashboard(); 992 const warranty = buildWarrantyCommon(product.serialNumber); 993 product.warranty = warranty; 994 reqObj.product = product; 995 reqObj.user = user; 996 ensureSessionId(reqObj, reqObj.user); 997 return reqObj; 998 } 999 1000 const user = buildUserCommon(pgName, segments, queryParams); 1001 const product = buildProductCommon(pgName, segments, queryParams); 1002 const warranty = buildWarrantyCommon(product.serialNumber); 1003 product.warranty = warranty; 1004 reqObj.product = product; 1005 reqObj.user = user; 1006 ensureSessionId(reqObj, reqObj.user); 1007 return reqObj; 1008} 1009 1010// --------- core functions starts here --------------- 1011 1012// await this to ensure DOM is ready (DOMContentLoaded), but don't block if it's already ready 1013function domReady() { 1014 if (document.readyState === "complete") return Promise.resolve(); 1015 return new Promise(resolve => { 1016 window.addEventListener("load", resolve, { once: true });
1017 }); 1018} 1019 1020async function initiateMastiffCall() { 1021 if (window._mastiffCallInProgress) return; 1022 window._mastiffCallInProgress = true; 1023 try { 1024 await domReady(); 1025 1026 deviceInfo = await getDeviceInfo(); 1027 pgName = pageName(); 1028 1029 if (pgName === "dashboard") { 1030 _quizReady = null; 1031 logInfo("[Dashboard Quiz] Reset Quiz Portal readiness for this Mastiff initiation."); 1032 } 1033 addSuppliesReporting(); 1034 replaceMerchImages(); 1035 1036 samePage = offerResults !== null && reqObj.user && reqObj.user.pageId === pgName; 1037 if (!samePage) { 1038 offerResults = null; 1039 reqObj = {}; 1040 } 1041 LeadOfferIndex = 1; 1042 enableDashTile = false; 1043 slide_index = 1; 1044 navBulletAvailable = false; 1045 clearTimeout(myVarTimeout); 1046 1047 // pdp_falcon same-page: reprocess cached offers only, no new request 1048 if (samePage && pgName === 'pdp_falcon') { 1049 processOffers(offerResults, pgName); 1050 1051 if (accessoriesOfferResults && reqObj.user.intent === "product-specs") { 1052 await showAccListOffers(accessoriesOfferResults); 1053 } else if (!accessoriesOfferResults && reqObj.user.intent === "product-specs") { 1054 await safeExecute(() => sendPdpAccessoriesRequest(reqObj)); 1055 } 1056 return; 1057 } 1058 1059 // drivers_details same-page: reprocess cached + send new request for version change 1060 if (samePage && pgName === 'drivers_details') { 1061 processOffers(offerResults, pgName); 1062 } 1063 1064 1065 await safeExecute(harvestData); 1066 } finally { 1067 window._mastiffCallInProgress = false; 1068 } 1069} 1070 1071async function beforeHarvestAjaxCall() { 1072 var quizSpinnerHtml = '<div class=sposQuizSpinner> <style>#mastiff-modal-cpc .sposQuizSpinner{display:none} .sposQuizSpinner { width: 100%; height: 250px; background: #fbfbfb; display: flex; justify-content: center; align-items: center; border-radius: 10px; margin-top: 20px; } .sposQuizSpinnerWheel { width: 50px; height: 50px; border: 8px solid #0096D6; border-top: 8px solid #fbfbfb; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style> <div class=sposQuizSpinnerWheel></div></div>'; 1073 var quizHtml = `<style>.quizPortalDiv { margin: 15px 0px; } .SPOSQuizDivider { height: 20px; border-bottom: 1px solid #E8E8E8; } /* Quiz container and header */ .CPConfiguratorContainer, .HUQConfiguratorContainer { font-family: "HPSimplifiedLight"; background: #fff; } .CPConfiguratorHeader { display: flex; align-items: center; margin-bottom: 13px; position: relative; height: 48px; padding-right: 68px; } .CPConfiguratorTitleDiv { display: flex; align-items: center; } .CPConfiguratorTitleIconDiv { width: 37px; height: auto; margin-right: 15px; } .CPConfiguratorTitleText { font-size: 16px; } /* close and reset buttons */ .CPConfiguratorTopButton { border-radius: 50%; width: 48px; height: 48px; display: flex; justify-content: center; align-items: center; cursor: pointer; position: absolute; right: 0px; } .CPConfiguratorCloseButton { background-color: #F3F8F3; } .HUQCloseButton { background-color: #FCF3F3 !important; } .CPConfiguratorTopButtonCloseImg { width: 12px; } .CPConfiguratorResetButton { background-color: #EFEFEF; display: none; } .CPConfiguratorTopButtonResetImg { width: 18px; margin-bottom: 2px; } /*Questions container */ .CPConfiguratorBody { border-radius: 10px; background-color: #fff; border: 11px solid #F3F8F3; padding: 11px; } .HUQBody { border: 11px solid #FCF3F3; } /*Questions */ .CPConfiguratorItem { border: 1px solid #EFEFEF; border-radius: 5px; border-left: 5px solid #d8d8d8; margin-bottom: 13px; padding-left: 15px; padding-right: 25px; padding-bottom: 12px; padding-top: 23px; } .CPConfiguratorItem-Two-column-layout { width: calc(50% - 7px); display: inline-block; vertical-align: top; } .CPConfiguratorItem-Two-column-layoutFirst { margin-right: 10px; } .CPConfiguratorQuestion { flex-wrap: wrap; margin-bottom: 22px; display: flex; align-items: center; flex-wrap: nowrap; }
1073 .CPConfiguratorQuestionIcon { border: 2.5px solid #d8d8d8; background-color: #d8d8d8; color: #E9F2E8; border-radius: 50%; height: 28px; min-width: 28px; margin-right: 10px; display: flex; align-items: center; justify-content: center; } .CPConfiguratorQuestionIconIndex { font-family: "HPSimplified"; font-size: 17px; color: #777777; } .CPConfiguratorQuestionText { font-size: 20px; line-height: 23px; color: #212121; font-family: "HPSimplified"; display: flex; align-items: center; } /* Active questions */ .CPConfiguratorItemActive { border-left: 5px solid #B7DAB5; } .CPConfiguratorQuestionIconActive { border: 2.5px solid #B7DAB5; background-color: #fff; } .CPConfiguratorQuestionIconImgActive { display: none; } /* Disabled questions */ .CPConfiguratorBodyDisabled { border: 11px solid #EFEFEF !important; } .CPConfiguratorQuestionIconDisabled { border: 2.5px solid #d8d8d8 !important; background-color: #fff !important; } .CPConfiguratorQuestionTextDisabled { color: #767676 !important; } .CPConfiguratorQuestionIconImgDisabled { display: none; } .CPConfiguratorItemActiveDisabled { border-left: 5px solid #f1f1f1 !important; } /*Answers container */ .CPConfiguratorAnswers { display: flex; flex-wrap: wrap; align-items: flex-start; align-content: flex-start; margin-left: 3px; width: 100%; } .CPConfiguratordurationRow, .CPConfiguratorlocationRow { width: calc(33% - 10px); margin-right: 10px; } .CPConfiguratortypeRow { width: 100%; margin-right: 10px; } .CPConfiguratorcoverageTypeRow { width: calc(33% - 10px); margin-right: 10px; } .CPConfiguratorfeatureRow { width: calc(50% - 20px); margin-right: 20px; } .CPConfiguratorfeaturesRow { width: 100%; margin-right: 20px; } /* Answsers */ .CPConfiguratorAnswer { display: flex; position: relative; flex-direction: row-reverse; justify-content: flex-end; align-items: flex-end; } .CPConfiguratorAnswerChild { padding-left: 15px; order: 999; width: 70%; } .CPConfiguratorAnswerSubChild { padding-left: 30px; } .CPConfiguratorAnswerfeature:hover, .CPConfiguratorAnswerfeature:focus, .CPConfiguratorAnswerfeature:focus-visible, .CPConfiguratorAnswerfeatures:hover, .CPConfiguratorAnswerfeatures:focus, .CPConfiguratorAnswerfeatures:focus-visible, .CPConfiguratorAnswerduration:hover, .CPConfiguratorAnswerduration:focus, .CPConfiguratorAnswerduration:focus-visible, .CPConfiguratorAnswerlocation:hover, .CPConfiguratorAnswerlocation:focus, .CPConfiguratorAnswerlocation:focus-visible, .CPConfiguratorAnswertype:hover, .CPConfiguratorAnswertype:focus, .CPConfiguratorAnswertype:focus-visible, .CPConfiguratorAnswercoverageType:hover, .CPConfiguratorAnswercoverageType:focus, .CPConfiguratorAnswercoverageType:focus-visible { outline: none; color: #000; .CPConfiguratorAnswerfeatureButton[type="checkbox"]:not(:checked), .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:not(:checked) { background-color: #E7E7E7 !important; box-shadow: 0 0 0 4px #E7E7E7, 0 0 0 4px #E7E7E7 !important; background-image: url(https://hp.widen.net/content/qybiqsn5op/svg/DSPOS_QUIZ_White_Checkmark.svg); background-repeat: no-repeat; background-position: center; background-size: 90%; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:not(:checked):focus, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:not(:checked):focus-visible, .CPConfiguratorAnswerfeatureButton[type="checkbox"]:not(:checked):focus, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:not(:checked):focus-visible { box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F !important; } .CPConfiguratorAnswerdurationButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswerlocationButton[type="radio"] { background-color: #E7E7E7; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F; outline: none; } } .CPConfiguratorAnswerdurationButton[type="radio"]:focus-visible, .CPConfiguratorAnswerdurationButton[type="radio"]:focus-visible, .CPConfiguratorAnswertypeButton[type="radio"]:focus-visible, .CPConfiguratorAnswertypeButton[type="radio"]:focus-visible, .CPConfiguratorAnswerlocationButton[type="radio"]:focus-visible, .CPConfiguratorAnswerlocationButton[type="radio"]:focus-visible, .CPConfiguratorAnswerfeatureButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswerfeatureButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:focus-visible, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:focus-visible { background-color: #E7E7E7; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F; outline: none; } .CPConfiguratorAnswerdurationButton[type="radio"]:checked, .CPConfiguratorAnswertypeButton[type="radio"]:checked, .CPConfiguratorAnswerlocationButton[type="radio"]:checked, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:checked { background-color: #165DBA !important; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #000000 !important; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:checked, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:checked { background-color: #165DBA !important; box-shadow: 0 0 0 4px #165DBA, 0 0 0 4px #000000 !important; background-image: url('https://hp.widen.net/content/qybiqsn5op/svg/DSPOS_QUIZ_White_Checkmark.svg'); background-repeat: no-repeat; background-position: center; background-size: 90%; }
1073 .CPConfiguratorAnswercoverageType, .CPConfiguratorAnswerduration, .CPConfiguratorAnswerlocation, .CPConfiguratorAnswertype, .CPConfiguratorAnswerfeature, .CPConfiguratorAnswerfeatures { font-size: 16px; line-height: 22px; color: #000; display: flex; margin-bottom: 20px; cursor: pointer; align-items: flex-start; } .CPConfiguratorAnswerLabel>span:first-of-type { margin-top: -5px } .CPConfiguratorAnswerdurationButton[type="radio"], .CPConfiguratorAnswerlocationButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswercoverageTypeButton[type="radio"] { border-radius: 50%; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"], .CPConfiguratorAnswercoverageTypeButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswerlocationButton[type="radio"], .CPConfiguratorAnswerdurationButton[type="radio"] { appearance: none; cursor: pointer; min-width: 14px !important; height: 14px; background-color: #fff; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F; margin-right: 10px; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"] { border-radius: 2px; } .CPConfiguratorAnswercoverageType:focus-within, .CPConfiguratorAnswerduration:focus-within, .CPConfiguratorAnswerlocation:focus-within, .CPConfiguratorAnswertype:focus-within, .CPConfiguratorAnswerfeature:focus-within, .CPConfiguratorAnswerfeatures:focus-within { color: #000 !important; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"] { border-radius: 2px; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F !important; } /* Toggle answers */ .CPConfiguratorToggle input { display: none; } .CPConfiguratorSlider { max-width: 35px; width: 35px; margin-right: 7px; height: 20px; cursor: pointer; background-color: #ccc; border: 1px solid #8F8F8F; border-radius: 34px; top: 0; left: 0; right: 0; bottom: 0; transition: 0.2s; padding-top: 2px; padding-left: 3px; } .CPConfiguratorSliderCircle { height: 14px; width: 14px; background-color: white; transition: 0.2s; border-radius: 50%; } /* Toggle answers checked */ .CPConfiguratorToggle input:checked+.CPConfiguratorSlider { background-color: #165DBA; border: 1px solid #165DBA; } .CPConfiguratorToggle input:checked+.CPConfiguratorSlider .CPConfiguratorSliderCircle { margin-left: 14px; } /* Disabled answers */ .CPConfiguratorAnswercoverageTypeButton[type="radio"]:checked:disabled, .CPConfiguratorAnswertypeButton[type="radio"]:checked:disabled, .CPConfiguratorAnswerlocationButton[type="radio"]:checked:disabled, .CPConfiguratorAnswerdurationButton[type="radio"]:checked:disabled { cursor: default; background-color: #CCCCCC !important; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #CCCCCC !important; pointer-events: none; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:checked:disabled, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:checked:disabled { cursor: default; background-color: #CCCCCC !important; box-shadow: 0 0 0 4px #CCCCCC, 0 0 0 4px #CCCCCC !important; pointer-events: none; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:disabled, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:disabled, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:disabled, .CPConfiguratorAnswertypeButton[type="radio"]:disabled, .CPConfiguratorAnswerlocationButton[type="radio"]:disabled, .CPConfiguratorAnswerdurationButton[type="radio"]:disabled { cursor: default; pointer-events: none; background-color: #ffffff !important; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #CCCCCC !important; } .CPConfiguratorAnswerDisabled { color: #999999 !important; cursor: default; pointer-events: none; } /* Toggle disabled */ .CPConfiguratorToggle input:disabled+.CPConfiguratorSlider { transition: 0s; background-color: #F3F3F3; pointer-events: none; border: 1px solid #F3F3F3; } .CPConfiguratorToggle input:disabled+.CPConfiguratorSlider .CPConfiguratorSliderCircle { transition: 0s; background-color: #DADADA; } /* tooltips */ .CPConfiguratorAnswerTooltip { width: 15px; margin-left: 2px; }
1073 .CPConfiguratorAnswerTooltipDiv:hover~.CPConfiguratorAnswerTooltipBubble, .CPConfiguratorAnswerTooltipDiv:hover>.CPConfiguratorAnswerTooltipBubbleChip::after { display: flex !important; pointer-events: none; } .CPConfiguratorAnswerTooltipDiv:active, .CPConfiguratorAnswerTooltipDiv:focus {} .CPConfiguratorAnswerTooltipDiv { position: relative; height: 16px; display: ruby; margin-bottom: 25px; cursor: default; white-space: nowrap; pointer-events: auto; } .CPConfiguratorAnswerTooltipBubble { width: 103%; position: absolute; bottom: 44px; left: 0px; display: none; min-width: inherit; height: 500px; align-items: flex-end; min-width: 450px; } .CPConfiguratorAnswerTooltipBubbleChip::after { content: ""; position: absolute; border-width: 7px; z-index: 1001; top: -17px; left: -14px; border-style: solid; border-color: #fff transparent transparent transparent; display: none; } .CPConfiguratorAnswerTooltipBubbleChip { position: relative; right: 0px; display: inline-block; top: -2px; } .CPConfiguratorAnswerTooltipBubbleText { font-family: "HPSimplified"; font-size: 14px; line-height: 20px; text-align: left; color: #000; background: #fff; border-radius: 10px; z-index: 1000; box-shadow: 0 0 30px 10px #0000001a; padding: 15px 14px 15px 19px; } .CPConfiguratorResultSubmission { display: flex; justify-content: space-between; align-items: center; } .CPConfiguratorResultSubmissionTotal { font-size: 16px; color: #404040; margin-left: 4px; } .CPConfiguratorResultSubmissionButton { font-size: 16px; line-height: 35px; height: 45px; color: #fff; background-color: #CCCCCC; border-radius: 4px; padding: 6px 20px 6px 20px; font-family: "HPSimplified"; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; text-align: center; transition: 0.1s; pointer-events: none; } .CPConfiguratorResultSubmissionButtonActive { background-color: #165DBA; pointer-events: initial; } .CPConfiguratorResultSubmissionButtonActive:hover, .CPConfiguratorResultSubmissionButtonActive:focus, .CPConfiguratorResultSubmissionButtonActive:active, .CPConfiguratorResultSubmissionButton:focus-visible { background-color: #114284; outline: none; cursor: pointer; } /* offer */ .CPConfiguratorResultOffer { border-left: 5px solid #1C7A17; box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.09); border-radius: 5px; margin-top: 17px; margin-bottom: 5px; display: none; } .CPConfiguratorResultOfferImageDiv { background-color: #ffffff; width: 30%; padding: 26px; display: flex; align-items: center; justify-content: center; overflow: hidden; } .CPConfiguratorResultOfferImage {} .CPConfiguratorResultOfferText { background-color: #F3F8F3; padding: 17px 25px; width: 80%; } .CPConfiguratorResultOfferHeader { display: flex; align-items: center; justify-content: space-between; margin-bottom: 11px; } .CPConfiguratorResultOfferHeaderHeadline { display: flex; align-items: flex-start; } .CPConfiguratorResultOfferHeaderHeadlineIcon { margin-right: 7px; margin-top: 4px; } .CPConfiguratorResultOfferHeaderHeadlineText { color: #1C7A17; line-height: 26px; font-size: 20px; font-family: "HPSimplified"; } .CPConfiguratorResultOfferHeaderPrice { display: flex; font-size: 16px; } .HUQResultOfferHeaderPrice { display: flex; justify-content: center; margin: 15px 0px; } .HUQRecommendedForYouPrice { margin-bottom: 28px; } .CPConfiguratorResultOfferHeaderDiscountPrice { color: #7D7D7D; margin-right: 8px; text-decoration: line-through; } .CPConfiguratorResultOfferHeaderSalePrice { color: #7D7D7D; } .HUQConfiguratorContainer .CPConfiguratorResultOfferHeaderSalePrice { font-family: "HPSimplified"; color: #373737; } .CPConfiguratorResultOfferDescription { margin-bottom: 20px; font-size: 16px; line-height: 24px; } .CPConfiguratorResultOfferCTA { font-size: 16px; font-family: "HPSimplified"; line-height: 35px; color: #165DBA; background-color: #fff; border: 1px solid #165DBA; border-radius: 4px; padding: 6px 20px 6px 20px; width: max-content; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; cursor: pointer; text-align: center; transition: 0.1s; } .CPConfiguratorResultOfferCTA:hover, .CPConfiguratorResultOfferCTA:focus, .CPConfiguratorResultOfferCTA:focus-visible { border: 1px solid #165DBA; color: #fff; background-color: #165DBA; outline: none; } .CPConfiguratorResultOfferCTA:active { border: 1px solid #114284; color: #fff; background-color: #114284; outline: none; } /* spinner */ .CPConfiguratorSpinner { transition: 0.3s; } .skeleton { animation: skeleton-loading 0.8s linear infinite alternate; } @keyframes skeleton-loading { 0% { background-color: rgb(216, 221, 223); } 100% { background-color: rgb(240, 243, 245); } } .CPConfiguratorSpinnerBody { border-radius: 10px; background-color: #ffffff; border: 11px solid #f0f3f5; padding: 11px } .CPConfiguratorSpinnerHeader { margin-top: 20px; display: flex; align-items: center; height: 48px; position: relative; } .CPConfiguratorSpinnerHeaderIcon { min-width: 29px; height: 29px; border-radius: 50%; margin-right: 15px; }
1073 .CPConfiguratorSpinnerHeaderText { border-radius: 10px; height: 16px; width: 357px; } .CPConfiguratorSpinnerHeaderButton { width: 48px; height: 48px; position: absolute; right: 0; border-radius: 50%; } .CPConfiguratorItem-Two-column-layoutFirstSpinner { margin-right: 9px; } .CPConfiguratorSpinnerQuestion { display: flex; align-items: center; } .CPConfiguratorSpinnerQuestionIcon { min-width: 32px; height: 32px; border-radius: 50%; margin-right: 10px; } .CPConfiguratorSpinnerQuestionText { border-radius: 10px; height: 20px; width: 357px; } .CPConfiguratorSpinnerHzAnswer { align-items: center; width: 100%; } .CPConfiguratorSpinnerHzAnswerText { border-radius: 10px; height: 16px; width: 100%; margin-bottom: 26px; } .CPConfiguratorSpinnerSubmission { height: 47px; } .CPConfiguratorSpinnerSubmissionTotal { border-radius: 10px; height: 21px; width: 94px; } .CPConfiguratorResultSubmissionTotalPrice { font-family: "HPSimplified"; font-size: 18px; } .CPConfiguratorSpinnerSubmissionButton { border-radius: 5px; height: 47px; width: 108px; } .CPConfiguratorSpinnerHzAnswerTextMobile { display: none; } .CPConfiguratorResultOfferSectionHUQ { display: none; width: 100%; justify-content: space-between; margin-top: 13px; } .CPConfiguratorResultOfferSectionHUQOffer { border-top: 5px solid #BDD8BC; border-radius: 4px; width: calc(33.33% - 9px); display: flex; flex-direction: column; align-items: center; box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.09); padding-bottom: 20px; } .CPConfiguratorResultOfferSectionHUQOfferRecommended { border-top: 5px solid #8EBD8B; } .CPConfiguratorResultOfferSectionHUQ> :nth-child(1), .CPConfiguratorResultOfferSectionHUQ> :nth-child(3) { margin-top: 13px; } .CPConfiguratorResultSubmissionButtonHUQRecommended { margin-top: 13px; } .CPConfiguratorResultOfferSectionHUQOfferHeader { background-color: #F3F8F3; width: 100%; text-align: center; padding: 14px 0px; display: flex; justify-content: center; } .CPConfiguratorResultOfferSectionHUQOfferHeaderImg { margin-right: 5px; min-width: 20px; max-height: 20px; } .CPConfiguratorResultOfferSectionHUQOfferImgDiv { margin-top: 20px; margin-bottom: 10px; display: flex; justify-content: center; align-items: center; height: 107px; } .CPConfiguratorResultOfferSectionHUQOfferImg { max-width: 125px; } .CPConfiguratorResultOfferSectionHUQOfferDescription { text-align: center; padding-left: 20px; padding-right: 20px; font-size: 14px; line-height: 20px; height: 80px; margin-bottom: 10px; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; color: #404040; } .CPConfiguratorResultSubmissionButtonHUQ { color: #165DBA; font-family: "HPSimplified"; cursor: pointer; display: flex; align-items: center; justify-content: center; } .diagsVRepairsCTAElipse { margin-right: 10px; background-color: #165dba; width: 25px; height: 25px; border-radius: 50%; position: relative; } .diagsVRepairsCTADivArrow { color: #fff; width: 5px; height: 5px; position: absolute; transform: scaleY(1.3) scaleX(0.85) rotate(-135deg); left: 9px; top: 9px; border-bottom: 2px solid; border-left: 2px solid; } .CPConfiguratorResultSubmissionButtonHUQ:hover, .CPConfiguratorResultSubmissionButtonHUQ:active, .CPConfiguratorResultSubmissionButtonHUQ:focus, .CPConfiguratorResultSubmissionButtonHUQ:focus-visible { color: #114284; outline: none; .diagsVRepairsCTAElipse { background-color: #114284; } } @media screen and (max-width: 792px) { .CPConfiguratorAnswerLabel>span:first-of-type { margin-top: -3px; } .CPConfiguratorQuestionText, .CPConfiguratorResultOfferHeaderHeadlineText { font-size: 16px !important; line-height: 20px; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"], .CPConfiguratorAnswerlocationButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswerdurationButton[type="radio"] { min-width: 12px !important; height: 12px !important; margin-top: 4px; } .CPConfiguratorAnswercoverageType, .CPConfiguratorAnswerduration, .CPConfiguratorAnswertype, .CPConfiguratorAnswerfeature, .CPConfiguratorAnswerfeatures, .CPConfiguratorAnswerlocation, .CPConfiguratorTitleText, .CPConfiguratorResultOfferDescription, .CPConfiguratorResultSubmissionTotal { font-size: 14px !important; line-height: 20px !important; } .CPConfiguratorResultSubmissionTotal { width: 129px; display: flex; flex-direction: column; }
1073 .CPConfiguratorResultSubmissionTotalPrice { font-size: 16px; } .CPConfiguratorAnswerTooltip { margin-left: 4px; width: 12px; } .CPConfiguratorResultOfferHeaderPrice { font-size: 14px; } .CPConfiguratorResultSticky { position: sticky; bottom: 0px; background: white; padding: 10px; border-top: 1px solid #dfdfdf; margin: -11px; margin-top: 13px; box-shadow: rgba(149, 157, 165, 0.1) 0px -4px 10px; } .CPConfiguratorResultOfferHeaderHeadlineIcon { margin-top: 2px; } .CPConfiguratorResultOffer { overflow: hidden; } .CPConfiguratorResultOfferText { width: 100% !important; } .CPConfiguratorResultOfferHeader { flex-direction: column; align-items: flex-start !important; max-width: 100%; } .CPConfiguratorResultOfferHeaderHeadline { margin-bottom: 10px; } .CPConfiguratorResultOfferImageDiv { display: none !important; } .CPConfiguratorAnswerTooltipBubble { min-width: initial; width: 108%; left: -3%; } .CPConfiguratorAnswerTooltipBubbleText { max-width: 100%; } .CPConfiguratorAnswer { min-width: 100%; } .CPConfiguratorSpinnerSubmissionButton { display: none; } .CPConfiguratorSpinnerHzAnswerTextMobile { width: 51%; display: block; } .CPConfiguratorSpinnerQuestionText { border-radius: 10px; height: 20px; width: 110px; } .CPConfiguratorItem-Two-column-layout { width: initial; display: block; vertical-align: initial; } .CPConfiguratorItem-Two-column-layoutFirst, .CPConfiguratorItem-Two-column-layoutFirstSpinner { margin-right: 0px; } .CPConfiguratorQuestion { flex-wrap: wrap; margin-bottom: 22px; display: flex; align-items: center; flex-wrap: nowrap; } .CPConfiguratorResultOfferSectionHUQ { flex-direction: column; } .CPConfiguratorResultOfferSectionHUQOffer { width: initial; border-top: none; display: initial; border-left: 5px solid #BDD8BC; margin: 6.5px 0px; padding: 13px; } .CPConfiguratorResultOfferSectionHUQ> :nth-child(1), .CPConfiguratorResultOfferSectionHUQ> :nth-child(3) { margin-top: 8px; } .CPConfiguratorResultOfferSectionHUQ> :nth-child(2) { order: -1; } .CPConfiguratorResultOfferSectionHUQOffercontentWrapper { display: flex; } .CPConfiguratorResultOfferSectionHUQOfferImgDiv { margin: 0px; margin-right: 13px; } .CPConfiguratorResultOfferSectionHUQOfferImg { width: 100px; } .CPConfiguratorResultSubmissionButtonHUQ { justify-content: flex-start; } .CPConfiguratorResultOfferSectionHUQOfferHeader { width: initial; max-width: fit-content; padding: 5px 15px; margin: auto; border-radius: 10px; margin-bottom: 10px; margin-top: 5px; } .CPConfiguratorResultOfferSectionHUQOfferDescription { text-align: left; padding: 0px; height: initial; max-height: 80px; } .CPConfiguratorSpinnerHzAnswerHUQ> :nth-child(2), .CPConfiguratorSpinnerHzAnswerHUQ> :nth-child(3) { display: none; } .HUQResultOfferHeaderPrice { justify-content: flex-start; } .HUQResultOfferHeaderPrice { margin-top: 5px; margin-bottom: 15px !important; } } @media screen and (max-width: 400px) { .CPConfiguratorAnswer { min-width: 100%; } .CPConfiguratorAnswerTooltipBubble { width: 109%; min-width: initial; } .CPConfiguratorResultOfferSectionHUQOfferImg { width: 90px; } } </style><div class="CPConfiguratorContainer quizPortalDiv"><div class="CPConfiguratorHeader"><div class="CPConfiguratorTitleDiv"><div class="CPConfiguratorTitleIconDiv"><img src="https://hp.widen.net/content/q2cfurljgw/png/CPC_CPIcon.png" class="CPConfiguratorTitleIcon" alt=""></div><div class="CPConfiguratorTitleText"></div></div><div class="CPConfiguratorCloseButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonCloseImg" src="https://hp.widen.net/content/bs9gwrpkho/png/CPC_xmark.png" alt=""></div><div class="CPConfiguratorResetButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonResetImg" src="https://hp.widen.net/content/7iclbe1bz2/png/CPC_Reset.png" alt=""></div><div class="CPConfiguratorResetButton"></div></div><div class="CPConfiguratorBody"><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">1</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div><div class="CPConfiguratorAnswers" id=CPConfiguratorAnswersduration></div></div><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">2</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div></div><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">3</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div></div><div class="CPConfiguratorResult CPConfiguratorResultSticky"><div class=CPConfiguratorResultSubmission><div class=CPConfiguratorResultSubmissionTotal><span class=CPConfiguratorResultSubmissionTotalText></span><span class="CPConfiguratorResultSubmissionTotalPrice incartPricePlaceholder"></span></div><div class=CPConfiguratorResultSubmissionButton tabindex=0></div></div><div class=CPConfiguratorResultOffer><div class=CPConfiguratorResultOfferImageDiv><img class=CPConfiguratorResultOfferImage src=https://hp.widen.net/content/nhkja006wg/png/CPC_CPImgimg.png alt=></div> <div class=CPConfiguratorResultOfferText><div class=CPConfiguratorResultOfferHeader><div class=CPConfiguratorResultOfferHeaderHeadline><div class=CPConfiguratorResultOfferHeaderHeadlineIcon><img src=https://hp.widen.net/content/mk7aaos2dh/png/CPC_Checkmark1.png alt=></div> <div class=CPConfiguratorResultOfferHeaderHeadlineText></div></div><div class=CPConfiguratorResultOfferHeaderPrice><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div></div><div class=CPConfiguratorResultOfferDescription></div><div class=CPConfiguratorResultOfferCTA tabindex=0></div></div></div></div></div><div class="SPOSQuizDivider"></div></div><div class="HUQConfiguratorContainer quizPortalDiv"><div class="preloadQuizImages" style="display: none"><img src=https://hp.widen.net/content/qybiqsn5op/svg/DSPOS_QUIZ_White_Checkmark.svg> <img src=https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png> <img src=https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png> </div><div class="CPConfiguratorHeader"><div class="CPConfiguratorTitleDiv"><div class="CPConfiguratorTitleIconDiv">
1073<img src="https://hp.widen.net/content/lb8570fxwi/svg/HardwareUpgradeQuizIcon.svg" class="CPConfiguratorTitleIcon" alt=""></div><div class="CPConfiguratorTitleText"></div></div><div class="CPConfiguratorCloseButton HUQCloseButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonCloseImg" src="https://hp.widen.net/content/bs9gwrpkho/png/CPC_xmark.png" alt=""></div><div class="CPConfiguratorResetButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonResetImg" src="https://hp.widen.net/content/7iclbe1bz2/png/CPC_Reset.png" alt=""></div><div class="CPConfiguratorResetButton"></div></div><div class="CPConfiguratorBody HUQBody"><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">1</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div><div class="CPConfiguratorAnswers" id=HUQAnswersLocation></div></div><div class="CPConfiguratorItem CPConfiguratorItem-Two-column-layout CPConfiguratorItem-Two-column-layoutFirst"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">2</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText">â</div></div><div class="CPConfiguratorAnswers" id=HUQAnswersType></div></div><div class="CPConfiguratorItem CPConfiguratorItem-Two-column-layout"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">3</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div><div class="CPConfiguratorAnswers" id=HUQAnswersFeatures></div></div><div class="CPConfiguratorResult CPConfiguratorResultSticky"><div class=CPConfiguratorResultSubmission><div class=CPConfiguratorResultSubmissionTotal></div><div class=CPConfiguratorResultSubmissionButton tabindex=0></div></div><div class=CPConfiguratorResultOffer><div class=CPConfiguratorResultOfferImageDiv><img class=CPConfiguratorResultOfferImage src=https://hp.widen.net/content/nhkja006wg/png/CPC_CPImgimg.png alt=></div> <div class=CPConfiguratorResultOfferText><div class=CPConfiguratorResultOfferHeader><div class=CPConfiguratorResultOfferHeaderHeadline><div class=CPConfiguratorResultOfferHeaderHeadlineIcon><img src=https://hp.widen.net/content/mk7aaos2dh/png/CPC_Checkmark1.png alt=></div> <div class=CPConfiguratorResultOfferHeaderHeadlineText></div></div><div class=CPConfiguratorResultOfferHeaderPrice><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div></div><div class=CPConfiguratorResultOfferDescription></div><div class=CPConfiguratorResultOfferCTA tabindex=0></div></div></div><div class=CPConfiguratorResultOfferSectionHUQ><div class=CPConfiguratorResultOfferSectionHUQOffer><div class=CPConfiguratorResultOfferSectionHUQOfferHeader><img class=CPConfiguratorResultOfferSectionHUQOfferHeaderImg src=https://hp.widen.net/content/fsq7hviqvc/png/HUQ_BudgetFriendly_Icon.png><span class=CPConfiguratorResultOfferSectionHUQOfferHeaderText></span></div><div class=CPConfiguratorResultOfferSectionHUQOffercontentWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferImgDiv><img class=CPConfiguratorResultOfferSectionHUQOfferImg src=""></div><div class=textWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferDescription></div><div class="HUQResultOfferHeaderPrice HUQBudgetFriendlyPrice"><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div><div class="CPConfiguratorResultSubmissionButtonHUQ CPConfiguratorResultSubmissionButtonHUQBudgetFriendly" tabindex=0><div class=diagsVRepairsCTAElipse><div class=diagsVRepairsCTADivArrow></div></div><span class=CPConfiguratorResultSubmissionButtonHUQText></span></div></div></div></div><div class="CPConfiguratorResultOfferSectionHUQOffer CPConfiguratorResultOfferSectionHUQOfferRecommended"><div class=CPConfiguratorResultOfferSectionHUQOfferHeader><img class=CPConfiguratorResultOfferSectionHUQOfferHeaderImg src=https://hp.widen.net/content/nvwc6kqvgd/png/HUQ_RecommendedForYou_Icon.png><span class=CPConfiguratorResultOfferSectionHUQOfferHeaderText></span></div><div class=CPConfiguratorResultOfferSectionHUQOffercontentWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferImgDiv><img class=CPConfiguratorResultOfferSectionHUQOfferImg src=""></div><div class=textWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferDescription></div><div class="HUQResultOfferHeaderPrice HUQRecommendedForYouPrice"><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div><div class="CPConfiguratorResultSubmissionButtonHUQ CPConfiguratorResultSubmissionButtonHUQRecommended" tabindex=0><div class=diagsVRepairsCTAElipse><div class=diagsVRepairsCTADivArrow></div></div><span class=CPConfiguratorResultSubmissionButtonHUQText></span></div></div></div></div><div class=CPConfiguratorResultOfferSectionHUQOffer><div class=CPConfiguratorResultOfferSectionHUQOfferHeader><img class=CPConfiguratorResultOfferSectionHUQOfferHeaderImg src=https://hp.widen.net/content/e6b8x6gxqo/png/HUQ_MostPopular_Icon.png><span class=CPConfiguratorResultOfferSectionHUQOfferHeaderText></span></div><div class=CPConfiguratorResultOfferSectionHUQOffercontentWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferImgDiv><img class=CPConfiguratorResultOfferSectionHUQOfferImg src=""></div><div class=textWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferDescription></div><div class="HUQResultOfferHeaderPrice HUQMostPopularPrice"><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div><div class="CPConfiguratorResultSubmissionButtonHUQ CPConfiguratorResultSubmissionButtonHUQMostPopular" tabindex=0><div class=diagsVRepairsCTAElipse><div class=diagsVRepairsCTADivArrow></div></div><span class=CPConfiguratorResultSubmissionButtonHUQText></span></div></div></div></div></div></div></div><div class="SPOSQuizDivider"></div></div>` 1074 var quizResetButton = '<div class="CPConfiguratorResetButton CPConfiguratorTopButton" style="display: none; margin: 5px;"><img class="CPConfiguratorTopButtonResetImg" src="https://hp.widen.net/content/7iclbe1bz2/png/CPC_Reset.png" alt=""></div>' 1075 if (pgName == "warrantyresult_falcon") { 1076 1077 waitForElement("#mastiff-check-warranty-primary-offer").then(() => { 1078 $("#mastiff-check-warranty-primary-offer").html(quizSpinnerHtml); 1079 $("#mastiff-check-warranty-primary-offer").append(quizHtml); 1080 $(".quizPortalDiv").hide(); 1081 }); 1082 prepareInitialUi(); 1083 handleQuizApiResponse(reqObj); 1084 } else if (pgName == "dashboard") { 1085 logInfo("[Dashboard Quiz] Starting the Quiz Portal request for the dashboard."); 1086 waitForElement("#mastiff-modal-cpc-content").then(() => { 1087 $("#mastiff-modal-cpc-content").html(quizSpinnerHtml); 1088 $("#mastiff-modal-cpc-content").append(quizHtml); 1089 $("#mastiff-modal-cpc-content .CPConfiguratorHeader").hide(); 1090 $(".quizPortalDiv").hide(); 1091 }); 1092 prepareInitialUi(); 1093 // insert reset button afetr .mastiff-modal-cpc-title 1094 waitForElement(".mastiff-modal-cpc-title").then(() => { 1095 $(".mastiff-modal-cpc-title").after(quizResetButton); 1096 }); 1097 handleQuizApiResponse(reqObj); 1098 } else if (pgName == 'drivers_details') { 1099 1100 // Retrieval order for platform value: 1101 // 1. globalDataLayer.versionchange 1102 // 2. globalDataLayer.OSversionName 1103 // 3. sniffedOsData.versionName (from localStorage) 1104 // 4. os-device-name element text content with spaces replaced by underscores 1105 // 5. `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}` 1106 // 6. '' as fallback 1107 1108 const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {}; 1109 var driverDetailsSelectedOSVersion = ""; 1110 1111 // Try globalDataLayer properties first 1112 if (isDefined(g.versionchange)) { 1113 driverDetailsSelectedOSVersion = g.versionchange; 1114 logInfo("Version change detected - using versionchange", driverDetailsSelectedOSVersion); 1115 } else if (isDefined(g.OSversionName)) { 1116 driverDetailsSelectedOSVersion = g.OSversionName; 1117 logInfo("Version change detected - using OSversionName", driverDetailsSelectedOSVersion); 1118 } else { 1119 // Try localStorage.sniffedOsData 1120 try { 1121 var sniffedOsData = JSON.parse(localStorage.getItem("sniffedOsData")); 1122 if (isDefined(sniffedOsData) && isDefined(sniffedOsData.versionName)) { 1123 driverDetailsSelectedOSVersion = sniffedOsData.versionName; 1124 logInfo("Using sniffedOsData.versionName", driverDetailsSelectedOSVersion); 1125 } 1126 } catch (e) { 1127 logInfo("Error parsing sniffedOsData from localStorage", e); 1128 } 1129 1130 // Try os-device-name element 1131 if (!isDefined(driverDetailsSelectedOSVersion)) { 1132 var osDeviceNameElement = document.querySelector(".os-device-name"); 1133 if (osDeviceNameElement) { 1134 driverDetailsSelectedOSVersion = osDeviceNameElement.textContent.trim().replace(/ /g, "_"); 1135 logInfo("Using os-device-name element", driverDetailsSelectedOSVersion); 1136 } 1137 } 1138 1139 // Try deviceInfo as final fallback 1140 if (!isDefined(driverDetailsSelectedOSVersion)) { 1141 driverDetailsSelectedOSVersion = `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}`; 1142 logInfo("Using deviceInfo fallback", driverDetailsSelectedOSVersion); 1143 } 1144 } 1145 1146 reqObj.product.platform = driverDetailsSelectedOSVersion || ''; 1147 } else if (pgName == 'pdp_falcon') { 1148 if (reqObj.user.intent === "product-specs") { 1149 await safeExecute(() => sendPdpAccessoriesRequest(reqObj)); 1150 } 1151 } 1152} 1153 1154async function sendPdpAccessoriesRequest(reqObj) { 1155 // this function will send an ajax api call same way we do for the main mastiff api call, 1156 //but this will be for the accessories api call. 1157 //The response will be processed in the processOffers function 1158 //same request id ands session id will be used for this api call as well. 1159 // same processoffer call on success 1160 1161 if (accessoriesOfferResults) { 1162 await showAccListOffers(accessoriesOfferResults); 1163 return Promise.resolve(); 1164 } 1165 1166 var accessoriesReqObj = JSON.parse(JSON.stringify(reqObj)); 1167 accessoriesReqObj.user.pageId = "PDP_ACCESSORY"; 1168 accessoriesReqObj.offerName = ''; 1169 accessoriesReqObj.acceptanceLevel = ''; 1170 1171 logInfo("PDP Accessories Request Object", accessoriesReqObj); 1172 1173 return new Promise((resolve, reject) => { 1174 $.ajax({
1175 url: getMastiffUrl(), 1176 method: "POST", 1177 async: true, 1178 data: encodeURIComponent(JSON.stringify(accessoriesReqObj)), 1179 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 1180 dataType: "json", 1181 timeout: 7000 1182 }) 1183 .done(async function (result) { 1184 logInfo("PDP Accessories Offer API call successful", result); 1185 accessoriesOfferResults = result; 1186 try { 1187 await showAccListOffers(accessoriesOfferResults); 1188 } catch (e) { 1189 logInfo("processOffers failed for accessories request", e); 1190 reject(e); 1191 return; 1192 } 1193 resolve(); 1194 }) 1195 .fail(function (xhr, textStatus, errorThrown) { 1196 logInfo("PDP Accessories AJAX fail:", xhr && xhr.status, textStatus, errorThrown); 1197 resolve(); 1198 }); 1199 }); 1200} 1201 1202function hideAllPlaceholders(checkIfEmpty = true) { 1203 if (pgName == "pdp_falcon") { 1204 //hideContainer("#mastiff_promotions_and_deals_PDP", "hide", checkIfEmpty); 1205 //hideContainer("#mastiff_view_in_store_PDP", "hide", checkIfEmpty); 1206 } 1207 1208 if (pgName == "document" && !checkIfEmpty) { 1209 1210 } 1211 1212 if (pgName === "service") { 1213 hideContainer("#sdp-mastiff-banner-container", "hide", checkIfEmpty); 1214 } 1215 1216 if (pgName === "contact") { 1217 Object.values(contactPageConfigs).forEach(cfg => { 1218 if (cfg.containerDivId) { 1219 waitForElement(`#${cfg.containerDivId}`, `.${cfg.parentClass}`) 1220 .then(() => { 1221 hideContainer(`#${cfg.containerDivId}`, "hide", checkIfEmpty); 1222 }) 1223 .catch(() => { logInfo(`Element #${cfg.containerDivId} not found`); }); 1224 } 1225 }); 1226 } 1227 1228 if (pgName === "help-computer" || pgName === "help-printer") { 1229 hideContainer("#mastiff-diag-banner", "hidden", checkIfEmpty); 1230 hideContainer("#diag-mastiff-banner-container", "hide", checkIfEmpty); 1231 // New Shop1 placeholder for help-computer page 1232 hideContainer("#mastiff-partstore", "hidden", checkIfEmpty); 1233 } 1234 1235 if (pgName === "repair" || pgName === "hardware-diagnostics") { 1236 waitForElement("#mastiff-sticky-banner").then(() => { 1237 hideContainer("#mastiff-sticky-banner", "hide", checkIfEmpty); 1238 }) 1239 } 1240 1241 if (pgName === "help-windows") { 1242 hideContainer("#mastiff-sticky-banner", "hide", checkIfEmpty); 1243 } 1244 1245 if (pgName.indexOf("home") > -1 && (isContainerEmpty(".mastiff_template_container") || !checkIfEmpty)) { 1246 window.isMastiffChecked = true; 1247 window.isMastiffRemoved = true; 1248 } 1249 1250 if (pgName === "dashboard") { 1251 hideContainer("#compatibleCartridgesTile", "hidden", checkIfEmpty); 1252 hideContainer("#dashboard_tile_instantink_print", "hide", checkIfEmpty); 1253 hideContainer("#dy-mastiff-warranty", "hidden", checkIfEmpty); 1254 hideContainer("#dashboard_tile_mastiff_template", "removeparent", checkIfEmpty); 1255 } 1256 1257 if (pgName === "warrantyresult_falcon") { 1258 if (!checkIfEmpty) removeQuizSpinner(); 1259 waitForElement("#mastiff-dy-compatible-oow-section").then(() => { 1260 if (isContainerEmpty('#mastiff-check-warranty-primary-offer')) { 1261 if (!checkIfEmpty) $("#mastiff-dy-compatible-oow-section").addClass("hidden"); 1262 } 1263 }) 1264 } 1265} 1266 1267function harvestData() { 1268 const mastiffIntegrated = pageSupported(pgName); 1269 if (!mastiffIntegrated) return; 1270 1271 try { 1272 reqObj = buildRequestPayload(); 1273 } catch (e) { 1274 logInfo("buildRequestPayload failed", e); 1275 hideAllPlaceholders(false); 1276 return; 1277 } 1278 1279 logInfo("Request Object", reqObj); 1280 1281 if (globalDataLayer.SPOSOffers == null) { 1282 globalDataLayer.SPOSOffers = { 1283 errorCode: "", 1284 requestId: reqObj.requestId, 1285 sessionId: reqObj.user.sessionId 1286 }; 1287 } else { 1288 globalDataLayer.SPOSOffers.requestId = reqObj.requestId; 1289 globalDataLayer.SPOSOffers.sessionId = reqObj.user.sessionId; 1290 } 1291 1292 beforeHarvestAjaxCall(); 1293 1294 // Wrapped in a promise (resolved via .always) so callers can await the full 1295 // request lifecycle instead of just the synchronous ajax kickoff. 1296 return new Promise((resolve) => { 1297 $.ajax({
1298 url: getMastiffUrl(), 1299 method: "POST", 1300 async: true, 1301 data: encodeURIComponent(JSON.stringify(reqObj)), 1302 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 1303 dataType: "json", 1304 timeout: 7000 1305 }) 1306 .done(function (result) { 1307 logInfo("SPOS Offer API call successful", result); 1308 offerResults = result; 1309 try { 1310 processOffers(offerResults, pgName); 1311 } catch (e) { 1312 logInfo("processOffers failed", e); 1313 hideAllPlaceholders(false); 1314 } finally { 1315 // remove placeholders on success only if containers are empty 1316 //hideAllPlaceholders(true); 1317 } 1318 }) 1319 .fail(function (xhr, textStatus, errorThrown) { 1320 logInfo("AJAX fail:", xhr && xhr.status, textStatus, errorThrown); 1321 if (isDefined(globalDataLayer.SPOSOffers)) { 1322 if (xhr && xhr.responseJSON) { 1323 logInfo(xhr.responseJSON.errorCode + "-" + xhr.responseJSON.errorMessage); 1324 globalDataLayer.SPOSOffers.errorCode = xhr.responseJSON.errorCode; 1325 } else if (textStatus === "timeout") { 1326 globalDataLayer.SPOSOffers.errorCode = "timeout"; 1327 } else if (xhr && xhr.status === 0) { 1328 globalDataLayer.SPOSOffers.errorCode = "500"; 1329 } else { 1330 globalDataLayer.SPOSOffers.errorCode = xhr ? xhr.status : "unknown"; 1331 } 1332 } 1333 1334 // remove placeholders on error path 1335 hideAllPlaceholders(false); 1336 }) 1337 .always(resolve); 1338 }); 1339} 1340 1341async function processOffers(offerResults, pgName) { 1342 if (!offerResults || offerResults.offerCount <= 0) { 1343 if (isDefined(globalDataLayer.SPOSOffers)) { 1344 globalDataLayer.SPOSOffers.errorCode = "No Offers Available for this Profile/Device"; 1345 } 1346 hideAllPlaceholders(false); 1347 return; 1348 } 1349 1350 const offers = offerResults.offers && Array.isArray(offerResults.offers.offer) 1351 ? offerResults.offers.offer 1352 : []; 1353 1354 // Start network checks in parallel without blocking offer rendering. 1355 prepareOfferImages(offers); 1356 1357 var enablePromoTab = false; 1358 var showWtyOffers = false; 1359 var quizInitiatorElement = null; 1360 var quizDiscardElement = null; 1361 var owDiagContainerOfferElement = null; 1362 // Track whether contact-solution offer already rendered (only 1 allowed) 1363 var contactSolutionRendered = false; 1364 1365 const isShop = (pos) => pos === "shop1" || pos === "shop2" || pos === "shop3"; 1366 const lc = (s) => (typeof s === "string" ? s.toLowerCase() : ""); 1367 const isWarrantyOwXOffer = (offer) => lc(offer?.category).startsWith("owx"); 1368 const owxOffers = pgName === "warrantyresult_falcon" 1369 ? (offerResults.offers.offer || []).filter(isWarrantyOwXOffer) 1370 : []; 1371 1372 //pre process logic for specific pages 1373 // it should be here as might process offers without going through harvestData 1374 if (pgName === "pdp_falcon") { 1375 const { segments: seg } = normalizeUrl(); 1376 intentBasedLocationEmpty = true; 1377 if (isDefined(seg[5])) { 1378 reqObj.user.intent = segments[5]; 1379 } 1380 } 1381 1382 1383 // main processing logic 1384 for (var i = 0; i < offerResults.offerCount; i++) { 1385 const element = offers[i]; 1386 const pos = element.templatePosition; 1387 1388 switch (pgName) { 1389 case "home": 1390 case "home_printer": 1391 case "home_computer": 1392 if (pos === "primary") { 1393 showCarouselBanner(element); 1394 } 1395 break; 1396 1397 case "drivers_details": 1398 if (lc(element.category).startsWith("details")) { 1399 showSwdViewInStoreOffer(element); 1400 } else if (pos === "shop1") { 1401 showStickyBannerSecondaryOffer(element, "mastiff-sticky-banner-swd", "mastiff-sticky-banner-swd"); 1402 } else { 1403 showDriverDetailsOffer(element); 1404 } 1405 break; 1406 1407 case "drivers_closure": 1408 if (pos === "primary") showDriverClosurePrimaryOffer(element); 1409 break; 1410 //check later 1411 case "service": 1412 showStickyBannerSecondaryOffer(element, "sdp-mastiff
1412-banner-container", "mastiff_SDP_sticky_banner"); 1413 break; 1414 1415 case "repair": 1416 case "hardware-diagnostics": 1417 if (lc(pos) === "primary") { 1418 showHelpPageOffer(element); 1419 } 1420 1421 if (lc(pos) === "1r4ccontainer") { 1422 const rendered = await standardRenderOffer( 1423 pgName, 1424 lc(pos), 1425 element, 1426 null, 1427 false, 1428 false 1429 ); 1430 1431 if (rendered) { 1432 if (isDefined(element.offerTitle)) { 1433 $("#mastiff-offer-tab .msSubTitle, #mastiff-offer-tabMobile .msSubTitle") 1434 .text(element.offerTitle); 1435 } 1436 1437 addUrlAndClickEvent("mastiff-offer-tab", element, false); 1438 addUrlAndClickEvent("mastiff-offer-tabMobile", element, false); 1439 } 1440 } 1441 1442 if (lc(pos) === "secondary") 1443 showStickyBannerSecondaryOffer(element, "mastiff-sticky-banner", "mastiff-sticky-banner"); 1444 break; 1445 1446 case "help-computer": 1447 if (pos === "shop1") { 1448 // New Shop1 rendering uses the generic standardRenderOffer logic & PAGE_OFFER_MAP config 1449 standardRenderOffer(pgName, "shop1", element); 1450 } 1451 case "help-printer": 1452 if (pos === "primary") { 1453 showHelpPrimaryOffer(element); 1454 } else if (pos === "secondary") { 1455 //check later 1456 showStickyBannerSecondaryOffer(element, "diag-mastiff-banner-container", "mastiff_diag_sticky_banner"); 1457 } 1458 break; 1459 1460 case "help-windows": 1461 if (pos === "secondary") { 1462 showStickyBannerSecondaryOffer(element, "mastiff-sticky-banner", "mastiff-sticky-banner"); 1463 } 1464 case "document": 1465 if (pos === "primary") showDocumentOffer(element); 1466 if (pos === "secondary") 1467 showStickyBannerSecondaryOffer(element, "document-mastiff-banner-container", "mastiff-smartfriend"); 1468 break; 1469 1470 case "contact": 1471 waitForElementToDisappear(".select-country-modal", handleContactPageOffers, element); 1472 break; 1473 1474 case "contact-solution": 1475 // Render only the first valid primary offer 1476 if (!contactSolutionRendered && pos === "primary") { 1477 contactSolutionRendered = renderContactSolutionOffer(element); 1478 } 1479 break; 1480 1481 case "contact_closure": 1482 if (pos === "primary") showCarouselBanner(element); 1483 if (pos === "secondary") showContactSummaryOffer(element); 1484 break; 1485 1486 case "contact-landing": 1487 if (lc(pos) === "1r3ccontainer") { 1488 const rendered = await standardRenderOffer( 1489 pgName, 1490 lc(pos), 1491 element, 1492 null, 1493 false, 1494 false 1495 ); 1496 1497 if (rendered) { 1498 if (isDefined(element.offerTitle)) $("#mastiff-quicklink-title").text(element.offerTitle); 1499 addUrlAndClickEvent("mastiff-quicklink-tile", element, false); 1500 } 1501 } 1502 break; 1503 1504 case "warrantyresult_falcon": 1505 if (isWarrantyOwXOffer(element)) { 1506 continue; 1507 } 1508 if (lc(element.name).includes("quizinitiator")) { quizInitiatorElement = element; continue; } 1509 if (lc(element.name).includes("quizdiscard")) { quizDiscardElement = element; continue; } 1510 1511 //render container offers based on offer category 1512 if (lc(element.category).startsWith("container ow experiment")) { 1513 insertWarrantyOWContainerOffer(element); 1514 continue; 1515 } 1516 1517 if (lc(element.category).startsWith("container regular")) { 1518 insertWarrantyRegularContainerOffer(element); 1519 continue; 1520 } 1521 1522 if (lc(element.category).startsWith("ow experiment")) { 1523 element.OWTileOffer = true; 1524 } 1525 1526 1527 waitForQuizReady().then(() => { 1528 if (quizReadyState.value === true || quizReadyState.value === false) { 1529 if (pos === "primary" && (!element.OWTileOffer)) showWtyPrimaryOffer(element); 1530 if (isShop(pos) && (!element.OWTileOffer)) showWtyOffers = true; 1531 } 1532 }); 1533 1534 if (pos === "secondary" && (!element.OWTileOffer)) showWtySecondaryOffer(element); 1535 1536 break; 1537 1538 case "pdp_falcon": { 1539 // Skip accList offers - handled in post-processing via showAccListOffers 1540 if (safeLower(element.name).includes("swcomp") || safeLower(element.name).includes("acclist") || safeLower(element.name).includes("accessorieslist")) break; 1541 const cat = lc(element.category); 1542 if (!isDefined(element.category)) { 1543 enablePromoTab = true; 1544 } else { 1545 if (cat.startsWith("details")) { 1546 showViewInStoreOffer(element); 1547 } else if (cat.startsWith("warranty widget")) { 1548 standardRenderOffer(pgName, pos, element); 1549 } else if (intentPDPCategories.some(category => cat.startsWith(category))) { 1550 if (cat.includes(reqObj.user.intent)) { 1551 handlePDPintentOffer(element); 1552 } 1553 } else { 1554 element.category = null; 1555 enablePromoTab = true; 1556 } 1557 } 1558 break; 1559 } 1560 1561 case "printer-setup": 1562 printerSetupOffers(); 1563 i = offerResults.offerCount; 1564 break; 1565 1566 case "dashboard": 1567 if (element.templatePosition == "primary" && element.category.toLowerCase().startsWith("dashboard t
1567ile")) { 1568 element.ibOffer = true; 1569 showSingleDashboardTileOffer(element); 1570 } else if (isDefined(element.category) && element.category.toLowerCase().startsWith("warranty dashboard")) { 1571 element.ibOffer = true; 1572 } else if (isDefined(element.category) && element.category.toLowerCase().startsWith("cartridges tile")) { 1573 element.ibOffer = true; 1574 showCartidgesDashboardOffer(element); 1575 } 1576 break; 1577 1578 default: 1579 break; 1580 } 1581 } 1582 1583 //post process logic for specific pages 1584 1585 if (pgName === "dashboard") { 1586 await showDashboardTile(); 1587 1588 waitForQuizReady().then(() => { 1589 var warrantyOffer = offerResults.offers.offer.find(o => 1590 isDefined(o.category) 1591 && safeLower(o.category).startsWith("warranty dashboard") 1592 && safeLower(o.name) !== "cp_quizinitiator" 1593 ); 1594 var quizInit = offerResults.offers.offer.find(element => safeLower(element.name) === "cp_quizinitiator"); 1595 1596 logInfo("[Dashboard Quiz] render decision", { 1597 quizPortalReady: quizReadyState.value, 1598 quizInitiatorAvailable: Boolean(quizInit), 1599 quizInitiatorName: quizInit?.name || "none", 1600 warrantyFallbackAvailable: Boolean(warrantyOffer), 1601 warrantyFallbackName: warrantyOffer?.name || "none" 1602 }); 1603 1604 if (quizReadyState.value === true) { 1605 if (quizInit) { 1606 logInfo("[Dashboard Quiz] Quiz Portal is valid; rendering the quiz initiator.", quizInit.name); 1607 $("#dy-mastiff-warranty").html(""); 1608 showWarrantyDashboardOffer(quizInit, false) 1609 .then(divId => { 1610 if (divId) bindDashboardQuizInitiator(quizInit); 1611 }); 1612 } else if (warrantyOffer) { 1613 logInfo("[Dashboard Quiz] Quiz Portal is valid, but no initiator was returned; rendering the regular warranty fallback.", warrantyOffer.name); 1614 $("#dy-mastiff-warranty").html(""); 1615 showWarrantyDashboardOffer(warrantyOffer, true); 1616 } else { 1617 logInfo("[Dashboard Quiz] Quiz Portal is valid, but neither a quiz initiator nor a regular warranty fallback was returned; leaving the placement unchanged."); 1618 } 1619 } else if (quizReadyState.value === false) { 1620 if (warrantyOffer) { 1621 logInfo("[Dashboard Quiz] Quiz Portal failed, was invali
1621d, or timed out; rendering the regular warranty fallback.", warrantyOffer.name); 1622 $("#dy-mastiff-warranty").html(""); 1623 showWarrantyDashboardOffer(warrantyOffer, true); 1624 } else { 1625 logInfo("[Dashboard Quiz] Quiz Portal failed, was invalid, or timed out, and no regular warranty fallback was returned; leaving the placement unchanged."); 1626 } 1627 } else { 1628 logInfo("[Dashboard Quiz] Quiz Portal readiness is unresolved; no warranty placement will be rendered yet."); 1629 } 1630 }); 1631 } 1632 1633 if (pgName === "help-computer" || pgName === "help-printer") { 1634 1635 var owDiagContainerOffers = offerResults.offers.offer.filter( 1636 offer => 1637 isDefined(offer.category) 1638 && lc(offer.category).startsWith("ow diagnostics - container") 1639 ); 1640 1641 var owDiagoffers = offerResults.offers.offer.filter(function (o) { 1642 return (safeLower(o.templatePosition).startsWith("owdiags")) 1643 && !safeLower(o.templatePosition).includes("container"); 1644 }); 1645 1646 // Sort by numeric suffix after "_"; unnumbered go to the end 1647 var getPos = function (tp) { 1648 var match = (tp || "").match(/_(\d+)/); 1649 return match ? parseInt(match[1], 10) : Infinity; 1650 }; 1651 1652 owDiagoffers.sort(function (a, b) { 1653 return getPos(a.templatePosition) - getPos(b.templatePosition); 1654 }); 1655 1656 if (owDiagContainerOffers.length) { 1657 $(".warranty-container").html(""); 1658 1659 standardRenderOffer(pgName, "owDiagsContainer", owDiagContainerOffers[0]).then(function () { 1660 for (var i = 0; i < owDiagoffers.length; i++) { 1661 standardRenderOffer(pgName, "owDiags", owDiagoffers[i]); 1662 } 1663 }); 1664 } 1665 1666 } 1667 1668 if (pgName === "pdp_falcon") { 1669 if (enablePromoTab && !samePage) showPromoTabOffer(); 1670 } 1671 1672 if (pgName === "warrantyresult_falcon") { 1673 1674 if (owxOffers.length) { 1675 renderWarrantyNestedOwExperiment(owxOffers).then(function (renderResult) { 1676 if (renderResult.oneFullPathrendered) { 1677 //remove hidden .from .mastiff-dy-oow-section 1678 $("#mastiff-dy-oow-section").removeClass("hidden"); 1679 } 1680 }); 1681 } 1682 1683 //renderWarrantyOwTileOffers(); 1684 1685 waitForQuizReady().then(() => { 1686 if (quizReadyState.value === true && quizInitiatorElement) { 1687 $(".WRPrimaryTile").hide(); 1688 showWtyQuizInitiatorOffer(quizInitiatorElement).then(() => { 1689 if (quizDiscardElement) appendQuizDiscardInsideInitiator(quizDiscardElement); 1690 }); 1691 } else if (quizReadyState.value === false) { 1692 $(".WRPrimaryTile").show(); 1693 } 1694 if (showWtyOffers) showWtyShopOffers(); 1695 $(".quizPortalDiv").hide(); 1696 $("#mastiff-check-warranty-secondary-offers").show(); 1697 removeQuizSpinner(); 1698 }); 1699 } 1700 1701 if (pgName === "contact-landing") { 1702 1703 var offerTiles = offerResults.offers.offer.filter(element => 1704 safeLower(element.templatePosition).startsWith("1r3ctile")); 1705 1706 offerTiles.sort(positionSortByUnderscoreOrder); 1707 1708 for (const element of offerTiles) { 1709 await standardRenderOffer(pgName, "1r3cTile", element); 1710 } 1711 1712 if ($("#contactEntryOffersContainer").children().length > 0) { 1713 $("#mastiff-quicklink-tile").removeClass("hidden"); 1714 } 1715 } 1716 1717 if (pgName === "repair" || pgName === "hardware-diagnostics") { 1718 1719 var offerTiles = offerResults.offers.offer.filter(element => 1720 safeLower(element.templatePosition).startsWith("1r4ctile")); 1721 1722 offerTiles.sort(positionSortByUnderscoreOrder); 1723 1724 for (const element of offerTiles) { 1725 await standardRenderOffer(pgName, "1r4cTile", element); 1726 } 1727
1728 if ($("#DiagsRepairsDSPOSOffersContainer").children().length > 0) { 1729 $("#mastiff-offer-tab").parent().removeClass("hidden"); 1730 } 1731 1732 } 1733 1734 hideAllPlaceholders(true); 1735 SaveReqObjToSessionStorage(); 1736} 1737 1738function resetRPMMastiffCall() { 1739 logInfo("Retired Product Modal Closed - Resetting reqObj "); 1740 var reqObjFSS = GetReqObjFromSessionStorage(); 1741 if (reqObjFSS) { 1742 reqObj = reqObjFSS; 1743 pgName = reqObj.user.pageId; 1744 } 1745 if (pgName == 'dashboard') { 1746 sliderClassName = "DashTempshowSlide"; 1747 navBulletAvailable = true; 1748 slide_index = 0; 1749 } 1750 if (!isDefined(offerResults)) { 1751 offerResults = JSON.parse(sessionStorage.getItem("offerResults")) || {}; 1752 } 1753} 1754 1755function initiateRPMMastiffCall() { 1756 navBulletAvailable = false; 1757 1758 const rpmSposTitle = { 1759 "es": "Actualizaciones recomendadas", 1760 "pt": "Atualizações recomendadas", 1761 "fr": "Mises à niveau recommandées", 1762 "nl": "Aanbevolen upgrades", 1763 "bg": "ÐÑепоÑÑÑиÑелни надÑÑÑойки", 1764 "cs": "DoporuÄené upgrady", 1765 "hr": "PreporuÄene nadogradnje", 1766 "da": "Anbefalede opgraderinger", 1767 "de": "Empfohlene Upgrades", 1768 "et": "Soovitatud uuendused", 1769 "el": "Î ÏοÏεινÏÎ¼ÎµÎ½ÎµÏ Î±Î½Î±Î²Î±Î¸Î¼Î¯ÏειÏ", 1770 "he": "ש×ר×××× ××××צ××", 1771 "it": "Aggiornamenti consigliati", 1772 "kk": "Ò°ÑÑнÑлаÑÑн жаңаÑÑÑлаÑ", 1773 "lv": "Ieteicamie jauninÄjumi", 1774 "lt": "Rekomenduojami atnaujinimai", 1775 "hu": "Ajánlott frissÃtések", 1776 "ar": "Ø§ÙØªØ±ÙÙØ§Øª اÙÙ ÙØµÙ Ø¨ÙØ§", 1777 "no": "Anbefalte oppgraderinger", 1778 "pl": "Zalecane ulepszenia", 1779 "ro": "ActualizÄri recomandate", 1780 "sr": "ÐÑепоÑÑÑене надогÑадÑе", 1781 "sk": "OdporúÄané aktualizácie", 1782 "sl": "PriporoÄene nadgradnje", 1783 "fi": "Suositellut päivitykset", 1784 "sv": "Rekommenderade uppgraderingar", 1785 "tr": "Ãnerilen Yükseltmeler", 1786 "uk": "Ð ÐµÐºÐ¾Ð¼ÐµÐ½Ð´Ð¾Ð²Ð°Ð½Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ", 1787 "zh": "æ¨èå级", 1788 "id": "Peningkatan yang Disarankan", 1789 "ja": "æ¨å¥¨ã¢ããã°ã¬ã¼ã", 1790 "ko": "ì¶ì² ì ê·¸ë ì´ë", 1791 "ms": "Naik Taraf yang Disyorkan", 1792 "fil": "Inirerekomendang Mga Pag-upgrade", 1793 "th": "à¸à¸²à¸£à¸à¸±à¸à¹à¸à¸£à¸à¸à¸µà¹à¹à¸à¸°à¸à¸³", 1794 "vi": "Nâng cấp ÄÆ°á»£c Äá» xuất" 1795 }; 1796 1797 logInfo("Initiating Mastiff call for the Retired Product Modal..."); 1798 reqObj = {}; 1799 1800 if (!reqObj.user) { 1801 reqObj.user = {}; 1802 } 1803 if (!reqObj.product) { 1804 reqObj.product = {}; 1805 } 1806 if (!reqObj.product.warranty) { 1807 reqObj.product.warranty = {}; 1808 } 1809 pgName = "retiredproductmodal"; 1810 1811 reqObj.requestId = createReqId(); 1812 reqObj.user.callerId = "supportweb"; 1813 reqObj.user.pageId = pgName; 1814 reqObj.offerLocations = "primary,carousel"; 1815 1816 if (typeof globalDataLayer !== "undefined") { 1817 reqObj.user.sessionId = globalDataLayer.sessionId; 1818 1819 if (reqObj.user.sessionId == null || reqObj.user.sessionId == "") { 1820 if (localStorage == null || typeof (localStorage) == "undefined") { 1821 var mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10); 1822 } else { 1823 var mastiffSessionId = localStorage.getItem('MastiffSessionId'); 1824 if (mastiffSessionId == null || mastiffSessionId == "" || typeof (mastiffSessionId) == "undefined") { 1825 mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10); 1826 localStorage.setItem('MastiffSessionId', mastiffSessionId); 1827 } 1828 } 1829 reqObj.user.sessionId = mastiffSessionId; 1830 } 1831 reqObj.user.locale = globalDataLayer.Locale; 1832 reqObj.user.countryCode = globalDataLayer.CountryCode; 1833 reqObj.user.language = globalDataLayer.LanguageCode; 1834 reqObj.product.modelNumber = globalDataLayer.Product?.productNumber || ""; 1835 reqObj.product.serialNumber = globalDataLayer?.Product?.serialNumber || ""; 1836 reqObj.product.productLine = globalDataLayer.Product?.productLineCode || ""; 1837 reqObj.product.productSeries = globalDataLayer.Product?.seriesName || ""; 1838 reqObj.product.productName = globalDataLayer.Product?.supportNameName || ""; 1839 reqObj.product.productNameOid = globalDataLayer.Product?.supportNameO
1839id || ""; 1840 reqObj.product.productSeriesOid = globalDataLayer.Product?.seriesOid || ""; 1841 reqObj.product.platform = globalDataLayer.Product?.platformId || ""; 1842 reqObj.product.productSupportCategoryName = globalDataLayer.Product?.supportCategoryName || ""; 1843 reqObj.product.bigSeriesOid = globalDataLayer.Product?.bigSeriesOid || ""; 1844 } 1845 1846 if (!globalDataLayer.SPOSOffers) { 1847 globalDataLayer.SPOSOffers = { 1848 errorCode: "", 1849 requestId: reqObj.requestId, 1850 sessionId: reqObj.user.sessionId 1851 }; 1852 } else { 1853 globalDataLayer.SPOSOffers.requestId = reqObj.requestId; 1854 globalDataLayer.SPOSOffers.sessionId = reqObj.user.sessionId; 1855 } 1856 1857 function removeRetiredModalSpinner() { 1858 const spinner = document.querySelector("#retired-product-modal-spinner"); 1859 if (spinner) { 1860 spinner.remove(); 1861 } 1862 1863 const retiredProductModal = document.getElementById("mastiff_retired_product_spos"); 1864 if (retiredProductModal) { 1865 retiredProductModal.innerHTML = ""; 1866 } 1867 } 1868 1869 function renderRPMTitle() { 1870 var rpmTitleHtml = '<span style="font-family: HPSimplifiedRegular;font-size: 24px;font-weight: 400;line-height: 2.08;color: #333;text-align: center;box-sizing: border-box;">Recommended Upgrades</span>' 1871 1872 if (rpmSposTitle[reqObj.user.language] !== undefined) { 1873 rpmTitleHtml = rpmTitleHtml.replace(/Recommended Upgrades/, rpmSposTitle[reqObj.user.language]) 1874 } 1875 1876 const container = document.getElementById("mastiff_retired_product_spos"); 1877 container.insertAdjacentHTML("afterbegin", rpmTitleHtml); 1878 } 1879 1880 function hideRPMPlacement() { 1881 const container = document.getElementById("mastiff_retired_product_spos"); 1882 if (container) { 1883 container.style.display = "none"; 1884 } 1885 } 1886 1887 function renderPrimaryOffer(offerElement) { 1888 if ( 1889 !offerElement.storeURL || offerElement.storeURL === "null" || 1890 !offerElement.primaryButtonText || offerElement.primaryButtonText === "null" || 1891 !offerElement.html || offerElement.html === "null" 1892 ) { 1893 hideRPMPlacement(); 1894 return false; 1895 } 1896 1897 var offerId = ""; 1898 offerId = `${offerElement.templatePosition}_${offerElement.name}`; 1899 var htmlTemplate = offerElement.html || ""; 1900 htmlTemplate = htmlTemplate.replace("{cta}", offerElement.primaryButtonText); 1901 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", offerId); 1902 1903 const container = document.getElementById("mastiff_retired_product_spos"); 1904 if (!container) { 1905 logInfo("No container found for primary retired product modal offer."); 1906 return false; 1907 } 1908 1909 container.insertAdjacentHTML("beforeend", htmlTemplate); 1910 1911 container.setAttribute("aria-label", offerElement.offerType); 1912 container.setAttribute("tabindex", "0"); 1913 1914 if (reqObj.user.language === "ar" || reqObj.user.language === "he") { 1915 container.css("text-align", "right"); 1916 } 1917 1918 addUrlAndClickEvent(`#${offerId}`, offerElement, /* openLinkInNewTab: */ true); 1919 1920 var sposGDLoffers = globalDataLayer.SPOSOffers; 1921 Object.keys(sposGDLoffers).forEach(function (key) { 1922 if (sposGDLoffers[key].OfferID === offerId) { 1923 sposGDLoffers[key].offerShown = "yes"; 1924 sposGDLoffers[key].errorData = ""; 1925 delete sposGDLoffers[key].errorData; 1926 } 1927 } 1928 ); 1929 1930 return true; 1931 } 1932 1933 1934 function renderCarouselOffers(carouselOffers) { 1935 var slide_index = 1; 1936 sliderClassName = "rpmCarouselSlide"; 1937 if (!carouselOffers || !carouselOffers.length) return; 1938 1939 const container = document.getElementById("mastiff_retired_product_spos"); 1940 if (!container) { 1941 logInfo("No container found for retired product modal carousel offers."); 1942 hideRPMPlacement(); 1943 return; 1944 } 1945
1946 var validOffers = carouselOffers.filter(o => 1947 o.html && o.html !== "null" && 1948 o.imageURL && o.imageURL !== "null" && 1949 o.storeURL && o.storeURL !== "null" && 1950 o.primaryButtonText && o.primaryButtonText !== "null" 1951 ); 1952 1953 if (!validOffers.length) { 1954 logInfo("No valid carousel offers for retired product modal."); 1955 hideRPMPlacement(); 1956 return; 1957 } 1958 1959 var carouselHtml = "<div class=\"RPMCarousel\"> <style> .RPMCarousel { border-radius: 16px; background: #FFFFFF; display: flex; flex-direction: column; } .RPMCarousel #navigation { margin-top: 20.75px; display: flex; align-items: center; height: 56px; border-radius: 16px; } .RPMCarousel .elipse { border: 1px solid #000; cursor: pointer; width: 38px; height: 38px; position: relative; } .disabledElipse:focus { box-shadow: none; width: 36px; height: 36px; border: 2px #0278AB; } .RPMCarousel .elipse:hover { background: #EBF9FF; } .RPMCarousel .elipse:active { background: #CAF3FF; } .RPMCarousel .arrow { color: #000; width: 9.5px; height: 9.5px; position: absolute; border-bottom: 1px solid; } .RPMCarousel .left { border-left: 1px solid; transform: scaleY(1.2) rotate(45deg); left: 17px; top: 13px; } #SPOS_navLeft{ margin-right: 20px; } .RPMCarousel .right { border-left: 1px solid; transform: scaleY(1.2) rotate(-135deg); right: 17px; top: 14px; } @media screen and (max-width: 600px) { .RPMCarousel #navigation { margin-top: 28px; } } </style> <div id=navigation> <a tabindex=0 class=elipse id=SPOS_navLeft onclick=\"nextSlide(-1)\"> <div class=\"arrow left\"></div> </a> <a tabindex=0 class=elipse id=SPOS_navRight onclick=\"nextSlide(1)\"> <div class=\"arrow right\"></div> </a> </div> </div>"; 1960 1961 container.insertAdjacentHTML("beforeend", carouselHtml); 1962 1963 if (validOffers.length == 1) { 1964 const navigation = container.querySelector("#navigation"); 1965 if (navigation) { 1966 navigation.style.display = "none"; 1967 } 1968 } 1969 1970 const slidesWrapper = container.querySelector(".RPMCarousel"); 1971 1972 validOffers.forEach((offer, index) => { 1973 var offerId = `${offer.templatePosition}_${offer.name}`; 1974 var slideHtml = offer.html || ""; 1975 1976 slideHtml = slideHtml.replace("{cta}", offer.primaryButtonText); 1977 slideHtml = slideHtml.replace("{rpmOfferTitle}", offer.primaryText1 || ""); 1978 slideHtml = slideHtml.replace("{rpmOfferDesc}", offer.primaryText2 || ""); 1979 slideHtml = slideHtml.replace("{rpmOfferImageUrl}", offer.imageURL || ""); 1980 1981 const slideMarkup = ` 1982 <div class="rpmCarouselSlide" style="display:none" id="${offerId}"> 1983 ${slideHtml} 1984 </div> 1985 `; 1986 1987 slidesWrapper.insertAdjacentHTML("afterbegin", slideMarkup); 1988 1989 allocateRecEngPrices(offer.strikePrice, offer.incartPrice, offerId, offer.currency); 1990 if (offer.name.toLowerCase().indexOf("rec_") > -1) { 1991 $("#" + offerId + " #SmallBannerImgDiv").addClass("SmallBannerImgDivREC"); 1992 } 1993 1994 const slideDiv = document.getElementById(offerId); 1995 slideDiv.setAttribute("aria-label", offer.offerType); 1996 slideDiv.setAttribute("tabindex", "0"); 1997 1998 if (reqObj.user.language === "ar" || reqObj.user.language === "he") { 1999 slideDiv.css("text-align", "right"); 2000 } 2001 2002 const ctaSel = `#${offerId} .SmallBannerCTADiv`; 2003 addUrlAndClickEvent(ctaSel, offer, true); 2004 2005 var sposGDLoffers = globalDataLayer.SPOSOffers; 2006 Object.keys(sposGDLoffers).forEach(function (key) { 2007 if (sposGDLoffers[key].OfferID === offerId) { 2008 sposGDLoffers[key].offerShown = "yes"; 2009 sposGDLoffers[key].errorData = ""; 2010 delete sposGDLoffers[key].errorData; 2011 } 2012 } 2013 ); 2014 }); 2015 2016 displaySlides(slide_index); 2017 } 2018 2019 2020 $.ajax({
2021 url: getMastiffUrl(), 2022 method: "POST", 2023 async: true, 2024 data: encodeURIComponent(JSON.stringify(reqObj)), 2025 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 2026 success: function (result) { 2027 logInfo("Retired Product Modal - Mastiff response:"); 2028 logInfo(result); 2029 2030 removeRetiredModalSpinner(); 2031 2032 if (!result || !result.offerCount || !result.offers?.offer?.length) { 2033 logInfo("No offers returned for retired product modal."); 2034 globalDataLayer.SPOSOffers.errorCode = "No Offers for Retired Product"; 2035 return; 2036 } 2037 2038 const allOffers = result.offers.offer; 2039 var primaryOffers = allOffers.filter(o => o.templatePosition === "primary"); 2040 var carouselOffers = allOffers.filter(o => o.templatePosition === "carousel"); 2041 2042 allOffers.forEach(offer => { 2043 var offerId = `${offer.templatePosition}_${offer.name}`; 2044 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 2045 var LeadOffer = {}; 2046 LeadOffer.OfferID = offerId; 2047 LeadOffer.OfferClicked = "no"; 2048 LeadOffer.offerShown = "no"; 2049 if (offer.templatePosition === "primary") { 2050 LeadOffer.SPOStemplate = "2"; 2051 } else if (offer.templatePosition === "carousel") { 2052 LeadOffer.SPOStemplate = "24"; 2053 } 2054 2055 logToGlobalDataLayer(LeadOffer); 2056 }); 2057 2058 renderRPMTitle(); 2059 2060 var displayedPrimary = false; 2061 for (var i = 0; i < primaryOffers.length; i++) { 2062 const isValid = renderPrimaryOffer(primaryOffers[i]); 2063 if (isValid) { 2064 displayedPrimary = true; 2065 break; 2066 } 2067 } 2068 2069 renderCarouselOffers(carouselOffers); 2070 2071 if ((typeof (globalDataLayer.SPOSOffers) !== "undefined") && (globalDataLayer.SPOSOffers !== null)) { 2072 if (!displayedPrimary && !carouselOffers.length) { 2073 globalDataLayer.SPOSOffers.errorCode = "No valid primary or carousel offers"; 2074 hideRPMPlacement(); 2075 } 2076 } 2077 2078 }, 2079 error: function (XMLHttpRequest, textStatus, errorThrown) { 2080 logInfo("Retired Product Modal - Mastiff call error"); 2081 logInfo(XMLHttpRequest.status); 2082 logInfo(textStatus); 2083 logInfo(errorThrown); 2084 2085 removeRetiredModalSpinner(); 2086 hideRPMPlacement(); 2087 2088 if (globalDataLayer.SPOSOffers) { 2089 if (XMLHttpRequest.responseJSON) { 2090 globalDataLayer.SPOSOffers.errorCode = XMLHttpRequest.responseJSON.errorCode || "MastiffError"; 2091 } else if (textStatus === "timeout") { 2092 globalDataLayer.SPOSOffers.errorCode = "timeout"; 2093 } else if (XMLHttpRequest.status === 0) { 2094 globalDataLayer.SPOSOffers.errorCode = "500"; 2095 } else { 2096 globalDataLayer.SPOSOffers.errorCode = String(XMLHttpRequest.status); 2097 } 2098 } 2099 }, 2100 timeout: 20000 2101 }); 2102} 2103 2104// ---------- core functions ends here ---------------- 2105 2106// ---------- helpers code starts here ---------------- 2107 2108function getPlacementSelectors(page, position) { 2109 const cfg = PAGE_CONFIG[page] || PAGE_CONFIG.default || {}; 2110 const pos = cfg.positions && cfg.positions[position]; 2111 if (!pos) return {}; 2112 const out = {}; 2113 if (pos.placeholderSelector) { 2114 out.placeholder = pos.placeholderSelector; 2115 } 2116 if (pos.containerSelector) { 2117 out.container = pos.containerSelector; 2118 } 2119 return out; 2120} 2121 2122function hidePlacement(page, position) { 2123 const selObj = getPlacementSelectors(page, position); 2124 if (selObj.placeholder) { 2125 hideContainer(selObj.placeholder, "default", false); 2126 } 2127 if (selObj.container) { 2128 hideContainer(selObj.container, "default", false); 2129 } 2130} 2131 2132function safeExecute(fn) { 2133 try { 2134 const result = fn(); 2135 if (result && typeof result.catch === "function") { 2136 return result.catch((err) => { 2137 logInfo(err); 2138 }); 2139 } 2140 return result; 2141 } catch (err) { 2142 logInfo(err); 2143 } 2144} 2145 2146function normalizeUrl() { 2147 const href = String(window.location || ""); 2148 const base = href.split("#")[0].split("?")[0]; 2149 const segments = base.split("/"); 2150 const query = href.includes("?") ? href.split("?")[1].split("#")[0] : ""; 2151 const queryParams = {}; 2152 if (query) { 2153 query.split("&").forEach(kv => { 2154 const [k, v] = kv.split("="); 2155 if (k) queryParams[k.toLowerCase()] = decodeURIComponent(v || ""); 2156 }); 2157 } 2158 window.segments = segments; 2159 return { href, base, segments, queryParams }; 2160} 2161 2162function strOrEmpty(v) { return (v == null || v === "null") ? "" : String(v); } 2163function safeLower(v) { return (typeof v === "string") ? v.toLowerCase() : ""; } 2164 2165// For Level > 1, prefer order from templatePosition suffix "_n". 2166// Example: "level2tile_3" => 3, and values without "_n" render first. 2167function parsePositionUnderscoreOrder(templatePosition) { 2168 const pos = String(templatePosition || ""); 2169 const match = pos.match(/_(\d+)(?!.*_\d+)/); 2170 return match ? Number(match[1]) : null; 2171}; 2172 2173function positionSortByUnderscoreOrder(a, b) { 2174 const aOrder = parsePositionUnderscoreOrder(a.templatePosition); 2175 const bOrder = parsePositionUnderscoreOrder(b.templatePosition); 2176 2177 if (aOrder === null && bOrder === null) return positionSort(a, b); 2178 if (aOrder === null) return -1; 2179 if (bOrder === null) return 1; 2180 if (aOrder !== bOrder) return aOrder - bOrder; 2181 return positionSort(a, b); 2182};
2183 2184function positionSort(a, b) { 2185 const aNum = parseNumber(a.templatePosition); 2186 const bNum = parseNumber(b.templatePosition); 2187 if (aNum === null && bNum === null) return 0; 2188 if (aNum === null) return -1; 2189 if (bNum === null) return 1; 2190 return aNum - bNum; 2191}; 2192 2193function parseNumber(value, fallback = null) { 2194 const match = value && String(value).match(/(\d+)/); 2195 return match ? Number(match[1]) : fallback; 2196}; 2197 2198function isDefined(variableName) { 2199 return variableName !== undefined && variableName !== null && variableName !== '' && variableName !== 'null'; 2200} 2201 2202var MASTIFF_IMAGE_FILLER_URL = "https://hp.widen.net/content/1dw15f0pxv/svg/Mastiff_Filler_Image.svg"; 2203var MASTIFF_MERCH_IMAGE_FILLER_URL = "https://hp.widen.net/content/bataicjkf0/svg/-PDP-SuppliesList-FillerImg.svg"; 2204//var MASTIFF_INK_PAPER_IMAGE_FILLER_URL = MASTIFF_IMAGE_FILLER_URL; 2205var MASTIFF_IMAGE_VALIDATION_TIMEOUT_MS = 1000; 2206var MASTIFF_IMAGE_VALIDATION_CACHE = Object.create(null); 2207 2208function prepareOfferImages(offers) { 2209 offers.forEach(function (offer) { 2210 if (!offer) return; 2211 2212 var failureLogState = Object.create(null); 2213 prepareOfferImageValue(offer, "imageURL", offer.imageURL, failureLogState); 2214 }); 2215} 2216 2217function prepareOfferImageValue(offer, fieldName, originalImageUrl, failureLogState) { 2218 var validation = validateOfferImageUrl(originalImageUrl, function (result) { 2219 applyOfferImageValidationResult(offer, fieldName, originalImageUrl, result, failureLogState); 2220 }); 2221 2222 if (validation.status !== "pending") { 2223 applyOfferImageValidationResult(offer, fieldName, originalImageUrl, validation, failureLogState); 2224 } else if (fieldName !== "html" && typeof originalImageUrl === "string") { 2225 // Keep the original URL for immediate rendering. The async error callback 2226 // replaces rendered instances if the browser later rejects the image. 2227 offer[fieldName] = originalImageUrl.trim(); 2228 } 2229} 2230 2231function applyOfferImageValidationResult(offer, fieldName, originalImageUrl, result, failureLogState) { 2232 if (result.status === "valid") { 2233 if (fieldName !== "html") offer[fieldName] = result.url; 2234 return; 2235 } 2236 2237 if (fieldName !== "html") offer[fieldName] = MASTIFF_IMAGE_FILLER_URL; 2238 offer.html = replaceOfferImageUrlInHtml(offer.html, originalImageUrl); 2239 2240 // This is needed for asynchronous failures because the offer may already be rendered. 2241 replaceRenderedImagesWithFiller(originalImageUrl, MASTIFF_IMAGE_FILLER_URL); 2242 logOfferImageFailure(offer, originalImageUrl, result.reason, failureLogState); 2243} 2244 2245function logOfferImageFailure(offer, imageReference, reason, failureLogState) { 2246 var logKey = String(imageReference || "missing") + "|" + reason; 2247 if (failureLogState[logKey]) return; 2248 failureLogState[logKey] = true; 2249 2250 logInfo( 2251 `[Image Validation] Failed image for offer "${offer.name || "unknown"}" ` + 2252 `(${offer.templatePosition || "unknown"}): ${reason}. ` + 2253 "Replaced the image reference with the filler image." 2254 ); 2255 2256 if (typeof globalDataLayer !== "undefined" && globalDataLayer.SPOSOffers) { 2257 globalDataLayer.SPOSOffers.imageValidationFailures = 2258 (Number(globalDataLayer.SPOSOffers.imageValidationFailures) || 0) + 1; 2259 } 2260} 2261 2262function inspectOfferImageUrl(imageUrl) { 2263 if (!isDefined(imageUrl) || typeof imageUrl !== "string" || imageUrl.trim() === "") { 2264 return { reason: "image URL is missing or null" }; 2265 } 2266 2267 var normalizedUrl = imageUrl.trim(); 2268 if (normalizedUrl.toLowerCase() === "null") { 2269 return { reason: "image URL is missing or null" }; 2270 } 2271 2272 var parsedUrl; 2273 try { 2274 parsedUrl = new URL(normalizedUrl); 2275 } catch (error) { 2276 return { reason: "image URL is malformed" }; 2277 } 2278 2279 if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") { 2280 return { reason: "image URL uses an unsupported protocol" }; 2281 } 2282 2283 return { normalizedUrl: normalizedUrl }; 2284} 2285 2286function validateOfferImageUrl(imageUrl, onComplete) { 2287 var inspectedUrl = inspectOfferImageUrl(imageUrl); 2288 if (inspectedUrl.reason) { 2289 return { status: "failed", reason: inspectedUrl.reason, url: MASTIFF_IMAGE_FILLER_URL }; 2290 } 2291 2292 var cacheKey = inspectedUrl.normalizedUrl; 2293 var cachedResult = MASTIFF_IMAGE_VALIDATION_CACHE[cacheKey]; 2294 if (cachedResult) { 2295 if (cachedResult.status === "pending") cachedResult.callbacks.push(onComplete); 2296 return cachedResult; 2297 } 2298 2299 var pendingResult = { status: "pending", url: inspectedUrl.normalizedUrl, callbacks: [onComplete] }; 2300 MASTIFF_IMAGE_VALIDATION_CACHE[cacheKey] = pendingResult; 2301 2302 var testImage; 2303 var settled = false; 2304 // Keep the check non-blocking. This is only a warning threshold; a slow 2305 // valid image must still be allowed to finish and reach onload/onerror. 2306 var timeoutId = window.setTimeout(function () { 2307 if (!settled) { 2308 logInfo("[Image Validation] Image check still pending after " + MASTIFF_IMAGE_VALIDATION_TIMEOUT_MS + "ms"); 2309 } 2310 }, MASTIFF_IMAGE_VALIDATION_TIMEOUT_MS); 2311 2312 function finish(result) { 2313 if (settled) return; 2314 settled = true; 2315 window.clearTimeout(timeoutId); 2316 if (testImage) { 2317 testImage.onload = null; 2318 testImage.onerror = null; 2319 } 2320 2321 var callbacks = pendingResult.callbacks.slice(); 2322 pendingResult.status = result.status; 2323 pendingResult.reason = result.reason; 2324 pendingResult.url = result.url;
2325 delete pendingResult.callbacks; 2326 callbacks.forEach(function (callback) { 2327 if (typeof callback === "function") callback(result); 2328 }); 2329 } 2330 2331 try { 2332 testImage = new Image(); 2333 testImage.onload = function () { 2334 finish({ status: "valid", url: inspectedUrl.normalizedUrl }); 2335 }; 2336 testImage.onerror = function () { 2337 finish({ 2338 status: "failed", 2339 reason: "image failed to load or is not a valid image", 2340 url: MASTIFF_IMAGE_FILLER_URL 2341 }); 2342 }; 2343 testImage.src = inspectedUrl.normalizedUrl; 2344 } catch (error) { 2345 finish({ 2346 status: "failed", 2347 reason: "browser could not start image validation", 2348 url: MASTIFF_IMAGE_FILLER_URL 2349 }); 2350 } 2351 2352 return pendingResult; 2353} 2354 2355function replaceOfferImageUrlInHtml(html, imageUrl) { 2356 if (typeof html !== "string") return html; 2357 2358 var brokenImageUrl = typeof imageUrl === "string" ? imageUrl.trim() : ""; 2359 var replaceNullOrEmpty = !brokenImageUrl || brokenImageUrl.toLowerCase() === "null"; 2360 2361 function replaceAttributeValue(value) { 2362 if (replaceNullOrEmpty && (value.trim() === "" || value.trim().toLowerCase() === "null")) { 2363 return MASTIFF_IMAGE_FILLER_URL; 2364 } 2365 if (brokenImageUrl && value.indexOf(brokenImageUrl) !== -1) { 2366 return value.split(brokenImageUrl).join(MASTIFF_IMAGE_FILLER_URL); 2367 } 2368 return value; 2369 } 2370 2371 html = replaceHtmlAttributeValue(html, "src", replaceAttributeValue); 2372 html = replaceHtmlAttributeValue(html, "srcset", replaceAttributeValue); 2373 html = replaceHtmlAttributeValue(html, "style", function (value) { 2374 if (!brokenImageUrl) return value; 2375 return value.split(brokenImageUrl).join(MASTIFF_IMAGE_FILLER_URL); 2376 }); 2377 2378 if (brokenImageUrl) { 2379 var escapedImageUrl = brokenImageUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); 2380 html = html.replace(new RegExp("url\\(\\s*([\\\"']?)" + escapedImageUrl + "\\1\\s*\\)", "gi"), "url(" + MASTIFF_IMAGE_FILLER_URL + ")"); 2381 } 2382 2383 return html; 2384} 2385 2386function replaceHtmlAttributeValue(html, attributeName, replaceValue) { 2387 var attributePattern = new RegExp("(\\b" + attributeName + "\\s*=\\s*)(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))", "gi"); 2388 return html.replace(attributePattern, function (match, prefix, doubleQuotedValue, singleQuotedValue, unquotedValue) { 2389 var originalValue = doubleQuotedValue !== undefined 2390 ? doubleQuotedValue 2391 : (singleQuotedValue !== undefined ? singleQuotedValue : unquotedValue); 2392 var replacedValue = replaceValue(originalValue); 2393 if (replacedValue === originalValue) return match; 2394 2395 var quote = doubleQuotedValue !== undefined ? '"' : (singleQuotedValue !== undefined ? "'" : ""); 2396 return prefix + quote + replacedValue + quote; 2397 }); 2398} 2399 2400function replaceRenderedImagesWithFiller(imageUrl, fillerImageUrl, rootElement) { 2401 if (typeof document === "undefined" || !isDefined(imageUrl) || typeof imageUrl !== "string" || 2402 typeof fillerImageUrl !== "string") return; 2403 2404 var normalizedUrl = imageUrl.trim(); 2405 var normalizedFillerUrl = fillerImageUrl.trim(); 2406 if (!normalizedUrl || normalizedUrl.toLowerCase() === "null" || 2407 !normalizedFillerUrl || normalizedFillerUrl.toLowerCase() === "null") return; 2408 2409 var searchRoot = rootElement || document; 2410 2411 searchRoot.querySelectorAll("img, source").forEach(function (imageElement) { 2412 var attributeUrl = imageElement.getAttribute("src"); 2413 if (attributeUrl === normalizedUrl || imageElement.src === normalizedUrl) { 2414 imageElement.setAttribute("src", normalizedFillerUrl); 2415 } 2416 2417 var srcset = imageElement.getAttribute("srcset"); 2418 if (srcset && srcset.indexOf(normalizedUrl) !== -1) { 2419 imageElement.setAttribute("srcset", srcset.split(normalizedUrl).join(normalizedFillerUrl)); 2420 } 2421 });
2422 2423 searchRoot.querySelectorAll("[style]").forEach(function (element) { 2424 var styleValue = element.getAttribute("style"); 2425 if (styleValue && styleValue.indexOf(normalizedUrl) !== -1) { 2426 element.setAttribute("style", styleValue.split(normalizedUrl).join(normalizedFillerUrl)); 2427 } 2428 }); 2429 2430 searchRoot.querySelectorAll("style").forEach(function (styleElement) { 2431 if (styleElement.textContent && styleElement.textContent.indexOf(normalizedUrl) !== -1) { 2432 styleElement.textContent = styleElement.textContent.split(normalizedUrl).join(normalizedFillerUrl); 2433 } 2434 }); 2435} 2436 2437// Returns true when a storeURL contains a phone number instead of a navigable URL. 2438// Phone numbers: start with 'tel:', or consist only of digits/spaces/dashes/parens/dots/plus 2439// and contain at least 7 digits. Standard URLs (http/https/www) always return false. 2440function isPhoneNumber(value) { 2441 if (!isDefined(value)) return false; 2442 if (/^tel:/i.test(value)) return true; 2443 if (/^https?:\/\//i.test(value) || /^www\./i.test(value)) return false; 2444 const stripped = value.trim(); 2445 const digits = stripped.replace(/\D/g, ''); 2446 if (digits.length < 7) return false; 2447 return /^[\+]?[\d][\d\s\-\.\(\)x]+$/.test(stripped); 2448} 2449 2450function offerClickEvent(acceptOfferReqObj, target, openLinkInNewTab = true) { 2451 // target can be an Element, an id, or any selector 2452 var el = target instanceof Element ? target : null; 2453 if (!el && typeof target === "string") { 2454 el = document.getElementById(target) || document.querySelector(target); 2455 } 2456 if (!el) { 2457 logInfo("offerClickEvent: element not found", target); 2458 return; 2459 } 2460 2461 // Derive URL; fall back to closest ancestor with data-store-url 2462 const url = 2463 el.getAttribute("data-store-url") || 2464 el.closest("[data-store-url]")?.getAttribute("data-store-url"); 2465 2466 if (!isDefined(url) && openLinkInNewTab) { 2467 logInfo("offerClickEvent: no URL found on element", target); 2468 //return; 2469 } 2470 2471 // Derive offer name; fall back to container id parsing 2472 const containerWithId = el.closest("[id]"); 2473 const elementIdClicked = containerWithId ? containerWithId.id : (el.id || ""); 2474 const offerName = 2475 el.getAttribute("data-offer-name") || 2476 el.closest("[data-offer-name]")?.getAttribute("data-offer-name") || 2477 (elementIdClicked ? elementIdClicked.replace(/^(?:Store_|SWD-)?SPOS_/, "").split("_").slice(1).join("_") : ""); 2478 2479 if (!isDefined(offerName)) { 2480 logInfo("offerClickEvent: no offer name found on element", target); 2481 return; 2482 } 2483 logInfo("offerClickEvent: element clicked", elementIdClicked); 2484 2485 acceptOfferReqObj.offerName = offerName; 2486 acceptOfferReqObj.acceptanceLevel = "Accepted"; 2487 2488 if (isDefined(globalDataLayer.SPOSOffers)) { 2489 for (property in globalDataLayer.SPOSOffers) { 2490 if (elementIdClicked === globalDataLayer.SPOSOffers[property].OfferID) { 2491 globalDataLayer.SPOSOffers[property].OfferClicked = "yes"; 2492 break; 2493 } 2494 } 2495 } 2496 2497 $.ajax({
2498 url: getMastiffUrl(), 2499 method: "POST", 2500 async: true, 2501 data: encodeURIComponent(JSON.stringify(acceptOfferReqObj)), 2502 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 2503 success: function () { 2504 logInfo("Offer accepted Api call sent " + offerName + " URL: " + url); 2505 }, 2506 error: function (XMLHttpRequest, textStatus, errorThrown) { 2507 logInfo("ERROR in Offer accepted Api call for " + offerName); 2508 logInfo(XMLHttpRequest); 2509 logInfo(textStatus); 2510 logInfo(errorThrown); 2511 } 2512 }); 2513 2514 if (url) { 2515 if (openLinkInNewTab) { 2516 window.open(url, "_blank", "noopener"); 2517 } 2518 } else { 2519 logInfo("offerClickEvent: no URL found on element", elementIdClicked); 2520 } 2521} 2522 2523function replaceMerchImages() { 2524 if (pgName !== "pdp_falcon") return; 2525 2526 const { segments: seg } = normalizeUrl(); 2527 if (!isDefined(seg[5]) || seg[5].toLowerCase() !== "ink-paper") return; 2528 2529 const merchImagePattern = /^https:\/\/www\.hp\.com\/[^?#]*\/shop\/Html\/Merch\/Images\/[^?#]+\.[^?#]+(?:[?#].*)?$/i; 2530 2531 waitForElement("#pdp .ink-paper", "#pdp").then(function (inkPaperRoot) { 2532 const checkedMerchUrls = new Set(); 2533 const merchImages = inkPaperRoot.querySelectorAll("img"); 2534 2535 merchImages.forEach(function (img) { 2536 const imageUrl = img.src; 2537 if (!merchImagePattern.test(imageUrl) || checkedMerchUrls.has(imageUrl)) return; 2538 2539 checkedMerchUrls.add(imageUrl); 2540 logInfo("[HP merch] image URL matched; replacing with filler:", imageUrl); 2541 replaceRenderedImagesWithFiller(imageUrl, MASTIFF_MERCH_IMAGE_FILLER_URL, inkPaperRoot); 2542 }); 2543 2544 if (checkedMerchUrls.size) { 2545 logInfo(checkedMerchUrls.size, "[HP merch] images replaced with filler:", MASTIFF_MERCH_IMAGE_FILLER_URL); 2546 } 2547 }).catch(function (error) { 2548 logInfo("[HP merch] image replacement skipped: .ink-paper not found", error); 2549 }); 2550} 2551 2552function addSuppliesReporting() { 2553 $('.ink-paper, .accessories-container') 2554 .off('click.mastiff', 'a') // remove previous namespaced handlers 2555 .on('click.mastiff', 'a', function (e) { 2556 const $a = $(this); 2557 2558 // ensure link has expected Offer_id param 2559 const href = $a.attr('href') || ''; 2560 const match = href.match(/Offer_id=MAS-([^_]+)_([^&]+)/); 2561 if (!match) return; // not a tracked shop link 2562 2563 // we matched - intercept navigation 2564 e.preventDefault(); 2565 2566 const reqId = match[1]; 2567 const offerName = match[2]; 2568 2569 // build payload copy (safe-guard reqObj existence) 2570 const reqObjCopy = JSON.parse(JSON.stringify(window.reqObj || {})); 2571 reqObjCopy.offerName = offerName; 2572 reqObjCopy.acceptanceLevel = 'Accepted'; 2573 reqObjCopy.requestId = reqId; 2574 reqObjCopy.user = reqObjCopy.user || {}; 2575 reqObjCopy.user.callerId = 'SW_COMPATIBILITY'; 2576 // choose pageId by id prefix 2577 const isSupplies = !!($a.attr('id') && $a.attr('id').startsWith('PDPsupplies_')); 2578 const isAccessory = !!($a.attr('id') && $a.attr('id').startsWith('View')); 2579 2580 reqObjCopy.user.pageId = isSupplies ? 'PDP_SUPPLIES' : isAccessory ? 'PDP_ACCESSORY' : 'PDP_FALCON'; 2581 2582 // send to mastiff 2583 $.ajax({
2584 url: getMastiffUrl(), 2585 method: 'POST', 2586 async: true, 2587 data: encodeURIComponent(JSON.stringify(reqObjCopy)), 2588 contentType: 'application/x-www-form-urlencoded; charset=UTF-8' 2589 }).done(function () { 2590 logInfo('Offer accepted Api call sent: ' + offerName + ' URL: ' + getMastiffUrl()); 2591 }).fail(function (jqXHR, textStatus, errorThrown) { 2592 logInfo('ERROR in Offer accepted Api call for ' + offerName); 2593 logInfo(jqXHR); 2594 logInfo(textStatus); 2595 logInfo(errorThrown); 2596 }); 2597 2598 logInfo('Clicked shop link: ' + href + ', offer: ' + offerName + ', reqId: ' + reqId); 2599 2600 // open in new tab 2601 window.open(href, '_blank', 'noopener'); 2602 }); 2603} 2604 2605function createReqId() { 2606 2607 var timestamp = Date.now(); 2608 var tsLength = String(timestamp).length; 2609 var randStrLen = 20 - parseInt(tsLength); 2610 var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 2611 var charactersLength = characters.length; 2612 var result = ""; 2613 2614 for (var i = 0; i < randStrLen; i++) { 2615 result += characters.charAt(Math.floor(Math.random() * charactersLength)); 2616 } 2617 2618 return String(timestamp).concat(result); 2619} 2620 2621function getDeviceType() { 2622 var ua = navigator.userAgent; 2623 if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) { 2624 return "tablet"; 2625 } 2626 if ( 2627 /Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test( 2628 ua 2629 ) 2630 ) { 2631 return "mobile"; 2632 } 2633 return "desktop"; 2634} 2635 2636function pageName() { 2637 const { segments: segs } = normalizeUrl(); 2638 2639 const s = (i) => (typeof segs[i] === "string" ? segs[i] : ""); 2640 const has = (str, sub) => str && str.indexOf(sub) > -1; 2641 const starts = (str, sub) => str && str.startsWith(sub); 2642 2643 const p4 = s(4); 2644 2645 // no section -> home 2646 if (!p4) return "home"; 2647 2648 // home variants 2649 if (p4 === "printer" || p4 === "computer") { 2650 // home_printer / home_computer 2651 return "home_" + p4; 2652 } 2653 2654 // drivers 2655 if (p4 === "drivers") { 2656 const p5 = s(5); 2657 const p6 = s(6); 2658 // check index 5 for "closure" 2659 if (has(p5, "closure")) { 2660 return "drivers_closure"; 2661 } else { 2662 return "drivers_details"; 2663 } 2664 } 2665 2666 // top-level document 2667 if (p4 === "document") { 2668 return "document"; 2669 } 2670 2671 // help 2672 if (p4 === "help") { 2673 const p5 = s(5); 2674 //return help-repair 2675 if (has(p5, "repair")) return "repair"; 2676 //same 2677 if (has(p5, "hp-pc-hardware-diagnostics")) return "hardware-diagnostics"; 2678 // help-windows (e.g. /help/windows-10-support-center) 2679 if (has(p5, "windows")) return "help-windows"; 2680 // e.g., help-computer, help-printer 2681 return "help-" + p5; 2682 } 2683 2684 // product (PDP or document under product) 2685 if (p4 === "product") { 2686 const p7 = s(7), p9 = s(9); 2687 if (p7 === "document" || p9 === "document") { 2688 return "document"; 2689 } 2690 return "pdp_falcon"; 2691 } 2692 2693 // contact (+ closure) 2694 if (p4 === "contact") { 2695 const p5 = s(5); 2696 if (p5 === "closure" || starts(p5, "closure")) { 2697 // contact_closure or contact_closure-* 2698 return "contact_" + p5; 2699 } 2700 if (p5 === "solution") { 2701 return "contact-solution"; 2702 } 2703 if (!isDefined(p5)) { 2704 return "contact-landing"; 2705 } 2706 return "contact"; 2707 } 2708 2709 // printer-setup 2710 if (p4 === "printer-setup") { 2711 return "printer-setup"; 2712 } 2713 2714 // warrantyresult 2715 if (p4 === "warrantyresult") { 2716 return "warrantyresult_falcon"; 2717 } 2718 2719 // service 2720 if (p4 === "service") { 2721 return "service"; 2722 } 2723 2724 // dashboard 2725 if (p4 === "dashboard") { 2726 return "dashboard"; 2727 } 2728 2729 // default 2730 return p4; 2731} 2732 2733function pageSupported(name) { 2734 var supportedPageList = [ 2735 "pdp_falcon", 2736 "drivers_closure", 2737 "drivers_details", 2738 "contact", 2739 "contact-solution", 2740 "warrantyresult_falcon", 2741 "service", 2742 "help-printer", 2743 "help-computer", 2744 "repair", 2745 "hardware-diagnostics", 2746 "home", 2747 "home_printer", 2748 "home_computer", 2749 "dashboard", 2750 "document", 2751 "contact_closure", 2752 "printer-setup", 2753 "help-windows", 2754 "contact-landing", 2755 ]; 2756 return supportedPageList.indexOf(name) >= 0; 2757} 2758 2759function AcceptOffer(acceptOfferReqObj) { 2760 2761 $.ajax({
2762 url: getMastiffUrl(), 2763 method: "POST", 2764 async: true, 2765 data: encodeURIComponent(JSON.stringify(acceptOfferReqObj)), 2766 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 2767 success: function (result) { 2768 2769 logInfo("Response object - Offer accepted."); 2770 }, 2771 error: function (XMLHttpRequest, textStatus, errorThrown) { 2772 2773 logInfo("ERROR"); 2774 2775 logInfo(XMLHttpRequest); 2776 logInfo(textStatus); 2777 logInfo(errorThrown); 2778 } 2779 }); 2780 2781} 2782 2783function offerDeclineEvent(declineOfferReqObj, offerName) { 2784 2785 declineOfferReqObj.offerName = offerName; 2786 declineOfferReqObj.acceptanceLevel = "Declined"; 2787 2788 $.ajax({ 2789 url: getMastiffUrl(), 2790 method: "POST", 2791 async: true, 2792 data: encodeURIComponent(JSON.stringify(declineOfferReqObj)), 2793 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 2794 success: function (result) { 2795 2796 logInfo("Response object - Offer Declined."); 2797 }, 2798 error: function (XMLHttpRequest, textStatus, errorThrown) { 2799 2800 logInfo("ERROR"); 2801 2802 logInfo(XMLHttpRequest); 2803 logInfo(textStatus); 2804 logInfo(errorThrown); 2805 } 2806 }); 2807} 2808 2809// Handles the click-to-reveal interaction for phone number offers (e.g. Asurion / HP Care Complete). 2810// On first click: updates the CTA text to show the phone number and fires an acceptance API call. 2811// Navigation is intentionally suppressed â the user dials manually after seeing the number. 2812// Handles the click-to-reveal interaction for phone number offers (e.g. Asurion / HP Care Complete). 2813// On first click: reads the pre-stripped phone number from data-phone (stamped by addUrlAndClickEvent), 2814// updates the CTA text, then delegates GDL tracking + acceptance API call to offerClickEvent. 2815// Navigation is intentionally suppressed â no offerElement closure needed. 2816function handlePhoneReveal($el, primaryButtonText) { 2817 const displayPhone = $el.attr("data-phone") || ""; 2818 2819 logInfo("handlePhoneReveal: revealing phone number", displayPhone); 2820 // Find and replace the primaryButtonText value with the phone number 2821 if (primaryButtonText) { 2822 // Search through element text nodes and replace primaryButtonText with displayPhone 2823 const walker = document.createTreeWalker( 2824 $el[0], 2825 NodeFilter.SHOW_TEXT, 2826 null, 2827 false 2828 ); 2829 let node; 2830 while (node = walker.nextNode()) { 2831 if (node.textContent.includes(primaryButtonText)) { 2832 logInfo("handlePhoneReveal: replacing primaryButtonText with phone number in text node."); 2833 node.textContent = node.textContent.replace(primaryButtonText, displayPhone); 2834 break; 2835 } 2836 } 2837 } else { 2838 // Fallback: if no primaryButtonText provided, just set based on any element that has a class name that contains cta or button 2839 const ctaElement = $el.find('[class*="cta"], [class*="button"]').first(); 2840 if (ctaElement.length) { 2841 logInfo("handlePhoneReveal: no primaryButtonText provided, updating first CTA/button element text."); 2842 ctaElement.text(displayPhone); 2843 } else { 2844 loginfo("handlePhoneReveal: no primaryButtonText or CTA/button element found to update text."); 2845 } 2846 } 2847 2848 // Remove the click handler to prevent re-triggering on subsequent clicks 2849 $el.off(".offerClick"); 2850 2851 // Delegate GDL tracking + acceptance API call to offerClickEvent. 2852 // Passing false for openLinkInNewTab suppresses window.open â no navigation occurs. 2853 offerClickEvent(reqObj, $el.get(0), false); 2854 2855 logInfo("Phone number revealed:", displayPhone); 2856} 2857 2858function addUrlAndClickEvent(divId, offerElement, openLinkInNewTab = true) { 2859 if (divId.charAt(0) !== '#' && divId.charAt(0) !== '.') { 2860 divId = "#" + divId; 2861 } 2862 const element = document.querySelector( 2863 divId.replace(/^#(\d)/, (_, d) => `#\\3${d} `) 2864 ); 2865 2866 // convert to jQuery object 2867 const $el = $(element); 2868 if ($el.length === 0) { 2869 logInfo("addUrlAndClickEvent: element not found", divId); 2870 return; 2871 } 2872 2873 // Stash metadata on the element 2874 if (offerElement.storeURL) $el.attr("data-store-url", offerElement.storeURL); 2875 2876 if (offerElement.name) $el.attr("data-offer-name", offerElement.name); 2877 2878 // Avoid duplicate bindings if re-rendered 2879 //we pass the whole element clicked to the event handler 2880 //so that we can derive URL and offer name from data attributes or ancestors (when id is not set on cta) 2881 $el.off(".offerClick"); 2882 2883 // Phone number in storeURL: stamp data-phone on the element and use click-to-reveal instead of navigation 2884 if (isPhoneNumber(offerElement.storeURL)) { 2885 $el.attr("data-phone", offerElement.storeURL.replace(/^tel:/i, "").replace(/[&?].*$/, "").trim()); 2886 $el.on("click.offerClick", function (e) { 2887 e.preventDefault(); 2888 handlePhoneReveal($(this), offerElement.primaryButtonText); 2889 });
2890 $el.on("keydown.offerClick", function (e) { 2891 const k = e.key || e.which; 2892 if (k === "Enter" || k === " " || k === 13 || k === 32) { 2893 e.preventDefault(); 2894 handlePhoneReveal($(this), offerElement.primaryButtonText); 2895 } 2896 }); 2897 return; 2898 } 2899 2900 $el.on("click.offerClick", function (e) { 2901 e.preventDefault(); 2902 offerClickEvent(reqObj, this, openLinkInNewTab); 2903 }); 2904 2905 $el.on("keydown.offerClick", function (e) { 2906 const k = e.key || e.which; 2907 if (k === "Enter" || k === " " || k === 13 || k === 32) { 2908 e.preventDefault(); 2909 offerClickEvent(reqObj, this, openLinkInNewTab); 2910 } 2911 }); 2912} 2913 2914function applyAccessibilityAttributes(selector, offerElement) { 2915 2916 if (selector.charAt(0) !== '#' && selector.charAt(0) !== '.') { 2917 selector = "#" + selector; 2918 } 2919 2920 // Cache the jQuery selector for the main element 2921 const element = document.querySelector( 2922 selector.replace(/^#(\d)/, (_, d) => `#\\3${d} `) 2923 ); 2924 2925 // convert to jQuery object 2926 const $element = $(element); 2927 if (!$element) { 2928 logInfo(`Selector "${selector}" matched 0 elements.`); 2929 // treat "not found" as not empty 2930 return; 2931 } 2932 2933 // Set accessibility attributes on the main element 2934 $element.attr({ 2935 "aria-label": offerElement.offerType, 2936 "tabindex": 0, 2937 "alt": offerElement.offerType 2938 }); 2939 2940 // Set title attribute based on primaryButtonText, then primaryText1, then offerTitle, ensuring no HTML tags are included 2941 const htmlTagRegex = /<[^>]*>/; 2942 const titleText = 2943 (offerElement.primaryButtonText 2944 && !htmlTagRegex.test(offerElement.primaryButtonText) && isDefined(offerElement.primaryButtonText)) 2945 ? offerElement.primaryButtonText 2946 : (isDefined(offerElement.primaryText1) && !htmlTagRegex.test(offerElement.primaryText1)) 2947 ? offerElement.primaryText1 2948 : (isDefined(offerElement.primaryText2) && !htmlTagRegex.test(offerElement.primaryText2)) 2949 ? offerElement.primaryText2 2950 : offerElement.offerType; 2951 2952 $element.attr("title", titleText); 2953 2954 if (reqObj.user.language === "ar" || reqObj.user.language === "he") {
2955 // Get parent directly rather than by class name 2956 $element.parent().css("text-align", "right"); 2957 } 2958 2959 // Apply attributes to images if they exist 2960 if (isDefined(offerElement.imageURL)) { 2961 $element.find("img").attr({ 2962 "title": titleText, 2963 "alt": offerElement.offerType 2964 }); 2965 } 2966} 2967 2968function isContainerEmpty(selector) { 2969 const el = document.querySelector(selector); 2970 if (!el) { 2971 logInfo(`Selector "${selector}" matched 0 elements.`); 2972 // treat "not found" as not empty 2973 return false; 2974 } 2975 const text = (el.textContent || "").trim(); 2976 const looksLoading = /loading|spinner|please wait/i.test(text); 2977 const havePlaceholder = /placeholder/i.test(text); 2978 const structurallyEmpty = el.children.length === 0 || text.length === 0; 2979 const isEmpty = $(el).is(":empty"); 2980 return structurallyEmpty || looksLoading || havePlaceholder || isEmpty; 2981} 2982 2983function hideContainer(selector, method = "hide", onlyWhenEmpty = true) { 2984 logInfo(`hideContainer called with selector="${selector}", method="${method}", onlyWhenEmpty=${onlyWhenEmpty}`); 2985 //log callstack 2986 //logInfo(new Error().stack); 2987 const el = document.querySelector(selector); 2988 if (!el) { 2989 logInfo(`Selector "${selector}" matched 0 elements. No action taken.`); 2990 return; 2991 } 2992 const empty = isContainerEmpty(selector); 2993 logInfo(`Container "${selector}" empty status: ${empty}`); 2994 if ((onlyWhenEmpty && empty) || (!onlyWhenEmpty)) { 2995 // only hide if empty, or always hide 2996 if (!onlyWhenEmpty) logInfo(`Hiding container "${selector}" using method "${method}" regardless of content.`); 2997 if (onlyWhenEmpty && empty) logInfo(`Hiding container "${selector}" using method "${method}" because it is empty.`); 2998 switch (method) { 2999 case "remove": 3000 if (el) { 3001 el.remove(); 3002 logInfo(`Element removed from DOM.`); 3003 } 3004 break; 3005 case "visibility": 3006 if (el) { 3007 el.style.visibility = "hidden"; 3008 logInfo(`Element visibility set to hidden.`); 3009 } 3010 break; 3011 case "hidden": 3012 if (el) { 3013 el.classList.add("hidden"); 3014 logInfo(`Element class 'hidden' added.`); 3015 } 3016 break; 3017 case "hide": 3018 if (el) { 3019 $(el).hide(); 3020 logInfo(`Element hidden using jQuery.`); 3021 } 3022 break; 3023 case "removeparent": 3024 if (el && el.parentElement) { 3025 el.parentElement.remove(); 3026 logInfo(`Parent element removed from DOM.`); 3027 } 3028 break; 3029 case "hideparent": 3030 if (el && el.parentElement) { 3031 $(el.parentElement).hide(); 3032 logInfo(`Parent element hidden using jQuery.`); 3033 } 3034 break; 3035 default: 3036 if (el) el.style.display = "none"; 3037 logInfo(`Element display set to none.`); 3038 break; 3039 } 3040 } 3041} 3042 3043function hideMastiffOfferPlacement() { 3044 var cfg = PAGE_CONFIG[pgName] || {}; 3045 if (cfg.positions) { 3046 Object.keys(cfg.positions).forEach(function (pos) { 3047 hidePlacement(pgName, pos); 3048 }); 3049 } 3050} 3051 3052function waitForElementToDisappear(selector, callback, callbackArg) { 3053 const targetElement = document.querySelector(selector); 3054 3055 if (!targetElement) { 3056 logInfo(`${selector} not found`); 3057 callback(callbackArg); 3058 return; 3059 } 3060 3061 logInfo(`waiting for ${selector} to disappear`); 3062 3063 const observer = new MutationObserver((mutationsList, observer) => { 3064 if (!document.querySelector(selector)) { 3065 logInfo(`${selector} removed`); 3066 observer.disconnect(); 3067 callback(callbackArg); 3068 } 3069 });
3070 3071 observer.observe(targetElement.parentNode, { childList: true }); 3072} 3073 3074function waitForElement(selector, parent, timeout = 30000) { 3075 logInfo("waiting for element", selector); 3076 return new Promise((resolve, reject) => { 3077 const element = document.querySelector(selector); 3078 if (element) { 3079 logInfo(selector, "element found using querySelector"); 3080 resolve(element); 3081 return; 3082 } 3083 3084 const observer = new MutationObserver((mutations, obs) => { 3085 const element = document.querySelector(selector); 3086 if (element) { 3087 logInfo(selector, "element found using observer"); 3088 resolve(element); 3089 obs.disconnect(); 3090 } 3091 }); 3092 3093 var parentNode = document.body; 3094 if (parent) { 3095 const parentElement = document.querySelector(parent); 3096 if (parentElement) { 3097 parentNode = parentElement; 3098 } else { 3099 logInfo(`Parent element "${parent}" not found. Defaulting to document.body`); 3100 } 3101 } 3102 3103 logInfo("observing", parentNode); 3104 3105 observer.observe(parentNode, { 3106 childList: true, 3107 subtree: true 3108 }); 3109 3110 setTimeout(() => { 3111 observer.disconnect(); 3112 logInfo("waited ", timeout, "ms for ", selector); 3113 reject(new Error("Observer timed out when waiting for element" + selector)); 3114 }, timeout); 3115 }); 3116} 3117 3118function sleep(milliseconds) { 3119 var date = Date.now(); 3120 var currentDate = null; 3121 do { 3122 currentDate = Date.now(); 3123 } while (currentDate - date < milliseconds); 3124} 3125 3126function logInfo(...args) { 3127 if (isMastiffDebug() || isForceLogOn()) console.info(...args); 3128} 3129 3130// add mastifflog as URL param to force logging #mastifflog=1 3131function isForceLogOn() { 3132 return sessionStorage.getItem("mastifflog") === "true"; 3133} 3134 3135function logToGlobalDataLayer(LeadOffer) { 3136 if (typeof globalDataLayer !== "undefined" && globalDataLayer.SPOSOffers) { 3137 globalDataLayer.SPOSOffers[`LeadOffer${LeadOfferIndex}`] = LeadOffer; 3138 LeadOfferIndex++; 3139 } 3140} 3141 3142function SaveReqObjToSessionStorage() { 3143 sessionStorage.setItem("reqObj", JSON.stringify(reqObj)); 3144 sessionStorage.setItem("offerResults", JSON.stringify(offerResults)); 3145} 3146 3147function GetReqObjFromSessionStorage() { 3148 return JSON.parse(sessionStorage.getItem("reqObj")) || {}; 3149} 3150 3151async function getDeviceInfo() { 3152 const ua = navigator.userAgent || ""; 3153 const hasUAData = !!navigator.userAgentData; 3154 3155 // --- helpers --- 3156 const detectBrowserFromUA = (uaStr) => { 3157 if (/Edg\//i.test(uaStr)) return "Microsoft Edge"; 3158 if (/OPR\//i.test(uaStr) || /Opera/i.test(uaStr)) return "Opera"; 3159 if (/Chrome\//i.test(uaStr) && !/Chromium/i.test(uaStr)) return "Chrome"; 3160 if (/Safari\//i.test(uaStr) && !/Chrome/i.test(uaStr)) return "Safari"; 3161 if (/Firefox\//i.test(uaStr)) return "Firefox"; 3162 if (/Chromium/i.test(uaStr)) return "Chromium"; 3163 if (/MSIE|Trident/i.test(uaStr)) return "Internet Explorer"; 3164 return "Unknown"; 3165 }; 3166 3167 const heuristicWin10vs11FromUA = (uaStr) => { 3168 // Both Win10/11 report Windows NT 10.0 in UA. 3169 if (/Windows 11/i.test(uaStr)) return "Windows 11"; 3170 const m = uaStr.match(/(Chrome|Edg|Firefox)\/(\d+)/i); 3171 if (!m) return "Windows 10"; 3172 const name = m[1].toLowerCase(); 3173 const ver = parseInt(m[2], 10); 3174 if ((name === "chrome" || name === "edg") && ver >= 92) return "Windows 11"; 3175 if (name === "firefox" && ver >= 90) return "Windows 11"; 3176 return "Windows 10"; 3177 }; 3178 3179 const detectOSFromUAWithWinSplit = (uaStr) => { 3180 if (/Windows NT 10\.0/i.test(uaStr)) return heuristicWin10vs11FromUA(uaStr); 3181 if (/Windows NT 6\.3/i.test(uaStr)) return "Windows 8.1"; 3182 if (/Windows NT 6\.2/i.test(uaStr)) return "Windows 8"; 3183 if (/Windows NT 6\.1/i.test(uaStr)) return "Windows 7"; 3184 if (/Windows NT 6\.0/i.test(uaStr)) return "Windows Vista"; 3185 if (/Windows NT 5\.1/i.test(uaStr)) return "Windows XP"; 3186 if (/Mac OS X 10[._]\d+/i.test(uaStr)) return "macOS"; 3187 if (/Android/i.test(uaStr)) return "Android"; 3188 if (/iPhone|iPad|iPod/i.test(uaStr)) return "iOS"; 3189 if (/Linux/i.test(uaStr)) return "Linux"; 3190 return "Unknown"; 3191 }; 3192 3193 const fallback = { 3194 browser: detectBrowserFromUA(ua), 3195 os: detectOSFromUAWithWinSplit(ua), 3196 deviceType: /Mobi|Android|iPhone|iPad|iPod/i.test(ua) ? "Mobile" : "Desktop" 3197 }; 3198 3199 if (!hasUAData) return fallback; 3200 3201 try { 3202 // UA-CH (Chromium): get high-entropy values 3203 const uaData = navigator.userAgentData; 3204 const { brands, mobile, platform } = uaData; 3205 // Some browsers expose fullVersionList instead of brands in getHighEntropyValues 3206 const hi = await uaData.getHighEntropyValues([ 3207 "platform", 3208 "platformVersion", 3209 "fullVersionList", 3210 "model" 3211 ]); 3212 3213 // --- Browser via UA-CH brands/fullVersionList --- 3214 const brandList = (hi.fullVersionList && Array.isArray(hi.fullVersionList)) 3215 ? hi.fullVersionList 3216 : (brands || []); 3217 3218 const brandNames = brandList.map(b => (b.brand || b.brandName || "")); 3219 3220 var browser = "Unknown"; 3221 if (brandNames.some(b => /Microsoft Edge/i.test(b))) browser = "Microsoft Edge"; 3222 else if (brandNames.some(b => /Opera/i.test(b))) browser = "Opera"; 3223 else if (brandNames.some(b => /Google Chrome/i.test(b))) browser = "Chrome"; 3224 else if (brandNames.some(b => /^Chromium$/i.test(b))) browser = "Chromium"; 3225 else { 3226 // Non-Chromium (Safari/Firefox) often wonât populate UA-CH; fallback to UA string 3227 browser = detectBrowserFromUA(ua);
3228 } 3229 3230 // --- Device Type from UA-CH (fallback UA) --- 3231 const deviceType = mobile ? "Mobile" : (/Mobi|Android|iPhone|iPad|iPod/i.test(ua) ? "Mobile" : "Desktop"); 3232 3233 // --- OS with Win10/11 split using UA-CH platformVersion --- 3234 var os = "Unknown"; 3235 const plat = (hi.platform || platform || "").toLowerCase(); 3236 3237 if (plat === "windows") { 3238 // Windows mapping per Chromium UA-CH: 3239 // major platformVersion >= 13 -> Windows 11+, >0 -> Windows 10, 0/undefined -> older/unknown 3240 const major = parseInt((hi.platformVersion || "0").split(".")[0], 10); 3241 if (!isNaN(major)) { 3242 if (major >= 13) os = "Windows 11"; 3243 else if (major > 0) os = "Windows 10"; 3244 else os = "Windows (before Windows 10)"; 3245 } else { 3246 // Fallback to UA heuristic if parsing failed 3247 os = detectOSFromUAWithWinSplit(ua); 3248 } 3249 } else if (plat === "mac" || plat === "macos") { 3250 os = "macOS"; 3251 } else if (plat === "android") { 3252 os = "Android"; 3253 } else if (plat === "ios") { 3254 os = "iOS"; 3255 } else if (plat === "chrome os" || plat === "chromeos") { 3256 os = "Chrome OS"; 3257 } else if (plat === "linux") { 3258 os = "Linux"; 3259 } else { 3260 os = detectOSFromUAWithWinSplit(ua); 3261 } 3262 3263 return { browser, os, deviceType }; 3264 } catch { 3265 return fallback; 3266 } 3267} 3268 3269// ------------------- helpers code ends here ------------------- 3270 3271// ----------- Offer rendering code starts here ---------------- 3272 3273function printerSetupOffers() { 3274 waitForElement("#opt-mastiff-setup") 3275 var primaryPositionElement = offerResults.offers.offer.filter(function (x) { 3276 return x.templatePosition === "primary"; 3277 })[0]; 3278 var secondaryPositionElement = offerResults.offers.offer.filter(function (x) { 3279 return x.templatePosition === "secondary"; 3280 })[0]; 3281 var shop1PositionElement = offerResults.offers.offer.filter(function (x) { 3282 return x.templatePosition === "shop1"; 3283 })[0]; 3284 3285 if (primaryPositionElement != null) { 3286 showpPrinterSetupOffer(primaryPositionElement); 3287 } 3288 if (secondaryPositionElement != null) { 3289 showpPrinterSetupOffer(secondaryPositionElement); 3290 } 3291 if (shop1PositionElement != null) { 3292 showpPrinterSetupOffer(shop1PositionElement); 3293 } 3294 $("#opt-mastiff-setup").css("margin-top", "20px"); 3295} 3296 3297function showpPrinterSetupOffer(prnSetupOfferElement) { 3298 var divId = ""; 3299 divId = divId.concat(prnSetupOfferElement.templatePosition, "_", prnSetupOfferElement.name); 3300 3301 var LeadOffer = {}; 3302 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 3303 LeadOffer.OfferID = divId; 3304 LeadOffer.OfferClicked = "no"; 3305 LeadOffer.SPOStemplate = "12"; 3306 if ( 3307 isDefined(prnSetupOfferElement.html) && 3308 isDefined(prnSetupOfferElement.primaryButtonText) && 3309 isDefined(prnSetupOfferElement.storeURL) 3310 ) { 3311 var htmlTemplate = prnSetupOfferElement.html; 3312 var html = ""; 3313 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", prnSetupOfferElement.primaryButtonText); 3314 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateURL%", prnSetupOfferElement.storeURL); 3315 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId); 3316 3317 $("#opt-mastiff-setup").append(htmlTemplate); 3318 $(".opt-mastiff-setup-box").removeClass("hidden"); 3319 3320 LeadOffer.offerShown = "yes"; 3321 3322 3323 applyAccessibilityAttributes(divId, prnSetupOfferElement); 3324 3325 $(".simpleLinkTemplateAnchor").css("font-family", "HPSimplified"); 3326 $(".simpleLinkTemplateAnchor").css("font-size", "14px"); 3327 $(".simpleLinkTemplateAnchor").css("line-height", "25px"); 3328 $("#" + divId).css("margin-top", "10px"); 3329 3330 addUrlAndClickEvent(divId, prnSetupOfferElement); 3331 logToGlobalDataLayer(LeadOffer); 3332 } else { 3333 LeadOffer.errorData = "No Content Available"; 3334 LeadOffer.offerShown = "no"; 3335 window.optRevertHpOffer(); 3336 logToGlobalDataLayer(LeadOffer) 3337 } 3338} 3339 3340function showDocumentOffer(primaryOfferElement) { 3341 var divId = ""; 3342 divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name); 3343 3344 var LeadOffer = {}; 3345 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 3346 LeadOffer.OfferID = divId; 3347 LeadOffer.OfferClicked = "no"; 3348 LeadOffer.SPOStemplate = "9"; 3349 if ( 3350 isDefined(primaryOfferElement.html) && 3351 isDefined(primaryOfferElement.imageURL) && 3352 isDefined(primaryOfferElement.primaryText1) && 3353 isDefined(primaryOfferElement.primaryButtonText) && 3354 isDefined(primaryOfferElement.storeURL) 3355 ) { 3356 var htmlTemplate = primaryOfferElement.html; 3357 var html = ""; 3358 html = html.concat("<div id=\"", divId, "\">", htmlTemplate, "</div>"); 3359 if (isContainerEmpty("#opt-mastiff-doc")) {
3360 html = html.replace("%offerimageURLPlaceholder%", primaryOfferElement.imageURL || ""); 3361 html = html.replace("%offerprimaryText1PlaceHolder%", primaryOfferElement.primaryText1 || ""); 3362 html = html.replace("%offerprimaryText2PlaceHolder%", primaryOfferElement.primaryText2 || ""); 3363 html = html.replace("%offerprimaryButtonTextPlaceHolder%", primaryOfferElement.primaryButtonText || ""); 3364 3365 $("#opt-mastiff-doc").append(html); 3366 LeadOffer.offerShown = "yes"; 3367 3368 applyAccessibilityAttributes(divId, primaryOfferElement); 3369 addUrlAndClickEvent(divId, primaryOfferElement); 3370 3371 } else { 3372 LeadOffer.errorData = "Document Offer Location is not empty"; 3373 LeadOffer.offerShown = "no"; 3374 window.optRevertHpOffer(); 3375 } 3376 logToGlobalDataLayer(LeadOffer); 3377 } else { 3378 LeadOffer.errorData = "No Content Available"; 3379 LeadOffer.offerShown = "no"; 3380 window.optRevertHpOffer(); 3381 logToGlobalDataLayer(LeadOffer); 3382 } 3383} 3384 3385function showHelpPageOffer(primaryOfferElement) { 3386 var divId = ""; 3387 divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name); 3388 3389 var LeadOffer = {}; 3390 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 3391 LeadOffer.OfferID = divId; 3392 LeadOffer.OfferClicked = "no"; 3393 LeadOffer.SPOStemplate = "15"; 3394 if ( 3395 isDefined(primaryOfferElement.html) && 3396 isDefined(primaryOfferElement.imageURL) && 3397 isDefined(primaryOfferElement.primaryText1) && 3398 isDefined(primaryOfferElement.primaryButtonText) && 3399 isDefined(primaryOfferElement.storeURL) 3400 ) { 3401 var htmlTemplate = primaryOfferElement.html; 3402 var html = ""; 3403 html = html.concat("<div id=\"", divId, "\">", htmlTemplate, "</div>"); 3404 if (isContainerEmpty("#mastiffoffers")) { 3405 html = html.replace("%DiagsVRepairsimageURLPlaceholder%", primaryOfferElement.imageURL); 3406 html = html.replace("%DiagsVRepairsText1PlaceHolder%", primaryOfferElement.primaryText1); 3407 html = html.replace("%DiagsVRepairsText2PlaceHolder%", primaryOfferElement.primaryText2); 3408 html = html.replace("%DiagsVRepairsButtonTextPlaceHolder%", primaryOfferElement.primaryButtonText); 3409 3410 $("#mastiffoffers").append(html); 3411 if (pgName === "repair") { 3412 document.getElementById('diagsVRepairsImg').classList.add('VRepairsImg'); 3413 document.getElementById('diagsVRepairsText1').classList.add('VRepairsText1'); 3414 document.getElementById('diagsVRepairsText2').classList.add('VRepairsText2'); 3415 document.getElementById('diagsVRepairsCTADiv').classList.add('VRepairsCTADiv'); 3416 } 3417 else if (pgName === "hardware-diagnostics") { 3418 document.getElementById('diagsVRepairsImg').classList.add('DiagsImg'); 3419 document.getElementById('diagsVRepairsText1').classList.add('DiagsText1'); 3420 document.getElementById('diagsVRepairsText2').classList.add('DiagsText2'); 3421 document.getElementById('diagsVRepairsCTADiv').classList.add('DiagsCTADiv'); 3422 } 3423 $('.mastiffoffersTile').removeClass('hidden'); 3424 3425 LeadOffer.offerShown = "yes"; 3426 applyAccessibilityAttributes(divId, primaryOfferElement); 3427 addUrlAndClickEvent(divId, primaryOfferElement); 3428 } else { 3429 LeadOffer.errorData = "Help Page Offer Location is not empty"; 3430 LeadOffer.offerShown = "no"; 3431 } 3432 logToGlobalDataLayer(LeadOffer); 3433 } else { 3434 LeadOffer.errorData = "No Content Available"; 3435 LeadOffer.offerShown = "no"; 3436 logToGlobalDataLayer(LeadOffer); 3437 } 3438} 3439 3440function showDriverClosurePrimaryOffer(offerElement) { 3441 var divId = ""; 3442 divId = divId.concat("SPOS_", offerElement.templatePosition, "_", offerElement.name); 3443 3444 var LeadOffer = {}; 3445 var GDLOfferName = "LeadOffer" + LeadOfferIndex; 3446 LeadOffer.OfferID = divId; 3447 LeadOffer.OfferClicked = "no"; 3448 LeadOffer.SPOStemplate = "15"; 3449 3450 if ( 3451 isDefined(offerElement.html) && 3452 isDefined(offerElement.primaryText1) && 3453 isDefined(offerElement.primaryText2) && 3454 isDefined(offerElement.primaryButtonText) && 3455 isDefined(offerElement.imageURL) && 3456 isDefined(offerElement.storeURL) 3457 ) { 3458 var htmlTemplate = offerElement.html; 3459 3460 if (isContainerEmpty("#swdClosurePageMastiffBanner")) { 3461 htmlTemplate = htmlTemplate.replace("%DriverTileOfferImgURLPlaceholder%", offerElement.imageURL); 3462 htmlTemplate = htmlTemplate.replace("%DriverTileOfferTitlePlaceholder%", offerElement.primaryText1); 3463 htmlTemplate = htmlTemplate.replace("%DriverTileOfferDescriptionPlaceholder%", offerElement.primaryText2); 3464 htmlTemplate = htmlTemplate.replace("%DriverTileOfferCTAPlaceholder%", offerElement.primaryButtonText); 3465 htmlTemplate = htmlTemplate.replace("%DriverTileOfferId%", divId); 3466 3467 $("#swdClosurePageMastiffBanner").html(htmlTemplate); 3468
3469 allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency); 3470 3471 $("#" + divId).css("margin-top", "50px"); 3472 $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" }); 3473 3474 applyAccessibilityAttributes(divId, offerElement); 3475 3476 LeadOffer.offerShown = "yes"; 3477 addUrlAndClickEvent(divId, offerElement); 3478 } else { 3479 LeadOffer.errorData = "Primary1 Location is not empty"; 3480 LeadOffer.offerShown = "no"; 3481 } 3482 logToGlobalDataLayer(LeadOffer); 3483 } else { 3484 LeadOffer.errorData = "No Content Available"; 3485 LeadOffer.offerShown = "no"; 3486 3487 logToGlobalDataLayer(LeadOffer); 3488 } 3489} 3490 3491 3492async function showDashboardTile() { 3493 enableDashTile = false; 3494 await waitForElement("#dashboard_tile_mastiff_template").then(() => { 3495 // if dashboard_tile_mastiff_template container is empty then only proceed 3496 if (!isContainerEmpty("#dashboard_tile_mastiff_template")) { 3497 $("#dashboard_tile_mastiff_template").empty(); 3498 } 3499 3500 var carouselOffers = offerResults.offers.offer.filter(function (x) { 3501 return x.templatePosition === "carousel" && !x.category.toLowerCase().includes("quiz") 3502 }); 3503 3504 carouselOffers.forEach(function (offer) { 3505 DashboardTileContent(offer); 3506 }); 3507 3508 if (enableDashTile) { 3509 var slides = $(".dashboardSlidercontainer .DashTempshowSlide"); 3510 var navBullets = $("#nav-bullets"); 3511 navBullets.empty(); 3512 slides.each(function (idx) { 3513 navBullets.append(`<div class="nav-bullet"></div>`); 3514 }); 3515 $('#nav-bullets').off('click').on('click', '.nav-bullet', function () { 3516 var idx = $(this).index() + 1; 3517 currentSlide(idx); 3518 }); 3519 3520 if (document.getElementsByClassName("DashTempshowSlide").length == 1) { 3521 var navigationDiv = document.getElementsByClassName('dashboard-navigation')[0]; 3522 if (navigationDiv) navigationDiv.style.visibility = "hidden"; 3523 } 3524 sliderClassName = "DashTempshowSlide"; 3525 navBulletAvailable = true; 3526 displaySlides(slide_index); 3527 } else { 3528 hideContainer("#dashboard_tile_mastiff_template", "removeparent", true); 3529 } 3530 }) 3531 .catch((err) => { 3532 logInfo("Error waiting for dashboard tile container:", err); 3533 }); 3534} 3535 3536function DashboardTileContent(offerElement) { 3537 var divId = ""; 3538 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 3539 var LeadOffer = {}; 3540 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 3541 LeadOffer.OfferID = divId; 3542 LeadOffer.OfferClicked = "no"; 3543 LeadOffer.SPOStemplate = "8"; 3544 3545 if ( 3546 isDefined(offerElement.html) && 3547 isDefined(offerElement.imageURL) && 3548 isDefined(offerElement.primaryText1) && 3549 isDefined(offerElement.primaryButtonText) && 3550 isDefined(offerElement.storeURL) 3551 ) { 3552 var htmlTemplate = offerElement.html; 3553 if (!$(".dashboardSlidercontainer").length && isContainerEmpty("#dashboard_tile_mastiff_template")) { 3554 $("#dashboard_tile_mastiff_template").attr("tabindex", "0"); 3555 $("#dashboard_tile_mastiff_template").append(dashboardSliderDiv); 3556 } 3557 enableDashTile = true; 3558 htmlTemplate = htmlTemplate.replace("%DashboardTileImgplaceholder%", offerElement.imageURL); 3559 htmlTemplate = htmlTemplate.replace("%DashboardTileTitleplaceholder%", offerElement.primaryText1); 3560 htmlTemplate = htmlTemplate.replace("%DashboardTileDescriptionplaceholder%", offerElement.primaryText2); 3561 htmlTemplate = htmlTemplate.replace("%DashboardTileCTAplaceholder%", offerElement.primaryButtonText); 3562 //htmlTemplate = htmlTemplate.replace("%dashboardTemplateTileLinkURL%", offerElement.storeURL || ""); 3563 htmlTemplate = htmlTemplate.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)"); 3564 htmlTemplate = htmlTemplate.replace("id=%DashboardTileCTAId%", ""); 3565 htmlTemplate = htmlTemplate.replace("class=dashboardTemplate>", "class='dashboardTemplate DashTempshowSlide DashTempfade'>"); 3566 htmlTemplate = htmlTemplate.replace("tabindex=0", ""); 3567 htmlTemplate = htmlTemplate.replace('target=_blank', "tabindex=0"); 3568 3569 //remove id from the htmlTemplate id="divId" 3570 htmlTemplate = htmlTemplate.replace("class='dashboardTemplate DashTempshowSlide DashTempfade'>", `id="${divId}" class='dashboardTemplate DashTempshowSlide DashTempfade'>`); 3571
3572 if (!isContainerEmpty(".dashboardSlidercontainer")) { 3573 $(".dashboardSlidercontainer").append(htmlTemplate); 3574 $("#nav-bullets").append("<div class=\"nav-bullet\" onclick=\"currentSlide(1)\"></div>"); 3575 } 3576 LeadOffer.offerShown = "yes"; 3577 applyAccessibilityAttributes(`#${divId} .dashboardTemplateTileLink`, offerElement); 3578 addUrlAndClickEvent(divId, offerElement); 3579 } else { 3580 logInfo("Dashboard offer content not available"); 3581 LeadOffer.errorData = "No Content Available"; 3582 LeadOffer.offerShown = "no"; 3583 } 3584 3585 logToGlobalDataLayer(LeadOffer); 3586} 3587function bindDashboardQuizInitiator(quizInitiator) { 3588 const $warrantyPlacement = $("#dy-mastiff-warranty"); 3589 if (!$warrantyPlacement.length) return; 3590 3591 const showDashboardQuizModal = function () { 3592 logInfo("[Dashboard Quiz] Initiator selected; revealing the prepared Quiz Portal modal."); 3593 $("#mastiff-modal-cpc-content .sposQuizSpinner").remove(); 3594 if (uiState.quiztype === "cpc") { 3595 $("#mastiff-modal-cpc-content .CPConfiguratorContainer").show(); 3596 } else if (uiState.quiztype === "huq") { 3597 $("#mastiff-modal-cpc-content .HUQConfiguratorContainer").show(); 3598 } 3599 $("#mastiff-modal-cpc, #mastiff-overlay").show(); 3600 }; 3601 3602 $warrantyPlacement 3603 .off(".dashboardQuiz") 3604 .on("click.dashboardQuiz", function (event) { 3605 event.preventDefault(); 3606 showDashboardQuizModal(); 3607 }).on("keydown.dashboardQuiz", function (event) { 3608 const key = event.key || event.which; 3609 if (key === "Enter" || key === " " || key === 13 || key === 32) { 3610 event.preventDefault(); 3611 showDashboardQuizModal(); 3612 } 3613 }); 3614 3615 $(document).off("click.dashboardQuizDiscard", "#mastiff-modal-cpc-close, #mastiff-overlay") 3616 .on("click.dashboardQuizDiscard", "#mastiff-modal-cpc-close, #mastiff-overlay", function (event) { 3617 if (this.id === "mastiff-overlay" && event.target !== this) return; 3618 3619 logInfo("[Dashboard Quiz] Modal dismissed; sending the Quiz Portal discard report for the initiator.", quizInitiator.name); 3620 discardQuizPortalExperience(quizInitiator.name); 3621 }); 3622} 3623 3624function showWarrantyDashboardOffer(offerElement, openLinkInNewTab) { 3625 const warrantyTileContainerId = "dy-mastiff-warranty"; 3626 3627 return waitForElement("#" + warrantyTileContainerId).then(() => { 3628 3629 var divId = ""; 3630 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 3631 3632 var LeadOffer = {}; 3633 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 3634 LeadOffer.OfferID = divId; 3635 LeadOffer.OfferClicked = "no"; 3636 LeadOffer.SPOStemplate = "10"; 3637 3638 if (isDefined(offerElement.primaryButtonText) && 3639 isDefined(offerElement.storeURL) && 3640 isDefined(offerElement.html)) { 3641 var renderedDivId = null; 3642 logInfo("Warranty dashboard offer content available"); 3643 if (isContainerEmpty(`#${warrantyTileContainerId}`)) { 3644 //$("#" + warrantyTileContainerId).attr("tabindex", "0"); 3645 var html = offerElement.html; 3646 html = html.replace(/{cta}/g, offerElement.primaryButtonText); 3647 html = html.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)"); 3648 html = html.replace("id=%DashboardTileCTAId%", ""); 3649 html = html.replace("%DashboardTileDescriptionplaceholder%", offerElement.primaryText2); 3650 html = html.replace("%DashboardTileCTAplaceholder%", offerElement.primaryButtonText); 3651 html = html.replace("tabindex=0", ""); 3652 html = html.replace("class=oldDashboardTemplate", `id="${divId}" class='oldDashboardTemplate'`); 3653 html = html.replace('target=_blank', "tabindex=0"); 3654 3655 $("#" + warrantyTileContainerId).html(html); 3656 3657 $("#" + warrantyTileContainerId).find(".oldDashboardTemplateTileHeader").remove(); 3658 $("#" + warrantyTileContainerId).find(".oldDashboardTemplateDescContainer").remove(); 3659 3660 $("#" + warrantyTileContainerId).removeClass("hidden"); 3661 $("#" + warrantyTileContainerId).addClass("show"); 3662 LeadOffer.offerShown = "yes"; 3663 3664 3665 applyAccessibilityAttributes(`#${divId} .oldDashboardTemplateTileLink `, offerElement); 3666 addUrlAndClickEvent(divId, offerElement, openLinkInNewTab); 3667 3668 logInfo("Warranty dashboard offer HTML inserted", offerElement); 3669 renderedDivId = divId; 3670 } else { 3671 LeadOffer.errorData = "Warranty Dashboard Offer Location is not empty"; 3672 LeadOffer.offerShown = "no"; 3673 } 3674 3675 logToGlobalDataLayer(LeadOffer); 3676 return renderedDivId; 3677 } else { 3678 logInfo("Warranty dashboard offer content not available"); 3679 LeadOffer.errorData = "No Content Available"; 3680 LeadOffer.offerShown = "no"; 3681 logToGlobalDataLayer(LeadOffer); 3682 return null; 3683 } 3684 }).catch((err) => { 3685 logInfo("Error waiting for warranty tile container:", err); 3686 return null; 3687 });
3688} 3689 3690function showSingleDashboardTileOffer(primaryOfferElement) { 3691 waitForElement("#dashboard_tile_instantink_print").then(() => { 3692 var divId = ""; 3693 divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name); 3694 3695 var LeadOffer = {}; 3696 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 3697 LeadOffer.OfferID = divId; 3698 LeadOffer.OfferClicked = "no"; 3699 LeadOffer.SPOStemplate = "10"; 3700 3701 if ( 3702 isDefined(primaryOfferElement.html) && 3703 isDefined(primaryOfferElement.primaryText1) && 3704 isDefined(primaryOfferElement.primaryButtonText) && 3705 isDefined(primaryOfferElement.imageURL) && 3706 isDefined(primaryOfferElement.storeURL) 3707 ) { 3708 3709 logInfo("offer content available"); 3710 if (isContainerEmpty("#dashboard_tile_instantink_print")) { 3711 $("#dashboard_tile_instantink_print").attr("tabindex", "0"); 3712 var html = primaryOfferElement.html; 3713 3714 html = html.replace("%DashboardTileImgplaceholder%", primaryOfferElement.imageURL); 3715 html = html.replace("%DashboardTileTitleplaceholder%", primaryOfferElement.primaryText1); 3716 html = html.replace("%DashboardTileDescriptionplaceholder%", primaryOfferElement.primaryText2); 3717 html = html.replace("%DashboardTileCTAplaceholder%", primaryOfferElement.primaryButtonText); 3718 html = html.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)"); 3719 html = html.replace("tabindex=0", ""); 3720 html = html.replace("id=%DashboardTileCTAId%", ""); 3721 html = html.replace("class=oldDashboardTemplate", `id="${divId}" class='dashboardTemplate'`); 3722 html = html.replace('target=_blank', "tabindex=0"); 3723 3724 $("#dashboard_tile_instantink_print").show(); 3725 $("#dashboard_tile_instantink_print").html(html); 3726 LeadOffer.offerShown = "yes"; 3727 3728 applyAccessibilityAttributes(`#${divId} .dashboardTemplateTileLink`, primaryOfferElement); 3729 addUrlAndClickEvent(divId, primaryOfferElement); 3730 3731 logInfo("Offer HTML inserted in ", primaryOfferElement); 3732 } else { 3733 LeadOffer.errorData = "SPOS Primary Offer Location is not empty"; 3734 LeadOffer.offerShown = "no"; 3735 } 3736 logToGlobalDataLayer(LeadOffer); 3737 } else { 3738 logInfo("offer content not available"); 3739 LeadOffer.errorData = "No Content Available"; 3740 LeadOffer.offerShown = "no"; 3741 logToGlobalDataLayer(LeadOffer); 3742 } 3743 3744 hideContainer("#dashboard_tile_instantink_print"); 3745 }).catch((err) => { 3746 logInfo("Error waiting for dashboard tile container:", err); 3747 }); 3748} 3749 3750async function showCartidgesDashboardOffer(offerElement) { 3751 const cartidgesTileContainerId = "compatibleCartridgesTile"; 3752 3753 await waitForElement("#" + cartidgesTileContainerId); 3754 3755 var divId = ""; 3756 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 3757 3758 var LeadOffer = {}; 3759 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 3760 LeadOffer.OfferID = divId; 3761 LeadOffer.OfferClicked = "no"; 3762 LeadOffer.SPOStemplate = "10"; 3763 3764 if ( 3765 isDefined(offerElement.imageURL) && 3766 isDefined(offerElement.primaryText1) && 3767 isDefined(offerElement.primaryButtonText) && 3768 isDefined(offerElement.storeURL) && 3769 isDefined(offerElement.html) 3770 ) { 3771 logInfo("Cartidges dashboard offer content available"); 3772 if (isContainerEmpty(`#${cartidgesTileContainerId}`)) { 3773 $("#" + cartidgesTileContainerId).attr("tabindex", "0"); 3774 3775 var html = offerElement.html; 3776 3777 html = html.replace("%DashboardTileImgplaceholder%", offerElement.imageURL); 3778 html = html.replace("%DashboardTileTitleplaceholder%", offerElement.primaryText1); 3779 html = html.replace("%DashboardTileDescriptionplaceholder%", offerElement.primaryText2); 3780 html = html.replace("%DashboardTileCTAplaceholder%", offerElement.primaryButtonText); 3781 html = html.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)"); 3782 html = html.replace("tabindex=0", ""); 3783 html = html.replace("id=%DashboardTileCTAId%", ""); 3784 html = html.replace("class=oldDashboardTemplate", `id="${divId}" class='dashboardTemplate'`); 3785 html = html.replace('target=_blank', "tabindex=0"); 3786 3787 $("#" + cartidgesTileContainerId).html(html).show(); 3788 $("#" + cartidgesTileContainerId).removeClass("hidden"); 3789 3790 LeadOffer.offerShown = "yes"; 3791 3792 //applyAccessibilityAttributes(cartidgesTileContainerId, offerElement); 3793 applyAccessibilityAttributes(`#${divId} .dashboardTemplateTileLink`, offerElement); 3794 3795 addUrlAndClickEvent(divId, offerElement); 3796 3797 logInfo("Cartidges dashboard offer HTML inserted", offerElement); 3798 } else { 3799 LeadOffer.errorData = "Cartidges Dashboard Offer Location is not empty"; 3800 LeadOffer.offerShown = "no"; 3801 } 3802 3803 logToGlobalDataLayer(LeadOffer); 3804 } else { 3805 logInfo("Cartidges dashboard offer content not available"); 3806 LeadOffer.errorData = "No Content Available"; 3807 LeadOffer.offerShown = "no"; 3808 logToGlobalDataLayer(LeadOffer); 3809 } 3810} 3811 3812var contactPageConfigs = { 3813 "primary-contact": { 3814 matchCondition: (offer) => !offer.category?.startsWith("phone-support") && offer.templatePosition === "primary", 3815 containerDivId: "contact_option_mastiff_tile_template", 3816 parentClass: "contact-options-container", 3817 templateNumber: "11", 3818 isValid: (offer) => ( 3819 isDefined(offer.primaryText1) && isDefined(offer.primaryText2) && 3820 isDefined(offer.imageURL) && isDefined(offer.storeURL) && isDefined(offer.primaryButtonText) 3821 ), 3822 renderTemplate: (offer, offerDivId) => { 3823 return offer.html 3824 .replace("%falconContactHPImgURLPlaceholder%", offer.imageURL) 3825 .replace("%falconContactHPOfferTitlePlaceholder%", offer.primaryText1) 3826 .replace("%falconContactHPOfferDescriptionPlaceholder%", offer.primaryText2) 3827 .replace("%falconContactHPOfferCTAPlaceholder%", offer.primaryButtonText) 3828 .replace("%falconContactHPOfferIdPlaceholder%", offerDivId); 3829 }, 3830 adjustStyles: (containerDivId) => { 3831 if (!containerDivId) return; 3832 const container = $(`#${containerDivId}`).parent(); 3833 if (container.hasClass("preffered-border-mastiff")) { 3834 $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivPreffered"); 3835 } else { 3836 $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivNonPreffered"); 3837 } 3838 $(".contactPageMastiffTemplateDescription").css("margin-bottom", `${$(".contactPageMastiffTemplateContainer").parent().height() - 325}px`); 3839 } 3840 }, 3841 "secondary-contact": { 3842 matchCondition: (offer) => offer.templatePosition === "secondary", 3843 containerDivId: "contact_resource_mastiff_template", 3844 parentClass: "support-resource-cards", 3845 templateNumber: "11", 3846 isValid: (offer) => ( 3847 isDefined(offer.primaryText1) && isDefined(offer.primaryText2) && 3848 isDefined(offer.imageURL) && isDefined(offer.storeURL) && isDefined(offer.primaryButtonText) 3849 ), 3850 renderTemplate: (offer, offerDivId) => { 3851 return offer.html 3852 .replace("%imageurlPlaceholder%", offer.imageURL) 3853 .replace("%titlePlaceholder%", offer.primaryText1) 3854 .replace("%descriptionPlaceholder%", offer.primaryText2) 3855 .replace("%ctaPlaceholder%", offer.primaryButtonText) 3856 .replace("%secondaryContactHPOfferIdPlaceholder%", offerDivId); 3857 }, 3858 adjustStyles: () => { } 3859 }, 3860 "phone-support": { 3861 matchCondition: (offer) => offer.category?.startsWith("phone-support") && offer.templatePosition === "primary", 3862 containerDivId: "phone_fee_mastiff_tile_template", 3863 parentClass: "contact-options-container", 3864 templateNumber: "11", 3865 isValid: (offer) => ( 3866 isDefined(offer.primaryText1) && isDefined(offer.primaryText2) && 3867 isDefined(offer.imageURL) && isDefined(offer.storeURL) && isDefined(offer.primaryButtonText) 3868 ), 3869 renderTemplate: (offer, offerDivId) => { 3870 return offer.html 3871 .replace("%falconContactHPImgURLPlaceholder%", offer.imageURL) 3872 .replace("%falconContactHPOfferTitlePlaceholder%", offer.primaryText1) 3873 .replace("%falconContactHPOfferDescriptionPlaceholder%", offer.primaryText2) 3874 .replace("%falconContactHPOfferCTAPlaceholder%", offer.primaryButtonText) 3875 .replace("%falconContactHPOfferIdPlaceholder%", offerDivId); 3876 }, 3877 adjustStyles: (containerDivId) => { 3878 if (!containerDivId) return; 3879 const container = $(`#${containerDivId}`).parent(); 3880 if (container.hasClass("preffered-border-mastiff")) { 3881 $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivPreffered"); 3882 } else { 3883 $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivNonPreffered"); 3884 } 3885 $(".contactPageMastiffTemplateDescription").css("margin-bottom", `${$(".contactPageMastiffTemplateContainer").parent().height() - 325}px`); 3886 } 3887 }, 3888 "warranty-widget": { 3889 matchCondition: (offer) => safeLower(offer.category).startsWith("warranty widget") && safeLower(offer.templatePosition) === "wtywidget", 3890 containerDivId: "mastiff-extend-wty-contact", 3891 parentClass: "device-details-container", 3892 templateNumber: "4", 3893 isValid: (offer) => ( 3894 isDefined(offer.html) 3895 && isDefined(offer.storeURL) 3896 && isDefined(offer.primaryButtonText) 3897 ), 3898 renderTemplate: (offer, offerDivId) => { 3899 return offer.html 3900 .replace("{cta}", offer.primaryButtonText) 3901 .replace("{imageurl}", offer.imageURL) 3902 .replace("%simpleLinkTemplateId%", offerDivId) 3903 }, 3904 adjustStyles: (containerDivId) => { 3905 if (!containerDivId) return; 3906 const $container = $(`#${containerDivId}`); 3907 if ($container.length > 0) { 3908 $container.children().first().css("margin-top", "0"); 3909 } 3910 3911 } 3912 } 3913}; 3914 3915function handleContactPageOffers(element) { 3916 const config = Object.values(contactPageConfigs).find(cfg => cfg.matchCondition(element)); 3917 if (!config) { 3918 logInfo(`No valid configuration found for contact page offer: ${element.category}`); 3919 return; 3920 } 3921 3922 showOffer(element, config) 3923 .finally(() => { 3924 hideContainer(`#${config.containerDivId}`); 3925 }); 3926
3927 async function showOffer(offer, config) { 3928 await waitForElement(`#${config.containerDivId}`, `.${config.parentClass}` || "", 5000); 3929 3930 const offerDivId = `SPOS_${offer.templatePosition}_${offer.name}`; 3931 var LeadOffer = { 3932 OfferID: offerDivId, 3933 OfferClicked: "no", 3934 offerShown: "no", 3935 SPOStemplate: config.templateNumber, 3936 }; 3937 3938 if (!config.isValid(offer)) { 3939 logInfo(`Invalid offer content for offer ${offerDivId}`, offer); 3940 LeadOffer.errorData = "Invalid Offer Content"; 3941 logToGlobalDataLayer(LeadOffer); 3942 return; 3943 } 3944 3945 const htmlTemplate = config.renderTemplate(offer, offerDivId); 3946 3947 if (!isContainerEmpty(`#${config.containerDivId}`)) { 3948 logInfo(`Skipping offer insertion due to non-empty container: ${config.containerDivId}`); 3949 LeadOffer.errorData = "Container not empty"; 3950 logToGlobalDataLayer(LeadOffer); 3951 return; 3952 } 3953 3954 $(`#${config.containerDivId}`).html(htmlTemplate).show().removeClass("hidden"); 3955 config.adjustStyles(config.containerDivId); 3956 applyAccessibilityAttributes(offerDivId, offer); 3957 addUrlAndClickEvent(offerDivId, offer); 3958 LeadOffer.offerShown = "yes"; 3959 logInfo(`Offer HTML inserted in #${config.containerDivId}`, offer); 3960 logToGlobalDataLayer(LeadOffer); 3961 } 3962} 3963 3964// ---------------- Contact Solution Offer Rendering ---------------- 3965function renderContactSolutionOffer(offerElement) { 3966 const divId = `${offerElement.templatePosition}_${offerElement.name}`; 3967 3968 var LeadOffer = { 3969 OfferID: divId, 3970 OfferClicked: "no", 3971 offerShown: "no", 3972 errorData: "", 3973 SPOStemplate: "33" 3974 }; 3975 3976 // Validate required fields 3977 if (!( 3978 isDefined(offerElement.primaryText1) && 3979 isDefined(offerElement.primaryText2) && 3980 isDefined(offerElement.storeURL) && 3981 isDefined(offerElement.imageURL) && 3982 isDefined(offerElement.primaryButtonText) 3983 )) { 3984 LeadOffer.errorData = "Missing Required Fields"; 3985 logInfo("Contact Solution offer missing required fields", offerElement); 3986 logToGlobalDataLayer(LeadOffer); 3987 return false; 3988 } 3989 3990 const containerSelector = "#mastiff-pfw-contact-solutions"; 3991 return waitForElement(containerSelector, "", 10000) 3992 .then(() => { 3993 if (!isContainerEmpty(containerSelector)) { 3994 LeadOffer.errorData = "Container not empty"; 3995 logToGlobalDataLayer(LeadOffer); 3996 logInfo("Contact Solution container not empty; skipping", containerSelector); 3997 return false; 3998 } 3999 4000 var templateHtml = offerElement.html || ""; 4001 templateHtml = templateHtml.replace("%{divId}%", divId); 4002 templateHtml = templateHtml.replace("{title}", offerElement.primaryText1 || ""); 4003 templateHtml = templateHtml.replace("{description}", offerElement.primaryText2 || ""); 4004 templateHtml = templateHtml.replace("{cta}", offerElement.primaryButtonText || ""); 4005 templateHtml = templateHtml.replace("{imageurl}", offerElement.imageURL || ""); 4006 4007 $(containerSelector).html(templateHtml).removeClass("hidden").show(); 4008 4009 // Accessibility 4010 applyAccessibilityAttributes(divId, offerElement); 4011 addUrlAndClickEvent("#" + divId + " .CDCOfferCTA", offerElement, true); 4012 4013 LeadOffer.offerShown = "yes"; 4014 logToGlobalDataLayer(LeadOffer); 4015 logInfo("Contact Solution offer rendered", offerElement); 4016 return true; 4017 }) 4018 .catch(err => { 4019 logInfo("Contact Solution container not found within timeout", err); 4020 return false; 4021 }); 4022} 4023 4024async function showStickyBannerSecondaryOffer(offerElement, containerDivId, offerDivId) { 4025 await waitForElement("#" + containerDivId); 4026 4027 var divId = ""; 4028 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 4029 4030 var LeadOffer = {}; 4031 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4032 LeadOffer.OfferID = divId; 4033 LeadOffer.OfferClicked = "no"; 4034 LeadOffer.SPOStemplate = "22"; 4035 4036 if ( 4037 isDefined(offerElement.html) && 4038 isDefined(offerElement.primaryText1) && 4039 isDefined(offerElement.primaryButtonText) && 4040 isDefined(offerElement.storeURL) 4041 ) { 4042 4043 logInfo("offer content available"); 4044 if (isContainerEmpty(`#${containerDivId}`) || samePage) { 4045 var html = offerElement.html; 4046 html = html.replace("{title}", offerElement.primaryText1 || ""); 4047 html = html.replace("{cta}", offerElement.primaryButtonText || ""); 4048 html = html.replace("%stickyFooterOfferId%", divId); 4049 4050 $("#" + containerDivId).show(); 4051 $("#" + containerDivId).removeClass('hidden'); 4052 $("#" + offerDivId).show(); 4053 $("#" + offerDivId).html(html); 4054 LeadOffer.offerShown = "yes"; 4055 offerNameForDecline = offerElement.name; 4056 4057 applyAccessibilityAttributes(divId, offerElement); 4058 addUrlAndClickEvent(divId, offerElement); 4059 } else { 4060 LeadOffer.errorData = "SPOS Primary Offer Location is not empty"; 4061 LeadOffer.offerShown = "no"; 4062 } 4063 logToGlobalDataLayer(LeadOffer); 4064 } else { 4065 logInfo("offer content not available"); 4066 LeadOffer.errorData = "No Content Available"; 4067 LeadOffer.offerShown = "no"; 4068 logToGlobalDataLayer(LeadOffer); 4069 } 4070 4071 hideContainer(`#${containerDivId}`, "hide"); 4072} 4073 4074function hideStickyBannerSecondaryOffer_closeAction() { 4075 var offerDeclined = ""; 4076 if (pgName === "document") { 4077 hideContainer("#document-mastiff-banner-container", "hide", false); 4078 offerDeclined = $("#document-mastiff-banner-container").find("[data-offer-name]").attr("data-offer-name"); 4079 } 4080 4081 if (pgName === "service") {
4082 hideContainer("#sdp-mastiff-banner-container", "hide", false); 4083 offerDeclined = $("#sdp-mastiff-banner-container").find("[data-offer-name]").attr("data-offer-name"); 4084 } 4085 4086 if (pgName === "help-windows") { 4087 hideContainer("#mastiff-sticky-banner", "hide", false); 4088 offerDeclined = $("#mastiff-sticky-banner").find("[data-offer-name]").attr("data-offer-name"); 4089 } 4090 4091 if (pgName === "drivers_details") { 4092 hideContainer("#mastiff-sticky-banner-swd", "hide", false); 4093 offerDeclined = $("#mastiff-sticky-banner-swd").find("[data-offer-name]").attr("data-offer-name"); 4094 } 4095 4096 if (pgName === "repair" || pgName === "hardware-diagnostics") { 4097 hideContainer("#mastiff-sticky-banner-swd", "hide", false); 4098 offerDeclined = $("#mastiff-sticky-banner-swd").find("[data-offer-name]").attr("data-offer-name"); 4099 } 4100 4101 offerDeclineEvent(reqObj, offerDeclined); 4102} 4103 4104function hideServiceSecondaryOffer_closeAction() { 4105 hideContainer("#sdp-mastiff-banner-container", "hide", false); 4106 offerDeclineEvent(reqObj, offerNameForDecline); 4107} 4108 4109function showHelpPrimaryOffer(offerElement) { 4110 waitForElement("#mastiff-diag-banner", "", 5000).then(function () { 4111 var divId = ""; 4112 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 4113 4114 var LeadOffer = {}; 4115 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4116 LeadOffer.OfferID = divId; 4117 LeadOffer.OfferClicked = "no"; 4118 LeadOffer.SPOStemplate = "15"; 4119 if (isDefined(offerElement.html) 4120 && isDefined(offerElement.storeURL) 4121 && isDefined(offerElement.primaryButtonText) 4122 && isDefined(offerElement.primaryText1) 4123 && isDefined(offerElement.primaryText2) 4124 && isDefined(offerElement.imageURL)) { 4125 4126 if (isContainerEmpty("#mastiff-diag-banner")) { 4127 var html = offerElement.html; 4128 html = html.replace("%imageurlPlaceholder%", offerElement.imageURL); 4129 html = html.replace("%titlePlaceholder%", offerElement.primaryText1); 4130 html = html.replace("%descriptionPlaceholder%", offerElement.primaryText2); 4131 html = html.replace("%ctaPlaceholder%", offerElement.primaryButtonText); 4132 html = html.replace("%PrimaryDiagnosticsTabsTileOfferIdPlaceholder%", divId); 4133 4134 $("#mastiff-diag-banner").removeClass("hidden"); 4135 $("#mastiff-diag-banner").html(html).show(); 4136 4137 allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency); 4138 applyAccessibilityAttributes(divId, offerElement); 4139 addUrlAndClickEvent(divId, offerElement); 4140 LeadOffer.offerShown = "yes"; 4141 logInfo("Help Primary offer HTML inserted", offerElement); 4142 } else { 4143 logInfo("Help Primary offer content location not empty"); 4144 LeadOffer.errorData = "Help Primary Offer Location is not empty"; 4145 LeadOffer.offerShown = "no"; 4146 } 4147 logToGlobalDataLayer(LeadOffer); 4148 } else { 4149 logInfo("Help Primary offer content not available"); 4150 LeadOffer.errorData = "No Content Available"; 4151 LeadOffer.offerShown = "no"; 4152 logToGlobalDataLayer(LeadOffer); 4153 } 4154 }).finally(() => { 4155 hideContainer("#mastiff-diag-banner", "hidden") 4156 }); 4157} 4158 4159/** 4160 * Renders OW Diagnostics child offers into .oneRowThreeColumnsContainer under #mastiff-diag-banner. 4161 * Pulls offers whose templatePosition starts with "owDiags" from offerResults, 4162 * sorts by numeric suffix (owDiags_X), and delegates to standardRenderOffer. 4163 */ 4164function renderOwDiagnosticsOffers(offerResults) { 4165 if (!offerResults || !offerResults.offers || !offerResults.offers.offer) return; 4166 4167} 4168 4169function handlePDPintentOffer(offerElement) { 4170 const pdpIntentCategoryConfigs = { 4171 "setup-user-guides": { 4172 matchCondition: (offer) => offer.category?.startsWith("setup-user-guides"), 4173 containerDivId: "mastiff_check_available_security_and_software_PDP_setup_user_guides", 4174 parentClass: "setup-user-guide-content", 4175 templateNumber: "2", 4176 renderTemplate: (offer, offerDivId) => { 4177 return offer.html 4178 .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText) 4179 .replace("%simpleButtonTemplateId%", offerDivId); 4180 }, 4181 adjustStyles: (offerDivId) => { 4182 $("#" + offerDivId).css("margin-bottom", "2rem"); 4183 }, 4184 }, 4185 "tools-dignostics": { 4186 matchCondition: (offer) => offer.category?.startsWith("tools-dignostics"), 4187 containerDivId: "mastiff_check_available_security_and_software_PDP_product-related-documents", 4188 parentClass: "tools-diagnostics-content", 4189 templateNumber: "2", 4190 renderTemplate: (offer, offerDivId) => { 4191 return offer.html 4192 .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText) 4193 .replace("%simpleButtonTemplateId%", offerDivId); 4194 }, 4195 adjustStyles: (offerDivId) => { 4196 $("#" + offerDivId).css("margin-bottom", "2rem"); 4197 }, 4198 }, 4199 "warranty-repair-double": { 4200 matchCondition: (offer) => offer.category?.startsWith("warranty-repair") && offer.category.indexOf("anonymous") === -1, 4201 containerDivId: "mastiff_explore_warranty_options_PDP", 4202 parentClass: "", 4203 templateNumber: offerElement.templatePosition === "shop2" ? "26" : "4", 4204 renderTemplate: (offer, offerDivId) => { 4205 if (offer.templatePosition === "shop2") { 4206 return offer.html 4207 .replace("{cta}", offer.primaryButtonText) 4208 .replace("%PromoTileId%", offerDivId) 4209 .replace("{imageurl}", offer.imageURL || "") 4210 } else { 4211 return offer.html 4212 .replace("{cta}", offer.primaryButtonText) 4213 .replace("%simpleButtonTemplateId%", offerDivId) 4214 } 4215 }, 4216 adjustStyles: (offerDivId) => { 4217 4218 }, 4219 multipleOffersSupported: () => true, 4220 initContainer: (containerDivId, offer) => { 4221 const parentContainer = $("#mastiff_explore_warranty_options_PDP"); 4222 4223 var customContainer = $(`#custom_warranty_options_container`); 4224 if (customContainer.length === 0) { 4225 customContainer = $(`<div id="custom_warranty_options_container"> <style> #custom_warranty_options_container { display: flex; gap: 1rem; justify-content: flex-start; flex-wrap: wrap; } @media screen and (max-width: 600px) { #custom_warranty_options_container { flex-direction: column; } } </style> </div>`);
4226 parentContainer.append(customContainer); 4227 } 4228 4229 const wrapperId = `WRP_${offer.templatePosition}_${offer.name}`; 4230 if (!document.getElementById(wrapperId)) { 4231 const htmlWrapper = `<div class="intent-offer" id="${wrapperId}"></div>`; 4232 if (offer.templatePosition === "shop2") { 4233 customContainer.prepend(htmlWrapper); 4234 } else { 4235 customContainer.append(htmlWrapper); 4236 } 4237 } 4238 customContainer.removeClass("hidden").show(); 4239 }, 4240 getTargetPlaceholder: (offer) => { 4241 return `WRP_${offer.templatePosition}_${offer.name}`; 4242 } 4243 }, 4244 4245 "warranty-repair-anonymous": { 4246 matchCondition: (offer) => offer.category?.startsWith("warranty-repair") && offer.category.indexOf("anonymous") !== -1, 4247 containerDivId: "mastiff_check_available_security_and_software_PDP_warranty_and_repair", 4248 parentClass: "warranty-repair-content", 4249 templateNumber: "2", 4250 renderTemplate: (offer, offerDivId) => { 4251 return offer.html 4252 .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText) 4253 .replace("%simpleButtonTemplateId%", offerDivId); 4254 }, 4255 adjustStyles: (offerDivId) => { 4256 $("#" + offerDivId).css("margin-bottom", "2rem"); 4257 }, 4258 }, 4259 "security-viruses": { 4260 matchCondition: (offer) => offer.category?.startsWith("security-viruses"), 4261 containerDivId: "mastiff_check_available_security_and_software_PDP", 4262 parentClass: "parent", 4263 templateNumber: "2", 4264 renderTemplate: (offer, offerDivId) => { 4265 return offer.html 4266 .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText) 4267 .replace("%simpleButtonTemplateId%", offerDivId); 4268 }, 4269 adjustStyles: (offerDivId) => { 4270 $("#" + offerDivId).css("margin-bottom", "2rem"); 4271 }, 4272 }, 4273 "ink-paper": { 4274 matchCondition: (offer) => offer.category?.startsWith("ink-paper") && offer.templatePosition != "shop1", 4275 containerDivId: "mastiff_shop_cartridges_PDP", 4276 parentClass: "", 4277 templateNumber: "2", 4278 renderTemplate: (offer, offerDivId) => { 4279 return offer.html 4280 .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText) 4281 .replace("%simpleButtonTemplateId%", offerDivId); 4282 }, 4283 adjustStyles: (offerDivId) => { 4284 $("#" + offerDivId).css("margin-bottom", "2rem"); 4285 }, 4286 }, 4287 "ink-paper-multiple": { 4288 matchCondition: (offer) => offer.category?.startsWith("ink-paper") && offer.templatePosition === "shop1", 4289 containerDivId: "mastiff_shop_cartridges_PDP", 4290 parentClass: "", 4291 templateNumber: "23", 4292 renderTemplate: (offer, offerDivId) => { 4293 return offer.html 4294 .replace("%{title}%", offer.primaryText1) 4295 .replace("%{description}%", offer.primaryText2) 4296 .replace("%{imageurl}%", offer.imageURL) 4297 .replace("%{cta}%", offer.primaryButtonText) 4298 .replace("%simpleButtonTemplateId%", offerDivId); 4299 }, 4300 adjustStyles: (offerDivId) => { 4301 $("#" + offerDivId).css("display", "flex"); 4302 }, 4303 multipleOffersSupported: (offer) => offer.templatePosition === "shop1", 4304 initContainer: (containerDivId) => { 4305 const flexId = "InkPaperOffersFlexContainer"; 4306 if (!document.getElementById(flexId)) { 4307 const InkPaperContainer = `<div id=${flexId} class=InkPaperOffersContainer> <style> .InkPaperOffersContainer { display: flex; flex-wrap: wrap; } .InkPaperOfferTile { flex-direction: column; align-items: center; width: calc(49% - 18px); background: #fff; box-shadow: 0 1px 4px 1px #21212133; border-radius: 16px; margin: 1.5%; display: none; } .InkPaperOfferTile .troubleshootingOfferCTA { background-color: #0278AB !important; color: #fff !important; border: none; padding: 9px 21px !important; } .InkPaperOfferTile .troubleshootingOfferCTA:hover { background-color: #035C84 !important; border: none; color: #fff !important; } .InkPaperOfferTile .troubleshootingOfferCTA:active, .InkPaperOfferTile .troubleshootingOfferCTA:focus { background-color: #015985 !important; border: none; color: #fff !important; } @media screen and (max-width : 600px) { .InkPaperOffersContainer { flex-direction: column; } .InkPaperOfferTile { width: 100%; margin: 0px; margin-bottom: 10px; } } </style> </div>`; 4308 $(`#${containerDivId}`).append(InkPaperContainer).removeClass("hidden").show(); 4309 } 4310 }, 4311 getTargetPlaceholder: (offer) => { 4312 const wrapperId = `WRP_${offer.templatePosition}_${offer.name}`; 4313 const container = $("#InkPaperOffersFlexContainer"); 4314
4315 if (!document.getElementById(wrapperId)) { 4316 const wrapper = `<div class="InkPaperOfferTile" id="${wrapperId}"></div>`; 4317 container.append(wrapper); 4318 } 4319 4320 return wrapperId; 4321 } 4322 }, 4323 "troubleshooting": { 4324 matchCondition: (offer) => offer.category?.startsWith("troubleshooting"), 4325 containerDivId: "Mastiff_Troubleshooting", 4326 parentClass: "", 4327 templateNumber: "2", 4328 renderTemplate: (offer, offerDivId) => { 4329 const containerSelector = `#${pdpIntentCategoryConfigs["troubleshooting"].containerDivId}`; 4330 const templateContainer = document.createElement("div"); 4331 templateContainer.innerHTML = offer.html; 4332 4333 const templateDiv = templateContainer.querySelector(".troubleshootingOfferTemplate") || templateContainer.querySelector("div"); 4334 4335 templateDiv.innerHTML = templateDiv.innerHTML 4336 .replace("%simpleButtonTemplateId%", offerDivId) 4337 .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText); 4338 4339 waitForElement(containerSelector, ".option-details", 5000).then(() => { 4340 const container = document.querySelector(containerSelector); 4341 4342 const optionCard = document.querySelector(".option-card"); 4343 if (optionCard) { 4344 const ngContentAttr = optionCard.getAttributeNames().find(name => 4345 name.startsWith("_ngcontent") 4346 ); 4347 if (ngContentAttr) { 4348 container.setAttribute(ngContentAttr, ""); 4349 } 4350 } 4351 4352 const redictionTxt = document.querySelector(".rediction-txt"); 4353 if (redictionTxt?.firstChild) { 4354 const redictionTxtCopy = redictionTxt.cloneNode(true); 4355 copyStyles(redictionTxt.firstChild, redictionTxtCopy.firstChild); 4356 templateDiv.appendChild(redictionTxtCopy); 4357 } 4358 }); 4359 4360 return templateDiv; 4361 }, 4362 adjustStyles: (offerDivId) => { 4363 $("#" + offerDivId).css("display", "flex"); 4364 }, 4365 }, 4366 }; 4367 4368 const categoryConfig = Object.values(pdpIntentCategoryConfigs).find(cfg => cfg.matchCondition(offerElement)) || null; 4369 4370 showIntentOffer(offerElement, categoryConfig); 4371 4372 4373 async function showIntentOffer(offerElement, categoryConfig) { 4374 const offerDivId = `SPOS_${offerElement.templatePosition}_${offerElement.name}`; 4375 4376 var LeadOffer = {}; 4377 LeadOffer.OfferID = offerDivId; 4378 LeadOffer.OfferClicked = "no"; 4379 4380 if (!offerElement || !categoryConfig) { 4381 logInfo(`Invalid offer or category config for category: ${offerElement.category}`); 4382 LeadOffer.errorData = "Invalid Offer or Category Config"; 4383 LeadOffer.offerShown = "no"; 4384 logToGlobalDataLayer(LeadOffer); 4385 hideIntentBasedOffer(); 4386 return; 4387 } 4388 4389 const { 4390 containerDivId, 4391 parentClass, 4392 templateNumber, 4393 renderTemplate, 4394 adjustStyles, 4395 multipleOffersSupported, 4396 initContainer, 4397 getTargetPlaceholder 4398 } = categoryConfig; 4399 4400 LeadOffer.SPOStemplate = templateNumber; 4401 4402 var multipleOffers = typeof multipleOffersSupported === "function" 4403 ? multipleOffersSupported(offerElement) 4404 : multipleOffersSupported || false; 4405 4406 var targetContainerId = containerDivId; 4407 4408 if (!isDefined(offerElement.storeURL) || !isDefined(offerElement.primaryButtonText) || !isDefined(offerElement.html)) { 4409 logInfo(`Offer missing required fields for category: ${offerElement.category}`); 4410 LeadOffer.errorData = "No Content Available"; 4411 LeadOffer.offerShown = "no"; 4412 logToGlobalDataLayer(LeadOffer); 4413 hideIntentBasedOffer(); 4414 return; 4415 } 4416 4417 try { 4418 await waitForElement(`#${targetContainerId}
4418`, ".option-details", 5000); 4419 } catch (error) { 4420 logInfo(error); 4421 LeadOffer.errorData = "Placeholder " + targetContainerId + " not found"; 4422 LeadOffer.offerShown = "no"; 4423 logToGlobalDataLayer(LeadOffer); 4424 hideIntentBasedOffer(); 4425 return; 4426 } 4427 4428 if (multipleOffers) { 4429 if (typeof initContainer === "function") { 4430 initContainer(containerDivId, offerElement); 4431 } 4432 4433 if (typeof getTargetPlaceholder === "function") { 4434 const placeholder = getTargetPlaceholder(offerElement); 4435 if (!placeholder) { 4436 LeadOffer.errorData = "No available ink-paper placeholders"; 4437 LeadOffer.offerShown = "no"; 4438 logToGlobalDataLayer(LeadOffer); 4439 hideIntentBasedOffer(); 4440 return; 4441 } 4442 targetContainerId = placeholder; 4443 } 4444 } 4445 4446 if (intentBasedLocationEmpty || multipleOffers) { 4447 const htmlTemplate = renderTemplate(offerElement, offerDivId); 4448 4449 $(`#${targetContainerId}`).html(htmlTemplate).show(); 4450 4451 adjustStyles(targetContainerId); 4452 4453 if (isDefined(parentClass) && parentClass !== "parent") { 4454 $(`.${parentClass}`).removeClass("hidden"); 4455 } 4456 4457 $(`#${targetContainerId}`).removeClass("hidden"); 4458 4459 applyAccessibilityAttributes(offerDivId, offerElement); 4460 4461 addUrlAndClickEvent(offerDivId, offerElement); 4462 4463 LeadOffer.offerShown = "yes"; 4464 logInfo(`Offer rendered successfully for category: ${offerElement.category}`); 4465 if (!multipleOffers && document.getElementById(offerDivId)) { 4466 intentBasedLocationEmpty = false; 4467 } 4468 } else { 4469 logInfo("Intent Based Location is not empty", offerElement); 4470 LeadOffer.errorData = "Intent Based Location is not empty"; 4471 LeadOffer.offerShown = "no"; 4472 hideIntentBasedOffer(); 4473 } 4474 4475 logToGlobalDataLayer(LeadOffer); 4476 4477 function hideIntentBasedOffer() { 4478 if (intentBasedLocationEmpty) { 4479 if (isDefined(parentClass)) { 4480 if ((parentClass) === "parent") { 4481 hideContainer(`#${targetContainerId}`, "hideparent", false); 4482 } else { 4483 $(`.${parentClass}`).hide(); 4484 } 4485 } else { 4486 $(`#${targetContainerId}`).hide(); 4487 } 4488 } 4489 } 4490 4491 if (!multipleOffers) hideIntentBasedOffer(); 4492 } 4493} 4494 4495function copyStyles(sourceElement, targetElement) { 4496 const styles = getComputedStyle(sourceElement); 4497 for (const property in styles) { 4498 if (styles.hasOwnProperty(property)) { 4499 targetElement.style[property] = styles[property]; 4500 } 4501 } 4502} 4503 4504function showPromoTabOffer() { 4505 waitForElement("#mastiff_promotions_and_deals_PDP", ".support-options"); 4506 4507 if (offerResults.offerCount > 0) { 4508 4509 if (promoTitle[reqObj.user.language] !== undefined) { 4510 promoTab = promoTab.replace(/Promotions\s&\sdeals/, promoTitle[reqObj.user.language]) 4511 } 4512 for (i = 0; i < offerResults.offerCount; i++) { 4513 var element = offerResults.offers.offer[i]; 4514 if ((element.templatePosition === "primary" || element.templatePosition === "secondary") && !isDefined(element.category)) { 4515 var divId = ""; 4516 divId = divId.concat("SPOS_", element.templatePosition, "_", element.name); 4517 var LeadOffer = {}; 4518 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4519 LeadOffer.OfferID = divId; 4520 LeadOffer.OfferClicked = "no"; 4521 LeadOffer.SPOStemplate = "2"; 4522 4523 if ( 4524 isDefined(element.html) && 4525 isDefined(element.primaryText1) && 4526 isDefined(element.primaryText2) && 4527 isDefined(element.primaryButtonText) && 4528 isDefined(element.storeURL) 4529 ) { 4530 4531 var htmlTemplate = element.html; 4532 if (element.templatePosition === "primary") { 4533 4534 if (isContainerEmpty("#mastiff_promotions_and_deals_PDP")) { 4535 $("#mastiff_promotions_and_deals_PDP").append(promoTab); 4536 } 4537 if (isContainerEmpty(".promoPrimaryTile")) { 4538 htmlTemplate = htmlTemplate.replace("%PromoTileImgURLPlaceholder%", element.imageURL); 4539 htmlTemplate = htmlTemplate.replace("%PromoTileTitlePlaceholder%", element.primaryText1); 4540 htmlTemplate = htmlTemplate.replace("%PromoTileDescriptionPlaceholder%", element.primaryText2); 4541 htmlTemplate = htmlTemplate.replace("%PromoTileCTAPlaceholder%", element.primaryButtonText); 4542 htmlTemplate = htmlTemplate.replace("%PromoTileId%", divId); 4543 $(".promoPrimaryTile").html(htmlTemplate); 4544 4545 allocateRecEngPrices(element.strikePrice, element.incartPrice, divId, element.currency); 4546 4547 LeadOffer.offerShown = "yes"; 4548 applyAccessibilityAttributes(divId, element); 4549 addUrlAndClickEvent(divId, element); 4550 } else { 4551 LeadOffer.errorData = "Primary Location is not empty"; 4552 LeadOffer.offerShown = "no"; 4553 } 4554 logToGlobalDataLayer(LeadOffer); 4555 } else if (element.templatePosition === "secondary") { 4556 if (isContainerEmpty("#mastiff_promotions_and_deals_PDP")) { 4557 $("#mastiff_promotions_and_deals_PDP").append(promoTab); 4558 } 4559 if (isContainerEmpty(".promoSecondaryTile")) { 4560 htmlTemplate = htmlTemplate.replace("%PromoTileImgURLPlaceholder%", element.imageURL); 4561 htmlTemplate = htmlTemplate.replace("%PromoTileTitlePlaceholder%", element.primaryText1); 4562 htmlTemplate = htmlTemplate.replace("%PromoTileDescriptionPlaceholder%", element.primaryText2); 4563 htmlTemplate = htmlTemplate.replace("%PromoTileCTAPlaceholder%", element.primaryButtonText); 4564 htmlTemplate = htmlTemplate.replace("%PromoTileId%", divId); 4565 $(".promoSecondaryTile").html(htmlTemplate); 4566 4567 allocateRecEngPrices(element.strikePrice, element.incartPrice, divId, element.currency); 4568 4569 LeadOffer.offerShown = "yes"; 4570 4571 applyAccessibilityAttributes(divId, element); 4572 addUrlAndClickEvent(divId, element); 4573 } else { 4574 LeadOffer.errorData = "Secondary Location is not empty"; 4575 LeadOffer.offerShown = "no"; 4576 } 4577 4578 logToGlobalDataLayer(LeadOffer); 4579 } 4580 } 4581 else { 4582 LeadOffer.errorData = "No Content Available"; 4583 LeadOffer.offerShown = "no"; 4584 logToGlobalDataLayer(LeadOffer); 4585 } 4586 } else if (element.templatePosition === "shop1" || element.templatePosition === "shop2" || element.templatePosition === "shop3") { 4587 enablepdpCarousel = true; 4588 } 4589 } 4590 4591 } 4592 if (enablepdpCarousel) { 4593 showPromoShopOffers(); 4594 } 4595 4596} 4597 4598function showPromoShopOffers() { 4599 enablepdpCarousel = false; 4600 var elements = offerResults.offers.offer; 4601 var shopPositions = ["shop1", "shop2", "shop3"]; 4602 var sortedElements = elements.filter(element => shopPositions.includes(element.templatePosition) && element.category === null); 4603 sortedElements.sort((a, b) => shopPositions.indexOf(a.templatePosition) - shopPositions.indexOf(b.templatePosition)); 4604 4605 if (isContainerEmpty(".promoCarouselOffer")) { 4606 for (i = 0; i < sortedElements.length; i++) { 4607 PromoShopOfferContent(sortedElements[i], "Missing"); 4608 } 4609 } else { 4610 for (j = 1; j < 4; j++) { 4611 var getIndex = num => $(`div[id^="shop${num}"].promoCarouselOffer`).first().index('.promoCarouselOffer'); 4612 var firstShopIndex = getIndex(j) > -1 ? getIndex(j) : j === 1 && (getIndex(2) > -1 || getIndex(3) > -1) ? 0 : j === 2 && getIndex(3) > -1 ? getIndex(3) : "Missing"; 4613 var sortedShopElements = sortedElements.filter(sortedElement => (`shop${j}`).includes(sortedElement.templatePosition)); 4614 for (i = 0; i < sortedShopElements.length; i++) { 4615 PromoShopOfferContent(sortedShopElements[i], (firstShopIndex !== "Missing" ? firstShopIndex + i : "Missing")); 4616 } 4617 } 4618 } 4619 4620 if ($(".promoCarousel").length) { 4621 if (document.getElementsByClassName("promoCarouselOffer").length === 1) { 4622 var navigationDiv = document.getElementById('navigation'); 4623 navigationDiv.style.display = "none"; 4624 } 4625 $("#SPOS_navLeft").keypress(function (event) { 4626 var code = event.keyCode || event.which; 4627 if (code === 13) { 4628 nextSlide(-1); 4629 } 4630 }); 4631 $("#SPOS_navRight").keypress(function (event) { 4632 var code = event.keyCode || event.which; 4633 if (code === 13) { 4634 nextSlide(1); 4635 } 4636 }); 4637 sliderClassName = "promoCarouselOffer"; 4638 navBulletAvailable = false; 4639 displaySlides(slide_index); 4640 } 4641 4642} 4643 4644function PromoShopOfferContent(offerElement, firstIndex) { 4645 var divId = ""; 4646 divId = divId.concat("SPOS_", offerElement.templatePosition, "_", offerElement.name); 4647 var LeadOffer = {}; 4648 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4649 LeadOffer.OfferID = divId; 4650 LeadOffer.OfferClicked = "no"; 4651 LeadOffer.SPOStemplate = "2"; 4652 4653 if ( 4654 isDefined(offerElement.html) && 4655 isDefined(offerElement.primaryText1) && 4656 isDefined(offerElement.primaryButtonText) && 4657 isDefined(offerElement.storeURL) && 4658 isDefined(offerElement.imageURL) 4659 ) { 4660 var htmlTemplate = offerElement.html; 4661 if (isContainerEmpty("#mastiff_promotions_and_deals_PDP")) { 4662 $("#mastiff_promotions_and_deals_PDP").append(promoTab); 4663 } 4664 enablePromoTab = true; 4665 if (!$('.promoCarousel').length || isContainerEmpty('.promoOffers')) { 4666 $(".promoOffers").prepend(promoShopOfferSliderDiv); 4667 } 4668 4669 htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferImgURLPlaceholder%", offerElement.imageURL || ""); 4670 htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferTitlePlaceholder%", offerElement.primaryText1 || ""); 4671 htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferDescriptionPlaceholder%", offerElement.primaryText2 || ""); 4672 htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferCTAPlaceholder%", offerElement.primaryButtonText || ""); 4673 htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferId%", divId); 4674 4675 if (!isContainerEmpty('.promoCarousel')) { 4676 if (firstIndex !== "Missing") { 4677 $(htmlTemplate).insertBefore($('.promoCarouselOffer').eq(firstIndex)); 4678 } else { 4679 $(".promoCarousel").append(htmlTemplate); 4680 } 4681 } 4682
4683 allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency); 4684 4685 $("#" + divId).find('a').attr({ title: offerElement.primaryButtonText, alt: offerElement.offerType }); 4686 LeadOffer.offerShown = "yes"; 4687 // To Be Reviewed 4688 //if (isDefined(offerElement.imageURL)) { 4689 // $("#" + divId).attr('style', "color: #212121 !important"); 4690 //} else { 4691 $("#" + divId).find('img').attr({ title: offerElement.primaryButtonText, alt: offerElement.offerType }); 4692 //} 4693 if (reqObj.user.language === "ar" || reqObj.user.language === "he") 4694 $(".promoCarouselOffer").css("text-align", "right").eq(); 4695 $("#" + divId).attr("aria-label", offerElement.offerType); 4696 $("#" + divId).attr("tabindex", 0); 4697 addUrlAndClickEvent(divId, offerElement); 4698 } else { 4699 LeadOffer.errorData = "No Content Available"; 4700 LeadOffer.offerShown = "no"; 4701 } 4702 4703 logToGlobalDataLayer(LeadOffer); 4704} 4705 4706var promoTitle = { 4707 "es": "Promociones y ofertas", 4708 "pt": "Promoções e ofertas", 4709 "fr": "Promotions et offres", 4710 "nl": "Promoties en deals", 4711 "bg": "ÐÑомоÑии и оÑеÑÑи", 4712 "cs": "Promoce a nabÃdky", 4713 "hr": "Promocije i ponude", 4714 "da": "Kampagner og tilbud", 4715 "de": "Aktionen & Angebote", 4716 "et": "Kampaaniad ja pakkumised", 4717 "el": "Î ÏοÏÏοÏÎÏ ÎºÎ±Î¹ εκÏÏÏÏειÏ", 4718 "he": "××צע×× ×××××ת", 4719 "it": "Promozioni e offerte", 4720 "kk": "ÐаÑÐ½Ð°Ð¼Ð°Ð»Ð°Ñ Ð¶Óне дейÑндÑлеÑ", 4721 "lv": "Akcijas un piedÄvÄjumi", 4722 "lt": "Akcijos ir pasiÅ«lymai", 4723 "hu": "Akciók és ajánlatok", 4724 "ar": "Ø§ÙØ¹Ø±Ùض ÙØ§ÙÙØ±Øµ", 4725 "no": "Kampanjer og tilbud", 4726 "pl": "Promocje i oferty", 4727 "ro": "PromoÈii Èi oferte", 4728 "sr": "Promocije i ponude", 4729 "sk": "Akcie a ponuky", 4730 "sl": "Promocije in ponudbe", 4731 "fi": "Tarjoukset ja diilit", 4732 "sv": "Kampanjer och erbjudanden", 4733 "tr": "Promosyonlar ve fırsatlar", 4734 "uk": "ÐкÑÑÑ Ñа пÑопозиÑÑÑ", 4735 "zh": "ä¿éå伿 ", 4736 "id": "Promosi & deal", 4737 "ja": "ããã¢ã¼ã·ã§ã³ï¼ãå¾ãªæ å ±", 4738 "ko": "íë¡ëª¨ì ë° ê±°ë", 4739 "ms": "Promosi & tawaran", 4740 "fil": "Promosyon at mga deal", 4741 "th": "à¹à¸à¸£à¹à¸¡à¸à¸±à¹à¸à¹à¸¥à¸°à¸à¸µà¸¥", 4742 "vi": "Khuyến mãi & Ưu Äãi" 4743}; 4744 4745function showViewInStoreOffer(offerElement) { 4746 var divId = ""; 4747 divId = divId.concat("Store_SPOS_", offerElement.templatePosition, "_", offerElement.name); 4748 4749 var LeadOffer = {}; 4750 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4751 LeadOffer.OfferID = divId; 4752 LeadOffer.OfferClicked = "no"; 4753 LeadOffer.SPOStemplate = "15"; 4754 if ( 4755 isDefined(offerElement.html) && 4756 isDefined(offerElement.primaryButtonText) && 4757 isDefined(offerElement.storeURL) 4758 ) { 4759 var htmlTemplate = offerElement.html; 4760 if (isContainerEmpty("#mastiff_view_in_store_PDP")) { 4761 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateImgURL%", offerElement.imageURL || ""); 4762 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", offerElement.primaryButtonText || ""); 4763 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId); 4764 4765 $("#mastiff_view_in_store_PDP").html(htmlTemplate); 4766 4767 $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" }); 4768 4769 LeadOffer.offerShown = "yes"; 4770 applyAccessibilityAttributes(divId, offerElement); 4771 addUrlAndClickEvent(divId, offerElement); 4772 4773 } else { 4774 LeadOffer.errorData = "View In Store Location is not empty"; 4775 LeadOffer.offerShown = "no"; 4776 } 4777 logToGlobalDataLayer(LeadOffer); 4778 } else { 4779 LeadOffer.errorData = "No Content Available"; 4780 LeadOffer.offerShown = "no"; 4781 4782 logToGlobalDataLayer(LeadOffer); 4783 } 4784} 4785 4786function showCarouselBanner(primaryOfferElement) { 4787 var divId = ""; 4788 divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name); 4789 4790 var LeadOffer = {}; 4791 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4792 LeadOffer.OfferID = divId; 4793 LeadOffer.OfferClicked = "no"; 4794 if (pgName.indexOf("home") > -1) 4795 LeadOffer.SPOStemplate = "7"; 4796 else if (pgName === "contact_closure") 4797 LeadOffer.SPOStemplate = "11"; 4798 if ( 4799 isDefined(primaryOfferElement.html) && 4800 isDefined(primaryOfferElement.imageURL) && 4801 isDefined(primaryOfferElement.primaryText1) && 4802 isDefined(primaryOfferElement.primaryButtonText) && 4803 isDefined(primaryOfferElement.storeURL) 4804 ) { 4805 var htmlTemplate = primaryOfferElement.html; 4806 var html = ""; 4807 html = html.concat("<div id=\"", divId, "\">", htmlTemplate, "</div>"); 4808 if (isContainerEmpty('.mastiff_template_container')) { 4809 html = html.replace("%LargeBannerImgPlaceholder%", primaryOfferElement.imageURL || ""); 4810 html = html.replace("%LargeBannerTitleplaceholder%", primaryOfferElement.primaryText1 || ""); 4811 html = html.replace("%LargeBannerDescriptionplaceholder%", primaryOfferElement.primaryText2 || ""); 4812 html = html.replace("%LargeBannerCTAplaceholder%", "\"" + (primaryOfferElement.primaryButtonText || "") + "\""); 4813 html = html.replace("%LargeBannerCTAplaceholder%", primaryOfferElement.primaryButtonText || ""); 4814 4815 $(".mastiff_template_container").html(html); 4816 4817 LeadOffer.offerShown = "yes"; 4818 if (reqObj.user.language === "ar" || reqObj.user.language === "he") { 4819 $("#LargeBannerContent").css("text-align", "left !important"); 4820 $("#LargeBannerContent").css("float", "left"); 4821 $("#LargeBannerContent").addClass("arabicContent"); 4822 } 4823 $("#" + divId).attr("aria-label", primaryOfferElement.offerType); 4824 $("#LargeBannerTemplate").attr("tabindex", 0); 4825 $(".LargeBannerCTADiv").attr("tabindex", 0); 4826 4827 addUrlAndClickEvent(`#${divId} .LargeBannerCTADiv`, primaryOfferElement, /* openLinkInNewTab: */ true); 4828 applyAccessibilityAttributes(`#${divId} .LargeBannerCTADiv`, primaryOfferElement); 4829 4830 logInfo("Carousel Banner - Offer displayed successfully", ".mastiff_template_container"); 4831 } else { 4832 LeadOffer.errorData = "Large banner Location is not empty"; 4833 LeadOffer.offerShown = "no"; 4834 } 4835 logToGlobalDataLayer(LeadOffer); 4836 4837 } else { 4838 LeadOffer.errorData = "No Content Available"; 4839 LeadOffer.offerShown = "no"; 4840 logToGlobalDataLayer(LeadOffer); 4841 } 4842} 4843 4844function showContactSummaryOffer(contactSumOfferElement) { 4845 var divId = ""; 4846 divId = divId.concat(contactSumOfferElement.templatePosition, "_", contactSumOfferElement.name); 4847 4848 var LeadOffer = {}; 4849 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4850 LeadOffer.OfferID = divId; 4851 LeadOffer.OfferClicked = "no"; 4852 LeadOffer.SPOStemplate = "16"; 4853 if ( 4854 isDefined(contactSumOfferElement.html) && 4855 isDefined(contactSumOfferElement.primaryButtonText) && 4856 isDefined(contactSumOfferElement.storeURL) 4857 ) { 4858 var htmlTemplate = contactSumOfferElement.html; 4859 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", contactSumOfferElement.primaryButtonText); 4860 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateURL%", contactSumOfferElement.storeURL); 4861 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId); 4862 4863 $("#contact-summary-warranty-mastiff").append(htmlTemplate); 4864 LeadOffer.offerShown = "yes"; 4865 applyAccessibilityAttributes(divId, contactSumOfferElement); 4866 addUrlAndClickEvent(divId, contactSumOfferElement); 4867 logToGlobalDataLayer(LeadOffer); 4868 } else { 4869 LeadOffer.errorData = "No Content Available"; 4870 LeadOffer.offerShown = "no"; 4871 $("#contact-summary-warranty-mastiff").hide(); 4872 logToGlobalDataLayer(LeadOffer); 4873 } 4874} 4875 4876async function showWtyPrimaryOffer(wtyPrimaryOfferElement) { 4877 await waitForElement("#mastiff-check-warranty-primary-offer"); 4878 4879 var divId = ""; 4880 divId = divId.concat(wtyPrimaryOfferElement.templatePosition, "_", wtyPrimaryOfferElement.name); 4881 4882 var LeadOffer = {}; 4883 LeadOffer.OfferID = divId; 4884 LeadOffer.OfferClicked = "no"; 4885 LeadOffer.SPOStemplate = "13"; 4886 4887 if (
4888 isDefined(wtyPrimaryOfferElement.html) && 4889 isDefined(wtyPrimaryOfferElement.primaryText1) && 4890 isDefined(wtyPrimaryOfferElement.primaryButtonText) && 4891 isDefined(wtyPrimaryOfferElement.storeURL) 4892 ) { 4893 var htmlTemplate = wtyPrimaryOfferElement.html; 4894 if (isContainerEmpty("#mastiff-check-warranty-primary-offer")) { 4895 htmlTemplate = htmlTemplate.replace("%WRPrimaryTileTitleplaceholder%", wtyPrimaryOfferElement.primaryText1 || ""); 4896 htmlTemplate = htmlTemplate.replace("%WRPrimaryTileDescriptionplaceholder%", wtyPrimaryOfferElement.primaryText2 || ""); 4897 htmlTemplate = htmlTemplate.replace("%WRPrimaryTileCTAplaceholder%", wtyPrimaryOfferElement.primaryButtonText || ""); 4898 htmlTemplate = htmlTemplate.replace("%WRPrimaryTileCTAId%", divId); 4899 4900 $("#mastiff-check-warranty-primary-offer").append(htmlTemplate); 4901 $("#mastiff-dy-compatible-oow-section").show().removeClass("hidden"); 4902 4903 $(".WRPrimaryTile").css("margin-top", "20px"); 4904 LeadOffer.offerShown = "yes"; 4905 4906 applyAccessibilityAttributes(divId, wtyPrimaryOfferElement); 4907 4908 addUrlAndClickEvent(divId, wtyPrimaryOfferElement); 4909 } else { 4910 LeadOffer.errorData = "Primary Location is not empty"; 4911 LeadOffer.offerShown = "no"; 4912 } 4913 logToGlobalDataLayer(LeadOffer); 4914 4915 } else { 4916 LeadOffer.errorData = "No Content Available"; 4917 LeadOffer.offerShown = "no"; 4918 logToGlobalDataLayer(LeadOffer); 4919 } 4920} 4921 4922async function showWtySecondaryOffer(wtySecondaryOfferElement) { 4923 4924 await waitForElement("#warrantyoptions", ".warranty-details"); 4925 4926 var divId = ""; 4927 divId = divId.concat(wtySecondaryOfferElement.templatePosition, "_", wtySecondaryOfferElement.name); 4928 4929 var LeadOffer = {}; 4930 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 4931 LeadOffer.OfferID = divId; 4932 LeadOffer.OfferClicked = "no"; 4933 LeadOffer.SPOStemplate = "15"; 4934 if ( 4935 isDefined(wtySecondaryOfferElement.html) && 4936 isDefined(wtySecondaryOfferElement.primaryButtonText) && 4937 isDefined(wtySecondaryOfferElement.storeURL) 4938 ) { 4939 var htmlTemplate = wtySecondaryOfferElement.html; 4940 var html = ""; 4941 if (isContainerEmpty("#warrantyoptions")) { 4942 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", wtySecondaryOfferElement.primaryButtonText); 4943 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateURL%", wtySecondaryOfferElement.storeURL); 4944 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId); 4945 4946 $("#warrantyoptions").append(htmlTemplate); 4947 $(".simpleLinkTemplate").css("margin-top", "20px"); 4948 LeadOffer.offerShown = "yes"; 4949 applyAccessibilityAttributes(divId, wtySecondaryOfferElement); 4950 addUrlAndClickEvent(divId, wtySecondaryOfferElement); 4951 } else { 4952 LeadOffer.errorData = "Secondary Location is not empty"; 4953 LeadOffer.offerShown = "no"; 4954 } 4955 logToGlobalDataLayer(LeadOffer); 4956 } else { 4957 LeadOffer.errorData = "No Content Available"; 4958 LeadOffer.offerShown = "no"; 4959 //window.optRevertHpOffer(); 4960 logToGlobalDataLayer(LeadOffer); 4961 } 4962 4963 4964} 4965 4966function showWtyShopOffers() { 4967 waitForElement("#mastiff-check-warranty-secondary-offers"); 4968 var shop1PositionElement = offerResults.offers.offer.filter(function (x) { 4969 return x.templatePosition === "shop1" && !x.OWTileOffer; 4970 })[0]; 4971 var shop2PositionElement = offerResults.offers.offer.filter(function (x) { 4972 return x.templatePosition === "shop2" && !x.OWTileOffer; 4973 })[0]; 4974 var shop3PositionElement = offerResults.offers.offer.filter(function (x) { 4975 return x.templatePosition === "shop3" && !x.OWTileOffer; 4976 })[0]; 4977 4978 if (shop1PositionElement != null) { 4979 wtyShopOfferContent(shop1PositionElement); 4980 } 4981 if (shop2PositionElement != null) { 4982 wtyShopOfferContent(shop2PositionElement); 4983 } 4984 if (shop3PositionElement != null) { 4985 wtyShopOfferContent(shop3PositionElement); 4986 } 4987 4988 4989 if (document.getElementsByClassName("WRSecondaryTile").length == 1) { 4990 var navigationDiv = document.getElementById('navigation'); 4991 navigationDiv.style.display = "none"; 4992 } 4993 4994 $(".WRSecondarySlidercontainer").css("margin-top", "20px"); 4995 $(".WRSecondarySlidercontainer").css("margin-bottom", "20px"); 4996 $("#navLeft").keypress(function (event) { 4997 var code = event.keyCode || event.which; 4998 if (code == 13) { 4999 nextSlide(-1); 5000 } 5001 });
5002 $("#navRight").keypress(function (event) { 5003 var code = event.keyCode || event.which; 5004 if (code == 13) { 5005 nextSlide(1); 5006 } 5007 }); 5008 sliderClassName = "WRSecondaryTile"; 5009 navBulletAvailable = false; 5010 displaySlides(slide_index); 5011 5012} 5013 5014function wtyShopOfferContent(offerElement) { 5015 var divId = ""; 5016 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 5017 var LeadOffer = {}; 5018 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 5019 LeadOffer.OfferID = divId; 5020 LeadOffer.OfferClicked = "no"; 5021 LeadOffer.SPOStemplate = "14"; 5022 if ( 5023 isDefined(offerElement.html) && 5024 isDefined(offerElement.primaryText1) && 5025 isDefined(offerElement.primaryButtonText) && 5026 isDefined(offerElement.storeURL) 5027 ) { 5028 var htmlTemplate = offerElement.html; 5029 if (isContainerEmpty("#mastiff-check-warranty-secondary-offers")) { 5030 $("#mastiff-check-warranty-secondary-offers").append(wtyShopOfferSliderDiv); 5031 $("#mastiff-dy-compatible-oow-section").show().removeClass("hidden"); 5032 } 5033 htmlTemplate = htmlTemplate.replace("%WRSecondaryTileTitleplaceholder%", offerElement.primaryText1 || ""); 5034 htmlTemplate = htmlTemplate.replace("%WRSecondaryTileDescriptionplaceholder%", offerElement.primaryText2 || ""); 5035 htmlTemplate = htmlTemplate.replace("%WRSecondaryTileCTAplaceholder%", offerElement.primaryButtonText || ""); 5036 htmlTemplate = htmlTemplate.replace("%WRSecondaryTileCTAId%", divId); 5037 5038 $(".WRSecondarySlidercontainer").append(htmlTemplate); 5039 5040 allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency); 5041 5042 LeadOffer.offerShown = "yes"; 5043 5044 applyAccessibilityAttributes(divId, offerElement); 5045 addUrlAndClickEvent(divId, offerElement); 5046 } else { 5047 LeadOffer.errorData = "No Content Available"; 5048 LeadOffer.offerShown = "no"; 5049 } 5050 5051 logToGlobalDataLayer(LeadOffer); 5052} 5053 5054async function showWtyQuizInitiatorOffer(offerElement) { 5055 await waitForElement("#mastiff-check-warranty-primary-offer"); 5056 5057 const divId = `${offerElement.templatePosition}_${offerElement.name}`; 5058 5059 const LeadOffer = { 5060 OfferID: divId, 5061 OfferClicked: "no", 5062 SPOStemplate: "27" 5063 }; 5064 const GDLOfferName = "LeadOffer" + LeadOfferIndex; 5065 5066 const hasValidContent = 5067 isDefined(offerElement.primaryText1) && 5068 isDefined(offerElement.primaryText2) && 5069 isDefined(offerElement.primaryButtonText) && 5070 isDefined(offerElement.storeURL); 5071 5072 if (hasValidContent) { 5073 const title = offerElement.primaryText1 || ""; 5074 const description = offerElement.primaryText2 || ""; 5075 const cta = offerElement.primaryButtonText || ""; 5076 5077 var htmlTemplate = offerElement.html; 5078 htmlTemplate = htmlTemplate.replace("{title}", title); 5079 htmlTemplate = htmlTemplate.replace("{description}", description); 5080 htmlTemplate = htmlTemplate.replace("{cta}", cta); 5081 htmlTemplate = htmlTemplate.replace("%sposQuizInitiatorCTATwoId%", divId); 5082 $("#mastiff-check-warranty-primary-offer").append(htmlTemplate); 5083 $("#mastiff-check-warranty-primary-offer").css("margin-top", "20px"); 5084 $('.WRPrimaryTile').hide(); 5085 5086 applyAccessibilityAttributes(divId, offerElement); 5087 5088 $("#" + divId).keypress(function (e) { 5089 var code = e.keyCode || e.which; 5090 if (code === 13) { 5091 $('.sposQuizInitiatorContainer').hide(); 5092 $("#mastiff-check-warranty-secondary-offers").hide(); 5093 5094 if (uiState.quiztype.toLowerCase() === "huq") { 5095 $(".HUQConfiguratorContainer").show(); 5096 } else if (uiState.quiztype.toLowerCase() === "cpc") { 5097 $(".CPConfiguratorContainer").show(); 5098 } 5099 } 5100 }); 5101 5102 $("#" + divId).click(function () { 5103 $('.sposQuizInitiatorContainer').hide(); 5104 $("#mastiff-check-warranty-secondary-offers").hide(); 5105 5106 if (uiState.quiztype.toLowerCase() === "huq") { 5107 $(".HUQConfiguratorContainer").show(); 5108 } else if (uiState.quiztype.toLowerCase() === "cpc") { 5109 $(".CPConfiguratorContainer").show(); 5110 } 5111 }); 5112 5113 5114 addUrlAndClickEvent(divId, offerElement, false); 5115 5116 LeadOffer.offerShown = "yes"; 5117 } else { 5118 LeadOffer.errorData = "No Content Available"; 5119 LeadOffer.offerShown = "no"; 5120 } 5121 5122 logToGlobalDataLayer(LeadOffer); 5123 5124 return Promise.resolve(); 5125} 5126 5127function appendQuizDiscardInsideInitiator(discardElement) { 5128 const divId = `${discardElement.templatePosition}_${discardElement.name}`; 5129 5130 const LeadOffer = { 5131 OfferID: divId, 5132 OfferClicked: "no", 5133 SPOStemplate: "29" 5134 }; 5135 const GDLOfferName = "LeadOffer" + LeadOfferIndex; 5136 5137 const hasValidContent = 5138 isDefined(discardElement.primaryButtonText) && 5139 isDefined(discardElement.storeURL); 5140 5141 if (hasValidContent) { 5142 const cta = discardElement.primaryButtonText || ""; 5143 5144 var htmlTemplate = discardElement.html; 5145 5146 htmlTemplate = htmlTemplate.replace("{cta}", cta); 5147 htmlTemplate = htmlTemplate.replace("%sposQuizInitiatorDeclineOfferCTAId%", divId); 5148 5149 $("#sposQuizDeclineOfferDiv").html(htmlTemplate); 5150 5151 applyAccessibilityAttributes(divId, discardElement); 5152 5153 $("#" + divId).keypress(function (e) { 5154 var code = e.keyCode || e.which; 5155 if (code === 13) { 5156 offerDeclineEvent(reqObj, discardElement.name); 5157 $('.sposQuizInitiatorContainer').hide(); 5158 $('.WRPrimaryTile').show(); 5159 5160 } 5161 }); 5162 5163 $("#" + divId).click(function () { 5164 offerDeclineEvent(reqObj, discardElement.name); 5165 $('.sposQuizInitiatorContainer').hide(); 5166 $('.WRPrimaryTile').show(); 5167 }); 5168 5169 5170 LeadOffer.offerShown = "yes"; 5171 } else { 5172 LeadOffer.errorData = "No Content Available"; 5173 LeadOffer.offerShown = "no"; 5174 } 5175 5176 logToGlobalDataLayer(LeadOffer); 5177} 5178 5179async function insertWarrantyOWContainerOffer(offerElement) { 5180 //wait for mastiff-dy-oow-section 5181 await waitForElement("#mastiff-dy-oow-section"); 5182 var divId = ""; 5183 divId = divId.concat("DY-OOW_", offerElement.templatePosition, "_", offerElement.name); 5184 var LeadOffer = {}; 5185 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 5186 LeadOffer.OfferID = divId; 5187 5188 LeadOffer.OfferClicked = "no"; 5189 LeadOffer.SPOStemplate = "31"; 5190 //clickSelector is mastiff-dy-oow-section .accordion .accordion-button 5191 var clickSelector = "#mastiff-dy-oow-section .accordion .accordion-button"; 5192 //addUrlAndClickEvent(clickSelector, offerElement, false); 5193 5194 var $el = $(clickSelector); 5195 if (offerElement.name) $el.attr("data-offer-name", offerElement.name); 5196 5197 // only send click when it's not active 5198 $(clickSelector).click(function () { 5199 if ($(this).hasClass("active")) { 5200 offerClickEvent(reqObj, this, false); 5201 } 5202 });
5203 5204 5205 if (isDefined(offerElement.primaryText1)) { 5206 //insert it in mastiff-dy-oow-section-title 5207 $("#mastiff-dy-oow-section-title").text(offerElement.primaryText1); 5208 } 5209 5210 if (isDefined(offerElement.primaryText2)) { 5211 //insert it in mastiff-dy-oow-section-subtitle 5212 $("#mastiff-dy-oow-section-subtitle").text(offerElement.primaryText2); 5213 } 5214 5215 if (isDefined(offerElement.html)) { 5216 var htmlContainer = offerElement.html; 5217 // insert in mastiff-dy-oow-tiles 5218 if (isContainerEmpty("#mastiff-dy-oow-tiles")) { 5219 $("#mastiff-dy-oow-tiles").html(htmlContainer); 5220 LeadOffer.offerShown = "yes"; 5221 logInfo("DY OOW Container - Offers container inserted successfully", "#mastiff-dy-oow-tiles"); 5222 } else { 5223 logInfo("DY OOW Container - Placement location is not empty", "#mastiff-dy-oow-tiles"); 5224 LeadOffer.errorData = "OOW Container Location is not empty"; 5225 LeadOffer.offerShown = "no"; 5226 } 5227 logToGlobalDataLayer(LeadOffer); 5228 } else { 5229 logInfo("DY OOW Container - Missing mandatory fields", "#mastiff-dy-oow-tiles"); 5230 LeadOffer.errorData = "No html container Available"; 5231 LeadOffer.offerShown = "no"; 5232 logToGlobalDataLayer(LeadOffer); 5233 } 5234} 5235 5236async function insertWarrantyRegularContainerOffer(offerElement) { 5237 //wait for mastiff-dy-oow-section 5238 await waitForElement("#mastiff-dy-compatible-oow-section"); 5239 var divId = ""; 5240 divId = divId.concat("DY-COMP-OOW_", offerElement.templatePosition, "_", offerElement.name); 5241 var LeadOffer = {}; 5242 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 5243 LeadOffer.OfferID = divId; 5244 5245 LeadOffer.OfferClicked = "no"; 5246 LeadOffer.SPOStemplate = "26"; 5247 //clickSelector is mastiff-dy-compatible-oow-section .accordion .accordion-button 5248 var clickSelector = "#mastiff-dy-compatible-oow-section .accordion .accordion-button"; 5249 //addUrlAndClickEvent(clickSelector, offerElement, false); 5250 5251 var $el = $(clickSelector); 5252 if (offerElement.name) $el.attr("data-offer-name", offerElement.name); 5253 5254 // only send click when it's not active 5255 $(clickSelector).click(function () { 5256 if ($(this).hasClass("active")) { 5257 offerClickEvent(reqObj, this, false); 5258 } 5259 }); 5260 5261 if (isDefined(offerElement.primaryText1)) { 5262 //insert it in mastiff-dy-compatible-oow-section-title 5263 $("#mastiff-dy-compatible-section-title").text(offerElement.primaryText1); 5264 } 5265 5266 if (isDefined(offerElement.html)) { 5267 var htmlContainer = offerElement.html; 5268 // insert container in mastiff-dy-compatible-tiles 5269 if (isContainerEmpty("#mastiff-dy-compatible-tiles")) { 5270 $("#mastiff-dy-compatible-tiles").html(htmlContainer); 5271 $("#mastiff-dy-compatible-oow-section").show().removeClass("hidden"); 5272 5273 LeadOffer.offerShown = "yes"; 5274 logInfo("DY Comp OOW Container - Offers container inserted successfully", "#mastiff-dy-compatible-tiles"); 5275 } else { 5276 logInfo("DY comp OOW Container - Placement location is not empty", "#mastiff-dy-compatible-tiles"); 5277 LeadOffer.errorData = "Comp OOW Container Location is not empty"; 5278 LeadOffer.offerShown = "no"; 5279 } 5280 logToGlobalDataLayer(LeadOffer); 5281 } else { 5282 logInfo("DY Comp OOW Container - Missing mandatory fields", "#mastiff-dy-compatible-tiles"); 5283 LeadOffer.errorData = "No html container Available"; 5284 LeadOffer.offerShown = "no"; 5285 logToGlobalDataLayer(LeadOffer); 5286 } 5287} 5288 5289/** 5290 * OWX Nested Experience Renderer (FINAL) 5291 * Update: Tab number is extracted from offer.category (NOT templatePosition). 5292 * 5293 * Expected behavior covered: 5294 * 1) OWExperiment_ib_Container inserts #SPOSOWEntryTiles under #mastiff-dy-oow-section (handled elsewhere: insertWarrantyOWContainerOffer) 5295 * 2) OWX_Navigation_Container_Shell is inserted under #SPOSOWEntryTiles but kept hidden 5296 * 3) Level0 offers are grouped in one wrapper (shown first). Order by templatePosition Level0Tab_{order} 5297 * 4) Clicking Level0 nested -> show shell, focus correct tab + show correct level containers 5298 * 5) Level1 grouped by Level1 containers 5299 * 6) Level2 grouped/filtered by tile_{n} relationship to its parent Level1 selection 5300 * 7) Back button hides shell and shows Level0 tiles 5301 */ 5302async function renderWarrantyNestedOwExperiment(offerElements) { 5303 const owOffers = (offerElements || []).filter((offer) => safeLower(offer?.category).startsWith("owx")); 5304 const handled = new Set(); 5305 if (!owOffers.length) return handled; 5306 5307 const LEVEL0_SELECTOR = "#SPOSOWEntryTiles"; 5308 const EXPERIENCE_SELECTOR = "#mastiff-dy-oow-tiles"; 5309 5310 // ------------------------- 5311 // Helpers 5312 // ------------------------- 5313 5314 const isActivationKey = (key) => key === "Enter" || key === " " || key === 13 || key === 32;
5315 const bindActivationKeyToClick = ($element, namespace) => { 5316 $element.off(`keydown.${namespace}`).on(`keydown.${namespace}`, function (e) { 5317 const k = e.key || e.which; 5318 if (!isActivationKey(k)) return; 5319 e.preventDefault(); 5320 $(this).trigger("click"); 5321 }); 5322 }; 5323 5324 // TAB NUMBER: from CATEGORY 5325 // Category examples supported: 5326 // "OWX Tab1 - Level0 - Nested" 5327 // "OWX Tab2 - Level1 - Tiles - nested" 5328 // "OWX Tab3 - Level1 - Container" 5329 const parseTabNumberFromCategory = (category) => { 5330 const match = category && String(category).match(/tab\s*([0-9]+)/i); 5331 return match ? Number(match[1]) : 0; 5332 }; 5333 5334 const parseLevelNumber = (category, templatePosition) => { 5335 const cat = String(category || ""); 5336 const pos = String(templatePosition || ""); 5337 const match = cat.match(/level\s*([0-9]+)/i); 5338 if (match) return Number(match[1]); 5339 5340 // fallback: some payloads may encode in templatePosition 5341 const posMatch = pos.match(/level\s*([0-9]+)/i); 5342 if (posMatch) return Number(posMatch[1]); 5343 5344 // special: level0tab_* is level 0 5345 if (pos.match(/level0tab/i)) return 0; 5346 5347 return 0; 5348 }; 5349 5350 // Order for Level0 tiles: templatePosition like "level0tab_3" or "Level0Tab-2" 5351 const parseLevel0Order = (templatePosition) => { 5352 const match = templatePosition && String(templatePosition).match(/level0tab[_-]?([0-9]+)/i); 5353 return match ? Number(match[1]) : null; 5354 }; 5355 5356 // tile key extraction: "tile_1", "tile-2", "tile2" 5357 const parseTileKey = (value) => { 5358 const v = String(value || ""); 5359 const match = v.match(/tile[_\s-]?(\d+)/i); 5360 return match ? `tile_${match[1]}`.toLowerCase() : null; 5361 }; 5362 5363 const isContainerPosition = (templatePosition) => safeLower(templatePosition || "").includes("container"); 5364 const isTilePosition = (templatePosition) => safeLower(templatePosition || "").includes("tile"); 5365 const isContainerCategory = (category) => safeLower(category || "").includes("container"); 5366 const isOptionCategory = (category) => { 5367 const c = safeLower(category || ""); 5368 return c.includes("option") || c.includes("tile"); 5369 }; 5370 const isContainerOffer = (offer) => isContainerPosition(offer?.templatePosition) || isContainerCategory(offer?.category); 5371 const isTileOffer = (offer) => isTilePosition(offer?.templatePosition) || isOptionCategory(offer?.category); 5372 5373 const containerSelectorCache = new Map(); 5374 5375 const containerSelectorForPosition = (templatePosition) => { 5376 const key = templatePosition || ""; 5377 if (containerSelectorCache.has(key)) return containerSelectorCache.get(key); 5378 const pos = safeLower(key); 5379 var selector = null; 5380 if (pos.includes("1r3c")) selector = ".oneRowThreeColumnsContainer"; 5381 else if (pos.includes("2r3c")) selector = ".TwoRowsThreeColumnsContainer"; 5382 else if (pos.includes("3r2c")) selector = ".ThreeRowsTwoColumnsContainer"; 5383 containerSelectorCache.set(key, selector); 5384 return selector; 5385 }; 5386 5387 const buildOwTileHtml = (offer, divId) => { 5388 5389 const requiredFields = { 5390 "level0tab": ["primaryText1", "primaryButtonText", "imageURL"], 5391 "3r2ctile": ["primaryText2"], 5392 "2r3ctile": ["primaryText1", "imageURL"], 5393 "1r3ctile": ["primaryText1", "primaryButtonText", "imageURL"] 5394 } 5395 5396 var templateKey = offer.templatePosition.toLowerCase().replace(/_\d+$/, ""); 5397 var offerRequiredFields = requiredFields[templateKey] || []; 5398 var hasAllFields = offerRequiredFields.every(field => isDefined(offer[field])); 5399 5400 const isContainer = isContainerCategory(offer.category) || isContainerPosition(offer.templatePosition); 5401 5402 // required fields apply only to non-container offers 5403 const missingRequired = !isContainer && !hasAllFields; 5404 5405 if (missingRequired) { 5406 logInfo(`OWX Nested Experience: Missing required fields for offer ${offer.name} with 5407templatePosition ${offer.templatePosition}`); 5408 return null; 5409 } 5410 5411 var html = offer.html; 5412 html = html.replace("%OWEntryOfferTitlePlaceholder%", offer.primaryText1 || ""); 5413 html = html.replace("%OWEntryOfferDescriptionPlaceholder%", offer.primaryText2 || ""); 5414 html = html.replace("%OWEntryOfferCTAPlaceholder%", offer.primaryButtonText || ""); 5415 html = html.replace("%OWEntryOfferImgURLPlaceholder%", offer.imageURL || "''"); 5416 html = html.replace("%falconContactHPOfferIdPlaceholder%", divId); 5417 5418 html = html.replace("%imageurl%", offer.imageURL || "''"); 5419 if (isDefined(offer.offerTitle)) 5420 html = html.replace("%description%", offer.offerTitle); 5421 else 5422 html = html.replace("%description%", offer.offerSubTitle); 5423 return html; 5424 }; 5425 5426 // ------------------------- 5427 // Find roots 5428 // ------------------------- 5429 // Level 0 offers go to #SPOSOWEntryTiles 5430 var sposContainer; 5431 try { 5432 sposContainer = await waitForElement(LEVEL0_SELECTOR); 5433 } catch (e) { 5434 logInfo(`OWX nested experience: ${LEVEL0_SELECTOR} not found`); 5435 return handled; 5436 } 5437 const $level0Root = $(sposContainer); 5438 5439 // Nested experience shell goes to #mastiff-dy-oow-tiles 5440 var tileContainer; 5441 try { 5442 tileContainer = await waitForElement(EXPERIENCE_SELECTOR); 5443 } catch (e) { 5444 logInfo(`OWX nested experience: ${EXPERIENCE_SELECTOR} not found`); 5445 return handled; 5446 } 5447 const $experienceParent = $(tileContainer); 5448 5449 // ------------------------- 5450 // Identify shell + build model (tabs/levels) 5451 // ------------------------- 5452 const tabs = new Map(); 5453 5454 // shell offer (level0container in templatePosition) 5455 const level0ContainerOffer = owOffers.find((offer) => safeLower(offer.templatePosition || "").includes("level0container")); 5456 5457 // add offers to model
5458 owOffers.forEach((offer) => { 5459 handled.add(offer.name); 5460 5461 const rawCategory = offer.category || ""; 5462 const category = safeLower(rawCategory); 5463 const templatePosition = offer.templatePosition || ""; 5464 const lowerTemplatePosition = safeLower(templatePosition); 5465 const isShell = lowerTemplatePosition.includes("level0container"); 5466 if (isShell) return; 5467 5468 const tabNumber = parseTabNumberFromCategory(category); 5469 const levelNumber = parseLevelNumber(category, templatePosition); 5470 const isNested = category.includes("nested"); 5471 // Hidden offers ("Nested - Hidden") build the tab model at Level0 but are never 5472 // rendered as visible tiles. They only require primaryText1 (tab label). 5473 const isHiddenNested = isNested && category.includes("hidden"); 5474 5475 // Optimized: tileKey extracted purely from offer.category (matching groups) 5476 const tileKey = parseTileKey(rawCategory); 5477 const level0Order = parseLevel0Order(templatePosition); 5478 5479 if (!tabs.has(tabNumber)) { 5480 tabs.set(tabNumber, { 5481 tabNumber, 5482 tabOffer: null, // a representative offer for analytics / title fallback 5483 levels: new Map(), // Map<levelNumber, Array<{offer,isNested,tileKey}>> 5484 level0Order: null, // ordering for Level0 tiles 5485 tabTitle: "" // title shown in nav items 5486 }); 5487 } 5488 5489 const tabData = tabs.get(tabNumber); 5490 if (!tabData.levels.has(levelNumber)) tabData.levels.set(levelNumber, []); 5491 tabData.levels.get(levelNumber).push({ offer, isNested, isHiddenNested, tileKey }); 5492 5493 if (level0Order !== null) tabData.level0Order = level0Order; 5494 5495 // Tab title preference: 5496 // - If we find a level1 container with primaryText1, use it 5497 // - Else fallback to tab offer (level0) title/name 5498 if (levelNumber === 1 && isContainerPosition(templatePosition) && isDefined(offer.primaryText1)) { 5499 tabData.tabTitle = offer.primaryText1; 5500 } 5501 5502 if (!tabData.tabOffer || levelNumber === 0) { 5503 tabData.tabOffer = offer; 5504 if (!tabData.tabTitle) { 5505 tabData.tabTitle = offer.primaryText1 || offer.name || `Tab ${tabNumber}`; 5506 } 5507 } 5508 }); 5509 5510 const tabKeys = Array.from(tabs.keys()).sort((a, b) => { 5511 const aOrder = tabs.get(a)?.level0Order; 5512 const bOrder = tabs.get(b)?.level0Order; 5513 if (aOrder != null && bOrder != null) return aOrder - bOrder; 5514 if (aOrder != null) return -1; 5515 if (bOrder != null) return 1; 5516 return a - b; 5517 }); 5518 if (!tabKeys.length) return handled; 5519 5520 const sortedLevelsForTabCache = new Map(); 5521 const getSortedLevelsForTab = (tabNumber) => { 5522 if (sortedLevelsForTabCache.has(tabNumber)) return sortedLevelsForTabCache.get(tabNumber); 5523 const tabData = tabs.get(tabNumber); 5524 const levels = tabData ? Array.from(tabData.levels.keys()).sort((a, b) => a - b) : []; 5525 sortedLevelsForTabCache.set(tabNumber, levels); 5526 return levels; 5527 }; 5528 const getNextLevelForTab = (tabNumber, level) => { 5529 const levels = getSortedLevelsForTab(tabNumber); 5530 for (var i = 0; i < levels.length; i++) { 5531 if (levels[i] > level) return levels[i]; 5532 } 5533 return undefined; 5534 }; 5535 const getPreviousLevelForTab = (tabNumber, level) => { 5536 const levels = getSortedLevelsForTab(tabNumber); 5537 for (var i = levels.length - 1; i >= 0; i--) { 5538 if (levels[i] < level) return levels[i]; 5539 } 5540 return level; 5541 }; 5542 5543 const hasValidChildrenMemo = new Map(); 5544 const hasValidChildren = (tabNumber, currentLevel, parentKey) => { 5545 const memoKey = `${tabNumber}|${currentLevel}|${safeLower(parentKey || "")}`; 5546 if (hasValidChildrenMemo.has(memoKey)) return hasValidChildrenMemo.get(memoKey); 5547
5548 const nextLevel = getNextLevelForTab(tabNumber, currentLevel); 5549 if (typeof nextLevel === "undefined") { 5550 hasValidChildrenMemo.set(memoKey, false); 5551 return false; 5552 } 5553 5554 const allNext = tabs.get(tabNumber).levels.get(nextLevel) || []; 5555 // For Level 1 (nextLevel=1), we assume all items in the tab are L1 roots unless filtered otherwise. 5556 // For Level > 1, we must match the parent's tileKey. 5557 const candidates = (nextLevel > 1) 5558 ? allNext.filter(c => safeLower(c.tileKey) === safeLower(parentKey)) 5559 : allNext; 5560 5561 if (!candidates.length) { 5562 hasValidChildrenMemo.set(memoKey, false); 5563 return false; 5564 } 5565 5566 const result = candidates.some(c => { 5567 // Containers are structural only, never count as valid leaves 5568 if (isContainerOffer(c.offer)) return false; 5569 if (!c.isNested) { 5570 // Leaf tile: verify it would actually render (html, storeURL, required fields) 5571 if (!isDefined(c.offer.html)) return false; 5572 if (!isDefined(c.offer.storeURL)) return false; 5573 return buildOwTileHtml(c.offer, '_validationCheck') !== null; 5574 } 5575 // Nested: recursively check for valid children 5576 return hasValidChildren(tabNumber, nextLevel, c.tileKey); 5577 }); 5578 hasValidChildrenMemo.set(memoKey, result); 5579 return result; 5580 }; 5581 5582 // Filter out tabs with no renderable Level 0 offers to prevent 5583 // empty shell containers and orphaned tab navigation items. 5584 for (var i = tabKeys.length - 1; i >= 0; i--) { 5585 const tn = tabKeys[i]; 5586 const td = tabs.get(tn); 5587 const l0 = td ? (td.levels.get(0) || []) : []; 5588 const hasRenderable = l0.some(({ offer, isNested, isHiddenNested, tileKey }) => { 5589 // Hidden offers have no html/storeURL; only primaryText1 is required. 5590 if (isHiddenNested) return isDefined(offer.primaryText1) && hasValidChildren(tn, 0, tileKey); 5591 if (!isDefined(offer.html)) return false; 5592 if (isNested) return hasValidChildren(tn, 0, tileKey); 5593 return buildOwTileHtml(offer, '_validationCheck') !== null; 5594 }); 5595 if (!hasRenderable) { 5596 // Tab0 without a complete nested path: keep it if at least one other tab 5597 // has valid children â Tab0 will act as a visual entry tile and redirect 5598 // on click to the first valid tab. If no other tab survives, Tab0 is removed too. 5599 const tab0Survives = tn === 0 && tabKeys.length > 1 && l0.some(({ offer }) => isDefined(offer.html)); 5600 if (!tab0Survives) tabKeys.splice(i, 1); 5601 } 5602 } 5603 if (!tabKeys.length) return handled; 5604 5605 // ------------------------- 5606 // Reset and create experience root 5607 // ------------------------- 5608 $experienceParent.find(".OWEntryNestedExperienceRoot").remove(); 5609 5610 const $experienceRoot = $("<div class='OWEntryNestedExperienceRoot'></div>"); 5611 $experienceParent.append($experienceRoot); 5612 5613 // Level 0 offers are inserted directly into #SPOSOWEntryTiles ($level0Root), no wrapper needed. 5614 5615 // Shell inserted under #SPOSOWEntryTiles but hidden initially 5616 var $level0Shell = $("<div class='OWEntryNestedContainer OWEntryNestedLevel0Shell'></div>"); 5617 if (level0ContainerOffer && isDefined(level0ContainerOffer.html)) { 5618 // replace {title} placeholder if exists with level0ContainerOffer.primaryText1 5619 const level0ShellHtml = level0ContainerOffer.html.replace("{title}", level0ContainerOffer.primaryText1 || ""); 5620 $level0Shell = $(level0ShellHtml); 5621 } 5622 $level0Shell.addClass("OWEntryNestedLevel0Shell"); 5623 5624 $experienceRoot.append($level0Shell); 5625 5626 // ------------------------- 5627 // Build navigation items (tabs) inside shell 5628 // ------------------------- 5629 const navItemsHtml = tabKeys 5630 .filter((tabNumber) => { 5631 const td = tabs.get(tabNumber); 5632 const l0 = td ? (td.levels.get(0) || []) : []; 5633 return l0.some(({ isNested, tileKey }) => isNested && hasValidChildren(tabNumber, 0, tileKey)); 5634 }) 5635 .map((tabNumber) => { 5636 const tabData = tabs.get(tabNumber); 5637 const title = tabData?.tabTitle || `Tab ${tabNumber}`; 5638 const offerName = tabData?.tabOffer?.name || ""; 5639 return `<div class="OWEntryNavigationItem" data-tab="${tabNumber}" data-offer-name="${offerName}" tabindex="0" role="button" aria-label="${title}"> 5640 <div class="OWEntryNavigationItemElipse"></div>${title} 5641 </div>`; 5642 }) 5643 .join(""); 5644 5645 const $navContainers = $level0Shell.find(".OWEntryNavigationItems"); 5646 if ($navContainers.length) { 5647 $navContainers.each(function () { 5648 $(this).html(navItemsHtml); 5649 }); 5650 } else { 5651 $level0Shell.prepend(`<div class="OWEntryNavigationItems">${navItemsHtml}</div>`); 5652 } 5653 5654 const $shellContainersRoot = $level0Shell.find(".OWEntryNestedContainers").first().length 5655 ? $level0Shell.find(".OWEntryNestedContainers").first() 5656 : $level0Shell; 5657 const $navItems = $experienceRoot.find(".OWEntryNavigationItem"); 5658 const levelElementByTabLevel = new Map(); 5659 5660 // ------------------------- 5661 // Render levels (L1+ only) inside shell per tab 5662 // ------------------------- 5663 tabKeys.forEach((tabNumber) => { 5664 const tabData = tabs.get(tabNumber); 5665 const $tabContainer = $("<div class='OWEntryNestedTab'></div>").attr("data-tab", tabNumber); 5666 $shellContainersRoot.append($tabContainer); 5667 5668 const levelKeys = Array.from(tabData.levels.keys()).sort((a, b) => a - b); 5669 levelKeys.forEach((level) => { 5670 if (level === 0) return; // L0 is outside (level0Group) 5671 5672 const $levelWrapper = $("<div class='OWEntryNestedLevel'></div>") 5673 .attr("data-tab", tabNumber) 5674 .attr("data-level", level); 5675 $tabContainer.append($levelWrapper); 5676 5677 const levelEntries = tabData.levels.get(level) || []; 5678 const sorted = levelEntries.slice().sort((a, b) => { 5679 return level >= 1 5680 ? positionSortByUnderscoreOrder(a.offer, b.offer) 5681 : positionSort(a.offer, b.offer); 5682 }); 5683 5684 const containers = sorted.filter(({ offer }) => isContainerOffer(offer)); 5685 const tiles = sorted.filter(({ offer }) => isTileOffer(offer)); 5686 5687 // 5) Container & Tile Placement 5688 // Level 1: Containers appended to level wrapper. Tiles inside containers. 5689 // Level > 1: TileGroups appended to level wrapper. Containers inside Groups. Tiles inside Containers inside Groups. 5690 5691 const level1ContainerInstances = []; 5692 const levelNContainerOffers = []; // Store offers to instantiate on demand 5693 const levelNContainerByTileKey = new Map(); 5694 const tileGroupCache = new Map(); 5695 const tileGroupContainerCache = new Map(); 5696 const level1MatchedContainerBySelector = new Map(); 5697 5698 const resolveLevel1TargetContainer = (containerSelector) => { 5699 if (!level1ContainerInstances.length) return null; 5700 if (!containerSelector) return level1ContainerInstances[0]; 5701 if (level1MatchedContainerBySelector.has(containerSelector)) { 5702 return level1MatchedContainerBySelector.get(containerSelector); 5703 } 5704 5705 var $matched = null; 5706 for (var i = 0; i < level1ContainerInstances.length; i++) { 5707 const $candidate = level1ContainerInstances[i].find(containerSelector).first(); 5708 if ($candidate.length) { 5709 $matched = $candidate; 5710 break; 5711 } 5712 } 5713 if (!$matched || !$matched.length) $matched = level1ContainerInstances[0]; 5714 level1MatchedContainerBySelector.set(containerSelector, $matched); 5715 return $matched; 5716 }; 5717 5718 if (level === 1) {
5719 containers.forEach(({ offer, tileKey }) => { 5720 if (!isDefined(offer.html)) return; 5721 const $container = $(offer.html); 5722 if (tileKey) $container.attr("data-tile-key", tileKey); 5723 level1ContainerInstances.push($container); 5724 $levelWrapper.append($container); 5725 }); 5726 } else { 5727 containers.forEach(({ offer, tileKey }) => { 5728 if (!isDefined(offer.html)) return; 5729 const containerData = { offer, lowerHtml: safeLower(offer.html) }; 5730 levelNContainerOffers.push(containerData); 5731 if (tileKey && !levelNContainerByTileKey.has(tileKey)) { 5732 levelNContainerByTileKey.set(tileKey, containerData); 5733 } 5734 }); 5735 } 5736 5737 tiles.forEach(({ offer, isNested, tileKey }, tileIndex) => { 5738 // Validate nested paths: if it's nested but leads to nowhere, don't show it. 5739 if (isNested && !hasValidChildren(tabNumber, level, tileKey)) return; 5740 5741 // Nested tiles can ignore storeURL. Link tiles must have storeURL. 5742 const requiresStoreUrl = !isNested; 5743 const hasRequired = isDefined(offer.html) && (!requiresStoreUrl || isDefined(offer.storeURL)); 5744 if (!hasRequired) return; 5745 5746 const tileId = `OWX_${tabNumber}_${level}_${tileIndex}`; 5747 const tileHtml = buildOwTileHtml(offer, tileId); 5748 if (!isDefined(tileHtml)) return; 5749 5750 const $tile = $(tileHtml); 5751 const $tileRoot = $tile.first(); 5752 if (!$tileRoot.length) return; 5753 5754 $tileRoot.attr("id", tileId); 5755 $tileRoot.attr("data-offer-name", offer.name || ""); 5756 $tileRoot.attr("data-experience", isNested ? "nested" : "link"); 5757 if (tileKey) $tileRoot.attr("data-tile-key", tileKey); 5758 if (offer.storeURL) $tileRoot.attr("data-store-url", offer.storeURL); 5759 5760 const containerSelector = containerSelectorForPosition(offer.templatePosition); 5761 5762 // Placement Logic 5763 if (level > 1 && tileKey) { 5764 // Structure: $levelWrapper -> .OWEntryNestedTileGroup -> Container -> Tile 5765 var $tileGroup = tileGroupCache.get(tileKey); 5766 if (!$tileGroup || !$tileGroup.length) { 5767 $tileGroup = $(`<div class="OWEntryNestedTileGroup" data-tile-key="${tileKey}"></div>`); 5768 $levelWrapper.append($tileGroup); 5769 tileGroupCache.set(tileKey, $tileGroup); 5770 } 5771 5772 // Match container offer by tab+level+tileKey (tab+level scope is already active in this loop) 5773 var $targetContainer = tileGroupContainerCache.get(tileKey) || null; 5774 if (!$targetContainer || !$targetContainer.length) { 5775 var chosenContainerData = levelNContainerByTileKey.get(tileKey) || null; 5776 5777 if (!chosenContainerData && levelNContainerOffers.length) { 5778 // fallback to selector-compatible container when explicit tile match is missing 5779 if (containerSelector) { 5780 const selName = containerSelector.replace(".", ""); 5781 const lowerSelectorName = safeLower(selName); 5782 chosenContainerData = levelNContainerOffers.find((o) => o.lowerHtml.includes(lowerSelectorName)); 5783 } 5784 if (!chosenContainerData) chosenContainerData = levelNContainerOffers[0]; 5785 } 5786 5787 if (chosenContainerData) { 5788 const $newContainer = $(chosenContainerData.offer.html); 5789 if (tileKey) $newContainer.attr("data-tile-key", tileKey); 5790 $tileGroup.append($newContainer); 5791 5792 // prefer container selector within inserted HTML if present 5793 if (containerSelector) { 5794 $targetContainer = $newContainer.find(containerSelector).first(); 5795 if (!$targetContainer.length && $newContainer.is(containerSelector)) { 5796 $targetContainer = $newContainer; 5797 } 5798 } 5799 if (!$targetContainer || !$targetContainer.length) { 5800 $targetContainer = $newContainer; 5801 } 5802 } else { 5803 $targetContainer = $tileGroup; 5804 } 5805 5806 tileGroupContainerCache.set(tileKey, $targetContainer); 5807 } 5808 5809 $targetContainer.append($tile); 5810 5811 } else { 5812 // Level 1 logic (or fallback for L>1 without tileKey): LevelWrapper -> Container -> Tile 5813 // Note: For Level 1, containers are ALREADY in $levelWrapper. 5814 5815 var $targetContainer = containerSelector ? $levelWrapper.find(containerSelector).first() : $levelWrapper; 5816 5817 if (level === 1 && level1ContainerInstances.length) { 5818 var $matched = resolveLevel1TargetContainer(containerSelector); 5819 if ($matched && $matched.length) $targetContainer = $matched; 5820 } 5821 else if (level > 1 && !tileKey) { 5822 // Edge case: Level > 1 but no tileKey -> append to wrapper directly 5823 // (We didn't instantiate containers for L>1 outside groups) 5824 $targetContainer = $levelWrapper; 5825 } 5826 5827 $targetContainer.append($tile); 5828 5829 // 6) Level2+ related to parent by tileKey (tile_1 / tile_2...) - LEGACY LOGIC REMOVED/HANDLED ABOVE 5830 // We incorporated grouping into the placement logic for L>1 above. 5831 } 5832 5833 // a11y + pricing placeholders 5834 applyAccessibilityAttributes(`#${tileId}`, offer); 5835 allocateRecEngPrices(offer.strikePrice, offer.incartPrice, tileId, offer.currency); 5836 5837 // Determine the key to use for navigation. 5838 // Rely on tile matching groups by offer category only. 5839 // Identifiers propagate down; L(N) tile with key 'X' opens L(N+1) group 'X'. 5840 const nextNavigationKey = tileKey; 5841 5842 // click behavior 5843 if (isNested) { 5844 $tileRoot.off(".owxNested").on("click.owxNested", function (e) { 5845 e.preventDefault(); 5846 offerClickEvent(reqObj, this, false); 5847 5848 const nextLevel = getNextLevelForTab(tabNumber, level); 5849 if (typeof nextLevel === "number") { 5850 navigationStack.push({ tabNumber: lastActiveTab, level: lastActiveLevel, tileKey: lastActiveTileKey }); 5851 activateTabLevel(tabNumber, nextLevel, nextNavigationKey || null); 5852 } 5853 }); 5854 bindActivationKeyToClick($tileRoot, "owxNestedKey"); 5855 } else { 5856 $tileRoot.off(".owxLink"); 5857 addUrlAndClickEvent(tileId, offer); 5858 } 5859 }); 5860 5861 levelElementByTabLevel.set(`${tabNumber}|${level}`, $levelWrapper); 5862 }); 5863 });
5864 5865 // ------------------------- 5866 // Render Level0 tiles (outside shell) 5867 // ------------------------- 5868 const level0Offers = []; 5869 tabKeys.forEach((tabNumber) => { 5870 const tabData = tabs.get(tabNumber); 5871 const list = tabData.levels.get(0) || []; 5872 list.forEach((entry) => level0Offers.push({ tabNumber, ...entry })); 5873 }); 5874 5875 // Order Level0 tiles strictly by Level0Tab_{order} from templatePosition (fallback: tab number) 5876 level0Offers.sort((a, b) => { 5877 const aOrder = parseLevel0Order(a.offer?.templatePosition); 5878 const bOrder = parseLevel0Order(b.offer?.templatePosition); 5879 if (aOrder != null && bOrder != null) return aOrder - bOrder; 5880 if (aOrder != null) return -1; 5881 if (bOrder != null) return 1; 5882 return a.tabNumber - b.tabNumber; 5883 }); 5884 5885 // ------------------------- 5886 // Navigation state + show/hide 5887 // ------------------------- 5888 const navigationStack = []; 5889 var lastActiveTab = tabKeys[0]; 5890 var lastActiveLevel = 0; 5891 var lastActiveTileKey = null; 5892 5893 const showLevel0View = () => { 5894 $level0Root.show(); 5895 $experienceRoot.hide(); 5896 }; 5897 5898 const showNestedView = () => { 5899 $level0Root.hide(); 5900 $experienceRoot.show(); 5901 //normalizeHeightsOnce(); 5902 }; 5903 5904 function activateTabLevel(tabNumber, levelNumber, tileKey = null) { 5905 lastActiveTab = tabNumber; 5906 lastActiveLevel = levelNumber; 5907 lastActiveTileKey = levelNumber > 1 ? tileKey : null; 5908 5909 $shellContainersRoot.find(".OWEntryNestedLevel").hide(); 5910 const activeKey = `${tabNumber}|${levelNumber}`; 5911 const $activeLevel = levelElementByTabLevel.get(activeKey) 5912 || $shellContainersRoot.find(`.OWEntryNestedLevel[data-tab="${tabNumber}"][data-level="${levelNumber}"]`); 5913 $activeLevel.show(); 5914 5915 $navItems.removeClass("OWEntryNavigationItemActive"); 5916 $navItems.filter(`[data-tab="${tabNumber}"]`).addClass("OWEntryNavigationItemActive"); 5917 5918 // if level>1 and tileKey provided, show only the matching tile group 5919 if (tileKey && levelNumber > 1) { 5920 $activeLevel.find("[data-tile-key]").hide(); 5921 $activeLevel.find(`[data-tile-key="${tileKey}"]`).show(); 5922 } else { 5923 $activeLevel.find("[data-tile-key]").show(); 5924 } 5925 } 5926 5927 // Create Level0 tiles UI (grouped) 5928 level0Offers.forEach(({ offer, tileKey, tabNumber, isNested, isHiddenNested }, index) => { 5929 // Hidden offers are structural only - they define tab content but never appear as Level0 tiles. 5930 if (isHiddenNested) return; 5931 // Tab0 without a fulfilled happy path is kept at Level0 (redirects to first valid tab on click). 5932 if (isNested && tabNumber !== 0 && !hasValidChildren(tabNumber, 0, tileKey)) return; 5933 5934 const tileId = `OWX_Level0_${tabNumber}_${index}`; 5935 const tileHtml = buildOwTileHtml(offer, tileId); 5936 if (!tileHtml) return; 5937 5938 const $tile = $(tileHtml); 5939 const $tileRoot = $tile.first(); 5940 if (!$tileRoot.length) return; 5941 5942 $tileRoot.attr("id", tileId); 5943 $tileRoot.attr("data-offer-name", offer.name || ""); 5944 $tileRoot.attr("data-tab", tabNumber); 5945 if (tileKey) $tileRoot.attr("data-tile-key", tileKey); 5946 $level0Root.append($tile); 5947 5948 applyAccessibilityAttributes(`#${tileId}`, offer); 5949 5950 if (!isNested) { 5951 // Non-nested Level0 uses only addUrlAndClickEvent for click + key activation + reporting. 5952 addUrlAndClickEvent(tileId, offer); 5953 return; 5954 } 5955 5956 $tileRoot.off(".owxLevel0").on("click.owxLevel0", function (e) { 5957 e.preventDefault(); 5958 5959 // Only nested Level0 tiles should enter the shell. 5960 // If a Level0 tile is not nested, it can behave as a link (storeURL). 5961 const isNested = safeLower(offer.category || "").includes("nested"); 5962 offerClickEvent(reqObj, this, false); 5963 5964 // Tab0 with no fulfilled nested path: redirect to the first tab with valid children 5965 // (i.e. the first tab that will appear in the navigation bar). 5966 if (isNested && tabNumber === 0 && !hasValidChildren(tabNumber, 0, tileKey)) { 5967 const firstValidTab = tabKeys.find(tn => { 5968 if (tn === 0) return false; 5969 const td = tabs.get(tn); 5970 const l0items = td ? (td.levels.get(0) || []) : []; 5971 return l0items.some(({ isNested: iN, tileKey: tk }) => iN && hasValidChildren(tn, 0, tk)); 5972 }); 5973 if (firstValidTab !== undefined) { 5974 navigationStack.length = 0; 5975 showNestedView(); 5976 activateTabLevel(firstValidTab, getNextLevelForTab(firstValidTab, 0) ?? 1, null); 5977 } 5978 return; 5979 } 5980 5981 navigationStack.length = 0; 5982 showNestedView(); 5983 // Use this tile's own tab when it is still a valid tab (backward-compat with 5984 // multiple "Nested" L0 tiles). Fall back to tabKeys[0] only for the single-entry 5985 // scenario where the entry tile's tab was filtered out (e.g. no tab number -> Tab0). 5986 const entryTab = tabKeys.indexOf(tabNumber) !== -1 ? tabNumber : tabKeys[0]; 5987 activateTabLevel(entryTab, getNextLevelForTab(entryTab, 0) ?? 1, null); 5988 }); 5989 bindActivationKeyToClick($tileRoot, "owxLevel0Key"); 5990 });
5991 5992 // ------------------------- 5993 // Tab click -> open nested shell and show L1 for that tab 5994 // ------------------------- 5995 $experienceRoot.on("click", ".OWEntryNavigationItem", function (e) { 5996 e.preventDefault(); 5997 const tabNumber = Number($(this).attr("data-tab")); 5998 if (!Number.isFinite(tabNumber)) return; 5999 6000 offerClickEvent(reqObj, this, false); 6001 const tabData = tabs.get(tabNumber); 6002 if (!tabData) return; 6003 6004 navigationStack.length = 0; 6005 showNestedView(); 6006 activateTabLevel(tabNumber, getNextLevelForTab(tabNumber, 0) ?? 1, null); 6007 }); 6008 6009 $experienceRoot.on("keydown", ".OWEntryNavigationItem", function (e) { 6010 const k = e.key || e.which; 6011 if (!isActivationKey(k)) return; 6012 e.preventDefault(); 6013 $(this).trigger("click"); 6014 }); 6015 6016 // ------------------------- 6017 // Back button: pop stack OR go to previous level OR return to Level0 tiles 6018 // ------------------------- 6019 $experienceRoot.on("click", ".OWEntryNavigationBarReturnButton, .OWEntryNavigationBarElipse, .OWEntryNavigationBarReturn", function (e) { 6020 e.preventDefault(); 6021 e.stopPropagation(); 6022 // only send reporting if we can derive an offer name (avoid spurious reports for pure navigation) 6023 const $btn = $(this); 6024 const offerName = $btn.attr('data-offer-name') || $btn.closest('[data-offer-name]').attr('data-offer-name'); 6025 if (isDefined(offerName)) { 6026 offerClickEvent(reqObj, this, false); 6027 } else { 6028 logInfo('OWX back nav clicked - no offerName, skipping reporting'); 6029 } 6030 6031 const previous = navigationStack.pop(); 6032 if (previous) { 6033 const previousTileKey = previous.level > 1 ? (previous.tileKey || null) : null; 6034 activateTabLevel(previous.tabNumber, previous.level, previousTileKey); 6035 return; 6036 } 6037 6038 const prevLevel = getPreviousLevelForTab(lastActiveTab, lastActiveLevel); 6039 if (prevLevel <= 0) { 6040 // 7) Hide shell and show Level0 tiles 6041 showLevel0View(); 6042 return; 6043 } 6044 6045 const prevTileKey = prevLevel > 1 ? (lastActiveTileKey || null) : null; 6046 activateTabLevel(lastActiveTab, prevLevel, prevTileKey); 6047 }); 6048 6049 // ------------------------- 6050 // Normalize heights for all levels (same level index => same min-height) 6051 // Deferred to first show of the nested view: at that point all ancestors are 6052 // guaranteed to be in the live render tree so outerHeight() returns real values. 6053 // ------------------------- 6054 let heightsNormalized = false; 6055 const normalizeHeightsOnce = () => { 6056 if (heightsNormalized) return; 6057 heightsNormalized = true; 6058 6059 const $levels = $shellContainersRoot.find(".OWEntryNestedLevel"); 6060 $levels.css({ display: "block", visibility: "hidden" }); 6061 6062 const levelHeights = {}; 6063 $levels.each(function () { 6064 const lvl = $(this).attr("data-level"); 6065 const h = $(this).outerHeight(true); 6066 levelHeights[lvl] = Math.max(levelHeights[lvl] || 0, h); 6067 }); 6068 6069 $levels.each(function () { 6070 const lvl = $(this).attr("data-level"); 6071 const h = levelHeights[lvl]; 6072 if (h) $(this).css("min-height", h); 6073 }); 6074 6075 $levels.css({ display: "none", visibility: "" }); 6076 }; 6077 6078 // Calculate oneFullPathrendered: 6079 // Check if there is at least one tab where the *highest level* contains a "leaf" offer (not nested, not container). 6080 // This indicates a full path is rendered/ready for that tab. 6081 var oneFullPathrendered = false; 6082 for (const [tabNumber, data] of tabs.entries()) { 6083 const levels = getSortedLevelsForTab(tabNumber); 6084 if (levels.length === 0) continue; 6085 6086 const maxLevel = levels[levels.length - 1]; 6087 const entries = data.levels.get(maxLevel) || []; 6088 6089 const hasLeaf = entries.some(({ offer, isNested }) => { 6090 const isContainer = isContainerPosition(offer.templatePosition); 6091 return !isNested && !isContainer; 6092 }); 6093 6094 if (hasLeaf) { 6095 oneFullPathrendered = true; 6096 break; 6097 } 6098 } 6099 handled.oneFullPathrendered = oneFullPathrendered; 6100 6101 // initial view 6102 showLevel0View(); 6103 return handled; 6104} 6105 6106function renderWarrantyOwTileOffers() { 6107 var warrantyTileOffers = offerResults.offers.offer.filter(function (x) { 6108 return x.OWTileOffer === true; 6109 });
6110 6111 6112 // order offer based on x.templatePosition (primary, secondary, shop1, shop2) 6113 warrantyTileOffers.sort(function (a, b) { 6114 var positionOrder = { "primary": 1, "secondary": 2, "shop1": 3, "shop2": 4, "shop3": 5 }; 6115 return positionOrder[a.templatePosition] - positionOrder[b.templatePosition]; 6116 }); 6117 6118 waitForElement("#SPOSOWEntryTiles").then(() => { 6119 var anyInserted = false; 6120 warrantyTileOffers.forEach(function (offerElement) { 6121 var offerInserted = insertWarrantyOWContainerOffer(offerElement); 6122 if (offerInserted) { 6123 anyInserted = true; 6124 } 6125 }); 6126 if (anyInserted) { 6127 // remove hidden from mastiff-dy-oow-section 6128 $("#mastiff-dy-oow-section").removeClass("hidden"); 6129 } 6130 }); 6131 6132 function insertWarrantyOWContainerOffer(offerElement) { 6133 var divId = ""; 6134 divId = divId.concat(offerElement.templatePosition, "_", offerElement.name); 6135 var LeadOffer = {}; 6136 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 6137 LeadOffer.OfferID = divId; 6138 LeadOffer.OfferClicked = "no"; 6139 LeadOffer.SPOStemplate = "32"; 6140 6141 if (isDefined(offerElement.html) 6142 && isDefined(offerElement.primaryText1) 6143 && isDefined(offerElement.primaryText2) 6144 && isDefined(offerElement.primaryButtonText) 6145 && isDefined(offerElement.storeURL) 6146 && isDefined(offerElement.imageURL) 6147 ) { 6148 var htmlTemplate = offerElement.html; 6149 6150 //replace placeholders 6151 htmlTemplate = htmlTemplate.replace("%OWEntryOfferTitlePlaceholder%", offerElement.primaryText1); 6152 htmlTemplate = htmlTemplate.replace("%OWEntryOfferDescriptionPlaceholder%", offerElement.primaryText2); 6153 htmlTemplate = htmlTemplate.replace("%OWEntryOfferCTAPlaceholder%", offerElement.primaryButtonText); 6154 htmlTemplate = htmlTemplate.replace("%OWEntryOfferImgURLPlaceholder%", offerElement.imageURL); 6155 htmlTemplate = htmlTemplate.replace("%falconContactHPOfferIdPlaceholder%", divId); 6156 6157 $("#mastiff-dy-oow-tiles").append(htmlTemplate); 6158 6159 LeadOffer.offerShown = "yes"; 6160 6161 applyAccessibilityAttributes(divId, offerElement); 6162 addUrlAndClickEvent(divId, offerElement); 6163 logInfo("DY OOW Tile Offer - Offer displayed successfully", "#mastiff-dy-oow-tiles"); 6164 return true; 6165 6166 // } else { 6167 // logInfo("DY OOW Tile Offer - Placement location is not empty", "#mastiff-dy-oow-tiles"); 6168 // } 6169 } else { 6170 logInfo("DY OOW Tile Offer - Missing mandatory fields", "#mastiff-dy-oow-tiles"); 6171 } 6172 return false; 6173 } 6174} 6175 6176function showSwdViewInStoreOffer(offerElement) { 6177 var divId = ""; 6178 divId = divId.concat("SWD-SPOS_", offerElement.templatePosition, "_", offerElement.name); 6179 6180 var LeadOffer = {}; 6181 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 6182 LeadOffer.OfferID = divId; 6183 LeadOffer.OfferClicked = "no"; 6184 LeadOffer.SPOStemplate = "15"; 6185 if ( 6186 isDefined(offerElement.html) && 6187 isDefined(offerElement.primaryButtonText) && 6188 isDefined(offerElement.storeURL) 6189 ) { 6190 var htmlTemplate = offerElement.html; 6191 if (isContainerEmpty("#mastiff_view_in_store_SWD")) { 6192 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateImgURL%", offerElement.imageURL); 6193 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", offerElement.primaryButtonText); 6194 htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId); 6195 6196 $("#mastiff_view_in_store_SWD").html(htmlTemplate); 6197 $("#mastiff_view_in_store_SWD").removeClass("hidden"); 6198 6199 $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" }); 6200 6201 applyAccessibilityAttributes(divId, offerElement); 6202 addUrlAndClickEvent(divId, offerElement); 6203 LeadOffer.offerShown = "yes"; 6204 logInfo("SWD View In Store Offer - Offer displayed successfully", "#mastiff_view_in_store_SWD"); 6205 } else { 6206 logInfo("SWD View In Store Offer - Placement location is not empty"); 6207 LeadOffer.errorData = "View In Store Location is not empty"; 6208 LeadOffer.offerShown = "no"; 6209 } 6210 logToGlobalDataLayer(LeadOffer); 6211 6212 } else { 6213 logInfo("SWD View In Store Offer - Missing mandatory fields"); 6214 LeadOffer.errorData = "No Content Available"; 6215 LeadOffer.offerShown = "no"; 6216 6217 logToGlobalDataLayer(LeadOffer); 6218 6219 } 6220} 6221 6222function showDriverDetailsOffer(offerElement) { 6223 var divId = ""; 6224 divId = divId.concat("SPOS_", offerElement.templatePosition, "_", offerElement.name); 6225 6226 var placeholderToinsertAt = ""; 6227 if (offerElement.templatePosition === "primary") { 6228 placeholderToinsertAt = "#driversPageMastiffBannerTop"; 6229 } else if (offerElement.templatePosition === "secondary") { 6230 placeholderToinsertAt = "#driversPageMastiffBannerBot"; 6231 } 6232 6233 var LeadOffer = {}; 6234 var GDLOfferName = "LeadOffer" + (LeadOfferIndex); 6235 LeadOffer.OfferID = divId; 6236 LeadOffer.OfferClicked = "no"; 6237 LeadOffer.SPOStemplate = "15"; 6238 6239 if ( 6240 isDefined(offerElement.html) && 6241 isDefined(offerElement.primaryText1) && 6242 isDefined(offerElement.primaryText2) && 6243 isDefined(offerElement.primaryButtonText) && 6244 isDefined(offerElement.imageURL) && 6245 isDefined(offerElement.storeURL) 6246 ) { 6247 var htmlTemplate = offerElement.html; 6248 if (isContainerEmpty(placeholderToinsertAt)) { 6249 htmlTemplate = htmlTemplate.replace("%DriverTileOfferImgURLPlaceholder%", offerElement.imageURL); 6250 htmlTemplate = htmlTemplate.replace("%DriverTileOfferTitlePlaceholder%", offerElement.primaryText1); 6251 htmlTemplate = htmlTemplate.replace("%DriverTileOfferDescriptionPlaceholder%", offerElement.primaryText2); 6252 htmlTemplate = htmlTemplate.replace("%DriverTileOfferCTAPlaceholder%", offerElement.primaryButtonText); 6253 htmlTemplate = htmlTemplate.replace("%DriverTileOfferId%", divId); 6254 htmlTemplate = htmlTemplate.replace("%secondaryContactHPOfferIdPlaceholder%", divId); 6255 6256 $(placeholderToinsertAt).html(htmlTemplate).css({ 'display': 'block', 'padding-bottom': '0px' }); 6257
6258 allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency); 6259 6260 $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" }); 6261 applyAccessibilityAttributes(divId, offerElement); 6262 6263 addUrlAndClickEvent(divId, offerElement); 6264 LeadOffer.offerShown = "yes"; 6265 logInfo("Driver Details Offer - Offer displayed successfully", placeholderToinsertAt); 6266 } else { 6267 logInfo("Driver Details Offer - Placement location is not empty", placeholderToinsertAt); 6268 LeadOffer.errorData = "Offer Location is not empty"; 6269 LeadOffer.offerShown = "no"; 6270 } 6271 logToGlobalDataLayer(LeadOffer); 6272 } else { 6273 logInfo("Driver Details Offer - Missing mandatory fields"); 6274 LeadOffer.errorData = "No Content Available"; 6275 LeadOffer.offerShown = "no"; 6276 6277 logToGlobalDataLayer(LeadOffer); 6278 } 6279} 6280 6281// ----------- Accessories Navigation Experiment ----------------- 6282async function showAccListOffers(accessoriesOffers) { 6283 // Normalize the API payload (or a legacy offer array) and retain only accessory-list offers. 6284 // This keeps response flattening in one place and avoids repeating it at every call site. 6285 var rawOffers = Array.isArray(accessoriesOffers) 6286 ? accessoriesOffers 6287 : accessoriesOffers && accessoriesOffers.offers 6288 ? accessoriesOffers.offers.offer 6289 : []; 6290 var accListOffers = []; 6291 var flattenOffers = function (offers) { 6292 if (Array.isArray(offers)) { 6293 offers.forEach(flattenOffers); 6294 return; 6295 } 6296 6297 if (offers && 6298 (safeLower(offers.name).includes("swcomp") || 6299 safeLower(offers.name).includes("acclist") || 6300 safeLower(offers.name).includes("accessorieslist")) && 6301 isDefined(offers.html)) { 6302 accListOffers.push(offers); 6303 } 6304 }; 6305 6306 flattenOffers(rawOffers); 6307 6308 if (!accListOffers || !accListOffers.length) return; 6309 6310 var containerSelector = "#mastiff-pdp-accessories"; 6311 6312 logInfo("AccList: starting render -", accListOffers.length, "offers"); 6313 6314 // -- local helpers ---------------------------------------------------------- 6315 6316 var parseFamilyKey = function (cat) { var m = (cat || "").match(/family(\d+)/i); return m ? "family" + m[1].toLowerCase() : null; }; 6317 var parseCategoryKey = function (cat) { var m = (cat || "").match(/category(\d+)/i); return m ? "category" + m[1].toLowerCase() : null; }; 6318 var parseOrderNum = function (key) { var m = (key || "").match(/\d+$/); return m ? parseInt(m[0], 10) : 0; }; 6319 var lp = function (o) { return safeLower(o.templatePosition || ""); }; 6320 var makeDivId = function (o) { return o.templatePosition + "_" + o.name; }; 6321 var replaceDivId = function (html, id) { return (html || "").replace(/%divId%/g, id); }; 6322 6323 // LeadOffer factory + status helpers (mirrors GDL pattern used throughout the file) 6324 var makeLeadOffer = function (divId, t) { return { OfferID: divId, OfferClicked: "no", offerShown: "no", SPOStemplate: t }; }; 6325 var failLeadOffer = function (lo, reason) { lo.offerShown = "no"; lo.errorData = reason; logInfo("AccList [skip]", lo.OfferID, "-", reason); logToGlobalDataLayer(lo); }; 6326 var doneLeadOffer = function (lo) { lo.offerShown = "yes"; logToGlobalDataLayer(lo); }; 6327 6328 // bind Enter/Space -> click (mirrors bindActivationKeyToClick in renderWarrantyNestedOwExperiment) 6329 var bindActivation = function ($el, ns) { 6330 $el.off("keydown." + ns).on("keydown." + ns, function (e) { 6331 var k = e.key || e.which; 6332 if (k === "Enter" || k === " " || k === 13 || k === 32) { e.preventDefault(); $(this).trigger("click"); } 6333 }); 6334 }; 6335 6336 var sortByFamily = function (a, b) { return parseOrderNum(parseFamilyKey(a.category)) - parseOrderNum(parseFamilyKey(b.category)); }; 6337 var sortByCategory = function (a, b) { return parseOrderNum(parseCategoryKey(a.category)) - parseOrderNum(parseCategoryKey(b.category)); }; 6338 6339 // -- per-templatePosition required fields + HTML token replacements --------- 6340 // required: fields that must be isDefined() before the offer is rendered. 6341 // replacements: { %token% : "offerFieldName" } applied (globally) after %divId% substitution. 6342 // Token naming convention mirrors existing codebase patterns (e.g. %OWEntryOffer*Placeholder%). 6343 var accTemplateConfig = { 6344 "level0container": { 6345 required: ["html"], 6346 replacements: { 6347 "%title%": "primaryText1" 6348 } 6349 }, 6350 "level0tile": { 6351 required: ["html", "imageURL", "primaryText1"], 6352 replacements: { 6353 "{title}": "primaryText1", 6354 "{imageurl}": "imageURL" 6355 } 6356 }, 6357 "familycontainer": { 6358 required: ["html", "primaryText1"], 6359 replacements: { 6360 "{title}": "primaryText1" 6361 } 6362 }, 6363 "categorycontainer": { 6364 required: ["html", "primaryText1"], 6365 replacements: { 6366 "{title}": "primaryText1" 6367 } 6368 }, 6369 "accessorycard": { 6370 required: ["html", "imageURL", "storeURL", "primaryButtonText"], 6371 replacements: { 6372 "{title}": "primaryText1", 6373 "%imageurl%": "imageURL", 6374 "%description%": "primaryText2", 6375 "{cta}": "primaryButtonText" 6376 } 6377 } 6378 }; 6379 6380 // escapeRegex: make a literal string safe for use inside RegExp (token chars like % are safe, but included for robustness) 6381 var escapeRegex = function (s) { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }; 6382 6383 // isOfferValid: check all required fields for the given templatePosition 6384 var isOfferValid = function (offer, pos) { 6385 var cfg = accTemplateConfig[pos] || { required: ["html"], replacements: {} }; 6386 return cfg.required.every(function (f) { return isDefined(offer[f]); }); 6387 }; 6388 6389 // applyTemplate: replace %divId% + all config tokens in the offer html 6390 var applyTemplate = function (offer, pos) { 6391 var cfg = accTemplateConfig[pos] || { required: ["html"], replacements: {} }; 6392 var html = replaceDivId(offer.html || "", makeDivId(offer));
6393 Object.keys(cfg.replacements).forEach(function (token) { 6394 html = html.replace(new RegExp(escapeRegex(token), "g"), offer[cfg.replacements[token]] || ""); 6395 }); 6396 return html; 6397 }; 6398 6399 // -- partition offers by templatePosition ---------------------------------- 6400 6401 var level0ContainerOffer = accListOffers.find(function (o) { return lp(o) === "level0container"; }); 6402 var level0TileOffers = accListOffers.filter(function (o) { return lp(o) === "level0tile"; }); 6403 var familyContainerOffers = accListOffers.filter(function (o) { return lp(o) === "familycontainer"; }); 6404 var categoryContainerOffers = accListOffers.filter(function (o) { return lp(o) === "categorycontainer"; }); 6405 var accessoryCardOffers = accListOffers.filter(function (o) { return lp(o) === "accessorycard"; }); 6406 6407 logInfo("AccList: partitioned - container:", !!level0ContainerOffer, 6408 "| tiles:", level0TileOffers.length, "| families:", familyContainerOffers.length, 6409 "| categories:", categoryContainerOffers.length, "| cards:", accessoryCardOffers.length); 6410 6411 // familyHasRenderableCards: pure look-ahead - returns true when the given familyKey 6412 // has at least one valid categorycontainer that itself contains at least one valid 6413 // accessorycard. No DOM or GDL side effects. Used to pre-filter level0 tiles. 6414 var familyHasRenderableCards = function (familyKey) { 6415 if (!familyKey) return false; 6416 return categoryContainerOffers.some(function (cat) { 6417 if (parseFamilyKey(cat.category) !== familyKey || !isOfferValid(cat, "categorycontainer")) return false; 6418 var catKey = parseCategoryKey(cat.category); 6419 return accessoryCardOffers.some(function (card) { 6420 return parseFamilyKey(card.category) === familyKey && 6421 parseCategoryKey(card.category) === catKey && 6422 isOfferValid(card, "accessorycard"); 6423 }); 6424 }); 6425 }; 6426 6427 if (!level0ContainerOffer || !isOfferValid(level0ContainerOffer, "level0container")) { 6428 logInfo("AccList: no valid level0container - aborting"); 6429 return; 6430 } 6431 6432 // -- wait for page placeholder --------------------------------------------- 6433 6434 var containerLo = makeLeadOffer(makeDivId(level0ContainerOffer), "45"); 6435 try { 6436 await waitForElement(containerSelector, "", 5000); 6437 } catch (e) { 6438 failLeadOffer(containerLo, "Placeholder not found: " + containerSelector); 6439 return; 6440 } 6441 6442 if (!isContainerEmpty(containerSelector)) { 6443 logInfo("AccList: container not empty - skipping double-render"); 6444 return; 6445 } 6446 6447 // -- insert level0container (hidden until full path confirmed) ------------- 6448 // Mirrors renderWarrantyNestedOwExperiment: build DOM first, reveal only after oneFullPathRendered check 6449 6450 var level0ContainerId = containerLo.OfferID; 6451 $(containerSelector).html(applyTemplate(level0ContainerOffer, "level0container")).removeClass("hidden"); 6452 // intentionally NOT calling .show() here - deferred to end of function 6453 doneLeadOffer(containerLo); 6454 logInfo("AccList: level0container built (hidden pending full-path check)", level0ContainerId); 6455 6456 var oneFullPathRendered = false; 6457 6458 // -- level0 tile menu ------------------------------------------------------ 6459 6460 level0TileOffers.slice().sort(sortByFamily).forEach(function (offer) { 6461 var divId = makeDivId(offer), familyKey = parseFamilyKey(offer.category); 6462 var lo = makeLeadOffer(divId, "47"); 6463 if (!isOfferValid(offer, "level0tile")) { failLeadOffer(lo, "Missing required fields"); return; } 6464 if (!familyHasRenderableCards(familyKey)) { failLeadOffer(lo, "No renderable content for family"); return; } 6465 6466 var $tile = $(applyTemplate(offer, "level0tile")); 6467 if (familyKey) $tile.attr("data-acc-family", familyKey); 6468 $tile.attr("data-offer-name", offer.name || ""); 6469 $("#menuOffersContainer").append($tile); 6470 applyAccessibilityAttributes(divId, offer); 6471 6472 $tile.off(".accListNav").on("click.accListNav", function (e) { 6473 e.preventDefault(); 6474 offerClickEvent(reqObj, this, false); 6475 var fk = $tile.attr("data-acc-family"); 6476 if (fk) { 6477 logInfo("AccList: navigating to family", fk); 6478 $("#menuOffersContainer").hide(); 6479 $("#" + level0ContainerId).children("[data-acc-family='" + fk + "']").show(); 6480 } 6481 }); 6482 bindActivation($tile, "accListNav"); 6483 doneLeadOffer(lo); 6484 });
6485 6486 // -- family containers (hidden) + nested sub-structure -------------------- 6487 6488 familyContainerOffers.slice().sort(sortByFamily).forEach(function (familyOffer) { 6489 var familyDivId = makeDivId(familyOffer), familyKey = parseFamilyKey(familyOffer.category); 6490 var familyLo = makeLeadOffer(familyDivId, "48"); 6491 if (!isOfferValid(familyOffer, "familycontainer")) { failLeadOffer(familyLo, "Missing required fields"); return; } 6492 6493 var $familyDiv = $(applyTemplate(familyOffer, "familycontainer")); 6494 if (familyKey) $familyDiv.attr("data-acc-family", familyKey); 6495 $familyDiv.hide(); 6496 // DOM append deferred - $familyDiv is only inserted when â¥1 category has renderable cards 6497 6498 // back button: .menuCategoryTitle -> return to level0 tile view 6499 var $backBtn = $familyDiv.find(".menuCategoryTitle"); 6500 $backBtn.off(".accListBack").on("click.accListBack", function (e) { 6501 e.preventDefault(); 6502 logInfo("AccList: back -> level0 from family", familyKey); 6503 $familyDiv.hide(); 6504 $("#menuOffersContainer").show(); 6505 }); 6506 bindActivation($backBtn, "accListBack"); 6507 6508 // -- category containers for this family ------------------------------- 6509 6510 var familyHasCard = false; 6511 var pendingFamilyBindings = []; 6512 6513 categoryContainerOffers 6514 .filter(function (c) { return parseFamilyKey(c.category) === familyKey; }) 6515 .sort(sortByCategory) 6516 .forEach(function (catOffer) { 6517 var catDivId = makeDivId(catOffer), catKey = parseCategoryKey(catOffer.category); 6518 var catLo = makeLeadOffer(catDivId, "49"); 6519 if (!isOfferValid(catOffer, "categorycontainer")) { failLeadOffer(catLo, "Missing required fields"); return; } 6520 6521 var $catDiv = $(applyTemplate(catOffer, "categorycontainer")); 6522 if (catKey) $catDiv.attr("data-acc-category", catKey); 6523 // DOM append deferred - $catDiv is only inserted when â¥1 card renders below 6524 6525 // -- accessory cards for this family + category ----------------- 6526 6527 var catHasCard = false; 6528 6529 accessoryCardOffers 6530 .filter(function (card) { 6531 return parseFamilyKey(card.category) === familyKey && parseCategoryKey(card.category) === catKey; 6532 }) 6533 .forEach(function (cardOffer) { 6534 var cardDivId = makeDivId(cardOffer); 6535 var cardLo = makeLeadOffer(cardDivId, "44"); 6536 6537 // require html + storeURL + primaryButtonText - validated by accTemplateConfig["accessorycard"].required 6538 if (!isOfferValid(cardOffer, "accessorycard")) { 6539 failLeadOffer(cardLo, "Missing required fields"); 6540 return; 6541 } 6542 6543 var cardOfferForTemplate = Object.assign({}, cardOffer, { 6544 primaryText1: (cardOffer.name || "").endsWith("_01") ? cardOffer.primaryText1 : "" 6545 }); 6546 $catDiv.find("#menuSubCategoryOffers").append(applyTemplate(cardOfferForTemplate, "accessorycard")); 6547 6548 // defer DOM-dependent calls until $familyDiv is in the live document 6549 pendingFamilyBindings.push({ cardOffer: cardOffer, cardDivId: cardDivId, cardLo: cardLo }); 6550 catHasCard = true; 6551 }); 6552 6553 if (catHasCard) { 6554 $familyDiv.find("#menuSubCategoriesContainer").append($catDiv); 6555 logInfo("AccList: categoryContainer appended", catDivId, "| category:", catKey); 6556 familyHasCard = true; 6557 doneLeadOffer(catLo); 6558 } else { 6559 failLeadOffer(catLo, "No valid cards for category"); 6560 } 6561 }); 6562 6563 if (familyHasCard) { 6564 $("#" + level0ContainerId).append($familyDiv); 6565 // $familyDiv is now in the live DOM - safe to query cards by id
6566 pendingFamilyBindings.forEach(function (item) { 6567 allocateRecEngPrices(item.cardOffer.strikePrice, item.cardOffer.incartPrice, item.cardDivId, item.cardOffer.currency); 6568 applyAccessibilityAttributes(item.cardDivId, item.cardOffer); 6569 addUrlAndClickEvent(item.cardDivId, item.cardOffer); 6570 doneLeadOffer(item.cardLo); 6571 logInfo("AccList: accessoryCard rendered", item.cardDivId); 6572 }); 6573 logInfo("AccList: familyContainer appended (hidden)", familyDivId, "| family:", familyKey); 6574 oneFullPathRendered = true; 6575 doneLeadOffer(familyLo); 6576 } else { 6577 failLeadOffer(familyLo, "No valid cards for family"); 6578 } 6579 }); 6580 6581 // -- deferred reveal (same pattern as renderWarrantyNestedOwExperiment) ---- 6582 // Only show #mastiff-pdp-accessories when at least one full path 6583 // (level0container -> family -> category -> accessoryCard) is confirmed rendered. 6584 6585 if (oneFullPathRendered) { 6586 $(containerSelector).removeClass("hidden"); 6587 logInfo("AccList: accessories navigation visible - full path confirmed", containerSelector); 6588 } else { 6589 $(containerSelector).addClass("hidden"); 6590 logInfo("AccList: no fully accessible card found - keeping", containerSelector, "hidden"); 6591 } 6592} 6593// ----------- Offer rendering code ends here ---------------- 6594 6595// --------------- slider code starts here ----------------- 6596var slide_index = 1; 6597var myVarTimeout; 6598var sliderClassName = ""; 6599var navBulletAvailable = false; 6600 6601function nextSlide(n) { 6602 displaySlides(slide_index += n); 6603} 6604 6605function currentSlide(n) { 6606 displaySlides(slide_index = n); 6607} 6608 6609function displaySlides(n) { 6610 clearTimeout(myVarTimeout); 6611 var i; 6612 var slides = document.getElementsByClassName(sliderClassName); 6613 if (navBulletAvailable) { 6614 var bullets = document.querySelectorAll(".nav-bullet"); 6615 } 6616 6617 if (n > slides.length) { slide_index = 1 } 6618 if (n < 1) { slide_index = slides.length } 6619 for (i = 0; i < slides.length; i++) { 6620 slides[i].style.display = "none"; 6621 if (navBulletAvailable) { 6622 bullets[i].classList.remove("nav-bullet-active"); 6623 } 6624 } 6625 6626 if (slides[slide_index - 1]) { 6627 slides[slide_index - 1].style.display = "block"; 6628 } 6629 if (navBulletAvailable && bullets[slide_index - 1]) { 6630 bullets[slide_index - 1].className += " nav-bullet-active"; 6631 } 6632 myVarTimeout = setTimeout(showSlidesAuto, 5000); 6633} 6634 6635function showSlidesAuto() { 6636 clearTimeout(myVarTimeout); 6637 var i; 6638 var slides = document.getElementsByClassName(sliderClassName); 6639 if (navBulletAvailable) { 6640 var bullets = document.querySelectorAll(".nav-bullet"); 6641 } 6642 6643 for (i = 0; i < slides.length; i++) { 6644 slides[i].style.display = "none"; 6645 } 6646 if (navBulletAvailable) { 6647 for (i = 0; i < bullets.length; i++) { 6648 bullets[i].classList.remove("nav-bullet-active"); 6649 } 6650 } 6651 slide_index++; 6652 if (slide_index > slides.length) { slide_index = 1 } 6653 6654 if (slides[slide_index - 1]) { 6655 slides[slide_index - 1].style.display = "block"; 6656 } 6657 6658 if (navBulletAvailable && bullets[slide_index - 1]) { 6659 bullets[slide_index - 1].className += " nav-bullet-active"; 6660 } 6661 myVarTimeout = setTimeout(showSlidesAuto, 5000); 6662} 6663 6664 6665// --------------- slider code ends here ----------------- 6666 6667// --------------- RecEng Price Allocation code starts here ----------------- 6668function allocateRecEngPrices(strikePraw, inCartPraw, divId, currency) { 6669 const $root = $("#" + (divId || "")); 6670 const $strikeDiv = $root.find(".strikePricePlaceholder"); 6671 const $inCartDiv = $root.find(".incartPricePlaceholder"); 6672 const $discountDiv = $root.find(".discountPercentage"); 6673 6674 var locale = `${reqObj?.user?.language}-${reqObj?.user?.countryCode}` 6675 .toLowerCase(); 6676 6677 locale = /^[a-z]{2}-[a-z]{2}$/.test(locale) ? locale : 'en-us'; 6678 6679 const toNum = v => (v == null ? NaN : Number(v)); 6680 const a = toNum(strikePraw), b = toNum(inCartPraw); 6681 6682 if ((Number.isNaN(a) && Number.isNaN(b)) || !$root.length || !isDefined(currency)) { 6683 $strikeDiv.hide(); $inCartDiv.hide(); $discountDiv.hide(); return; 6684 } 6685
6686 // determine raw strike (higher) and incart (lower) 6687 var strikeRaw = Number.isFinite(strikePraw) ? strikePraw : 0; 6688 var inCartRaw = Number.isFinite(inCartPraw) ? inCartPraw : 0; 6689 if (strikeRaw < inCartRaw && strikeRaw > 0) { 6690 [strikeRaw, inCartRaw] = [inCartRaw, strikeRaw]; 6691 } 6692 6693 // identical prices => no strike price 6694 if (strikeRaw === inCartRaw) strikeRaw = 0; 6695 6696 // formatter that shows no decimals for whole numbers, 2 decimals otherwise 6697 const fmt = (value) => { 6698 if (!Number.isFinite(value) || value === 0) return null; 6699 const isInt = Number.isInteger(value); 6700 return new Intl.NumberFormat(locale, { 6701 style: "currency", 6702 currency, 6703 minimumFractionDigits: isInt ? 0 : 2, 6704 maximumFractionDigits: isInt ? 0 : 2 6705 }).format(value); 6706 }; 6707 6708 const strikeFmt = fmt(strikeRaw); 6709 const inCartFmt = fmt(inCartRaw); 6710 6711 // render or hide 6712 if (strikeFmt && $strikeDiv.length) 6713 $strikeDiv.html(strikeFmt).show(); 6714 else 6715 $strikeDiv.hide(); 6716 6717 if (inCartFmt && $inCartDiv.length) 6718 $inCartDiv.html(inCartFmt).show(); 6719 else 6720 $inCartDiv.hide(); 6721 6722 // discount: only shown when strike exists and >10% 6723 if ($discountDiv.length) { 6724 if (strikeRaw > 0) { 6725 const discount = Math.round(((strikeRaw - inCartRaw) / strikeRaw) * 100); 6726 discount > 10 ? $discountDiv.html(discount + "%").show() : $discountDiv.hide(); 6727 } else { 6728 $discountDiv.hide(); 6729 } 6730 } 6731} 6732 6733// --------------- RecEng Price Allocation code ends here ----------------- 6734 6735// --------------- Quiz Code Starts Here ----------------- 6736 6737var _quizReady = null; 6738var quizReadyWatchers = []; 6739 6740var quizReadyState = new Proxy({}, { 6741 set(target, prop, value) { 6742 if (prop === "value") { 6743 _quizReady = value; 6744 logInfo(`[quizReadyState] value set to:`, value); 6745 quizReadyWatchers.forEach((cb, idx) => { 6746 logInfo(`[quizReadyState] firing watcher #${idx + 1}`); 6747 cb(); 6748 }); 6749 quizReadyWatchers.length = 0; 6750 } 6751 return true; 6752 }, 6753 get(target, prop) { 6754 if (prop === "value") return _quizReady; 6755 } 6756}); 6757 6758function waitForQuizReady() { 6759 const ready = quizReadyState.value; 6760 if (ready === true || ready === false) { 6761 logInfo("[waitForQuizReady] quizReady is known:", ready); 6762 return Promise.resolve(); 6763 } 6764 6765 return new Promise((resolve) => { 6766 logInfo("[waitForQuizReady] quizReady is pending, adding to watchers"); 6767 quizReadyWatchers.push(() => { 6768 logInfo("[waitForQuizReady] watcher fired, value is now:", quizReadyState.value); 6769 resolve(); 6770 }); 6771 }); 6772} 6773 6774function handleQuizApiResponse(swReqObj) { 6775 handleApiResponse(swReqObj).then((response) => { 6776 const dashboardHuqQuiz = pgName === "dashboard" && uiState.quiztype === "huq"; 6777 quizReadyState.value = response === true && !dashboardHuqQuiz; 6778 6779 if (dashboardHuqQuiz) { 6780 logInfo("[Dashboard Quiz] HUQ is not supported on the dashboard; marking Quiz Portal as unavailable."); 6781 } 6782 }).finally(() => { 6783 if (uiState.quiztype === "cpc") { 6784 $('.CPConfiguratorContainer').hide(); 6785 } else if (uiState.quiztype === "huq") { 6786 $('.HUQConfiguratorContainer').hide(); 6787 } 6788 }); 6789} 6790 6791async function handleApiResponse(swReqObj) { 6792 try { 6793 structuredData = await getApiResponseStructuredData(swReqObj).catch((error) => { 6794 return false; 6795 }); 6796 6797 const offerName = structuredData.name?.toLowerCase() || ''; 6798 uiState.offerName = structuredData.name; 6799 uiState.quiztype = offerName.includes("cpc") ? "cpc" : (offerName.includes("huq") ? "huq" : null); 6800 6801 if (!uiState.quiztype) { 6802 console.error("No valid offer name found in the API response."); 6803 return false; 6804 } 6805 6806 uiState.quizCurrency = CPChardcodedContent.quizBodyContent.footer.currencies?.[quizReqOb
6806j.user.countryCode]; 6807 6808 if (structuredData.products.length === 0) { 6809 console.error("No valid products found in the API response."); 6810 $('.CPConfiguratorContainer').hide(); 6811 $('.HUQConfiguratorContainer').hide(); 6812 return false; 6813 } 6814 6815 if (offerName.includes("cpc")) { 6816 handleCPCScenario(structuredData); 6817 return true; 6818 } else if (offerName.includes("huq")) { 6819 handleHUQScenario(structuredData); 6820 return true; 6821 } else { 6822 console.error("Unknown scenario: ", structuredData.name); 6823 return false; 6824 } 6825 6826 6827 } catch (error) { 6828 console.error("Failed to handle API response:", error); 6829 } finally { 6830 $('.HUQonfiguratorSpinner').hide(); 6831 $('.CPConfiguratorSpinner').hide(); 6832 } 6833} 6834 6835async function getApiResponseStructuredData(requestObject) { 6836 quizReqObj = JSON.parse(JSON.stringify(requestObject)); 6837 setReqId(); 6838 setMastiffSessionId(); 6839 quizReqObj.user.callerId = "quizportal"; 6840 quizReqObj.user.pageId = "supportweb"; //should be changed later to supportweb 6841 //quizReqObj.product.modelNumber = "7Z8K5PC"; 6842 //quizReqObj.product.warranty.warrantyState = "IW"; 6843 6844 6845 try { 6846 var responseData; 6847 6848 6849 if (isMastiffDebug() && window.location.protocol === "file:") { 6850 responseData = await sendDemoPostRequest(sku, warranty); 6851 } else { 6852 responseData = await sendPostRequest(apiUrl, quizReqObj); 6853 } 6854 const structuredData = extractOffers(responseData); 6855 6856 if (!structuredData) { 6857 throw new Error("Empty or malformed offer data."); 6858 } 6859 6860 logInfo("Structured Offers:", structuredData); 6861 6862 return structuredData; 6863 6864 } catch (error) { 6865 console.error('Failed to fetch or process offers:', error); 6866 } 6867} 6868 6869function removeQuizSpinner() { 6870 return waitForElement(".sposQuizSpinner") 6871 .then(spinner => { spinner?.remove(); }) 6872 .catch(() => { }); 6873} 6874 6875function discardQuizPortalExperience(offerName) { 6876 uiState.status = "Abondoned"; 6877 if (offerName) uiState.offerName = offerName; 6878 6879 sendReportingRequest(uiState); 6880 uiState.reportAlreadySent = true; 6881 6882 uiState.results = []; 6883 uiState.acceptedSKU = ""; 6884 uiState.q1 = ""; 6885 uiState.q2 = ""; 6886 uiState.q3 = []; 6887 uiState.total = ""; 6888 uiState.userInteracted = false; 6889 uiState.matchedDirectSelection = undefined; 6890 uiState.relaxationIteration = undefined; 6891} 6892 6893$(document).on("click", ".CPConfiguratorCloseButton", function () { 6894 $(".quizPortalDiv").hide(); 6895 $('.WRPrimaryTile').show(); 6896 $("#mastiff-check-warranty-secondary-offers").show(); 6897 6898 discardQuizPortalExperience(); 6899}); 6900 6901var apiUrl = getMastiffUrl(); 6902 6903var cvgTypeTooltips = {}; 6904var matchedCarePack = undefined; 6905var quizSubmitted = false; 6906var analyzedCarepacks = {}; 6907 6908var answerClicked = 0; 6909var cvgTypeClicked = false; 6910 6911var checkboxType = { 6912 format: "", 6913 state: "", 6914 location: "", 6915 style: "", 6916 dependenciesIDs: "", 6917 exclusionsIDs: "" 6918}; 6919 6920var quizReqObj = { 6921 requestId: "", 6922 offerLocations: "primary,shop1,shop2,shop3,secondary", 6923 offerName: "", 6924 acceptanceLevel: "", 6925 consent: "", 6926 user: { 6927 callerId: "quizportal", 6928 sessionId: "", 6929 pageId: "supportweb", 6930 intent: "", 6931 locale: "us-en", 6932 countryCode: "us", 6933 language: "en", 6934 }, 6935 product: { 6936 carePackEligible: "", 6937 modelNumber: "", 6938 serialNumber: "", 6939 warranty: { 6940 warrantyState: "", 6941 warrantyStartdate: "", 6942 warrantyEnddate: "", 6943 6944 } 6945 } 6946}; 6947 6948var availableCarepacks = []; 6949var resultHUQOffers; 6950var structuredData = {}; 6951var uiState = {}; 6952 6953var pendingReportTimeoutId = null; 6954var REPORT_DELAY_MS = 60 * 1000 * 15; 6955 6956 6957async function prepareInitialUi(warranty = null) { 6958 uiState.userInteracted = false;
6959 uiState.reportAlreadySent = false; 6960 6961 $(document).on('click', '.CPConfiguratorContainer, .HUQConfiguratorContainer', function () { 6962 if (quizSubmitted) return; 6963 6964 uiState.userInteracted = true; 6965 uiState.status = "Not Completed"; 6966 }); 6967 6968 await sendPendingReport(); 6969 6970 $('.CPConfiguratorContainer').hide(); 6971 $('.HUQConfiguratorContainer').hide(); 6972 $('.CPConfiguratorSpinner').hide(); 6973 $('.HUQonfiguratorSpinner').hide(); 6974 6975 if (warranty === "PW" || warranty === "IW") { 6976 $('.CPConfiguratorSpinner').show(); 6977 } 6978 6979 if (warranty === "OW") { 6980 $('.HUQonfiguratorSpinner').show(); 6981 } 6982 6983 6984} 6985 6986$(document).on("click", ".CPConfiguratorStartButton", function () { 6987 $('.CPConfiguratorSpinner').show(); 6988 (async () => { const structuredData = await CPC_API.getApiReesponseStructuredData(); })(); 6989 const analyzedCarepacks = analyzeCarepacks(availableCarepacks.products); 6990 displayAnswers(analyzedCarepacks); 6991 $('.CPConfiguratorSpinner').hide(); 6992 $('.CPConfiguratorContainer').show(); 6993}); 6994 6995$(document).on("click", ".CPConfiguratorAnswerLabel", function () { 6996 if (Date.now() - answerClicked < 100) return; 6997 if (uiState.quiztype === "cpc") { 6998 if ($(this).find('input[type="radio"]:disabled').length === 0 && $(this).find('input[type="checkbox"]:disabled').length === 0) { 6999 var $answeredQuestion; 7000 7001 if ($(this).hasClass('CPConfiguratorAnswerduration')) { 7002 $(this).find('input[type="radio"]').prop('checked', true); 7003 $answeredQuestion = $('.CPConfiguratorItem').eq(0); 7004 $('.CPConfiguratorItem').eq(1).find('.CPConfiguratorAnswers').hide(); 7005 const displayedCoverageTypes = `#CPConfiguratorAnswerscoverageType__${$(this).attr('id')}`; 7006 $(displayedCoverageTypes).css('display', 'flex'); 7007 7008 if (answerClicked) { 7009 $(displayedCoverageTypes).find('input[type="radio"]').first().prop('checked', true).trigger('change') 7010 $answeredQuestion = $('.CPConfiguratorItem:lt(2)'); 7011 } 7012 $('.CPConfiguratorItem').eq(2).find('.CPConfiguratorAnswers').hide(); 7013 $(`#CPConfiguratorAnswersfeature__${$(displayedCoverageTypes).find('input[type="radio"]').first().closest('label').attr('id')}`).css('display', 'flex'); 7014 adjustQuestion($('.CPConfiguratorItem').eq(1), 'unchecked'); 7015 7016 } 7017 if ($(this).hasClass('CPConfiguratorAnswercoverageType')) { 7018 $(this).find('input[type="radio"]').prop('checked', true); 7019 $answeredQuestion = $('.CPConfiguratorItem').eq(1); 7020 $('.CPConfiguratorItem').eq(2).find('.CPConfiguratorAnswers').hide(); 7021 $(`#CPConfiguratorAnswersfeature__${$(this).attr('id')}`).css('display', 'flex'); 7022 } 7023 setTimeout(() => { 7024 if ($(this).hasClass('CPConfiguratorAnswerfeature')) { 7025 $answeredQuestion = $('.CPConfiguratorItem').eq(2); 7026 } 7027 const thirdQuestion = $('.CPConfiguratorItem').eq(2), 7028 secondQuestionSelected = $('#CPConfiguratorAnswerscoverageType__' + $($('input[name="duration"]:checked')).closest('label').attr('id')).find('input[type="radio"]:checked').length !== 0, 7029 thirdQuestionEmpty = $('#CPConfiguratorAnswersfeature__' + $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').attr('id')).find('input[type="checkbox"]').length === 0, 7030 thirdQuestionSelected = $('#CPConfiguratorAnswersfeature__' + $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').attr('id')).find('input[type="checkbox"]:checked').length > 0; 7031 7032 if (secondQuestionSelected) { 7033 adjustQuestion(thirdQuestion, thirdQuestionEmpty ? 'disabled:checked' : thirdQuestionSelected ? 'checked' : 'unchecked'); 7034 cvgTypeClicked = true; 7035 } 7036 7037 var isChecked = ($(this).closest('.CPConfiguratorAnswers').find('input[type="checkbox"]:checked').length > 0 || $(this).closest('.CPConfiguratorAnswers').find('input[type="radio"]:checked').length > 0); 7038 if (isChecked) { 7039 adjustQuestion($answeredQuestion, 'checked'); 7040 } else { 7041 $('.CPConfiguratorResultSubmissionButton').removeClass('CPConfiguratorResultSubmissionButtonActive'); 7042 adjustQuestion($answeredQuestion, 'unchecked'); 7043 } 7044 if ($(this).hasClass('CPConfiguratorAnswerfeature') || ($(this).hasClass('CPConfiguratorAnswercoverageType')) || $(this).hasClass('CPConfiguratorAnswerduration')) { 7045 var currentID = $(this).hasClass('CPConfiguratorAnswerfeature') ? `#${$(this).closest('.CPConfiguratorAnswers').attr('id')}` : $(this).hasClass('CPConfiguratorAnswercoverageType') ? `#CPConfiguratorAnswersfeature__${$(this).attr('id')}` : $(this).hasClass('CPConfiguratorAnswerduration') ? `#CPConfiguratorAnswersfeature__${$(`#CPConfiguratorAnswerscoverageType__${$(this).attr('id')}`).find('input[type="radio"]').first().closest('label').attr('id')}` : ""; 7046 if ($(currentID).find('div.CPCnoAddonNotif').length == 0) { 7047 $(`${currentID} > div`).each(function () { 7048 const deps = $(this).data('dependencies'); 7049 7050 const allChecked = deps 7051 .split(' ') 7052 .map(id => id.trim()) 7053 .filter(id => id.length > 0) 7054 .every(id => $('#' + id).find('input[type="checkbox"]').prop('checked')); 7055 7056 const excls = $(this).data('exclusions'); 7057 7058 const anyExcl = excls 7059 .split(' ') 7060 .map(id => id.trim()) 7061 .filter(id => id.length > 0) 7062 .some(id => $('#' + id).find('input[type="checkbox"]').prop('checked')); 7063 7064 var selectedDuration = $('input[name="duration"]:checked').closest('label').text().trim(), 7065 selectedcoverageType = $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(), 7066 selectedFeatures = $(`input[name=${selectedcoverageType.replace(/\s+/g, '_')}__${selectedDuration.replace(/\s+/g, '_')}]:checked`).map(function () { return $(this).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(); }).get(); 7067 7068 if (!$(this).find('input[type="checkbox"]:checked').length) 7069 selectedFeatures.push(($(this).find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim())); 7070 7071 var isAddon = availableCarepacks.products.some(carePack => 7072 carePack.answers?.q1 === selectedDuration && 7073 carePack.answers?.q2 === selectedcoverageType && 7074 Array.isArray(carePack.answers?.q3) && 7075 selectedFeatures.length === carePack.answers.q3.length && 7076 selectedFeatures.every(f => carePack.answers.q3.includes(f)) 7077 ); 7078 7079 7080 if (allChecked && !anyExcl && isAddon || $(this).hasClass('CPConfiguratorAnswerChild') && !anyExcl && isAddon || $(this).hasClass('CPConfiguratorAnswerStandalone') && !anyExcl && isAddon) {
7081 $(this).find('input:checkbox:disabled').each(function () { 7082 if ($(this).hasClass('CPConfiguratorAnswerHasRootParents') || $(this).hasClass('CPConfiguratorAnswerStandalone')) { 7083 $(this).prop('disabled', false); 7084 } 7085 $(this).find('label').removeClass('CPConfiguratorAnswerDisabled'); 7086 7087 }) 7088 if (!$(this).hasClass('CPConfiguratorAnswerStandalone')) { 7089 $(this).find('input:checkbox:disabled').prop('checked', true); 7090 $(this).find('input:checkbox:not(:disabled)').prop('disabled', false); 7091 } else { 7092 $(this).find('input:checkbox:disabled').prop('disabled', false); 7093 $(this).find('label').removeClass('CPConfiguratorAnswerDisabled'); 7094 7095 } 7096 } else if (anyExcl || !isAddon) { 7097 $(this).find('label').addClass('CPConfiguratorAnswerDisabled'); 7098 7099 $(this).find('input:checkbox:disabled').prop('checked', false); 7100 $(this).find('input:checkbox:not(:disabled)').prop('disabled', true); 7101 $(this).find('input:checkbox:not(:disabled):checked').prop('disabled', true).prop('checked', false); 7102 } else if (!allChecked) { 7103 $(this).find('input:checkbox:disabled').prop('checked', false); 7104 $(this).find('input:checkbox:not(:disabled):not(:checked)').prop('disabled', true); 7105 7106 $(this).find('input:checkbox:not(:disabled):not(:checked)').each(function () { 7107 if ($(this).hasClass('CPConfiguratorAnswerHasRootParents')) { 7108 $(this).prop('disabled', true); 7109 } 7110 }); 7111 } 7112 }); 7113 } 7114 } 7115 captureSelectedElements(); 7116 if (matchedCarePack !== undefined) { 7117 allocateQuizPrices(matchedCarePack.strikePrice, matchedCarePack.incartPrice, ".CPConfiguratorResultSubmissionTotal"); 7118 $('.CPConfiguratorResultSubmissionButton').addClass('CPConfiguratorResultSubmissionButtonActive'); 7119 } else { 7120 $('.CPConfiguratorResultSubmissionTotalPrice').html(uiState.quizCurrency.replace("%price%", '0')); 7121 $('.CPConfiguratorResultSubmissionButton').removeClass('CPConfiguratorResultSubmissionButtonActive'); 7122 } 7123 7124 }, 0); 7125 7126 } 7127 } else if (uiState.quiztype === "huq") { 7128 const answerClasses = ['location', 'type', 'features']; 7129 const questionIndexes = [3, 4, 5]; 7130 7131 if (answerClicked === 0) { 7132 answerClasses.forEach((answerClass, index) => { 7133 if ($(this).hasClass('CPConfiguratorAnswer' + answerClass)) { 7134 const $answeredQuestion = $('.CPConfiguratorItem').eq(questionIndexes[index]); 7135 adjustQuestion($answeredQuestion, 'checked'); 7136 } 7137 }); 7138 setTimeout(captureSelectedElements, 0); 7139 } else { 7140 setTimeout(() => { 7141 answerClasses.forEach((answerClass, index) => { 7142 const $answeredQuestion = $('.CPConfiguratorItem').eq(questionIndexes[index]); 7143 if ($(this).hasClass('CPConfiguratorAnswer' + answerClass)) { 7144 if (answerClass === 'features') { 7145 const isChecked = $('input[name="features"]:checked').length > 0; 7146 adjustQuestion($answeredQuestion, isChecked ? 'checked' : 'unchecked'); 7147 } else { 7148 adjustQuestion($answeredQuestion, 'checked'); 7149 } 7150 } 7151 }); 7152 7153 captureSelectedElements(); 7154 7155 const allAnswered = answerClasses.every( 7156 name => $('input[name="' + name + '"]:checked').length > 0 7157 ); 7158 $('.CPConfiguratorResultSubmissionButton').toggleClass( 7159 'CPConfiguratorResultSubmissionButtonActive', 7160 allAnswered 7161 ); 7162 }, 0); 7163 } 7164 7165 7166 } 7167 answerClicked = Date.now(); 7168}); 7169 7170$(document).on("click", ".CPConfiguratorResultSubmissionButtonActive", function () { 7171 logInfo("submit clicked"); 7172 cvgTypeClicked = false; 7173 $('.CPConfiguratorBody').addClass('CPConfiguratorBodyDisabled'); 7174 $('.CPConfiguratorResultSubmission').hide(); 7175 $('.CPConfiguratorCloseButton').hide(); 7176 $('.CPConfiguratorResetButton').css('display', 'flex'); 7177 adjustQuestion($('.CPConfiguratorItem'), 'disabled:checked'); 7178 7179 quizSubmitted = true; 7180 uiState.status = "Completed"; 7181 7182 if (uiState.quiztype === "cpc") { 7183 allocateQuizPrices(matchedCarePack.strikePrice, matchedCarePack.incartPrice, ".CPConfiguratorResultOfferHeaderPrice"); 7184 $('.CPConfiguratorResultOfferDescription').text(matchedCarePack.skuName); 7185 uiState.results.push(matchedCarePack.productSKU); 7186 uiState.offerResults.push(matchedCarePack); 7187 7188 $('.CPConfiguratorResultOfferCTA') 7189 .off('click') 7190 .on('click', function () { 7191 uiState.acceptedSKU = matchedCarePack.productSKU; 7192 sendReportingRequest(uiState);
7193 uiState.reportAlreadySent = true; 7194 window.open(matchedCarePack.storeURL, '_blank'); 7195 }); 7196 7197 $('.CPConfiguratorResultOffer').css('display', 'flex'); 7198 } 7199 7200 if (uiState.quiztype === "huq") { 7201 const offerTypes = [ 7202 { key: 'budgetFriendly', pricesWrapper: '.HUQBudgetFriendlyPrice', CTA: '.CPConfiguratorResultSubmissionButtonHUQBudgetFriendly' }, 7203 { key: 'recommended', pricesWrapper: '.HUQRecommendedForYouPrice', CTA: '.CPConfiguratorResultSubmissionButtonHUQRecommended' }, 7204 { key: 'mostPopular', pricesWrapper: '.HUQMostPopularPrice', CTA: '.CPConfiguratorResultSubmissionButtonHUQMostPopular' } 7205 ]; 7206 7207 resultHUQOffers = getRecommendedProductSet(structuredData.products, uiState); 7208 7209 offerTypes.forEach((offerType, index) => { 7210 const offer = resultHUQOffers[offerType.key]; 7211 uiState.results.push(offerType.key + "_" + offer.productSKU); 7212 uiState.offerResults.push(offer); 7213 $('.CPConfiguratorResultOfferSectionHUQOfferImg').eq(index).attr('src', offer.imageURL); 7214 $('.CPConfiguratorResultOfferSectionHUQOfferDescription').eq(index).text(offer.skuName); 7215 allocateQuizPrices(offer.strikePrice, offer.incartPrice, offerType.pricesWrapper); 7216 7217 $(offerType.CTA) 7218 .off('click') 7219 .attr('id', offer.productSKU) 7220 .on('click', () => { 7221 uiState.acceptedSKU = $(offerType.CTA).attr('id'); 7222 sendReportingRequest(uiState); 7223 uiState.reportAlreadySent = true; 7224 window.open(offer.storeURL, '_blank'); 7225 }); 7226 }); 7227 7228 $('.CPConfiguratorResultOfferSectionHUQ').css('display', 'flex'); 7229 } 7230 7231 $('.CPConfiguratorResult').removeClass('CPConfiguratorResultSticky'); 7232 $('.CPConfiguratorBody')[0]?.scrollIntoView({ behavior: 'smooth', block: 'end' }); 7233}); 7234 7235 7236$(document).on("click", ".CPConfiguratorResetButton", function () { 7237 logInfo("reset clicked") 7238 if (uiState.quiztype === "cpc") { 7239 $('.CPConfiguratorResultOffer').hide(); 7240 adjustQuestion($('.CPConfiguratorItem').eq(0), 'unchecked'); 7241 adjustQuestion($('.CPConfiguratorItem:gt(0):lt(3)'), 'disabled:unchecked') 7242 $('.CPConfiguratorResultSubmissionTotalPrice').html(uiState.quizCurrency.replace("%price%", '0')); 7243 $('.CPConfiguratorAnswerActive').prop('checked', false); 7244 7245 } 7246 if (uiState.quiztype === "huq") { 7247 $('.CPConfiguratorResultOfferSectionHUQ').hide(); 7248 $('.CPConfiguratorResultOfferSectionHUQOfferImg').attr("src", ""); 7249 7250 adjustQuestion($('.CPConfiguratorItem').eq(3), 'unchecked'); 7251 adjustQuestion($('.CPConfiguratorItem').eq(4), 'unchecked'); 7252 adjustQuestion($('.CPConfiguratorItem').eq(5), 'unchecked'); 7253 $('.CPConfiguratorAnswerActive').prop('checked', false); 7254 $('input[name="location"]').prop('checked', false); 7255 $(`input[name="type"]`).prop('checked', false); 7256 $(`input[name="features"]`).prop('checked', false); 7257 } 7258 7259 $('.CPConfiguratorResultSubmission').css('display', 'flex'); 7260 $('.CPConfiguratorBody').removeClass('CPConfiguratorBodyDisabled'); 7261 7262 7263 $('.CPConfiguratorResultSubmissionButton').removeClass('CPConfiguratorResultSubmissionButtonActive'); 7264 $('.CPConfiguratorCloseButton').css('display', 'flex'); 7265 $('.CPConfiguratorResetButton').hide(); 7266 $('.CPConfiguratorResult').addClass('CPConfiguratorResultSticky'); 7267 answerClicked = 0; 7268 quizSubmitted = false; 7269 cvgTypeClicked = false; 7270 7271 if (!uiState.reportAlreadySent) { 7272 sendReportingRequest(uiState); 7273 } 7274 7275 uiState.results = []; 7276 uiState.acceptedSKU = ""; 7277 uiState.q1 = ""; 7278 uiState.q2 = ""; 7279 uiState.q3 = []; 7280 uiState.total = ""; 7281 uiState.userInteracted = false; 7282 uiState.reportAlreadySent = false; 7283 uiState.matchedDirectSelection = undefined; 7284 uiState.relaxationIteration = undefined; 7285 7286}); 7287 7288 7289document.addEventListener("visibilitychange", () => { 7290 if (document.visibilityState === "hidden") {
7291 if (uiState.userInteracted && !uiState.reportAlreadySent && !pendingReportTimeoutId) { 7292 pendingReportTimeoutId = setTimeout(() => { 7293 sendReportingRequest(uiState); 7294 uiState.reportAlreadySent = true; 7295 pendingReportTimeoutId = null; 7296 }, REPORT_DELAY_MS); 7297 } 7298 } 7299}); 7300 7301window.addEventListener("beforeunload", () => { 7302 if (uiState.userInteracted && !uiState.reportAlreadySent) { 7303 localStorage.setItem("quiz_lastState", JSON.stringify(uiState)); 7304 } 7305 _quizReady = null; 7306 quizReadyState.value = null; 7307}); 7308 7309function adjustQuestion(selectedQuestions, status) { 7310 const locate = selectedQuestions.find.bind(selectedQuestions); 7311 const icon = locate('.CPConfiguratorQuestionIcon'); 7312 const text = locate('.CPConfiguratorQuestionText'); 7313 const index = locate('.CPConfiguratorQuestionIconIndex'); 7314 const imgActive = locate('.CPConfiguratorQuestionIconImgActive'); 7315 const imgDisabled = locate('.CPConfiguratorQuestionIconImgDisabled'); 7316 const inputs = quizSubmitted || !cvgTypeClicked ? locate('.CPConfiguratorAnswerActive') : locate('.CPConfiguratorAnswer').not('.CPConfiguratorAnswerStandalone:has(input[disabled])').find('.CPConfiguratorAnswerActive'); 7317 const labels = quizSubmitted || !cvgTypeClicked ? locate('.CPConfiguratorAnswerLabelActive') : locate('.CPConfiguratorAnswer').not('.CPConfiguratorAnswerStandalone:has(input[disabled])').find('.CPConfiguratorAnswerLabelActive'); 7318 if (status === "disabled:checked") { 7319 imgActive.hide(); 7320 imgDisabled.show(); 7321 icon.addClass('CPConfiguratorQuestionIconDisabled'); 7322 selectedQuestions.removeClass('CPConfiguratorItemActive').addClass('CPConfiguratorItemActiveDisabled');; 7323 text.addClass('CPConfiguratorQuestionTextDisabled'); 7324 index.hide(); 7325 if (!cvgTypeClicked) 7326 inputs.prop('disabled', true); 7327 labels.addClass('CPConfiguratorAnswerDisabled'); 7328 } else if (status === "checked") { 7329 selectedQuestions.addClass('CPConfiguratorItemActive').removeClass('CPConfiguratorItemActiveDisabled'); 7330 icon.addClass('CPConfiguratorQuestionIconActive').removeClass('CPConfiguratorQuestionIconDisabled'); 7331 index.hide(); 7332 imgActive.show(); 7333 imgDisabled.hide(); 7334 inputs.prop('disabled', false); 7335 labels.removeClass('CPConfiguratorAnswerDisabled'); 7336 7337 } else if (status === "unchecked") { 7338 icon.removeClass('CPConfiguratorQuestionIconDisabled CPConfiguratorQuestionIconActive'); 7339 text.removeClass('CPConfiguratorQuestionTextDisabled'); 7340 imgActive.hide(); 7341 selectedQuestions.removeClass('CPConfiguratorItemActive CPConfiguratorItemActiveDisabled'); 7342 index.show(); 7343 imgDisabled.hide(); 7344 inputs.prop('disabled', false); 7345 labels.removeClass('CPConfiguratorAnswerDisabled'); 7346 7347 } else if (status === "disabled:unchecked") { 7348 imgActive.hide(); 7349 imgDisabled.hide(); 7350 icon.removeClass('CPConfiguratorQuestionIconActive').addClass('CPConfiguratorQuestionIconDisabled'); 7351 selectedQuestions.removeClass('CPConfiguratorItemActive').addClass('CPConfiguratorItemActiveDisabled'); 7352 text.addClass('CPConfiguratorQuestionTextDisabled'); 7353 index.show(); 7354 inputs.prop('disabled', true); 7355 labels.addClass('CPConfiguratorAnswerDisabled'); 7356 } 7357}; 7358 7359function captureSelectedElements() { 7360 if (uiState.quiztype === "cpc") { 7361 var selectedDuration = $('input[name="duration"]:checked').closest('label').text().trim(), 7362 selectedcoverageType = $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(), 7363 selectedFeatures = $(`input[name=${selectedcoverageType.replace(/\s+/g, '_')}__${selectedDuration.replace(/\s+/g, '_')}]:checked`).map(function () { return $(this).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(); }).get(); 7364 matchedCarePack = availableCarepacks.products.find(carePack => 7365 carePack.answers?.q1 === selectedDuration && 7366 carePack.answers?.q2 === selectedcoverageType && 7367 Array.isArray(carePack.answers?.q3) && 7368 selectedFeatures.length === carePack.answers.q3.length && 7369 selectedFeatures.every(f => carePack.answers.q3.includes(f)) 7370 );
7371 const features = analyzedCarepacks[selectedDuration][selectedcoverageType], 7372 total = Object.values(features ?? {})?.[0]?.total ?? ""; 7373 7374 7375 uiState = { 7376 ...uiState, 7377 q1: selectedDuration || "", 7378 q2: selectedcoverageType || "", 7379 q3: selectedFeatures.map(feature => { 7380 const freq = features[feature]?.frequency ?? 1; 7381 return `${feature}_${freq}`; 7382 }) || [], 7383 total: total, 7384 results: [], 7385 offerResults: [], 7386 acceptedSKU: "" 7387 } 7388 }; 7389 if (uiState.quiztype === "huq") { 7390 var selectedLocationId = $('input[name="location"]:checked').closest('label').attr('id') || ""; 7391 var selectedTypeId = $('input[name="type"]:checked').closest('label').attr('id') || ""; 7392 var selectedFeatureIds = $('input[name="features"]:checked').map(function () { 7393 return $(this).closest('label').attr('id'); 7394 }).get(); 7395 7396 uiState = { 7397 ...uiState, 7398 q1: selectedLocationId, 7399 q2: selectedTypeId, 7400 q3: selectedFeatureIds, 7401 results: [], 7402 offerResults: [], 7403 acceptedSKU: "" 7404 } 7405 } 7406 7407}; 7408 7409function displayHUQAnswers(q1, q2, q3) { 7410 const hardcodedAnswers = HUQhardcodedContent.quizBodyContent.answers; 7411 const countryCode = quizReqObj.user.countryCode; 7412 7413 [ 7414 { answers: q1, category: 'location', type: 'radio', wrapper: 'HUQAnswersLocation' }, 7415 { answers: q2, category: 'type', type: 'radio', wrapper: 'HUQAnswersType' }, 7416 { answers: q3, category: 'features', type: 'checkbox', wrapper: 'HUQAnswersFeatures' }, 7417 ].forEach(({ answers, category, type, wrapper }) => 7418 answers.forEach(answer => 7419 displayAnswer(category, (hardcodedAnswers[answer]?.[countryCode]) || answer, type, wrapper, answer, category) 7420 ) 7421 ); 7422 7423 $('.CPConfiguratorItem input:not(:disabled)').addClass('CPConfiguratorAnswerActive') 7424 .closest('label').addClass('CPConfiguratorAnswerLabelActive'); 7425 7426 $('.HUQConfiguratorContainer').show(); 7427} 7428 7429 7430function displayAnswers(analyzedCarepacks) { 7431 const durations = Object.keys(analyzedCarepacks); 7432 durations.forEach(duration => { 7433 var coverageTypes = Object.keys(analyzedCarepacks[duration]), 7434 7435 durationWrapper = 'CPConfiguratorAnswersduration', 7436 coverageTypesWrapper = `CPConfiguratorAnswerscoverageType__${duration.replace(/\s+/g, '_')}`; 7437 $($('.CPConfiguratorItem')[1]).append(`<div id="${coverageTypesWrapper}" class="CPConfiguratorAnswers"></div>`); 7438 displayAnswer('duration', duration, "radio", durationWrapper, duration, 'duration'); 7439 7440 coverageTypes.forEach(coverageType => { 7441 var featuresWrapper = `CPConfiguratorAnswersfeature__${coverageType.replace(/\s+/g, '_')}__${duration.replace(/\s+/g, '_')}`; 7442 7443 $($('.CPConfiguratorItem')[2]).append(`<div id="${featuresWrapper}" class="CPConfiguratorAnswers"></div>`); 7444 displayAnswer('coverageType', coverageType, "radio", coverageTypesWrapper, coverageType + "__" + duration, duration); 7445 const features = Object.keys(analyzedCarepacks[duration][coverageType]); 7446 if (features.length === 0) $("#" + featuresWrapper).append('<style> .CPCnoAddonNotif { font-size: 16px; line-height: 22px; color: #767676; display: flex; margin-bottom: 20px; } </style> <div class=CPCnoAddonNotif>No additional selections are required for this option.</div>') 7447 7448 features.forEach(feature => { 7449 const featureData = analyzedCarepacks[duration][coverageType][feature]; 7450 if (featureData.dependencies.length === 0 && featureData.exclusions.length === 0 && featureData.standalone) { 7451 featureData.commonFeature = true; 7452 } 7453 }); 7454 features.forEach(feature => { 7455 7456 const featureData = analyzedCarepacks[duration][coverageType][feature]; 7457 const frequency = featureData.frequency, dependencies = featureData.dependencies, exclusions = featureData.exclusions, standalone = featureData.standalone; 7458 7459 checkboxType.format = "toggle"; 7460 exclusions.forEach((exclusion) => { 7461 checkboxType.exclusionsIDs += (exclusion + "__" + coverageType + "__" + duration).replace(/\s+/g, '_') + ' '; 7462 }) 7463 7464 var dependancyTree = { 7465 rootParents: [], 7466 directParents: [], 7467 dependantSiblings: [], 7468 independantSiblings: [] 7469 }
7470 dependencies.forEach((dependency, index) => { 7471 if ((analyzedCarepacks[duration][coverageType][dependencies[index]].dependencies.length === 0)) { 7472 dependancyTree.rootParents.push(dependency); 7473 } else if (!analyzedCarepacks[duration][coverageType][dependencies[index]].dependencies.includes(feature)) { 7474 dependancyTree.directParents.push(dependency); 7475 } else { 7476 dependancyTree.dependantSiblings.push(dependency); 7477 } 7478 dependancyTree.independantSiblings = features.filter(x => !exclusions.includes(x) && !dependencies.includes(x) && x !== feature); 7479 7480 checkboxType.dependenciesIDs += (dependency + "__" + coverageType + "__" + duration).replace(/\s+/g, '_') + ' '; 7481 }); 7482 7483 if (frequency === 1 && dependencies.length === 0 && exclusions.length === 0 && !standalone) { 7484 7485 checkboxType.format = "toggle"; 7486 checkboxType.state = "checked disabled"; 7487 7488 } else if (dependencies.length === 0 && exclusions.length === 0 && standalone) { 7489 7490 checkboxType.format = features.length > 1 ? "checkbox" : "toggle"; 7491 7492 } else if (dependencies.length === 0 && exclusions.length !== 0) { 7493 if (dependancyTree.independantSiblings.length === 0) { 7494 7495 checkboxType.style = "CPConfiguratorAnswerStandalone"; 7496 } 7497 7498 } 7499 else { 7500 if (dependancyTree.independantSiblings.length > 0 && dependancyTree.dependantSiblings.length === 0) { 7501 checkboxType.format = "checkbox"; 7502 7503 } else if (dependancyTree.dependantSiblings.length === 0) { 7504 checkboxType.format = "toggle"; 7505 } else if (dependancyTree.dependantSiblings.length > 0) { 7506 checkboxType.format = "toggle"; 7507 } 7508 var siblingDisplayed = false; 7509 7510 dependancyTree.dependantSiblings.forEach(dependantSibling => { 7511 siblingDisplayed = ($("#" + (dependantSibling + "__" + coverageType + "__" + duration).replace(/\s+/g, '_'))).length > 0; 7512 }); 7513 7514 if (dependancyTree.directParents.length !== 0 || siblingDisplayed) { 7515 checkboxType.style = "CPConfiguratorAnswerSubChild"; 7516 checkboxType.state = "disabled" 7517 } else if (dependancyTree.rootParents.length !== 0) { 7518 checkboxType.style = "CPConfiguratorAnswerChild"; 7519 7520 if ($("#" + (dependancyTree.rootParents[0] + "__" + coverageType + "__" + duration).replace(/\s+/g, '_')).find('input[type="checkbox"]:disabled:not(:checked)').length === 0) 7521 checkboxType.style = "CPConfiguratorAnswerChild CPConfiguratorAnswerHasRootParents"; 7522 7523 } 7524 7525 } 7526 displayAnswer('feature', feature, 'checkbox', featuresWrapper, feature + "__" + coverageType + "__" + duration, coverageType + "__" + duration, checkboxType); 7527 checkboxType = { 7528 format: "", 7529 state: "", 7530 location: "", 7531 style: "", 7532 dependenciesIDs: "", 7533 exclusionsIDs: "" 7534 }; 7535 }); 7536 7537 }); 7538 $('.CPConfiguratorContainer').show(); 7539 7540 $('.CPConfiguratorItem').find('.CPConfiguratorAnswer input:not(:disabled)').addClass('CPConfiguratorAnswerActive').closest('label').addClass('CPConfiguratorAnswerLabelActive'); 7541 adjustQuestion($('.CPConfiguratorItem:gt(0):lt(3)'), 'disabled:unchecked') 7542 7543 }); 7544 $('.CPConfiguratorAnswer:not(:has(label.CPConfiguratorToggle))').each(function () { 7545 $(this).appendTo($(this).parent()); 7546 });
7547}; 7548 7549function displayAnswer(answerType, answerValue, inputType, wrapperID, answerID, inputName, checkboxType = { format: "", state: "", location: "", style: "", dependenciesIDs: "", exclusionsIDs: "" }) { 7550 if (uiState.quiztype === "cpc") { 7551 var tooltipContent = CPChardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerValue]?.summary || (wrapperID.includes("coverageType") ? cvgTypeTooltips[answerValue] : ''), 7552 tooltipBenefits = CPChardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerValue]?.benefits, 7553 idealForText = CPChardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerValue]?.idealFor || "", 7554 idealForPrefix = isDefined(idealForText) ? CPChardcodedContent?.tooltipsContent?.prefix?.[quizReqObj.user.countryCode] : "", 7555 tooltipIdealFor = idealForText !== "" ? '<div style="height: 10px"></div><span style="color:#418d3c">' + idealForPrefix + '</span>' + idealForText : "", 7556 benefitsDiv = tooltipBenefits !== undefined ? ('<br><div style="height: 10px"></div>' + tooltipBenefits.map(benefit => `<img class="" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt="" style="display: inline; width:12.5px; margin-right: 5px">${benefit}<br>`).join('')) : ""; 7557 } else if (uiState.quiztype === "huq") { 7558 var tooltipContent = HUQhardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerID]?.summary || '', tooltipBenefits = "", benefitsDiv = "", tooltipIdealFor = ""; 7559 } 7560 var tooltipdiv = tooltipContent ? `<span class=CPConfiguratorAnswerTooltipDiv><img class=CPConfiguratorAnswerTooltip src=https://hp.widen.net/content/w27rpukk05/svg/CPC_toolTip.svg><div class=CPConfiguratorAnswerTooltipBubbleChip></div></span><div class=CPConfiguratorAnswerTooltipBubble><div class=CPConfiguratorAnswerTooltipBubbleText>${tooltipContent + benefitsDiv + tooltipIdealFor}</div></div>` : '', 7561 answerDiv = `<div data-dependencies="${checkboxType.dependenciesIDs}" data-exclusions="${checkboxType.exclusionsIDs}" class="${checkboxType.style} CPConfiguratorAnswer CPConfigurator${answerType}Row"><label id="${answerID.replace(/\s+/g, '_')}" class="${checkboxType.format === "toggle" ? 'CPConfiguratorToggle' : ""} ${checkboxType.state === "disabled" || checkboxType.state === "checked disabled" ? 'CPConfiguratorAnswerDisabled' : ""} CPConfiguratorAnswerLabel CPConfiguratorAnswer${answerType}"><input ${checkboxType.state} class=CPConfiguratorAnswer${answerType}Button tabindex=0 type="${inputType}" name="${inputName.replace(/\s+/g, '_')}" />${checkboxType.format === "toggle" ? '<div class="CPConfiguratorSlider"> <div class="CPConfiguratorSliderCircle"></div></div>' : ""}<span>${answerValue} ${tooltipdiv}</span></label></div>`; 7562 $("#" + wrapperID).append(answerDiv); 7563}; 7564 7565function allocateQuizPrices(strikePrice, incartPrice, priceWrapper) { 7566 const strikeDiv = $(priceWrapper).find(".strikePricePlaceholder"), 7567 incartDiv = $(priceWrapper).find(".incartPricePlaceholder"), 7568 discountDiv = $(priceWrapper).find(".discountPercentage"); 7569 if ((strikePrice || incartPrice) && strikePrice !== 0 && incartPrice !== 0) { 7570 const f = p => Number.isInteger(p) ? p : p.toFixed(2), 7571 s0 = Math.max(strikePrice, incartPrice), 7572 i0 = Math.min(strikePrice, incartPrice), 7573 s = f(s0) == f(i0) ? 0 : f(s0), 7574 i = f(i0); 7575 s && strikeDiv.length ? strikeDiv.html(uiState.quizCurrency.replace("%price%", s)) : strikeDiv.hide(); 7576 i && incartDiv.length ? incartDiv.html(uiState.quizCurrency.replace("%price%", i)) : incartDiv.hide(); 7577 discountDiv.length && s ? Math.round(((s - i) / s) * 100) > 10 ? discountDiv.html(Math.round(((s - i) / s) * 100) + "%") : discountDiv.hide() : 0; 7578 } else strikeDiv.hide(), incartDiv.hide(), discountDiv.hide(); 7579}; 7580 7581function equalizeAnswersHeight() { 7582 $('#mastiff-modal-cpc').show(); 7583 $('#mastiff-check-warranty-primary-offer').show(); 7584 $('#mastiff-check-warranty-primary-offer').css('visibility', 'hidden'); 7585 7586 if (uiState.quiztype === "cpc") {
7587 [2, 1].forEach(index => { 7588 const $answerWrappers = $('.CPConfiguratorItem').eq(index).find('.CPConfiguratorAnswers'); 7589 $answerWrappers.show() 7590 $answerWrappers.height(Math.max(...$answerWrappers.map((_, wrapper) => $(wrapper).outerHeight()).get())).hide().eq(0).show(); 7591 }); 7592 } 7593 if (uiState.quiztype === "huq" && $(window).width() > 539) { 7594 const items = [4, 5]; 7595 const matchHeights = (selector) => { 7596 const elements = items.map(i => $('.CPConfiguratorItem').eq(i).find(selector)); 7597 const maxHeight = Math.max(...elements.map(el => el.height())); 7598 elements.forEach(el => el.height(maxHeight)); 7599 }; 7600 matchHeights('.CPConfiguratorAnswers'); 7601 matchHeights('.CPConfiguratorQuestionText'); 7602 } 7603 $('#mastiff-check-warranty-primary-offer').css('visibility', 'visible'); 7604 $('#mastiff-modal-cpc').hide(); 7605 7606}; 7607 7608function displayQuizHardcodedContent() { 7609 const countryCode = quizReqObj.user.countryCode, 7610 currentQuizContent = uiState.quiztype === "cpc" ? CPChardcodedContent : uiState.quiztype === "huq" ? HUQhardcodedContent : "", 7611 quizContent = currentQuizContent.quizBodyContent, 7612 offerContent = currentQuizContent.offerContent, 7613 { header: offerHeader, cta: offerCTA } = offerContent, 7614 { header: quizHeader, questions: { first: firstQuestion, second: secondQuestion, third: thirdQuestion }, 7615 footer: { totalPrice, cta: quizCTA, currencies } } = quizContent; 7616 7617 const headerText = quizHeader[countryCode], 7618 firstQuestionText = firstQuestion[countryCode], 7619 secondQuestionText = secondQuestion[countryCode], 7620 thirdQuestionText = thirdQuestion[countryCode], 7621 quizCTAText = quizCTA[countryCode], 7622 offerCTAText = offerCTA[countryCode], 7623 quizCurrency = currencies[countryCode]; 7624 7625 if (uiState.quiztype === "cpc") { 7626 var totalPriceText = totalPrice[countryCode], 7627 offerHeaderText = offerHeader[countryCode], 7628 quizContainer = ".CPConfiguratorContainer"; 7629 $('.CPConfiguratorResultSubmissionTotalText').text(totalPriceText); 7630 $('.CPConfiguratorResultSubmissionTotalPrice').html(quizCurrency.replace("%price%", '0')); 7631 $('.CPConfiguratorResultOfferHeaderHeadlineText').text(offerHeaderText); 7632 $('.CPConfiguratorResultOfferCTA').text(offerCTAText); 7633 } 7634 if (uiState.quiztype === "huq") { 7635 var recommendedText = offerHeader.recommended[countryCode], 7636 mostPopularText = offerHeader.mostPopular[countryCode], 7637 budgetFriendlyText = offerHeader.budgetFriendly[countryCode], 7638 quizContainer = ".HUQConfiguratorContainer"; 7639 $('.CPConfiguratorResultOfferSectionHUQOfferHeaderText').eq(0).text(budgetFriendlyText); 7640 $('.CPConfiguratorResultOfferSectionHUQOfferHeaderText').eq(1).text(recommendedText); 7641 $('.CPConfiguratorResultOfferSectionHUQOfferHeaderText').eq(2).text(mostPopularText); 7642 $('.CPConfiguratorResultSubmissionButtonHUQText').text(offerCTAText); 7643 } 7644 $(`${quizContainer} .CPConfiguratorTitleText`).text(headerText); 7645 $(`${quizContainer} .CPConfiguratorQuestionText`).eq(0).text(firstQuestionText); 7646 $(`${quizContainer} .CPConfiguratorQuestionText`).eq(1).text(secondQuestionText); 7647 $(`${quizContainer} .CPConfiguratorQuestionText`).eq(2).text(thirdQuestionText); 7648 $(`${quizContainer} .CPConfiguratorResultSubmissionButton`).text(quizCTAText); 7649 equalizeAnswersHeight() 7650 7651}; 7652 7653function analyzeCarepacks(availableCarepacks) { 7654 const result = {}; 7655 const coverageMap = {}; 7656 7657 availableCarepacks.sort((a, b) => parseInt(a.answers.q1) - parseInt(b.answers.q1)); 7658 7659 for (const pack of availableCarepacks) { 7660 const { answers = {}, primaryText2 } = pack; 7661 const duration = answers.q1; 7662 const coverageType = answers.q2; 7663 const features = Array.isArray(answers.q3) ? answers.q3 : []; 7664 7665 (result[duration] ??= {})[coverageType] ??= []; 7666 result[duration][coverageType].push(features); 7667 7668 if (!coverageMap[coverageType] || features.length < (coverageMap[coverageType].features?.length ?? 0)) { 7669 coverageMap[coverageType] = { primaryText2, features }; 7670 } 7671 } 7672 7673 cvgTypeTooltips = Object.fromEntries( 7674 Object.entries(coverageMap).map(([k, v]) => [k, v.primaryText2]) 7675 ); 7676 7677 for (const duration in result) { 7678 for (const coverageType in result[duration]) { 7679 const allFeatureSets = result[duration][coverageType]; 7680 var total = allFeatureSets.length; 7681 7682 const frequencyMap = {}; 7683 const coOccurMap = {}; 7684 var standalone = false; 7685
7686 allFeatureSets.forEach(set => { 7687 if (set.length === 0) 7688 standalone = true; 7689 set.forEach(f => { 7690 frequencyMap[f] = (frequencyMap[f] || 0) + 1; 7691 if (!coOccurMap[f]) coOccurMap[f] = {}; 7692 7693 set.forEach(other => { 7694 if (f !== other) { 7695 coOccurMap[f][other] = (coOccurMap[f][other] || 0) + 1; 7696 } 7697 }); 7698 }); 7699 }); 7700 var realTotal = total; 7701 if (standalone) total--; 7702 7703 const finalFeatures = {}; 7704 const allFeatures = Object.keys(frequencyMap); 7705 7706 for (const feature of allFeatures) { 7707 const freq = frequencyMap[feature] / total; 7708 const coMap = coOccurMap[feature] || {}; 7709 const dependency = Object.entries(coMap) 7710 .filter(([_, count]) => count === frequencyMap[feature]) 7711 .map(([f]) => f); 7712 const exclusions = allFeatures.filter(f => f !== feature && !(coMap[f] > 0)); 7713 7714 finalFeatures[feature] = { 7715 frequency: +freq.toFixed(2), 7716 dependencies: dependency.length ? dependency : [], 7717 exclusions: exclusions.length ? exclusions : [], 7718 standalone: standalone, 7719 total: realTotal 7720 }; 7721 } 7722 standalone = false; 7723 7724 result[duration][coverageType] = finalFeatures; 7725 } 7726 } 7727 7728 7729 return result; 7730}; 7731 7732 7733function handleCPCScenario(data) { 7734 $('.CPConfiguratorSpinner').show(); 7735 $('.CPConfiguratorContainer').show(); 7736 7737 availableCarepacks = data; 7738 analyzedCarepacks = analyzeCarepacks(data.products); 7739 logInfo("Analyzed CPC Carepacks:", analyzedCarepacks); 7740 7741 displayAnswers(analyzedCarepacks); 7742 displayQuizHardcodedContent(); 7743} 7744 7745function handleHUQScenario(data) { 7746 logInfo("Handling HUQ scenario"); 7747 7748 const q1Set = new Set(); 7749 const q2Set = new Set(); 7750 const q3Set = new Set(); 7751 7752 data.products.forEach(product => { 7753 q1Set.add(product.answers.q1); 7754 q2Set.add(product.answers.q2); 7755 (product.answers.q3 || []).forEach(feature => q3Set.add(feature)); 7756 }); 7757 7758 const uniqueQ1 = Array.from(q1Set); 7759 const uniqueQ2 = Array.from(q2Set); 7760 const uniqueQ3 = Array.from(q3Set); 7761 7762 logInfo("Unique Q1:", uniqueQ1); 7763 logInfo("Unique Q2:", uniqueQ2); 7764 logInfo("Unique Q3 (features):", uniqueQ3); 7765 7766 const randomFeatures = getRandomFeatures(data.products, 5); 7767 displayHUQAnswers(uniqueQ1, uniqueQ2, randomFeatures); 7768 displayQuizHardcodedContent() 7769 7770} 7771 7772async function sendPendingReport() { 7773 const savedState = localStorage.getItem("quiz_lastState"); 7774 const currentSessionId = localStorage.getItem("MastiffSessionId"); 7775 7776 if (savedState) { 7777 try { 7778 const restoredState = JSON.parse(savedState); 7779 7780 if (!restoredState?.sessionId || restoredState.sessionId !== currentSessionId) { 7781 localStorage.removeItem("quiz_lastState"); 7782 return; 7783 } 7784 7785 if (restoredState?.reportAlreadySent) { 7786 localStorage.removeItem("quiz_lastState"); 7787 return; 7788 } 7789 7790 const originalRequestId = quizReqObj.requestId; 7791 const originalSessionId = quizReqObj.user.sessionId; 7792 7793 await sendReportingRequest(restoredState, true); 7794 7795 quizReqObj.requestId = originalRequestId; 7796 quizReqObj.user.sessionId = originalSessionId; 7797 7798 } catch (error) { 7799 console.error("Failed to send pending report or parse state. Will retry next load.", error); 7800 return; 7801 } 7802 localStorage.removeItem("quiz_lastState"); 7803 } 7804} 7805function setReqId() { 7806 var timestamp = Date.now(); 7807 var tsLength = String(timestamp).length; 7808 var randStrLen = 20 - parseInt(tsLength); 7809 var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 7810 var charactersLength = characters.length; 7811 var result = ""; 7812 7813 for (var i = 0; i < randStrLen; i++) { 7814 result += characters.charAt(Math.floor(Math.random() * charactersLength)); 7815 } 7816 var reqId = String(timestamp).concat(result);
7817 quizReqObj.requestId = reqId; 7818 uiState.requestId = reqId; 7819} 7820 7821function setMastiffSessionId() { 7822 if (localStorage == null || typeof (localStorage) == "undefined") { 7823 quizReqObj.user.sessionId = quizReqObj.requestId.substring(quizReqObj.requestId.length - 10); 7824 } else { 7825 var mastiffSessionId = localStorage.getItem('MastiffSessionId'); 7826 if (mastiffSessionId == null || mastiffSessionId == "" || typeof (mastiffSessionId) == "undefined") { 7827 mastiffSessionId = quizReqObj.requestId.substring(quizReqObj.requestId.length - 10); 7828 localStorage.setItem('MastiffSessionId', mastiffSessionId); 7829 } 7830 quizReqObj.user.sessionId = mastiffSessionId; 7831 } 7832 uiState.sessionId = quizReqObj.user.sessionId; 7833} 7834 7835function parseDelimitedString(str = "", listKeys = []) { 7836 const result = {}; 7837 7838 str.split('|').forEach(pair => { 7839 const [key, value] = pair.split(':'); 7840 if (!value || value === 'null') return; 7841 7842 const cleanKey = key.trim(); 7843 const cleanValue = value.trim(); 7844 7845 if (listKeys.includes(cleanKey)) { 7846 result[cleanKey] = cleanValue.split(/[,;]\s*/).map(v => v.trim()); 7847 } else { 7848 result[cleanKey] = cleanValue; 7849 } 7850 }); 7851 7852 return result; 7853} 7854 7855var getRandomFeatures = (data, count = 5) => { 7856 const allFeatures = Array.from( 7857 new Set( 7858 data.flatMap(item => item.filters?.features || []) 7859 .map(f => featureCategoryMap[f.trim()]) 7860 .filter(Boolean) 7861 ) 7862 ); 7863 for (var i = allFeatures.length - 1; i > 0; i--) { 7864 const j = Math.floor(Math.random() * (i + 1)); 7865 [allFeatures[i], allFeatures[j]] = [allFeatures[j], allFeatures[i]]; 7866 } 7867 return allFeatures.slice(0, count); 7868}; 7869 7870 7871var getTopFeatures = (data, topN = 5) => 7872 Object.entries(extractFeatureCounts(data)) 7873 .sort(([, a], [, b]) => b - a) 7874 .slice(0, topN) 7875 .map(([feature]) => feature); 7876 7877 7878var extractFeatureCounts = (data) => 7879 data.flatMap(item => item.filters?.features || []) 7880 .map(f => featureCategoryMap[f.trim()]) 7881 .filter(Boolean) 7882 .reduce((countMap, category) => { 7883 countMap[category] = (countMap[category] || 0) + 1; 7884 return countMap; 7885 }, {}); 7886 7887function normalizeQ3(q3List) { 7888 return q3List 7889 .map(f => featureCategoryMap[f.trim()]) 7890 .filter(Boolean); 7891} 7892 7893function getRecommendedProductSet(products, selectedAnswers) { 7894 const enrich = product => { 7895 const discount = (product.strikePrice && product.incartPrice) 7896 ? Math.max(0, ((product.strikePrice - product.incartPrice) / product.strikePrice) * 100) 7897 : 0; 7898 return { ...product, discount }; 7899 }; 7900 7901 const shuffle = array => { 7902 const arr = [...array]; 7903 for (var i = arr.length - 1; i > 0; i--) { 7904 const j = Math.floor(Math.random() * (i + 1)); 7905 [arr[i], arr[j]] = [arr[j], arr[i]]; 7906 } 7907 return arr; 7908 }; 7909 7910 const relaxQ3 = (products, selectedQ1, selectedQ2, relaxedQ3) => { 7911 7912 if (!isDefined(uiState.relaxationIteration)) { 7913 uiState.relaxationIteration = 0; 7914 } 7915 const featureFreq = extractFeatureCounts(products); 7916 relaxedQ3.sort((a, b) => (featureFreq[a] || 0) - (featureFreq[b] || 0)); 7917 logInfo("Sorted Q3 by rarity:", relaxedQ3); 7918 7919 for (var i = 0; i <= relaxedQ3.length; i++) { 7920 const subset = relaxedQ3.slice(i); 7921 const matched = products.filter(p => 7922 p.answers.q1 === selectedQ1 && 7923 p.answers.q2 === selectedQ2 && 7924 subset.every(f => p.answers.q3.includes(f)) 7925 ); 7926 logInfo(`Relax Q3 step ${i}: ${subset.join(', ')} -> ${matched.length} matches`); 7927 if (uiState.relaxationIteration === 0) { 7928 uiState.matchedDirectSelection = matched.length; 7929 } 7930 if (matched.length > 0) { 7931 return matched; 7932 } else { 7933 uiState.relaxationIteration++; 7934 } 7935 } 7936 return []; 7937 }; 7938 7939 const getFallbackPool = (excludeSKUs, conditionFn) => 7940 products.filter(p => 7941 !excludeSKUs.has(p.productSKU) && 7942 conditionFn(p) 7943 ); 7944 7945 const pickThree = enrichedPool => { 7946 const budgetFriendly = enrichedPool.sort((a, b) => a.incartPrice - b.incartPrice)[0]; 7947 const recommended = shuffle(enrichedPool.filter(p => p.productSKU !== budgetFriendly?.productSKU))[0]; 7948 const mostPopular = enrichedPool 7949 .filter(p => p.productSKU !== recommended?.productSKU && p.productSKU !== budgetFriendly?.productSKU) 7950 .sort((a, b) => b.discount - a.discount)[0]; 7951 7952 var finalSet = { 7953 recommended, 7954 mostPopular, 7955 budgetFriendly 7956 }; 7957 7958 const selectedSKUs = new Set(Object.values(finalSet).filter(
7958Boolean).map(p => p.productSKU)); 7959 for (const p of enrichedPool) { 7960 if (!selectedSKUs.has(p.productSKU)) { 7961 if (!finalSet.recommended) finalSet.recommended = p; 7962 else if (!finalSet.mostPopular) finalSet.mostPopular = p; 7963 else if (!finalSet.budgetFriendly) finalSet.budgetFriendly = p; 7964 if (Object.values(finalSet).filter(Boolean).length === 3) break; 7965 } 7966 } 7967 7968 return finalSet; 7969 }; 7970 7971 const { q1, q2 } = selectedAnswers; 7972 const relaxedQ3 = [...(selectedAnswers.q3 || [])].map(f => f.replace(/_/g, ' ')); 7973 var matchedByQ123 = relaxQ3(products, q1, q2, relaxedQ3); 7974 7975 if (matchedByQ123.length > 0) { 7976 logInfo(`(${matchedByQ123.length} matched products)`); 7977 var enrichedPool = matchedByQ123.map(enrich); 7978 7979 if (matchedByQ123.length < 3) { 7980 const excludeSKUs = new Set(matchedByQ123.map(p => p.productSKU)); 7981 7982 var relaxedFallback = relaxQ3(products.filter(p => !excludeSKUs.has(p.productSKU)), q1, q2, relaxedQ3); 7983 if (relaxedFallback.length) { 7984 enrichedPool = enrichedPool.concat(relaxedFallback.map(enrich)); 7985 } 7986 7987 if (enrichedPool.length < 3) { 7988 const q1q2 = getFallbackPool(excludeSKUs, p => p.answers.q1 === q1 && p.answers.q2 === q2); 7989 enrichedPool = enrichedPool.concat(q1q2.map(enrich)); 7990 } 7991 7992 if (enrichedPool.length < 3) { 7993 const q1Only = getFallbackPool(excludeSKUs, p => p.answers.q1 === q1); 7994 enrichedPool = enrichedPool.concat(q1Only.map(enrich)); 7995 } 7996 } 7997 7998 const result = pickThree(enrichedPool); 7999 logInfo("Final recommendations:", result); 8000 return result; 8001 } 8002 8003 logInfo("No matches. Fallback initiated."); 8004 var candidates = products.filter(p => p.answers.q1 === q1 && p.answers.q2 === q2); 8005 if (candidates.length < 3) { 8006 candidates = products.filter(p => p.answers.q1 === q1); 8007 } 8008 if (candidates.length < 3) { 8009 candidates = [...products]; 8010 } 8011 8012 const enrichedFallback = candidates.map(enrich); 8013 const result = pickThree(enrichedFallback); 8014 logInfo("Final fallback recommendations:", result); 8015 return result; 8016} 8017 8018function testRecommendationEngine(products, iterations = 250) { 8019 const errors = []; 8020 const rolesSeen = new Set(); 8021 8022 const normalizedProducts = products.map(p => ({ 8023 ...p, 8024 answers: { 8025 ...p.answers, 8026 q3: (p.answers.q3 || []) 8027 .map(f => featureCategoryMap[f.trim()] || f.trim()) 8028 .filter(Boolean) 8029 } 8030 })); 8031 8032 function getMatchLevel(product, selected) { 8033 const a = product.answers; 8034 if (!a?.q1 || !a?.q2) return 'invalid'; 8035 8036 const matchQ1 = a.q1 === selected.q1; 8037 const matchQ2 = a.q2 === selected.q2; 8038 const matchQ3 = selected.q3.every(f => a.q3?.includes(f)); 8039 8040 if (matchQ1 && matchQ2 && matchQ3) return "Q1+Q2+Q3"; 8041 if (matchQ1 && matchQ2) return "Q1+Q2"; 8042 if (matchQ1) return "Q1 only"; 8043 return "No match"; 8044 } 8045 8046 for (var i = 0; i < iterations; i++) { 8047 const randomProduct = normalizedProducts[Math.floor(Math.random() * normalizedProducts.length)]; 8048 if (!randomProduct?.answers) continue; 8049 8050 const selectedAnswers = { 8051 q1: randomProduct.answers.q1, 8052 q2: randomProduct.answers.q2, 8053 q3: [...new Set(randomProduct.answers.q3 || [])] 8054 }; 8055 8056 const result = getRecommendedProductSet(products, selectedAnswers); 8057 const { recommended, mostPopular, budgetFriendly } = result; 8058 8059 const assigned = [recommended?.productSKU, mostPopular?.productSKU, budgetFriendly?.productSKU]; 8060 const uniqueAssigned = [...new Set(assigned)]; 8061 8062 const matchLevels = { 8063 recommended: getMatchLevel(recommended, selectedAnswers), 8064 mostPopular: getMatchLevel(mostPopular, selectedAnswers), 8065 budgetFriendly: getMatchLevel(budgetFriendly, selectedAnswers) 8066 }; 8067 8068 logInfo(`Test ${i + 1}:`); 8069 logInfo("Selected Answers:", selectedAnswers); 8070 logInfo(`-> Recommended: ${recommended?.productSKU} [${matchLevels.recommended}]`); 8071 logInfo(`-> Most Popular: ${mostPopular?.productSKU} [${matchLevels.mostPopular}]`); 8072 logInfo(`-> Budget Friendly: ${budgetFriendly?.productSKU} [${matchLevels.budgetFriendly}]`); 8073 logInfo("*** Unique roles:", uniqueAssigned.length === 3 ? "PASS" : "X FAIL"); 8074 logInfo("--------------------------------------------------"); 8075 8076 if (uniqueAssigned.length !== 3) { 8077 errors.push({ 8078 test: i + 1, 8079 selectedAnswers, 8080 recommended: recommended?.productSKU, 8081 mostPopular: mostPopular?.productSKU, 8082 budgetFriendly: budgetFriendly?.productSKU 8083 }); 8084 } 8085 8086 rolesSeen.add(recommended?.productSKU); 8087 rolesSeen.add(mostPopular?.productSKU); 8088 rolesSeen.add(budgetFriendly?.productSKU); 8089 } 8090 8091 logInfo(`-> ${iterations} tests complete. Distinct products used: ${rolesSeen.size}`); 8092 if (errors.length > 0) { 8093 console.warn(`:( ${errors.length} tests failed due to duplicate role assignments:`); 8094 console.table(errors); 8095 } else { 8096 logInfo("YUH all tests passed with unique role assignments."); 8097 } 8098} 8099 8100var deviceUseCriteriaMap = {
8101 setLocation: { 8102 id: "setLocation", 8103 name: "Set location (Desktop)", 8104 formFactor: ["All-in-one", "microtower", "mini", "small form factor", 'tower'] 8105 }, 8106 onTheGo: { 8107 id: "onTheGo", 8108 name: "On the go (Laptop)", 8109 formFactor: ["Convertible", "Mobile workstation", "Mobile thin client", "standard laptop"] 8110 } 8111} 8112 8113var deviceCriteriaMap = { 8114 entertainment: { 8115 id: "entertainment", 8116 name: "Entertainment & Personal", 8117 usage: ["Everyday computing", "Safe and simple"], 8118 processors: ["Intel Core i3", "Intel Core 3", "AMD Ryzen 3"], 8119 memory: { min: 4, max: 8 }, 8120 storage: 64 8121 }, 8122 creativeTechnical: { 8123 id: "creativeTechnical", 8124 name: "Creative & Technical", 8125 usage: ["Performance computing"], 8126 processors: ["Intel Core i7", "Intel Core i9", "Intel Core Ultra 7", "Intel Core Ultra 9", "AMD Ryzen 7", "AMD Ryzen 9"], 8127 memory: { min: 16, max: null }, 8128 storage: 512 8129 }, 8130 education: { 8131 id: "education", 8132 name: "Education & Hobbies", 8133 usage: ["Premium computing"], 8134 processors: ["Intel Core i5", "Intel Core 5", "Intel Core Ultra 5", "AMD Ryzen 5"], 8135 memory: { min: 8, max: 16 }, 8136 storage: 256 8137 }, 8138 gaming: { 8139 id: "gaming", 8140 name: "Gaming", 8141 usage: ["Gaming"], 8142 processors: ["Intel Core i7", "Intel Core i9", "Intel Core Ultra 7", "Intel Core Ultra 9", "AMD Ryzen 5", "AMD Ryzen 7"], 8143 memory: { min: 16, max: null }, 8144 storage: 512 8145 }, 8146 business: { 8147 id: "business", 8148 name: "Business & Professional", 8149 usage: ["Premium computing", "Business professional", "Mission critical", "Proven productivity"], 8150 processors: ["Intel Core i5", "Intel Core 5", "AMD Ryzen 5", "Intel Core i7", "Intel Core Ultra 7", "AMD Ryzen 7"], 8151 memory: { min: 16, max: null }, 8152 storage: 256 8153 } 8154}; 8155 8156var featureCategoryMap = { 8157 "Large Display": "Large display", 8158 "Lightweight and Slim": "Lightweight and slim", 8159 "touch": "Touchscreen", 8160 "Touch screen": "Touchscreen", 8161 "Touchscreen display": "Touchscreen", 8162 "Fingerprint Reader": "Fingerprint Sensor", 8163 "Fingerprint sensor": "Fingerprint Sensor", 8164 "HP FingerPrint Sensor": "Fingerprint Sensor", 8165 "Integrated fingerprint reader": "Fingerprint Sensor", 8166 "HP Wolf Pro Security Edition (1 year)": "HP Wolf Pro Security", 8167 "HP Wolf Pro Security Edition (3 years)": "HP Wolf Pro Security", 8168 "HP Wolf Security Pro Edition": "HP Wolf Pro Security", 8169 "HP 510 Black Wireless Keyboard and mouse combo": "Wireless keyboard and mouse", 8170 "HP 510 White Wireless Keyboard and mouse combo": "Wireless keyboard and mouse", 8171 "HP 510SP Black Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse", 8172 "HP 510SP White Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse", 8173 "HP 655 Wireless Keyboard and mouse combo": "Wireless keyboard and mouse", 8174 "HP 655 Wireless Keyboard and mouse combo": "Wireless keyboard and mouse", 8175 "HP 710 Black Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse", 8176 "HP 710 White Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse", 8177 "HP 720 White Touchpad Integrated Bluetooth Keyboard": "Wireless keyboard and mouse", 8178 "HP 915 Wireless Keyboard and mouse combo": "Wireless keyboard and mouse", 8179 "HP Wireless Business Slim Keyboard and mouse combo": "Wireless keyboard and mouse", 8180 "USB black wireless keyboard and mouse combo": "Wireless keyboard and mouse", 8181 "USB nightfall black wireless keyboard and mouse combo": "Wireless keyboard and mouse", 8182 "USB white wireless keyboard and mouse combo": "Wireless keyboard and mouse", 8183 "Wi-Fi 6": "Faster Wi-Fi", 8184 "Wi-Fi 6E": "Faster Wi-Fi", 8185 "Wi-Fi 7": "Faster Wi-Fi", 8186 "Wi-Fi CERTIFIED 6Â?Â": "Faster Wi-Fi", 8187 "Wireless (WiFi)": "Faster Wi-Fi", 8188 "ENERGY STAR certified": "ENERGY STAR Certified", 8189 "ENERGY STAR qualified": "ENERGY STAR Certified", 8190 "ENERGY STAR® certified": "ENERGY STAR Certified", 8191 "Full HD": "Full HD", 8192 "three-sided micro-edge": "Three-sided micro-edge display", 8193 "Touchscreen": "Touchscreen", 8194 "HP Premium Collaboration Keyboard â spill-resistant keyboard with numeric keypad": "Spill-resistant", 8195 "HP Premium Collaboration Keyboard â spill-resistant": "Spill-resistant", 8196 "HP Premium Keyboard â spill-resistant keyboard": "Spill-resistant", 8197 "HP Premium Keyboard â spill resistant": "Spill-resistant", 8198 "Spill-resistant keyboard": "Spill-resistant", 8199 "Full-size keyboard": "Full-size keyboard", 8200 "Full-size keyboard with numeric keypad": "Full-size keyboard", 8201 "backlit": "Backlit keyboard", 8202 "Backlit keyboard": "Backlit keyboard", 8203 "dragon red backlit": "Backlit keyboard", 8204 "RGB backlit": "Backlit keyboard", 8205 "2 Super Speed USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8206 "2 SuperSpeed Type-A USB 5Gbps signaling rate (1 charging)": "Multiple USB ports", 8207 "2 SuperSpeed USB 10Gbps signaling rate": "Multiple USB ports", 8208 "2 SuperSpeed USB 5Gbps signaling rate": "Multiple USB ports", 8209 "2 SuperSpeed USB Type-A 10Gbps signaling rate": "Multiple USB ports", 8210 "2 SuperSpeed USB Type-A 10Gbps signaling rate (1 fast charging)": "Multiple USB ports", 8211 "2 SuperSpeed USB Type-A 10Gbps signaling rate (charging)": "Multiple USB ports", 8212 "2 SuperSpeed USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8213 "2 SuperSpeed USB Type-A 5Gbps signaling rate (1 charging)": "Multiple USB ports", 8214 "2 SuperSpeed USB Type-A 5Gbps signaling rate (1 fast charging)": "Multiple USB ports", 8215 "2 SuperSpeed USB Type-A 5Gbps signaling rate (Charging 1.2)": "Multiple USB ports", 8216 "2 SuperSpeed USB Type-A 5Gbps signaling rate (charging)": "Multiple USB ports", 8217 "2 SuperSpeed USB Type-C® 20Gbps signaling rate": "Multiple USB ports", 8218 "2 SuperSpeed USB Type-C® 20Gbps signaling rate (USB Power Delivery)": "Multiple USB ports", 8219 "2 Thunderbolt⢠4 with USB Type-C® 40Gbps signaling rate": "Multiple USB ports", 8220 "2 Thunderbolt⢠4 with USB4⢠Type-C® 40Gbps signaling rate": "Multiple USB ports", 8221 "2 USB 2.0": "Multiple USB ports", 8222 "2 USB 2.0 (1 charging)": "Multiple USB ports", 8223 "2 USB 2.0 Type-A": "Multiple USB ports", 8224 "2 USB 3.0": "Multiple USB ports", 8225 "2 USB 3.0 (1 charging)": "Multiple USB ports", 8226 "2 USB 3.1 Gen 1": "Multiple USB ports", 8227 "2 USB 3.1 Gen 1 (1 charging)": "Multiple USB ports", 8228 "2 USB 3.1 Gen 1 (charging)": "Multiple USB ports",
8229 "2 USB 3.1 Gen 1 (Data transfer only)": "Multiple USB ports", 8230 "2 USB 3.1 Gen 1 (Sleep and Charge support)": "Multiple USB ports", 8231 "2 USB 3.1 Gen 1 Type-A (Data Transfer Only)": "Multiple USB ports", 8232 "2 USB 3.1 Gen 2": "Multiple USB ports", 8233 "2 USB 3.1 Type A": "Multiple USB ports", 8234 "2 USB 3.1 Type-C®": "Multiple USB ports", 8235 "2 USB Type-A 10Gbps signaling rate": "Multiple USB ports", 8236 "2 USB Type-A 480Mbps signaling rate": "Multiple USB ports", 8237 "2 USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8238 "2 USB Type-A 5Gbps signaling rate (1 charging)": "Multiple USB ports", 8239 "2 USB Type-C (Alt mode)": "Multiple USB ports", 8240 "2 USB Type-C 20Gbps signaling rate (USB Power Delivery)": "Multiple USB ports", 8241 "3 SuperSpeed USB Type-A 10Gbps signaling rate": "Multiple USB ports", 8242 "3 SuperSpeed USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8243 "3 USB 2.0 Type-A": "Multiple USB ports", 8244 "3 USB Type-A 480 Mbps signaling rate": "Multiple USB ports", 8245 "3 USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8246 "4 SuperSpeed USB 10Gbps signaling rate": "Multiple USB ports", 8247 "4 SuperSpeed USB 5Gbps signaling rate (1 fast charging)": "Multiple USB ports", 8248 "4 SuperSpeed USB Type-A 10Gbps signaling rate": "Multiple USB ports", 8249 "4 SuperSpeed USB Type-A 10Gbps signaling rate (1 charging)": "Multiple USB ports", 8250 "4 SuperSpeed USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8251 "4 SuperSpeed USB Type-A 5Gbps signaling rate (1 Charging)": "Multiple USB ports", 8252 "4 USB 2.0 Type-A": "Multiple USB ports", 8253 "4 USB 3.1 (1 charging)": "Multiple USB ports", 8254 "4 USB 3.1 Gen 1": "Multiple USB ports", 8255 "4 USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8256 "4 USB Type-A 5Gbps signaling rate (1 charging)": "Multiple USB ports", 8257 "6 USB 3.1 Gen 1": "Multiple USB ports", 8258 "6 USB Type-A 5Gbps signaling rate": "Multiple USB ports", 8259 "OLED": "OLED", 8260 "10% post-consumer recycled plastic": "Recycled material", 8261 "10% post-industrial recycled metal": "Recycled material", 8262 "10% recycled metal": "Recycled material", 8263 "100% recycled polyester in speaker and pocket fabric": "Recycled material", 8264 "15% post-consumer recycled plastic": "Recycled material", 8265 "2% post-consumer recycled plastic": "Recycled material", 8266 "20% post-consumer recycled plastic": "Recycled material", 8267 "20% recycled metal": "Recycled material", 8268 "25% recycled metal": "Recycled material", 8269 "30% post-consumer recycled plastic": "Recycled material", 8270 "30% recycled metal": "Recycled material", 8271 "35% post-consumer recycled plastic": "Recycled material", 8272 "40% post-consumer recycled plastic": "Recycled material", 8273 "45% post-consumer recycled plastic": "Recycled material", 8274 "45% recycled metal": "Recycled material", 8275 "5% post-consumer recycled plastic": "Recycled material", 8276 "50% post-consumer recycled plastic": "Recycled material", 8277 "50% recycled metal": "Recycled material", 8278 "55% post-consumer recycled plastic": "Recycled material", 8279 "58% post-consumer recycled plastic": "Recycled material", 8280 "60% post-consumer recycled plastic": "Recycled material", 8281 "65% recycled metal": "Recycled material", 8282 "75% post-consumer recycled plastic": "Recycled material", 8283 "Contains recycled metal": "Recycled material", 8284 "Keyboard keycaps and scissors contain post-consumer recycled plastic": "Recycled material", 8285 "Keyboard keycaps made with post-consumer recycled plastic": "Recycled material", 8286 "LDPE bag contains 30% recycled plastic": "Recycled material", 8287 "Molded paper pulp cushion inside box is 100% sustainably sourced and recyclable": "Recycled material", 8288 "Outside box and corrugated cushions are 100% sustainably sourced and recyclable": "Recycled material", 8289 "Plastic cushion inserts contain 80% recycled content": "Recycled material", 8290 "Recycled fabric": "Recycled material", 8291 "Recycled fabric in speaker grill": "Recycled material", 8292 "Recycled Plastic cushions": "Recycled material", 8293}; 8294 8295function getAnswers(transformedOffer, offerName) { 8296 const answers = { 8297 q1: null, 8298 q2: null, 8299 q3: [] 8300 }; 8301 8302 try { 8303 const filters = transformedOffer.filters || {}; 8304 8305 if (offerName.toLowerCase().includes("cpc")) { 8306 answers.q1 = filters.filter_term_cp || null; 8307 answers.q2 = filters.filter_supptype_cp_01 || null; 8308 answers.q3 = filters.filter_supptype_cp_05 || [] 8309 8310 } else if (offerName.toLowerCase().includes("huq")) { 8311 if (!isDefined(filters.appearance) || 8312 !isDefined(filters.usage) || 8313 !isDefined(filters.processor) || 8314 !isDefined(filters.memory) || 8315 !isDefined(filters.drives)) { 8316 return null; 8317 } 8318 8319 answers.q1 = Object.values(deviceUseCriteriaMap).find(useCriteria => 8320 useCriteria.formFactor.some(formFactor => 8321 formFactor.toLowerCase() === filters.appearance.toLowerCase() 8322 ) 8323 )?.id || null; 8324 8325 if (!answers.q1) { 8326 console.error("No matching device use criteria for:", filters.appearance); 8327 } 8328 8329 answers.q2 = Object.values(deviceCriteriaMap).find(criteria => 8330 criteria.usage.some(usage => 8331 usage.toLowerCase() === filters.usage.toLowerCase() 8332 ) && 8333 criteria.processors.some(processor => 8334 processor.toLowerCase() === filters.processor.toLowerCase() 8335 ) && 8336 (filters.memory >= criteria.memory.min && 8337 (criteria.memory.max === null || filters.memory <= criteria.memory.max)) && 8338 filters.drives >= criteria.storage 8339 )?.id || null; 8340 8341 if (!answers.q2) { 8342 answers.q2 = Object.values(deviceCriteriaMap).find(criteria => 8343 criteria.processors.some(processor => 8344 processor.toLowerCase() === filters.processor.toLowerCase() 8345 ) && 8346 (filters.memory >= criteria.memory.min && 8347 (criteria.memory.max === null || filters.memory <= criteria.memory.max)) && 8348 filters.drives >= criteria.storage 8349 )?.id || null; 8350 } 8351 8352 if (!answers.q2) { 8353 answers.q2 = Object.values(deviceCriteriaMap).find(criteria => 8354 criteria.usage.some(usage => 8355 usage.toLowerCase() === filters.usage.toLowerCase() 8356 ) 8357 )?.id || null; 8358 } 8359 8360 if (!answers.q2) { 8361 console.error("No matching device criteria for HUQ:", filters); 8362 } 8363 8364 const rawFeatures = filters.features || []; 8365 answers.q3 = rawFeatures 8366 .map(f => featureCategoryMap[f.trim()]) 8367 .filter(Boolean); 8368 8369 } else { 8370 console.error("Unknown offer name:", offerName); 8371 return null; 8372 } 8373 8374 } catch (error) { 8375 console.error("Error while preparing answers:", error, transformedOffer); 8376 return null; 8377 } 8378 8379 return answers; 8380} 8381 8382function transformOffer(offer) { 8383 const categoryData = parseDelimitedString(offer.category, ['filter_supptype_cp_05', 'Ports', 'Features']);
8384 const descriptionData = parseDelimitedString(offer.primaryText2); 8385 8386 const cleanedExtended = (descriptionData.proddes_overview_extended || "").replace(/\[\d+\]/g, ''); 8387 const cleanedExtendedShort = (descriptionData.proddes_overview_short || "").replace(/\[\d+\]/g, ''); 8388 8389 const cleanedCoverage = categoryData.filter_supptype_cp_01 8390 ? categoryData.filter_supptype_cp_01.replace(/w\//gi, "with ").replace(/\//g, "with ") 8391 : null; 8392 8393 const trackingId = 'Offer_id=MAS-' + quizReqObj.requestId + '_' + (offer.productSKU) + '_' + (offer.name); 8394 var trackedStoreURL = offer.storeURL; 8395 if (trackedStoreURL && trackedStoreURL.lastIndexOf("?") > -1) { 8396 trackedStoreURL += "&" + trackingId; 8397 } else if (trackedStoreURL) { 8398 trackedStoreURL += "?" + trackingId; 8399 } else { 8400 trackedStoreURL = null; 8401 } 8402 8403 const filters = { 8404 appearance: categoryData.Appearance || null, 8405 usage: categoryData.Usage || null, 8406 processor: categoryData.Processor || null, 8407 memory: categoryData.Memory || null, 8408 drives: categoryData.Drives || null, 8409 screenSize: categoryData.ScreenSize || null, 8410 features: categoryData.Features || [], 8411 ports: categoryData.Ports || null, 8412 weight: categoryData.Weight || null, 8413 filter_term_cp: categoryData.filter_term_cp || null, 8414 filter_supptype_cp_01: cleanedCoverage, 8415 filter_supptype_cp_05: categoryData.filter_supptype_cp_05 || [] 8416 }; 8417 8418 const extraFeatures = []; 8419 8420 if (isDefined(filters.screenSize) && parseFloat(filters.screenSize) >= 15) { 8421 extraFeatures.push("Large Display"); 8422 } 8423 8424 if (isDefined(filters.weight) && parseFloat(filters.weight) <= 1.4) { 8425 extraFeatures.push("Lightweight and Slim"); 8426 } 8427 8428 filters.features = [...new Set([...filters.features, ...extraFeatures])]; 8429 8430 return { 8431 productSKU: offer.productSKU || null, 8432 skuName: offer.primaryText1 || "", 8433 skuDesciption: cleanedExtended || "", 8434 skuDesciptionShort: cleanedExtendedShort || "", 8435 storeURL: trackedStoreURL || null, 8436 imageURL: offer.imageURL || null, 8437 incartPrice: offer.incartPrice || null, 8438 strikePrice: offer.strikePrice || null, 8439 filters 8440 }; 8441} 8442 8443function extractOffers(apiResponse) { 8444 if (!apiResponse?.offers?.offer?.length) { 8445 if (Array.isArray(apiResponse?.offers) && apiResponse.offers.length === 1 && apiResponse.offers[0]?.offer?.length) { 8446 apiResponse.offers = apiResponse.offers[0]; 8447 } else { 8448 return []; 8449 } 8450 } 8451 8452 const products = []; 8453 var offerName = null; 8454 8455 if (apiResponse.offers.offer.length === 1 && !isDefined(apiResponse.offers.offer[0].offerTitle)) { 8456 console.warn("Only one offer found and no offerTitle defined. Exiting."); 8457 if (!offerName && isDefined(apiResponse.offers.offer[0].name)) { 8458 offerName = apiResponse.offers.offer[0].name; 8459 } 8460 return { 8461 name: offerName, 8462 products: products, 8463 }; 8464 } 8465 8466 for (const item of apiResponse.offers.offer) { 8467 const transformedOffer = transformOffer(item); 8468 8469 if (!offerName && isDefined(item.name)) { 8470 offerName = item.name; 8471 } 8472 transformedOffer.answers = getAnswers(transformedOffer, offerName); 8473 8474 if (isDefined(transformedOffer.answers) && isDefined(transformedOffer.answers.q1) && isDefined(transformedOffer.answers.q2)) { 8475 products.push(transformedOffer); 8476 } else { 8477 8478 8479 } 8480 8481 } 8482 8483 return { 8484 name: offerName, 8485 products: products, 8486 }; 8487} 8488async function sendPostRequest(endpoint, payload) { 8489 return new Promise((resolve, reject) => { 8490 $.ajax({
8491 url: endpoint, 8492 method: "POST", 8493 async: true, 8494 data: encodeURIComponent(JSON.stringify(payload)), 8495 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 8496 timeout: 7000, 8497 success: function (result) { 8498 logInfo("API Response:", result); 8499 resolve(result); 8500 }, 8501 error: function (XMLHttpRequest, textStatus, errorThrown) { 8502 console.error("API Error:", XMLHttpRequest, textStatus, errorThrown); 8503 reject({ XMLHttpRequest, textStatus, errorThrown }); 8504 } 8505 }); 8506 }); 8507} 8508async function sendDemoPostRequest(sku, warranty) { 8509 if (!isMastiffDebug() && window.location.protocol !== "file:") { 8510 console.error("Debug mode is OFF, cannot send demo request."); 8511 return null; 8512 } 8513 8514 logInfo("Debug mode is ON"); 8515 8516 await new Promise((resolve, reject) => { 8517 const script = document.createElement('script'); 8518 script.src = "hardCodedData.js"; 8519 8520 script.onload = () => { 8521 logInfo("Hardcoded data loaded successfully."); 8522 resolve(); 8523 }; 8524 8525 script.onerror = () => { 8526 console.error("Failed to load hardcoded data."); 8527 reject(new Error("Failed to load hardcoded data.")); 8528 }; 8529 8530 document.head.appendChild(script); 8531 }); 8532 8533 if (typeof liveDemoResponseData === 'undefined' || !Array.isArray(liveDemoResponseData)) { 8534 console.error("liveDemoResponseData is not defined or is not an array."); 8535 return null; 8536 } 8537 8538 const filteredResponse = liveDemoResponseData.filter( 8539 item => item.SKU === sku && item.WarrantyState === warranty 8540 ); 8541 8542 return filteredResponse.length > 0 ? filteredResponse[0] : null; 8543} 8544function stringifyReportingContext(context = {}) { 8545 logInfo("Reporting context:", context); 8546 const q1 = context.q1 || ""; 8547 const q2 = context.q2 || ""; 8548 const q3 = Array.isArray(context.q3) ? context.q3.join(";") : ""; 8549 const results = context.results || ""; 8550 const status = context.status || ""; 8551 const sku = context.acceptedSKU || ""; 8552 const totalProducts = context.total || 0; 8553 const matchedDirectSelection = context.matchedDirectSelection || null; 8554 const relaxationIteration = context.relaxationIteration || null; 8555 8556 var reportingString = `Q1:${q1}|Q2:${q2}|Q3:${q3}|Results:${results}|Status:${status}|SKUAccepted:${sku}|TotalQ3:${totalProducts}|matchedDirectSelection:${matchedDirectSelection}|relaxationIteration:${relaxationIteration}`; 8557 8558 reportingString = reportingString.replaceAll("&", "and"); 8559 logInfo("Reporting string:", reportingString); 8560 return reportingString; 8561} 8562 8563async function sendReportingRequest(context, pendingReqId = false) { 8564 const originalRequestId = quizReqObj.requestId; 8565 const originalSessionId = quizReqObj.user.sessionId; 8566 8567 if (pendingReqId) { 8568 quizReqObj.requestId = context.requestId; 8569 quizReqObj.user.sessionId = context.sessionId || quizReqObj.user.sessionId; 8570 } 8571 8572 const reportingString = encodeURIComponent(stringifyReportingContext(context)); 8573 quizReqObj.offerName = context.offerName || ""; 8574 quizReqObj.experienceResults = reportingString; 8575 quizReqObj.acceptanceLevel = "Accepted"; 8576 8577 try { 8578 const response = await sendPostRequest(apiUrl, quizReqObj); 8579 return response; 8580 } catch (error) { 8581 throw error; 8582 } finally { 8583 quizReqObj.requestId = originalRequestId; 8584 quizReqObj.user.sessionId = originalSessionId; 8585 quizReqObj.offerName = ""; 8586 quizReqObj.experienceResults = ""; 8587 quizReqObj.acceptanceLevel = ""; 8588 } 8589} 8590 8591var CPChardcodedContent = { 8592 tooltipsContent: { 8593 text: { 8594 "us": { 8595 "Active Care": { 8596 summary: 'HP Active Care leverages devices telemetry to identify, prevent, resolve employee device issues from anywhere, and includes:', 8597 benefits: ["Automated device health monitoring", "Predictive analytics & insights", "End user alerts & automated ticketing", "Next business day response", "24x7 remote support", "Onsite support from an HP expert", "Priority access to parts & HP service experts"], 8598 idealFor: "Mobile business users who divide their time between their office, travel and working remotely." 8599 }, 8600 "Onsite repair": { 8601 summary: "Onsite Service makes an HP authorized representative available at the customers' premises to begin hardware maintenance service , and includes:", 8602 benefits: ["Remote diagnosis and phone support", "Onsite hardware support", "Freight costs paid by HP for returning the defective product",], 8603 idealFor: "Mobile business users who divide their time between their office, travel and working remotely." 8604 }, 8605 "Exchange": { 8606 summary: 'Exchange provides a replacement product or part to be delivered free of freight charges to your location, and includes:', 8607 benefits: ["Remote diagnosis and phone support", "Replacements for defective products or parts", "Freight costs paid by HP for returning the defective product",], 8608 idealFor: "Mobile business users who divide their time between their office, travel and working remotely." 8609 }, 8610 "Pickup and return": { 8611 summary: "Pickup and Return provides access to an HP authorized courier to pick-up the faulty unit, repair, and return the operational unit, if the issue cannot be resolved remotely and includes:", 8612 benefits: ["Remote diagnosis and phone support", "lower-cost alternative to onsite support", "Repair at an HP center (materials & parts included)", "Flexible shipping to HP center", "Return shipping of repaired unit", "3â5 business-day turnaround (location-dependent) "], 8613 idealFor: "Customers seeking reliable, cost-effective repair with included parts and flexible shipping, without the need for on-site support." 8614 }, 8615 "Accidental damage protection": { 8616 summary: 'Accidental Damage Protection allows the customer to avoid out-of-pocket repair or replacement costs caused by accidents such as drops, spills or electrical surges. Refer to local datasheet for detailed coverage.', 8617 idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses." 8618 }, "HP SmartFriend": { 8619 summary: "SmartFriend connects you with SmartFriend agents who will help you solve a wide range of technical issues that may arise with your PCs and tablets, and includes:", 8620 benefits: ["Virus removal and PC security assistance", "Software installation, configuration & troubleshooting", "âHow-toâ assistance", "Wi-Fi network connectivity assistance and troubleshooting"], 8621 idealFor: "Mobile business users who divide their time between their office, travel and working remotely." 8622 }, 8623 "Defective media retention": { 8624 summary: 'Defective Media Retention provides a replacement drive while allowing customers to keep their malfunctioning drive on which their sensitive data is stored.', 8625 idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses." 8626 }, 8627 "Device life extension": { 8628 summary: 'HP Device Life Extension Service enables organizations to send PCs from their existing fleets to be optimized for performance and returned to the customer, giving devices a performance boost and allowing customers to use their devices for longer.', 8629 idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses." 8630 }, 8631 "PC Solution": { 8632 summary: 'Add repair or replace coverage on up to six peripherals when you purchase your commercial HP device.', 8633 idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses." 8634 }, 8635 "Travel coverage": { 8636 summary: 'Provides next-business-day onsite service in any of the covered (80) countries/regions for customers who travel internationally.', 8637 idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses." 8638 }, 8639 "Computer tracing": { 8640 summary: 'If your device is lost, or worse, stolen, we can lock your device, track it, and work with the authorities to help recover it. We can even wipe your hard drive so your private data stays private.', 8641 idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses." 8642 }, 8643 }, 8644 "es": {}, 8645 "pt": {}, 8646 "fr": {}, 8647 "nl": {}, 8648 "bg": {}, 8649 "cs": {}, 8650 "hr": {}, 8651 "da": {}, 8652 "de": {}, 8653 "et": {}, 8654 "el": {}, 8655 "he": {}, 8656 "it": {}, 8657 "kk": {}, 8658 "lv": {}, 8659 "lt": {}, 8660 "hu": {}, 8661 "ar": {}, 8662 "no": {}, 8663 "pl": {}, 8664 "ro": {}, 8665 "sr": {}, 8666 "sk": {}, 8667 "sl": {}, 8668 "fi": {}, 8669 "sv": {}, 8670 "tr": {}, 8671 "uk": {}, 8672 "zh": {}, 8673 "id": {}, 8674 "ja": {}, 8675 "ko": {}, 8676 "ms": {}, 8677 "fil": {}, 8678 "th": {}, 8679 "vi": {} 8680 }, prefix: { 8681 "us": "Ideal for: ", 8682 "es": "Ideal para: ", 8683 "pt": "Ideal para: ", 8684 "fr": "Idéal pour : ", 8685 "nl": "Ideaal voor: ", 8686 "bg": "ÐÐ¾Ð´Ñ Ð¾Ð´ÑÑ Ð·Ð°: ", 8687 "cs": "Ideálnà pro: ", 8688 "hr": "Idealno za: ", 8689 "da": "Ideel til: ", 8690 "de": "Ideal für: ", 8691 "et": "Ideaalne: ", 8692 "el": "ÎÎ´Î±Î½Î¹ÎºÏ Î³Î¹Î±: ", 8693 "he": "××××××× ×¢××ר: ", 8694 "it": "Ideale per: ", 8695 "kk": "Ò®ÑÑн ÒолайлÑ: ", 8696 "lv": "IdeÄli piemÄrots: ", 8697 "lt": "Idealiai tinka: ", 8698 "hu": "Ideális erre: ", 8699 "ar": "٠ثاÙÙ ÙÙ: ", 8700 "no": "Ideell for: ", 8701 "pl": "Idealne dla: ", 8702 "ro": "Ideal pentru: ", 8703 "sr": "Ðдеално за: ", 8704 "sk": "Ideálne pre: ", 8705 "sl": "Idealno za: ", 8706 "fi": "Ihanteellinen: ", 8707 "sv": "Perfekt för: ", 8708 "tr": "İdeal olan: ", 8709 "uk": "ÐдеалÑно длÑ: ", 8710 "zh": "éç¨äºï¼", 8711 "id": "Ideal untuk: ", 8712 "ja": "ãã«æé©ï¼", 8713 "ko": "ì´ìì ì: ", 8714 "ms": "Sesuai untuk: ", 8715 "fil": "Mainam para sa: ", 8716 "th": "à¹à¸«à¸¡à¸²à¸°à¸ªà¸³à¸«à¸£à¸±à¸: ", 8717 "vi": "Lý tưá»ng cho: " 8718 } 8719 }, 8720 quizEntryContent: { 8721 header: { 8722 "us": "Extend your Warranty", 8723 "es": "Extiende tu garantÃa", 8724 "pt": "Estenda sua garantia", 8725 "fr": "Prolongez votre garantie", 8726 "nl": "Verleng je garantie", 8727 "bg": "РазÑиÑеÑе гаÑанÑиÑÑа Ñи", 8728 "cs": "Prodloužit záruku", 8729 "hr": "Produžite jamstvo", 8730 "da": "Forlæng din garanti", 8731 "de": "Verlängern Sie Ihre Garantie", 8732 "et": "Pikenda oma garantiiaeg", 8733 "el": "ÎÏεκÏείνεÏε Ïην εγγÏηÏή ÏαÏ", 8734 "he": "×ר×× ×ת ×××ר××ת ש××", 8735 "it": "Estendi la tua garanzia", 8736 "kk": "ÐаÑанÑиÑÒ£ÑÐ·Ð´Ñ Ò±Ð·Ð°ÑÑÑÒа боладÑ", 8737 "lv": "Pagariniet savu garantiju", 8738 "lt": "IÅ¡plÄskite savo garantijÄ ", 8739 "hu": "HosszabbÃtsa meg a garanciát", 8740 "ar": "٠دد Ø¶Ù Ø§ÙØªÙ", 8741 "no": "Forleng garantien din", 8742 "pl": "Rozszerz swojÄ gwarancjÄ", 8743 "ro": "ExtindeÈi garanÈia", 8744 "sr": "ProÅ¡irite garanciju", 8745 "sk": "Predĺžte svoju záruku", 8746 "sl": "PodaljÅ¡ajte svojo garancijo", 8747 "fi": "Pidennä takuuta", 8748 "sv": "Förläng din garanti", 8749 "tr": "Garanti sürenizi uzatın", 8750 "uk": "ÐÑодовжÑÑÑ ÑÐ²Ð¾Ñ Ð³Ð°ÑанÑÑÑ", 8751 "zh": "å»¶é¿æ¨çä¿ä¿®æ", 8752 "id": "Perpanjang garansi Anda", 8753 "ja": "ä¿è¨¼ãå»¶é·ãã", 8754 "ko": "ë³´ì¦ ì°ì¥", 8755 "ms": "Panjang jaminan anda", 8756 "fil": "Palawigin ang iyong garantiya", 8757 "th": "à¸à¸¢à¸²à¸¢à¸à¸²à¸£à¸£à¸±à¸à¸à¸£à¸°à¸à¸±à¸à¸à¸à¸à¸à¸¸à¸",
8758 "vi": "Gia hạn bảo hà nh cá»§a bạn" 8759 }, 8760 description: { 8761 "us": "Answer 3 questions to build your coverage plan.", 8762 "es": "Responde 3 preguntas para crear tu plan de cobertura", 8763 "pt": "Responda a 3 perguntas para criar seu plano de cobertura", 8764 "fr": "Répondez à 3 questions pour créer votre plan de couverture", 8765 "nl": "Beantwoord 3 vragen om je dekking plan te maken", 8766 "bg": "ÐÑговоÑеÑе на 3 вÑпÑоÑа, за да ÑÑздадеÑе план за покÑиÑие", 8767 "cs": "OdpovÄzte na 3 otázky a vytvoÅte svůj plán krytÃ", 8768 "hr": "Odgovorite na 3 pitanja kako biste izradili svoj plan pokrivanja", 8769 "da": "Svar pÃ¥ 3 spørgsmÃ¥l for at opbygge din dækning plan", 8770 "de": "Beantworten Sie 3 Fragen, um Ihren Deckungsplan zu erstellen", 8771 "et": "Vastake 3 küsimusele, et koostada oma katteplaan", 8772 "el": "ÎÏανÏήÏÏε Ïε 3 εÏÏÏήÏÎµÎ¹Ï Î³Î¹Î± να Î´Î·Î¼Î¹Î¿Ï ÏγήÏεÏε Ïο ÏÏÎδιο ÎºÎ¬Î»Ï ÏηÏ", 8773 "he": "×¢× × ×¢× 3 ש×××ת ××× ××צ×ר ×ת ת×× ×ת ×××ס×× ×©××", 8774 "it": "Rispondi a 3 domande per creare il tuo piano di copertura", 8775 "kk": "ÒамÑÑ Ð¶Ð¾ÑпаÑÑн ÒÒ±ÑÑ Ò¯ÑÑн 3 ÑÒ±ÑаÒÒа жаÑап беÑÑÒ£Ñз", 8776 "lv": "Atbildiet uz 3 jautÄjumiem, lai izveidotu savu seguma plÄnu", 8777 "lt": "Atsakykite į 3 klausimus, kad sukurtumÄte savo aprÄpties planÄ ", 8778 "hu": "Válaszoljon 3 kérdésre a fedezeti terv létrehozásához", 8779 "ar": "أجب عÙÙ 3 Ø£Ø³Ø¦ÙØ© ÙØ¨Ùاء Ø§Ø´ØªØ±Ø§Ù Ø§ÙØªØºØ·ÙØ© Ø§ÙØ®Ø§Øµ بÙ", 8780 "no": "Svar pÃ¥ 3 spørsmÃ¥l for Ã¥ lage ditt dekning plan", 8781 "pl": "Odpowiedz na 3 pytania, aby stworzyÄ swój plan pokrycia", 8782 "ro": "RÄspundeÈi la 3 întrebÄri pentru a construi planul de acoperire", 8783 "sr": "Odgovorite na 3 pitanja kako biste izgradili svoj plan pokrivanja", 8784 "sk": "Odpovedzte na 3 otázky a vytvorte si svoj plán pokrytia", 8785 "sl": "Odgovorite na 3 vpraÅ¡anja, da sestavite svoj naÄrt kritja", 8786 "fi": "Vastaa 3 kysymykseen rakentaaksesi kattavussuunnitelmasi", 8787 "sv": "Svara pÃ¥ 3 frÃ¥gor för att bygga din täckningsplan", 8788 "tr": "Kapsama planınızı oluÅturmak için 3 soruyu yanıtlayın", 8789 "uk": "ÐÑдповÑдайÑе на 3 запиÑаннÑ, Ñоб ÑÑвоÑиÑи ÑвÑй план покÑиÑÑÑ", 8790 "zh": "åç 3 个é®é¢ä»¥æå»ºæ¨çä¿é计å", 8791 "id": "Jawab 3 pertanyaan untuk membangun rencana perlindungan Anda", 8792 "ja": "ã«ãã¬ãã¸ãã©ã³ã使ããããã«3ã¤ã®è³ªåã«çãã¦ãã ãã", 8793 "ko": "ë³´ì¥ ê³íì ìì±íë ¤ë©´ 3ê°ì ì§ë¬¸ì ëµíì¸ì", 8794 "ms": "Jawab 3 soalan untuk membina pelan perlindungan anda", 8795 "fil": "Sagot ang 3 tanong upang buuin ang iyong plano ng proteksyon", 8796 "th": "à¸à¸à¸à¸à¸³à¸à¸²à¸¡ 3 à¸à¹à¸à¹à¸à¸·à¹à¸à¸ªà¸£à¹à¸²à¸à¹à¸à¸à¸à¸²à¸£à¸à¸¸à¹à¸¡à¸à¸£à¸à¸à¸à¸à¸à¸à¸¸à¸", 8797 "vi": "Trả lá»i 3 câu há»i Äá» xây dá»±ng kế hoạch bảo hiá»m cá»§a bạn" 8798 }, 8799 cta: { 8800 "us": "Get started", 8801 "es": "Comenzar", 8802 "pt": "Começar", 8803 "fr": "Commencer", 8804 "nl": "Begin", 8805 "bg": "ÐапоÑнеÑе", 8806 "cs": "ZaÄÃt", 8807 "hr": "ZapoÄnite", 8808 "da": "Kom godt i gang", 8809 "de": "Loslegen", 8810 "et": "Alusta", 8811 "el": "ÎεκινήÏÏε", 8812 "he": "×ת××", 8813 "it": "Inizia", 8814 "kk": "ÐаÑÑаÑ", 8815 "lv": "SÄkt", 8816 "lt": "PradÄti", 8817 "hu": "Kezdjen", 8818 "ar": "ابدأ", 8819 "no": "Kom i gang", 8820 "pl": "Zacznij", 8821 "ro": "Ãncepe", 8822 "sr": "PoÄnite", 8823 "sk": "ZaÄnite", 8824 "sl": "ZaÄnite", 8825 "fi": "Aloita", 8826 "sv": "Kom igÃ¥ng", 8827 "tr": "BaÅlayın", 8828 "uk": "ÐоÑаÑи", 8829 "zh": "å¼å§", 8830 "id": "Mulai", 8831 "ja": "å§ãã", 8832 "ko": "ììí기", 8833 "ms": "Mula", 8834 "fil": "Magsimula", 8835 "th": "à¹à¸£à¸´à¹à¸¡à¸à¹à¸", 8836 "vi": "Bắt Äầu" 8837 } 8838 }, 8839 quizBodyContent: { 8840 header: { 8841 "us": "Your plan will unlock after you select your coverage needs", 8842 "es": "Tu plan se desbloqueará después de seleccionar tus necesidades de cobertura", 8843 "pt": "Seu plano será desbloqueado após você selecionar suas necessidades de cobertura", 8844 "fr": "Votre plan se débloquera après avoir sélectionné vos besoins en couverture", 8845 "nl": "Je plan wordt ontgrendeld nadat je je dekkingsbehoeften hebt geselecteerd", 8846 "bg": "ÐаÑиÑÑ Ð¿Ð»Ð°Ð½ Ñе Ñе оÑклÑÑи Ñлед каÑо избеÑеÑе ваÑиÑе нÑжди Ð¾Ñ Ð¿Ð¾ÐºÑиÑие", 8847 "cs": "Váš plán se odemkne, jakmile vyberete své potÅeby krytÃ", 8848 "hr": "VaÅ¡ plan bit Äe otkljuÄan nakon Å¡to odaberete svoje potrebe pokrivenosti", 8849 "da": "Din plan vil blive lÃ¥st op, nÃ¥r du har valgt dine dækningbehov", 8850 "de": "Ihr Plan wird freigeschaltet, nachdem Sie Ihre Deckungsbedürfnisse ausgewählt haben", 8851 "et": "Teie plaan avatakse pärast seda, kui olete valinud oma kattevajadused", 8852 "el": "Το ÏÏÎδιο ÏÎ±Ï Î¸Î± ξεκλειδÏÏει αÏÎ¿Ï ÎµÏιλÎξεÏε ÏÎ¹Ï Î±Î½Î¬Î³ÎºÎµÏ ÎºÎ¬Î»Ï ÏηÏ", 8853 "he": "×ת××× ×ת ש×× ×ª×¤×ª× ×××ר שת××ר ×ת צר×× ×××ס×× ×©××", 8854 "it": "Il tuo piano si sbloccherà dopo aver selezionato le tue esigenze di copertura", 8855 "kk": "ÐоÑпаÑÑÒ£Ñз жапÒÑÑ ÒажеÑÑÑлÑкÑеÑÑÒ£ÑÐ·Ð´Ñ ÑаңдаÒаннан кейÑн аÑÑладÑ", 8856 "lv": "JÅ«su plÄns tiks atbloÄ·Äts pÄc tam, kad izvÄlÄsieties savas seguma vajadzÄ«bas", 8857 "lt": "JÅ«sų planas bus atrakintas, kai pasirinksite savo aprÄpties poreikius", 8858 "hu": "A terved feloldódik, miután kiválasztottad a fedezeti igényeidet", 8859 "ar": "Ø³ÙØªÙ ØªÙØ¹Ù٠اشتراÙ٠بعد ØªØØ¯Ùد Ø§ØØªÙØ§Ø¬Ø§ØªÙ Ù Ù Ø§ÙØªØºØ·ÙØ©", 8860 "no": "Planen din vil bli lÃ¥st opp etter at du har valgt dine dekningbehov", 8861 "pl": "Twój plan zostanie odblokowany po wybraniu potrzeb pokrycia", 8862 "ro": "Planul tÄu se va debloca dupÄ ce îÈi selectezi nevoile de acoperire", 8863 "sr": "VaÅ¡ plan Äe biti otkljuÄan nakon Å¡to odaberete svoje potrebe pokrivanja", 8864 "sk": "Váš plán sa odomkne po výbere vaÅ¡ich potrieb pokrytia", 8865 "sl": "VaÅ¡ naÄrt se bo odklenil, ko izberete svoje potrebe po kritju", 8866 "fi": "Suunnitelmasi avautuu, kun ovar valinnut kattavuustarpeesi", 8867 "sv": "Din plan lÃ¥ses upp efter att du har valt dina täckningsbehov", 8868 "tr": "Planınız, kapsama ihtiyaçlarınızı seçtikten sonra açılacaktır", 8869 "uk": "ÐÐ°Ñ Ð¿Ð»Ð°Ð½ бÑде Ñозблоковано пÑÑÐ»Ñ Ð²Ð¸Ð±Ð¾ÑÑ Ð²Ð°ÑÐ¸Ñ Ð¿Ð¾ÑÑеб Ñ Ð¿Ð¾ÐºÑиÑÑÑ", 8870 "zh": "å¨éæ©æ¨çä¿ééæ±åï¼æ¨ç计åå°è§£é",
8871 "id": "Rencana Anda akan terbuka setelah Anda memilih kebutuhan perlindungan Anda", 8872 "ja": "ã«ãã¬ãã¸ã®ãã¼ãºã鏿ããå¾ããã©ã³ãã¢ã³ããã¯ããã¾ã", 8873 "ko": "ë³´ì¥ ì구 ì¬íì ì íí í íëì´ ì ê¸ í´ì ë©ëë¤", 8874 "ms": "Pelan anda akan dibuka selepas anda memilih keperluan perlindungan anda", 8875 "fil": "Bubukas ang iyong plano pagkatapos mong piliin ang iyong mga pangangailangan sa proteksyon", 8876 "th": "à¹à¸à¸à¸à¸à¸à¸à¸¸à¸à¸à¸°à¸à¸¹à¸à¸à¸¥à¸à¸¥à¹à¸à¸à¸«à¸¥à¸±à¸à¸à¸²à¸à¸à¸µà¹à¸à¸¸à¸à¹à¸¥à¸·à¸à¸à¸à¸§à¸²à¸¡à¸à¹à¸à¸à¸à¸²à¸£à¸à¸²à¸£à¸à¸¸à¹à¸¡à¸à¸£à¸à¸à¸à¸à¸à¸à¸¸à¸", 8877 "vi": "Kế hoạch cá»§a bạn sẽ ÄÆ°á»£c má» khóa sau khi bạn chá»n các nhu cầu bảo hiá»m cá»§a mình" 8878 }, 8879 questions: { 8880 first: { 8881 "us": "How much additional coverage do you need?", 8882 "es": "¿Cuánta cobertura adicional necesitas?", 8883 "pt": "De quanta cobertura adicional você precisa?", 8884 "fr": "De combien de couverture supplémentaire avez-vous besoin ?", 8885 "nl": "Hoeveel extra dekking heeft u nodig?", 8886 "bg": "ÐÑ ÐºÐ¾Ð»ÐºÐ¾ допÑлниÑелно покÑиÑие Ñе нÑждаеÑе?", 8887 "cs": "Kolik dalÅ¡Ãho krytà potÅebujete?", 8888 "hr": "Koliko dodatne pokrivenosti trebate?", 8889 "da": "Hvor meget ekstra dækning har du brug for?", 8890 "de": "Wie viel zusätzliche Deckung benötigen Sie?", 8891 "et": "Kui palju lisakatet vajate?", 8892 "el": "Î ÏÏη εÏιÏλÎον ÎºÎ¬Î»Ï Ïη ÏÏειάζεÏÏε;", 8893 "he": "××× ××ס×× × ×סף ××ª× ×¦×¨××?", 8894 "it": "Di quanta copertura aggiuntiva hai bisogno?", 8895 "kk": "ÒоÑÑмÑа ÒанÑа ÒамÑÑ ÒажеÑ?", 8896 "lv": "Cik daudz papildu seguma jums nepiecieÅ¡ams?", 8897 "lt": "Kiek papildomos apsaugos jums reikia?", 8898 "hu": "Mennyi további fedezetre van szüksége?", 8899 "ar": "ÙÙ Ù Ù Ø§ÙØªØºØ·ÙØ© Ø§ÙØ¥Ø¶Ø§ÙÙØ© ØªØØªØ§Ø¬Ø", 8900 "no": "Hvor mye ekstra dekning trenger du?", 8901 "pl": "Ile dodatkowego pokrycia potrzebujesz?", 8902 "ro": "De câtÄ acoperire suplimentarÄ ai nevoie?", 8903 "sr": "Ðолико додаÑног покÑиÑа вам Ñе поÑÑебно?", 8904 "sk": "Koľko dodatoÄného krytia potrebujete?", 8905 "sl": "Koliko dodatnega kritja potrebujete?", 8906 "fi": "Kuinka paljon lisäsuojaa tarvitset?", 8907 "sv": "Hur mycket extra täckning behöver du?", 8908 "tr": "Ne kadar ek kapsamaya ihtiyacınız var?", 8909 "uk": "СкÑлÑки додаÑкового покÑиÑÑÑ Ð²Ð°Ð¼ поÑÑÑбно?", 8910 "zh": "æ¨éè¦å¤å°é¢å¤çä¿éï¼", 8911 "id": "Berapa banyak pertanggungan tambahan yang Anda butuhkan?", 8912 "ja": "ã©ããããã®è¿½å è£åãå¿ è¦ã§ããï¼", 8913 "ko": "ì¶ê° ë³´ì¥ì´ ì¼ë§ë íìíìëê¹?", 8914 "ms": "Berapakah perlindungan tambahan yang anda perlukan?", 8915 "fil": "Gaano karaming karagdagang saklaw ang kailangan mo?", 8916 "th": "à¸à¸¸à¸à¸à¹à¸à¸à¸à¸²à¸£à¸à¸§à¸²à¸¡à¸à¸¸à¹à¸¡à¸à¸£à¸à¸à¹à¸à¸´à¹à¸¡à¹à¸à¸´à¸¡à¹à¸à¹à¸²à¹à¸?", 8917 "vi": "Bạn cần bao nhiêu bảo hiá»m bá» sung?" 8918 } 8919 , 8920 second: { 8921 "us": "Pick your coverage type", 8922 "es": "Elige tu tipo de cobertura", 8923 "pt": "Escolha seu tipo de cobertura", 8924 "fr": "Choisissez votre type de couverture", 8925 "nl": "Kies uw dekkingssoort", 8926 "bg": "ÐзбеÑеÑе вида на покÑиÑиеÑо Ñи", 8927 "cs": "Vyberte typ krytÃ", 8928 "hr": "Odaberite vrstu pokriÄa", 8929 "da": "Vælg din dækningsstype", 8930 "de": "Wählen Sie Ihren Versicherungstyp", 8931 "et": "Valige oma katte tüüp", 8932 "el": "ÎÏιλÎξÏε Ïον ÏÏÏο ÎºÎ¬Î»Ï ÏÎ·Ï ÏαÏ", 8933 "he": "××ר ×ת ס×× ×××ס×× ×©××", 8934 "it": "Scegli il tuo tipo di copertura", 8935 "kk": "СаÒÑандÑÑÑ ÑÒ¯ÑÑн ÑаңдаңÑз", 8936 "lv": "IzvÄlieties savu seguma veidu", 8937 "lt": "Pasirinkite savo draudimo tipÄ ", 8938 "hu": "Válassza ki a fedezet tÃpusát", 8939 "ar": "اختر ÙÙØ¹ Ø§ÙØªØºØ·ÙØ© Ø§ÙØ®Ø§Øµ بÙ", 8940 "no": "Velg din dekningstype", 8941 "pl": "Wybierz swój typ ubezpieczenia", 8942 "ro": "AlegeÈi tipul de acoperire", 8943 "sr": "ÐзабеÑиÑе Ñип покÑиÑа", 8944 "sk": "Vyberte typ krytia", 8945 "sl": "Izberite vrsto kritja", 8946 "fi": "Valitse vakuutustyyppisi", 8947 "sv": "Välj din täckningstyp", 8948 "tr": "Kapsama türünüzü seçin", 8949 "uk": "ÐибеÑÑÑÑ Ñип покÑиÑÑÑ", 8950 "zh": "éæ©æ¨çä¿éç±»å", 8951 "id": "Pilih jenis pertanggungan Anda", 8952 "ja": "è£åã¿ã¤ãã鏿ãã¦ãã ãã", 8953 "ko": "ë³´ì¥ ì íì ì ííì¸ì", 8954 "ms": "Pilih jenis perlindungan anda", 8955 "fil": "Piliin ang uri ng saklaw mo", 8956 "th": "à¹à¸¥à¸·à¸à¸à¸à¸£à¸°à¹à¸ à¸à¸à¸§à¸²à¸¡à¸à¸¸à¹à¸¡à¸à¸£à¸à¸à¸à¸à¸à¸à¸¸à¸", 8957 "vi": "Chá»n loại bảo hiá»m cá»§a bạn" 8958 } 8959 , 8960 third: { 8961 "us": "Configure your protection options", 8962 "es": "Selecciona y configura tu opción de protección", 8963 "pt": "Selecione e configure sua opção de proteção", 8964 "fr": "Sélectionnez et configurez votre option de protection", 8965 "nl": "Selecteer en configureer uw beschermingsoptie", 8966 "bg": "ÐзбеÑеÑе и конÑигÑÑиÑайÑе ваÑаÑа опÑÐ¸Ñ Ð·Ð° заÑиÑа", 8967 "cs": "Vyberte a nakonfigurujte svou možnost ochrany", 8968 "hr": "Odaberite i konfigurirajte svoju opciju zaÅ¡tite", 8969 "da": "Vælg og konfigurer din beskyttelsesmulighed", 8970 "de": "Wählen und konfigurieren Sie Ihre Schutzoption", 8971 "et": "Valige ja seadistage oma kaitsevalik", 8972 "el": "ÎÏιλÎξÏε και διαμοÏÏÏÏÏε Ïην εÏιλογή ÏÏοÏÏαÏÎ¯Î±Ï ÏαÏ", 8973 "he": "××ר ××××ר ×ת ×פשר×ת ×××× × ×©××", 8974 "it": "Seleziona e configura la tua opzione di protezione", 8975 "kk": "ÒоÑÒÐ°Ñ Ð¾Ð¿ÑиÑÒ£ÑÐ·Ð´Ñ ÑаңдаңÑз жÓне бапÑаңÑз", 8976 "lv": "IzvÄlieties un konfigurÄjiet savu aizsardzÄ«bas opciju", 8977 "lt": "Pasirinkite ir sukonfigÅ«ruokite savo apsaugos parinktį", 8978 "hu": "Válassza ki és konfigurálja a védelmi lehetÅségét", 8979 "ar": "اختر ÙÙ٠بتÙÙÙÙ Ø®ÙØ§Ø± Ø§ÙØÙ Ø§ÙØ© Ø§ÙØ®Ø§Øµ بÙ", 8980 "no": "Velg og konfigurer ditt beskyttelsesalternativ", 8981 "pl": "Wybierz i skonfiguruj swojÄ opcjÄ ochrony", 8982 "ro": "SelectaÈi Èi configuraÈi opÈiunea dvs. de protecÈie", 8983 "sr": "ÐзабеÑиÑе и конÑигÑÑиÑиÑе ÑвоÑÑ Ð¾Ð¿ÑиÑÑ Ð·Ð°ÑÑиÑе", 8984 "sk": "Vyberte a nakonfigurujte svoju možnosÅ¥ ochrany", 8985 "sl": "Izberite in konfigurirajte svojo možnost zaÅ¡Äite", 8986 "fi": "Valitse ja määritä suojausvaihtoehtosi", 8987 "sv": "Välj och konfigurera ditt skyddsalternativ", 8988 "tr": "Koruma seçeneÄinizi seçin ve yapılandırın", 8989 "uk": "ÐибеÑÑÑÑ Ñ Ð½Ð°Ð»Ð°ÑÑÑйÑе ÑвÑй ваÑÑÐ°Ð½Ñ Ð·Ð°Ñ Ð¸ÑÑÑ", 8990 "zh": "鿩并é ç½®æ¨çä¿æ¤é项", 8991 "id": "Pilih dan konfigurasikan opsi perlindungan Anda", 8992 "ja": "ä¿è·ãªãã·ã§ã³ã鏿ãã¦æ§æãã¦ãã ãã", 8993 "ko": "ë³´í¸ ìµì ì ì ííê³ êµ¬ì±íì¸ì", 8994 "ms": "Pilih dan konfigurasikan pilihan perlindungan anda", 8995 "fil": "Piliin at i-configure ang iyong opsyon sa proteksyon", 8996 "th": "à¹à¸¥à¸·à¸à¸à¹à¸¥à¸°à¸à¸³à¸«à¸à¸à¸à¹à¸²à¸à¸±à¸§à¹à¸¥à¸·à¸à¸à¸à¸²à¸£à¸à¹à¸à¸à¸à¸±à¸à¸à¸à¸à¸à¸¸à¸", 8997 "vi": "Chá»n và cấu hình tùy chá»n bảo vá» cá»§a bạn" 8998 } 8999 }, 9000 footer: { 9001 totalPrice: { 9002 "us": "Total: ", 9003 "es": "Total: ", 9004 "pt": "Total: ", 9005 "fr": "Total: ", 9006 "nl": "Totaal: ", 9007 "bg": "ÐбÑо: ", 9008 "cs": "Celkem: ", 9009 "hr": "Ukupno: ", 9010 "da": "I alt: ", 9011 "de": "Gesamt: ", 9012 "et": "Kokku: ", 9013 "el": "ΣÏνολο: ", 9014 "he": " :ס×\"×", 9015 "it": "Totale: ",
9016 "kk": "ÐалпÑ: ", 9017 "lv": "KopÄ: ", 9018 "lt": "IÅ¡ viso: ", 9019 "hu": "Ãsszesen: ", 9020 "ar": " :Ø§ÙØ¥Ø¬Ù اÙÙ", 9021 "no": "Totalt: ", 9022 "pl": "Razem: ", 9023 "ro": "Total: ", 9024 "sr": "УкÑпно: ", 9025 "sk": "Spolu: ", 9026 "sl": "Skupaj: ", 9027 "fi": "Yhteensä: ", 9028 "sv": "Totalt: ", 9029 "tr": "Toplam: ", 9030 "uk": "Разом: ", 9031 "zh": "æ»è®¡: ", 9032 "id": "Total: ", 9033 "ja": "åè¨: ", 9034 "ko": "í©ê³: ", 9035 "ms": "Jumlah: ", 9036 "fil": "Kabuuan: ", 9037 "th": "รวม: ", 9038 "vi": "Tá»ng cá»ng: " 9039 }, 9040 cta: { 9041 "us": "View & purchase plan", 9042 "es": "Ver y comprar plan", 9043 "pt": "Visualizar e comprar plano", 9044 "fr": "Voir et acheter le plan", 9045 "nl": "Plan bekijken en kopen", 9046 "bg": "ÐÑеглед и закÑпÑване на план", 9047 "cs": "Zobrazit a zakoupit plán", 9048 "hr": "Pregledaj i kupi plan", 9049 "da": "Se og køb plan", 9050 "de": "Plan anzeigen und kaufen", 9051 "et": "Vaata ja osta plaan", 9052 "el": "Î Ïοβολή και αγοÏά ÏÎ»Î¬Î½Î¿Ï ", 9053 "he": "×¦×¤× ×ר××ש ת××× ×ת", 9054 "it": "Visualizza e acquista il piano", 9055 "kk": "ÐоÑпаÑÐ´Ñ ÒаÑÐ°Ñ Ð¶Óне ÑаÑÑп алÑ", 9056 "lv": "SkatÄ«t un iegÄdÄties plÄnu", 9057 "lt": "PeržiÅ«rÄti ir įsigyti planÄ ", 9058 "hu": "Terv megtekintése és vásárlása", 9059 "ar": "عرض ÙØ´Ø±Ø§Ø¡ Ø§ÙØ§Ø´ØªØ±Ø§Ù", 9060 "no": "Se og kjøp plan", 9061 "pl": "Zobacz i kup plan", 9062 "ro": "VizualizeazÄ Èi cumpÄrÄ planul", 9063 "sr": "ÐÑÐµÐ³Ð»ÐµÐ´Ð°Ñ Ð¸ кÑпи план", 9064 "sk": "ZobraziÅ¥ a zakúpiÅ¥ plán", 9065 "sl": "Ogled in nakup naÄrta", 9066 "fi": "Näytä ja osta suunnitelma", 9067 "sv": "Visa och köp plan", 9068 "tr": "Planı görüntüle ve satın al", 9069 "uk": "ÐеÑеглÑнÑÑи Ñа пÑидбаÑи план", 9070 "zh": "æ¥çå¹¶è´ä¹°è®¡å", 9071 "id": "Lihat dan beli paket", 9072 "ja": "ãã©ã³ã表示ãã¦è³¼å ¥", 9073 "ko": "ê³í 보기 ë° êµ¬ë§¤", 9074 "ms": "Lihat dan beli pelan", 9075 "fil": "Tingnan at bilhin ang plano", 9076 "th": "à¸à¸¹à¹à¸¥à¸°à¸à¸·à¹à¸à¹à¸à¸", 9077 "vi": "Xem và mua gói" 9078 }, 9079 currencies: { 9080 "us": '$%price%', 9081 "de": '€%price%', 9082 "ch": 'fr. %price%', 9083 "se": '%price% kr',
9084 "gb": '£%price%', 9085 "au": '$%price%', 9086 "ca": '$%price%', 9087 "cl": '$%price%', 9088 "in": 'â¹ %price%', 9089 "ar": '$ %price%', 9090 "my": 'RM %price%', 9091 "mx": '$%price%', 9092 "sg": '$%price%', 9093 "pe": 'S/.%price%', 9094 "hk": 'HK$ %price%', 9095 "kr": 'â© %price%', 9096 "za": 'R %price%', 9097 "vn": '%price% â«', 9098 "tw": 'å %price%', 9099 "tr": '%price% âº', 9100 "th": '%price% ฿', 9101 "sa": '%price% ï·¼', 9102 "ru": '%price% â½', 9103 "ro": '%price% RON', 9104 "pl": '%price% zÅ', 9105 "ph": 'â± %price%', 9106 "nz": '%price%', 9107 "no": 'kr %price%', 9108 "ma": '%price% .د.Ù .', 9109 "kp": 'â© %price%', 9110 "jp": 'Â¥ %price%', 9111 "il": '⪠%price%', 9112 "id": 'Rp %price%', 9113 "hu": '%price% Ft',
9114 "hr": '⬠%price%', 9115 "dk": 'kr. %price%', 9116 "cz": '%price% KÄ', 9117 "cn": 'Â¥ %price%', 9118 "br": 'R$ %price%', 9119 "bg": '%price% лв', 9120 "an": '⬠%price%' 9121 } 9122 } 9123 }, 9124 offerContent: { 9125 header: { 9126 "us": "Recommended Coverage Plan", 9127 "es": "Plan de cobertura recomendado", 9128 "pt": "Plano de cobertura recomendado", 9129 "fr": "Plan de couverture recommandé", 9130 "nl": "Aanbevolen dekking plan", 9131 "bg": "ÐÑепоÑÑÑиÑелен план за покÑиÑие", 9132 "cs": "DoporuÄený plán krytÃ", 9133 "hr": "PreporuÄeni plan pokrivanja", 9134 "da": "Anbefavar dækning plan", 9135 "de": "Empfohlener Deckungsplan", 9136 "et": "Soovitatud katteplaan", 9137 "el": "Î ÏοÏεινÏμενο ÏÏÎδιο ÎºÎ¬Î»Ï ÏηÏ", 9138 "he": "ת×× ×ת ××ס×× ××××צת", 9139 "it": "Piano di copertura consigliato", 9140 "kk": "Ò°ÑÑнÑлаÑÑн ÒамÑÑ Ð¶Ð¾ÑпаÑÑ", 9141 "lv": "Ieteicamais seguma plÄns", 9142 "lt": "Rekomenduojamas aprÄpties planas", 9143 "hu": "Ajánlott fedezeti terv", 9144 "ar": "Ø§Ø´ØªØ±Ø§Ù Ø§ÙØªØºØ·ÙØ© اÙÙ ÙØµÙ بÙ", 9145 "no": "Anbefalt dekning plan", 9146 "pl": "Zalecany plan pokrycia", 9147 "ro": "Plan de acoperire recomandat", 9148 "sr": "PreporuÄeni plan pokrivanja", 9149 "sk": "OdporúÄaný plán pokrytia", 9150 "sl": "PriporoÄeni naÄrt kritja", 9151 "fi": "Suositeltu kattavuussuunnitelma", 9152 "sv": "Rekommenderad täckningsplan", 9153 "tr": "Ãnerilen Kapsam Planı", 9154 "uk": "Рекомендований план покÑиÑÑÑ", 9155 "zh": "æ¨èä¿é计å", 9156 "id": "Rencana Perlindungan yang Disarankan", 9157 "ja": "æ¨å¥¨ä¿éºãã©ã³", 9158 "ko": "ì¶ì² ë³´ì¥ íë", 9159 "ms": "Pelan Perlindungan yang Disyorkan", 9160 "fil": "Inirerekomendang Plano ng Proteksyon", 9161 "th": "à¹à¸à¸à¸à¸²à¸£à¸à¸¸à¹à¸¡à¸à¸£à¸à¸à¸à¸µà¹à¹à¸à¸°à¸à¸³", 9162 "vi": "Kế hoạch bảo hiá»m ÄÆ°á»£c Äá» xuất" 9163 }, 9164 cta: { 9165 "us": "Shop now", 9166 "es": "Compra ahora", 9167 "pt": "Compre agora", 9168 "fr": "Achetez maintenant", 9169 "nl": "Koop nu", 9170 "bg": "ÐÑпи Ñега", 9171 "cs": "Kup nynÃ", 9172 "hr": "Kupite sada", 9173 "da": "Køb nu", 9174 "de": "Jetzt kaufen", 9175 "et": "Osta nüüd", 9176 "el": "ÎγοÏάÏÏε ÏÏÏα", 9177 "he": "×§× × ×¢×ש××", 9178 "it": "Acquista ora", 9179 "kk": "ÒазÑÑ ÑаÑÑп алÑÒ£Ñз", 9180 "lv": "PÄrc tagad", 9181 "lt": "Pirkite dabar", 9182 "hu": "Vásároljon most", 9183 "ar": "Ø§Ø´ØªØ±Ù Ø§ÙØ¢Ù", 9184 "no": "Kjøp nÃ¥", 9185 "pl": "Kup teraz", 9186 "ro": "CumpÄrÄ acum", 9187 "sr": "Kupite sada", 9188 "sk": "Kúp teraz", 9189 "sl": "Kupite zdaj", 9190 "fi": "Osta nyt", 9191 "sv": "Köp nu", 9192 "tr": "Hemen satın al", 9193 "uk": "ÐÑпиÑи заÑаз", 9194 "zh": "ç«å³è´ä¹°", 9195 "id": "Beli sekarang", 9196 "ja": "ä»ããè³¼å ¥", 9197 "ko": "ì§ê¸ 구매", 9198 "ms": "Beli sekarang", 9199 "fil": "Bumili ngayon", 9200 "th": "à¸à¸·à¹à¸à¹à¸¥à¸¢", 9201 "vi": "Mua ngay" 9202 } 9203 } 9204}; 9205 9206var HUQhardcodedContent = { 9207 tooltipsContent: { 9208 text: { 9209 "us": { 9210 "entertainment": { 9211 summary: 'Best for streaming, browsing, email, and social media.', 9212 benefits: [""], 9213 idealFor: "" 9214 }, 9215 "education": { 9216 summary: 'Best for creative, photo editing, creating documents, and more.â', 9217 benefits: [""], 9218 idealFor: "" 9219 }, 9220 "creativeTechnical": { 9221 summary: 'Best for word processing, spreadsheets, presentations, and video calls...', 9222 benefits: [""], 9223 idealFor: "" 9224 }, 9225 "business": { 9226 summary: 'Best for photo, video, and sound editing, large files, and more.â', 9227 benefits: [""], 9228 idealFor: "" 9229 }, 9230 "gaming": { 9231 summary: 'Best for avid gamers.â', 9232 benefits: [""], 9233 idealFor: "" 9234 } 9235 }, 9236 9237 9238 "es": { 9239 "entertainment": { 9240 summary: "Ideal para streaming, navegación, correo electrónico y redes sociales.", 9241 benefits: [""], 9242 idealFor: "" 9243 }, 9244 "education": { 9245 summary: "Ideal para actividades creativas, edición de fotos, creación de documentos y más.", 9246 benefits: [""], 9247 idealFor: "" 9248 }, 9249 "creativeTechnical": { 9250 summary: "Ideal para procesamiento de texto, hojas de cálculo, presentaciones y videollamadas...", 9251 benefits: [""], 9252 idealFor: "" 9253 }, 9254 "business": { 9255 summary: "Ideal para edición de fotos, videos y audio, archivos grandes y más.", 9256 benefits: [""], 9257 idealFor: "" 9258 }, 9259 "gaming": { 9260 summary: "Ideal para jugadores entusiastas.", 9261 benefits: [""], 9262 idealFor: "" 9263 } 9264 }, 9265 "pt": { 9266 "entertainment": { 9267 summary: "Ideal para streaming, navegação, email e redes sociais.", 9268 benefits: [""], 9269 idealFor: "" 9270 }, 9271 "education": { 9272 summary: "Ideal para atividades criativas, edição de fotos, criação de documentos e mais.", 9273 benefits: [""], 9274 idealFor: "" 9275 }, 9276 "creativeTechnical": { 9277 summary: "Ideal para processamento de texto, planilhas, apresentações e videochamadas...", 9278 benefits: [""], 9279 idealFor: "" 9280 }, 9281 "business": { 9282 summary: "Ideal para edição de fotos, vÃdeos e áudio, arquivos grandes e mais.", 9283 benefits: [""], 9284 idealFor: "" 9285 }, 9286 "gaming": { 9287 summary: "Ideal para jogadores apaixonados.", 9288 benefits: [""], 9289 idealFor: "" 9290 } 9291 }, 9292 "fr": { 9293 "entertainment": { 9294 summary: "Idéal pour le streaming, la navigation, les emails et les réseaux sociaux.", 9295 benefits: [""], 9296 idealFor: "" 9297 }, 9298 "education": { 9299 summary: "Idéal pour les activités créatives, la retouche photo, la création de documents et plus.", 9300 benefits: [""], 9301 idealFor: "" 9302 }, 9303 "creativeTechnical": { 9304 summary: "Idéal pour le traitement de texte, les tableur
9304s, les présentations et les appels vidéo...", 9305 benefits: [""], 9306 idealFor: "" 9307 }, 9308 "business": { 9309 summary: "Idéal pour la retouche photo, vidéo, audio, fichiers volumineux et plus.", 9310 benefits: [""], 9311 idealFor: "" 9312 }, 9313 "gaming": { 9314 summary: "Idéal pour les joueurs passionnés.", 9315 benefits: [""], 9316 idealFor: "" 9317 } 9318 }, 9319 "nl": { 9320 "entertainment": { 9321 summary: "Geschikt voor streaming, surfen, e-mail en sociale media.", 9322 benefits: [""], 9323 idealFor: "" 9324 }, 9325 "education": { 9326 summary: "Geschikt voor creatieve activiteiten, fotobewerking, documenten maken en meer.", 9327 benefits: [""], 9328 idealFor: "" 9329 }, 9330 "creativeTechnical": { 9331 summary: "Geschikt voor tekstverwerking, spreadsheets, presentaties en videogesprekken...", 9332 benefits: [""], 9333 idealFor: "" 9334 }, 9335 "business": { 9336 summary: "Geschikt voor foto-, video- en geluidsbewerking, grote bestanden en meer.", 9337 benefits: [""], 9338 idealFor: "" 9339 }, 9340 "gaming": { 9341 summary: "Geschikt voor fanatieke gamers.", 9342 benefits: [""], 9343 idealFor: "" 9344 } 9345 }, 9346 "bg": { 9347 "entertainment": { 9348 summary: "ÐÐ¾Ð´Ñ Ð¾Ð´ÑÑ Ð·Ð° ÑÑÑийминг, ÑÑÑÑиÑане, елекÑÑонна поÑа и ÑоÑиални мÑежи.", 9349 benefits: [""], 9350 idealFor: "" 9351 }, 9352 "education": { 9353 summary: "ÐÐ¾Ð´Ñ Ð¾Ð´ÑÑ Ð·Ð° ÑвоÑÑеÑки дейноÑÑи, ÑедакÑиÑане на Ñнимки, ÑÑздаване на докÑменÑи и дÑ.", 9354 benefits: [""], 9355 idealFor: "" 9356 }, 9357 "creativeTechnical": { 9358 summary: "ÐÐ¾Ð´Ñ Ð¾Ð´ÑÑ Ð·Ð° ÑекÑÑообÑабоÑка, елекÑÑонни ÑаблиÑи, пÑезенÑаÑии и видео ÑазговоÑи...", 9359 benefits: [""], 9360 idealFor: "" 9361 }, 9362 "business": { 9363 summary: "ÐÐ¾Ð´Ñ Ð¾Ð´ÑÑ Ð·Ð° ÑедакÑиÑане на Ñнимки, видео и звÑк, големи Ñайлове и дÑ.", 9364 benefits: [""], 9365 idealFor: "" 9366 }, 9367 "gaming": { 9368 summary: "ÐÐ¾Ð´Ñ Ð¾Ð´ÑÑ Ð·Ð° запалени геймÑÑи.", 9369 benefits: [""], 9370 idealFor: "" 9371 } 9372 }, 9373 "cs": { 9374 "entertainment": { 9375 summary: "Vhodné pro streamovánÃ, prohlÞenÃ, e-mail a sociálnà sÃtÄ.", 9376 benefits: [""], 9377 idealFor: "" 9378 }, 9379 "education": { 9380 summary: "Vhodné pro kreativnà Äinnosti, úpravu fotografiÃ, tvorbu dokumentů a dalÅ¡Ã.", 9381 benefits: [""], 9382 idealFor: "" 9383 }, 9384 "creativeTechnical": { 9385 summary: "Vhodné pro zpracovánà textu, tabulky, prezentace a videohovory...", 9386 benefits: [""], 9387 idealFor: "" 9388 }, 9389 "business": { 9390 summary: "Vhodné pro úpravu fotografiÃ, videa a zvuku, velké soubory a dalÅ¡Ã.", 9391 benefits: [""], 9392 idealFor: "" 9393 }, 9394 "gaming": { 9395 summary: "Vhodné pro vášnivé hráÄe.", 9396 benefits: [""], 9397 idealFor: "" 9398 } 9399 }, 9400 "hr": { 9401 "entertainment": { 9402 summary: "Najbolje za streaming, pregledavanje, e-poÅ¡tu i druÅ¡tvene mreže.", 9403 benefits: [""], 9404 idealFor: "" 9405 }, 9406 "education": { 9407 summary: "Najbolje za kreativne aktivnosti, ureÄivanje fotografija, izradu dokumenata i joÅ¡ mnogo toga.", 9408 benefits: [""], 9409 idealFor: "" 9410 }, 9411 "creativeTechnical": { 9412 summary: "Najbolje za obradu teksta, tablice, prezentacije i video pozive...", 9413 benefits: [""], 9414 idealFor: "" 9415 }, 9416 "business": { 9417 summary: "Najbolje za ureÄivanje fotografija, video i zvuka, velike datoteke i joÅ¡ mnogo toga.", 9418 benefits: [""], 9419 idealFor: "" 9420 }, 9421 "gaming": { 9422 summary: "Najbolje za strastvene igraÄe.", 9423 benefits: [""], 9424 idealFor: "" 9425 } 9426 }, 9427 "da": { 9428 "entertainment": { 9429 summary: "Bedst til streaming, browsing, e-mail og sociale medier.", 9430 benefits: [""], 9431 idealFor: "" 9432 }, 9433 "education": { 9434 summary: "Bedst til kreative aktiviteter, fotoredigering, oprettelse af dokumenter og mere.", 9435 benefits: [""], 9436 idealFor: "" 9437 }, 9438 "creativeTechnical": { 9439 summary: "Bedst til tekstbehandling, regneark, præsentationer og videoopkald...", 9440 benefits: [""], 9441 idealFor: "" 9442 }, 9443 "business": { 9444 summary: "Bedst til foto-, video- og lydredigering, store filer og mere.", 9445 benefits: [""], 9446 idealFor: "" 9447 }, 9448 "gaming": { 9449 summary: "Bedst til ivrige gamere.", 9450 benefits: [""], 9451 idealFor: "" 9452 } 9453 }, 9454 "de": { 9455 "entertainment": { 9456 summary: "Ideal zum Streaming, Surfen, E-Mail und sozialen Medien.", 9457 benefits: [""], 9458 idealFor: "" 9459 }, 9460 "education": { 9461 summary: "Ideal für kreative Tätigkeiten, Fotobearbeitung, Dokumentenerstellung und mehr.", 9462 benefits: [""], 9463 idealFor: "" 9464 }, 9465 "creativeTechnical": { 9466 summary: "Ideal für Textverarbeitung, Tabellenkalkulationen, Präsentationen und Videoanrufe...", 9467 benefits: [""], 9468 idealFor: "" 9469 }, 9470 "business": { 9471 summary: "Ideal für Foto-, Video- und Tonbearbeitung, groÃe Dateien und mehr.", 9472 benefits: [""], 9473 idealFor: "" 9474 }, 9475 "gaming": { 9476 summary: "Ideal für leidenschaftliche Gamer.", 9477 benefits: [""], 9478 idealFor: "" 9479 } 9480 }, 9481 "et": { 9482 "entertainment": { 9483 summary: "Parim voogedastuseks, sirvimiseks, e-postiks ja sotsiaalmeediaks.",
9484 benefits: [""], 9485 idealFor: "" 9486 }, 9487 "education": { 9488 summary: "Parim loominguliseks tööks, fototöötluseks, dokumentide loomiseks ja muuks.", 9489 benefits: [""], 9490 idealFor: "" 9491 }, 9492 "creativeTechnical": { 9493 summary: "Parim tekstiredigeerimiseks, tabelarvutuseks, esitluste ja videokõnede jaoks...", 9494 benefits: [""], 9495 idealFor: "" 9496 }, 9497 "business": { 9498 summary: "Parim fotode, videote ja heli redigeerimiseks, suurte failide töötlemiseks ja muuks.", 9499 benefits: [""], 9500 idealFor: "" 9501 }, 9502 "gaming": { 9503 summary: "Parim aktiivsetele mänguritele.", 9504 benefits: [""], 9505 idealFor: "" 9506 } 9507 }, 9508 "el": { 9509 "entertainment": { 9510 summary: "ÎαλÏÏεÏο για streaming, ÏεÏιήγηÏη, email και κοινÏνικά δίκÏÏ Î±.", 9511 benefits: [""], 9512 idealFor: "" 9513 }, 9514 "education": { 9515 summary: "ÎαλÏÏεÏο για Î´Î·Î¼Î¹Î¿Ï ÏγικÎÏ Î´ÏαÏÏηÏιÏÏηÏεÏ, εÏεξεÏγαÏία ÏÏÏογÏαÏιÏν, Î´Î·Î¼Î¹Î¿Ï Ïγία εγγÏάÏÏν και άλλα.", 9516 benefits: [""], 9517 idealFor: "" 9518 }, 9519 "creativeTechnical": { 9520 summary: "ÎαλÏÏεÏο για εÏεξεÏγαÏία κειμÎÎ½Î¿Ï , Ï ÏολογιÏÏικά ÏÏλλα, ÏαÏÎ¿Ï ÏιάÏÎµÎ¹Ï ÎºÎ±Î¹ βινÏεοκλήÏειÏ...", 9521 benefits: [""], 9522 idealFor: "" 9523 }, 9524 "business": { 9525 summary: "ÎαλÏÏεÏο για εÏεξεÏγαÏία ÏÏÏογÏαÏιÏν, βίνÏεο και ήÏÎ¿Ï , μεγάλα αÏÏεία και άλλα.", 9526 benefits: [""], 9527 idealFor: "" 9528 }, 9529 "gaming": { 9530 summary: "ÎαλÏÏεÏο για ÎµÎ½Î¸Î¿Ï ÏιÏÎ´ÎµÎ¹Ï ÏαίκÏεÏ.", 9531 benefits: [""], 9532 idealFor: "" 9533 } 9534 }, 9535 "he": { 9536 "entertainment": { 9537 summary: "××× ×ת××× ×ס×ר×××× ×, ×××ש×, ×××ר ×××§×ר×× × ×רשת×ת ××רת××ת.", 9538 benefits: [""], 9539 idealFor: "" 9540 }, 9541 "education": { 9542 summary: "××× ×ת××× ×פע×××××ת ×צ×רת××ת, ער××ת ת××× ×ת, ×צ×רת ×ס×××× ××¢××.", 9543 benefits: [""], 9544 idealFor: "" 9545 }, 9546 "creativeTechnical": { 9547 summary: "××× ×ת××× ××¢×××× ×ª××××××, ×××××× ×ת ×××§×ר×× ×××, ×צ××ת ×ש×××ת ×××××...", 9548 benefits: [""], 9549 idealFor: "" 9550 }, 9551 "business": { 9552 summary: "××× ×ת××× ×ער××ת ת××× ×ת, ×××××, ס××× ×, ×§×צ×× ×××××× ××¢××.", 9553 benefits: [""], 9554 idealFor: "" 9555 }, 9556 "gaming": { 9557 summary: "××× ×ת××× ×ש××§× ×× × ×××××.", 9558 benefits: [""], 9559 idealFor: "" 9560 } 9561 }, 9562 "it": { 9563 "entertainment": { 9564 summary: "Ideale per streaming, navigazione, email e social media.", 9565 benefits: [""], 9566 idealFor: "" 9567 }, 9568 "education": { 9569 summary: "Ideale per attività creative, fotoritocco, creazione di documenti e altro.", 9570 benefits: [""], 9571 idealFor: "" 9572 }, 9573 "creativeTechnical": { 9574 summary: "Ideale per elaborazione testi, fogli di calcolo, presentazioni e videochiamate...", 9575 benefits: [""], 9576 idealFor: "" 9577 }, 9578 "business": { 9579 summary: "Ideale per fotoritocco, video, audio, file di grandi dimensioni e altro.", 9580 benefits: [""], 9581 idealFor: "" 9582 }, 9583 "gaming": { 9584 summary: "Ideale per giocatori appassionati.", 9585 benefits: [""], 9586 idealFor: "" 9587 } 9588 }, 9589 "kk": { 9590 "entertainment": { 9591 summary: "ÐÒÑÐ½Ð´Ñ Ð²Ð¸Ð´ÐµÐ¾ көÑÑ, бÑаÑзинг, ÑлекÑÑондÑÒ Ð¿Ð¾ÑÑа жÓне ÓлеÑмеÑÑÑк желÑÐ»ÐµÑ Ò¯ÑÑн ең ÒолайлÑ.", 9592 benefits: [""], 9593 idealFor: "" 9594 }, 9595 "education": { 9596 summary: "ШÑÒаÑмаÑÑлÑÒ, ÑоÑоÑÑÑеÑÑеÑÐ´Ñ Ó©Ò£Ð´ÐµÑ, ÒұжаÑÑÐ°Ñ Ð¶Ð°ÑÐ°Ñ Ð¶Óне ÑаÒÑ Ð±Ð°ÑÒÐ°Ð»Ð°Ñ Ò¯ÑÑн ең ÒолайлÑ.", 9597 benefits: [""], 9598 idealFor: "" 9599 }, 9600 "creativeTechnical": { 9601 summary: "ÐÓÑÑндÑк ÒұжаÑÑаÑ, кеÑÑелеÑ, пÑезенÑаÑиÑÐ»Ð°Ñ Ð¶Óне бейнеконÑеÑенÑиÑÐ»Ð°Ñ Ò¯ÑÑн ең ÒолайлÑ...", 9602 benefits: [""], 9603 idealFor: "" 9604 }, 9605 "business": { 9606 summary: "ФоÑоÑÑÑеÑÑеÑдÑ, Ð²Ð¸Ð´ÐµÐ¾Ð½Ñ Ð¶Óне дÑбÑÑÑÑ Ó©Ò£Ð´ÐµÑ, үлкен ÑÐ°Ð¹Ð»Ð´Ð°Ñ Ð¶Óне ÑаÒÑ Ð±Ð°ÑÒÐ°Ð»Ð°Ñ Ò¯ÑÑн ең ÒолайлÑ.", 9607 benefits: [""], 9608 idealFor: "" 9609 }, 9610 "gaming": { 9611 summary: "ÐйÑн ÑÒ¯Ð¹ÐµÑ ÒаÑÑмÒа ең ÒолайлÑ.", 9612 benefits: [""], 9613 idealFor: "" 9614 } 9615 }, 9616 "lv": { 9617 "entertainment": { 9618 summary: "VislabÄk piemÄrots straumÄÅ¡anai, pÄrlÅ«koÅ¡anai, e-pastam un sociÄlajiem tÄ«kliem.", 9619 benefits: [""], 9620 idealFor: "" 9621 }, 9622 "education": { 9623 summary: "VislabÄk piemÄrots radoÅ¡Äm aktivitÄtÄm, foto rediÄ£ÄÅ¡anai, dokumentu veidoÅ¡anai un citÄm darbÄ«bÄm.", 9624 benefits: [""], 9625 idealFor: "" 9626 }, 9627 "creativeTechnical": { 9628 summary: "VislabÄk piemÄrots teksta apstrÄdei, izklÄjlapÄm, prezentÄcijÄm un videozvaniem...", 9629 benefits: [""], 9630 idealFor: "" 9631 }, 9632 "business": { 9633 summary: "VislabÄk piemÄrots foto, video un skaÅas rediÄ£ÄÅ¡anai, lieliem failiem un citÄm vajadzÄ«bÄm.", 9634 benefits: [""], 9635 idealFor: "" 9636 }, 9637 "gaming": { 9638 summary: "VislabÄk piemÄrots entuziastiskiem spÄlÄtÄjiem.", 9639 benefits: [""], 9640 idealFor: "" 9641 } 9642 }, 9643 "lt": { 9644 "entertainment": { 9645 summary: "Geriausia transliacijai, narÅ¡ymui, el. paÅ¡tui ir socialiniams tinklams.", 9646 benefits: [""], 9647 idealFor: "" 9648 }, 9649 "education": { 9650 summary: "Geriausia kÅ«rybai, nuotraukų redagavimui, dokumentų kÅ«rimui ir pan.", 9651 benefits: [""], 9652 idealFor: "" 9653 }, 9654 "creativeTechnical": { 9655 summary: "Geriausia tekstų redagavimui, lentelÄms, pristatymams ir vaizdo skambuÄiams...", 9656 benefits: [""], 9657 idealFor: "" 9658 }, 9659 "business": { 9660 summary: "Geriausia nuotraukų, vaizdo ir garso redagavimui, dideliems failams ir daugiau.", 9661 benefits: [""], 9662 idealFor: "" 9663 }, 9664 "gaming": { 9665 summary: "Geriausia aistringiems žaidÄjams.", 9666 benefits: [""], 9667 idealFor: "" 9668 } 9669 }, 9670 "hu": { 9671 "entertainment": { 9672 summary: "Legjobb streaminghez, böngészéshez, e-mailhez és közösségi médiához.", 9673 benefits: [""], 9674 idealFor: "" 9675 }, 9676 "education": { 9677 summary: "Legjobb kreatÃv tevékenységekhez, fényképszerkesztéshez, dokumentumkészÃtéshez és még sok máshoz.", 9678 benefits: [""], 9679 idealFor: "" 9680 }, 9681 "creativeTechnical": { 9682 summary: "Legjobb szövegszerkesztéshez, táblázatokhoz, prezentációkhoz és videóhÃvásokhoz...", 9683 benefits: [""], 9684 idealFor: "" 9685 }, 9686 "business": { 9687 summary: "Legjobb fénykép-, videó- és hangszerkesztéshez, nagy fájlokhoz és még sok máshoz.", 9688 benefits: [""], 9689 idealFor: "" 9690 }, 9691 "gaming": { 9692 summary: "Legjobb lelkes játékosoknak.",
9693 benefits: [""], 9694 idealFor: "" 9695 } 9696 }, 9697 "ar": { 9698 "entertainment": { 9699 summary: "Ø£ÙØ¶Ù ÙÙØ¨Ø«Ø Ø§ÙØªØµÙØØ Ø§ÙØ¨Ø±Ùد Ø§ÙØ¥ÙÙØªØ±ÙÙÙ ÙÙØ³Ø§Ø¦Ù Ø§ÙØªÙØ§ØµÙ Ø§ÙØ§Ø¬ØªÙ اعÙ.", 9700 benefits: [""], 9701 idealFor: "" 9702 }, 9703 "education": { 9704 summary: "Ø£ÙØ¶Ù ÙÙØ£Ùشطة Ø§ÙØ¥Ø¨Ø¯Ø§Ø¹ÙØ©Ø ØªØØ±Ùر Ø§ÙØµÙØ±Ø Ø¥ÙØ´Ø§Ø¡ اÙÙ Ø³ØªÙØ¯Ø§Øª ÙØ§ÙÙ Ø²ÙØ¯.", 9705 benefits: [""], 9706 idealFor: "" 9707 }, 9708 "creativeTechnical": { 9709 summary: "Ø£ÙØ¶Ù ÙÙ Ø¹Ø§ÙØ¬Ø© اÙÙØµÙØµØ Ø¬Ø¯Ø§ÙÙ Ø§ÙØ¨ÙØ§ÙØ§ØªØ Ø§ÙØ¹Ø±Ùض Ø§ÙØªÙدÙÙ ÙØ© ÙØ§ÙÙ ÙØ§Ù٠ات اÙÙÙØ¯ÙÙ...", 9710 benefits: [""], 9711 idealFor: "" 9712 }, 9713 "business": { 9714 summary: "Ø£ÙØ¶Ù ÙØªØØ±Ùر Ø§ÙØµÙØ±Ø Ø§ÙÙÙØ¯ÙÙØ Ø§ÙØµÙØªØ Ø§ÙÙ ÙÙØ§Øª اÙÙØ¨Ùرة ÙØ§ÙÙ Ø²ÙØ¯.", 9715 benefits: [""], 9716 idealFor: "" 9717 }, 9718 "gaming": { 9719 summary: "Ø£ÙØ¶Ù ÙÙØ§Ø¹Ø¨Ù٠اÙ٠تØÙ سÙÙ.", 9720 benefits: [""], 9721 idealFor: "" 9722 } 9723 }, 9724 "no": { 9725 "entertainment": { 9726 summary: "Best for streaming, surfing, e-mail and social media.", 9727 benefits: [""], 9728 idealFor: "" 9729 }, 9730 "education": { 9731 summary: "Best for creative activities, photo editing, document creation and more.", 9732 benefits: [""], 9733 idealFor: "" 9734 }, 9735 "creativeTechnical": { 9736 summary: "Best for word processing, spreadsheets, presentations and video calls...", 9737 benefits: [""], 9738 idealFor: "" 9739 }, 9740 "business": { 9741 summary: "Best for photo, video and sound editing, large files and more.", 9742 benefits: [""], 9743 idealFor: "" 9744 }, 9745 "gaming": { 9746 summary: "Best for avid gamers.", 9747 benefits: [""], 9748 idealFor: "" 9749 } 9750 }, 9751 "pl": { 9752 "entertainment": { 9753 summary: "Najlepsze do streamingu, przeglÄ dania, e-maila i mediów spoÅecznoÅciowych.", 9754 benefits: [""], 9755 idealFor: "" 9756 }, 9757 "education": { 9758 summary: "Najlepsze do dziaÅaÅ kreatywnych, edycji zdjÄÄ, tworzenia dokumentów i innych.", 9759 benefits: [""], 9760 idealFor: "" 9761 }, 9762 "creativeTechnical": { 9763 summary: "Najlepsze do edycji tekstu, arkuszy kalkulacyjnych, prezentacji i rozmów wideo...", 9764 benefits: [""], 9765 idealFor: "" 9766 }, 9767 "business": { 9768 summary: "Najlepsze do edycji zdjÄÄ, wideo, dźwiÄku, dużych plików i innych.", 9769 benefits: [""], 9770 idealFor: "" 9771 }, 9772 "gaming": { 9773 summary: "Najlepsze dla zapalonych graczy.", 9774 benefits: [""], 9775 idealFor: "" 9776 } 9777 }, 9778 "ro": { 9779 "entertainment": { 9780 summary: "Ideal pentru streaming, navigare, email Èi social media.", 9781 benefits: [""], 9782 idealFor: "" 9783 }, 9784 "education": { 9785 summary: "Ideal pentru activitÄÈi creative, editare foto, creare de documente Èi altele.", 9786 benefits: [""], 9787 idealFor: "" 9788 }, 9789 "creativeTechnical": { 9790 summary: "Ideal pentru procesare text, foi de calcul, prezentÄri Èi apeluri video...", 9791 benefits: [""], 9792 idealFor: "" 9793 }, 9794 "business": { 9795 summary: "Ideal pentru editare foto, video Èi sunet, fiÈiere mari Èi altele.", 9796 benefits: [""], 9797 idealFor: "" 9798 }, 9799 "gaming": { 9800 summary: "Ideal pentru jucÄtori pasionaÈi.", 9801 benefits: [""], 9802 idealFor: "" 9803 } 9804 }, 9805 "sr": { 9806 "entertainment": { 9807 summary: "Najbolje za striming, pretraživanje, e-poÅ¡tu i druÅ¡tvene mreže.", 9808 benefits: [""], 9809 idealFor: "" 9810 }, 9811 "education": { 9812 summary: "Najbolje za kreativne aktivnosti, ureÄivanje fotografija, pravljenje dokumenata i joÅ¡ mnogo toga.", 9813 benefits: [""], 9814 idealFor: "" 9815 }, 9816 "creativeTechnical": { 9817 summary: "Najbolje za obradu teksta, tabele, prezentacije i video pozive...", 9818 benefits: [""], 9819 idealFor: "" 9820 }, 9821 "business": { 9822 summary: "Najbolje za ureÄivanje fotografija, videa, zvuka, velikih fajlova i joÅ¡ mnogo toga.", 9823 benefits: [""], 9824 idealFor: "" 9825 }, 9826 "gaming": { 9827 summary: "Najbolje za strastvene gejmere.", 9828 benefits: [""], 9829 idealFor: "" 9830 } 9831 }, 9832 "sk": { 9833 "entertainment": { 9834 summary: "NajlepÅ¡ie na streamovanie, prehliadanie, e-maily a sociálne siete.", 9835 benefits: [""], 9836 idealFor: "" 9837 }, 9838 "education": { 9839 summary: "NajlepÅ¡ie na tvorivé aktivity, úpravu fotiek, tvorbu dokumentov a ÄalÅ¡ie.", 9840 benefits: [""], 9841 idealFor: "" 9842 }, 9843 "creativeTechnical": { 9844 summary: "NajlepÅ¡ie na spracovanie textov, tabuľky, prezentácie a videohovory...", 9845 benefits: [""], 9846 idealFor: "" 9847 }, 9848 "business": { 9849 summary: "NajlepÅ¡ie na úpravu fotiek, videà a zvukov, veľkých súborov a ÄalÅ¡ie.", 9850 benefits: [""], 9851 idealFor: "" 9852 }, 9853 "gaming": {
9854 summary: "NajlepÅ¡ie pre zapálených hráÄov.", 9855 benefits: [""], 9856 idealFor: "" 9857 } 9858 }, 9859 "sl": { 9860 "entertainment": { 9861 summary: "Najbolje za pretakanje, brskanje, e-poÅ¡to in družbena omrežja.", 9862 benefits: [""], 9863 idealFor: "" 9864 }, 9865 "education": { 9866 summary: "Najbolje za ustvarjalne dejavnosti, urejanje fotografij, ustvarjanje dokumentov in drugo.", 9867 benefits: [""], 9868 idealFor: "" 9869 }, 9870 "creativeTechnical": { 9871 summary: "Najbolje za urejanje besedil, preglednic, predstavitev in video klice...", 9872 benefits: [""], 9873 idealFor: "" 9874 }, 9875 "business": { 9876 summary: "Najbolje za urejanje fotografij, videov in zvoka, velike datoteke in drugo.", 9877 benefits: [""], 9878 idealFor: "" 9879 }, 9880 "gaming": { 9881 summary: "Najbolje za strastne igralce.", 9882 benefits: [""], 9883 idealFor: "" 9884 } 9885 }, 9886 "fi": { 9887 "entertainment": { 9888 summary: "Paras suoratoistoon, selaamiseen, sähköpostiin ja sosiaaliseen mediaan.", 9889 benefits: [""], 9890 idealFor: "" 9891 }, 9892 "education": { 9893 summary: "Paras luovaan toimintaan, valokuvien muokkaamiseen, asiakirjojen luomiseen ja muuhun.", 9894 benefits: [""], 9895 idealFor: "" 9896 }, 9897 "creativeTechnical": { 9898 summary: "Paras tekstinkäsittelyyn, taulukoihin, esityksiin ja videopuheluihin...", 9899 benefits: [""], 9900 idealFor: "" 9901 }, 9902 "business": { 9903 summary: "Paras valokuvien, videoiden ja äänen muokkaukseen, suuriin tiedostoihin ja muuhun.", 9904 benefits: [""], 9905 idealFor: "" 9906 }, 9907 "gaming": { 9908 summary: "Paras innokkaille pelaajille.", 9909 benefits: [""], 9910 idealFor: "" 9911 } 9912 }, 9913 "sv": { 9914 "entertainment": { 9915 summary: "Bäst för streaming, surfning, e-post och sociala medier.", 9916 benefits: [""], 9917 idealFor: "" 9918 }, 9919 "education": { 9920 summary: "Bäst för kreativa aktiviteter, fotoredigering, dokumentskapande och mer.", 9921 benefits: [""], 9922 idealFor: "" 9923 }, 9924 "creativeTechnical": { 9925 summary: "Bäst för ordbehandling, kalkylblad, presentationer och videosamtal...", 9926 benefits: [""], 9927 idealFor: "" 9928 }, 9929 "business": { 9930 summary: "Bäst för foto-, video- och ljudredigering, stora filer och mer.", 9931 benefits: [""], 9932 idealFor: "" 9933 }, 9934 "gaming": { 9935 summary: "Bäst för hängivna spelare.", 9936 benefits: [""], 9937 idealFor: "" 9938 } 9939 }, 9940 "tr": { 9941 "entertainment": { 9942 summary: "AkıÅ, gezinme, e-posta ve sosyal medya için en iyisi.", 9943 benefits: [""], 9944 idealFor: "" 9945 }, 9946 "education": { 9947 summary: "Yaratıcı aktiviteler, fotoÄraf düzenleme, belge oluÅturma ve daha fazlası için en iyisi.", 9948 benefits: [""], 9949 idealFor: "" 9950 }, 9951 "creativeTechnical": { 9952 summary: "Kelime iÅlem, hesap tabloları, sunumlar ve video aramaları için en iyisi...", 9953 benefits: [""], 9954 idealFor: "" 9955 }, 9956 "business": { 9957 summary: "FotoÄraf, video ve ses düzenleme, büyük dosyalar ve daha fazlası için en iyisi.", 9958 benefits: [""], 9959 idealFor: "" 9960 }, 9961 "gaming": { 9962 summary: "Tutkulu oyuncular için en iyisi.", 9963 benefits: [""], 9964 idealFor: "" 9965 } 9966 }, 9967 "uk": { 9968 "entertainment": { 9969 summary: "ÐайкÑаÑе Ð´Ð»Ñ Ð¿Ð¾Ñокового пеÑеглÑдÑ, пеÑеглÑÐ´Ñ Ð²ÐµÐ±-ÑÑоÑÑнок, елекÑÑÐ¾Ð½Ð½Ð¾Ñ Ð¿Ð¾ÑÑи Ñа ÑоÑÑалÑÐ½Ð¸Ñ Ð¼ÐµÑеж.", 9970 benefits: [""], 9971 idealFor: "" 9972 }, 9973 "education": { 9974 summary: "ÐайкÑаÑе Ð´Ð»Ñ ÑвоÑÑÐ¸Ñ Ð·Ð°Ð²Ð´Ð°Ð½Ñ, ÑедагÑÐ²Ð°Ð½Ð½Ñ ÑоÑо, ÑÑвоÑÐµÐ½Ð½Ñ Ð´Ð¾ÐºÑменÑÑв Ñа ÑнÑого.", 9975 benefits: [""], 9976 idealFor: "" 9977 }, 9978 "creativeTechnical": { 9979 summary: "ÐайкÑаÑе Ð´Ð»Ñ Ð¾Ð±Ñобки ÑекÑÑÑв, елекÑÑÐ¾Ð½Ð½Ð¸Ñ ÑаблиÑÑ, пÑезенÑаÑÑй Ñ Ð²ÑдеодзвÑнкÑв...", 9980 benefits: [""], 9981 idealFor: "" 9982 }, 9983 "business": { 9984 summary: "ÐайкÑаÑе Ð´Ð»Ñ ÑедагÑÐ²Ð°Ð½Ð½Ñ ÑоÑо, вÑдео, звÑкÑ, Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ ÑайлÑв Ñа ÑнÑого.", 9985 benefits: [""], 9986 idealFor: "" 9987 }, 9988 "gaming": { 9989 summary: "ÐайкÑаÑе Ð´Ð»Ñ Ð·Ð°Ð²Ð·ÑÑÐ¸Ñ Ð³ÑавÑÑв.", 9990 benefits: [""], 9991 idealFor: "" 9992 } 9993 }, 9994 "zh": { 9995 "entertainment": { 9996 summary: "æéåæµåªä½ãæµè§ãçµåé®ä»¶å社交åªä½ã", 9997 benefits: [""], 9998 idealFor: "" 9999 }, 10000 "education": { 10001 summary: "æéååææ´»å¨ãç §çç¼è¾ãåå»ºææ¡£çã", 10002 benefits: [""], 10003 idealFor: "" 10004 }, 10005 "creativeTechnical": { 10006 summary: "æéåæåå¤çãçµåè¡¨æ ¼ãæ¼ç¤ºæç¨¿åè§é¢éè¯...", 10007 benefits: [""], 10008 idealFor: "" 10009 }, 10010 "business": { 10011 summary: "æéåç §çãè§é¢åé³é¢ç¼è¾ï¼å¤§æä»¶çã", 10012 benefits: [""], 10013 idealFor: "" 10014 }, 10015 "gaming": { 10016 summary: "æéåççç©å®¶ã", 10017 benefits: [""], 10018 idealFor: "" 10019 } 10020 } 10021 10022 , 10023 "id": { 10024 "entertainment": { 10025 summary: "Terbaik untuk streaming, browsing, email, dan media s
10025osial.", 10026 benefits: [""], 10027 idealFor: "" 10028 }, 10029 "education": { 10030 summary: "Terbaik untuk kreativitas, pengeditan foto, membuat dokumen, dan lainnya.", 10031 benefits: [""], 10032 idealFor: "" 10033 }, 10034 "creativeTechnical": { 10035 summary: "Terbaik untuk pengolahan kata, spreadsheet, presentasi, dan panggilan video.", 10036 benefits: [""], 10037 idealFor: "" 10038 }, 10039 "business": { 10040 summary: "Terbaik untuk pengeditan foto, video, suara, file besar, dan lainnya.", 10041 benefits: [""], 10042 idealFor: "" 10043 }, 10044 "gaming": { 10045 summary: "Terbaik untuk para gamer berat.", 10046 benefits: [""], 10047 idealFor: "" 10048 } 10049 }, 10050 "ja": { 10051 "entertainment": { 10052 summary: "ã¹ããªã¼ãã³ã°ããã©ã¦ã¸ã³ã°ãã¡ã¼ã«ãã½ã¼ã·ã£ã«ã¡ãã£ã¢ã«æé©ã§ãã", 10053 benefits: [""], 10054 idealFor: "" 10055 }, 10056 "education": { 10057 summary: "ã¯ãªã¨ã¤ãã£ããåçç·¨éãããã¥ã¡ã³ã使ãªã©ã«æé©ã§ãã", 10058 benefits: [""], 10059 idealFor: "" 10060 }, 10061 "creativeTechnical": { 10062 summary: "ã¯ã¼ãããã»ãã·ã³ã°ãã¹ãã¬ããã·ã¼ãããã¬ã¼ã³ãã¼ã·ã§ã³ããããªéè©±ã«æé©ã§ãã", 10063 benefits: [""], 10064 idealFor: "" 10065 }, 10066 "business": { 10067 summary: "åçããããªãé³å£°ç·¨éã大容éãã¡ã¤ã«ãªã©ã«æé©ã§ãã", 10068 benefits: [""], 10069 idealFor: "" 10070 }, 10071 "gaming": { 10072 summary: "ç±å¿ãªã²ã¼ãã¼ã«æé©ã§ãã", 10073 benefits: [""], 10074 idealFor: "" 10075 } 10076 }, 10077 "ko": { 10078 "entertainment": { 10079 summary: "ì¤í¸ë¦¬ë°, ë¸ë¼ì°ì§, ì´ë©ì¼ ë° ìì 미ëì´ì ê°ì¥ ì í©í©ëë¤.", 10080 benefits: [""], 10081 idealFor: "" 10082 }, 10083 "education": { 10084 summary: "ì°½ì, ì¬ì§ í¸ì§, 문ì ìì± ë±ì ê°ì¥ ì í©í©ëë¤.", 10085 benefits: [""], 10086 idealFor: "" 10087 }, 10088 "creativeTechnical": { 10089 summary: "ìë íë¡ì¸ì±, ì¤íë ëìí¸, íë ì í ì´ì ë° íì íµíì ê°ì¥ ì í©í©ëë¤.", 10090 benefits: [""], 10091 idealFor: "" 10092 }, 10093 "business": { 10094 summary: "ì¬ì§, ë¹ëì¤, ì¬ì´ë í¸ì§, ëì©ë íì¼ ë±ì ê°ì¥ ì í©í©ëë¤.", 10095 benefits: [""], 10096 idealFor: "" 10097 }, 10098 "gaming": { 10099 summary: "ì´ì± ê²ì´ë¨¸ìê² ê°ì¥ ì í©í©ëë¤.", 10100 benefits: [""], 10101 idealFor: "" 10102 } 10103 }, 10104 "ms": { 10105 "entertainment": { 10106 summary: "Terbaik untuk penstriman, pelayaran, emel, dan media sosial.", 10107 benefits: [""], 10108 idealFor: "" 10109 }, 10110 "education": { 10111 summary: "Terbaik untuk kreativiti, penyuntingan foto, membuat dokumen, dan lain-lain.", 10112 benefits: [""], 10113 idealFor: "" 10114 }, 10115 "creativeTechnical": { 10116 summary: "Terbaik untuk pemprosesan kata, hamparan, pembentangan, dan panggilan video.", 10117 benefits: [""], 10118 idealFor: "" 10119 }, 10120 "business": { 10121 summary: "Terbaik untuk penyuntingan foto, video, bunyi, fail besar, dan lain-lain.",
10122 benefits: [""], 10123 idealFor: "" 10124 }, 10125 "gaming": { 10126 summary: "Terbaik untuk pemain tegar.", 10127 benefits: [""], 10128 idealFor: "" 10129 } 10130 }, 10131 "fil": { 10132 "entertainment": { 10133 summary: "Pinakamainam para sa streaming, pag-browse, email, at social media.", 10134 benefits: [""], 10135 idealFor: "" 10136 }, 10137 "education": { 10138 summary: "Pinakamainam para sa malikhaing gawain, pag-edit ng larawan, paggawa ng dokumento, at iba pa.", 10139 benefits: [""], 10140 idealFor: "" 10141 }, 10142 "creativeTechnical": { 10143 summary: "Pinakamainam para sa word processing, spreadsheets, presentasyon, at video calls.", 10144 benefits: [""], 10145 idealFor: "" 10146 }, 10147 "business": { 10148 summary: "Pinakamainam para sa pag-edit ng larawan, video, tunog, malalaking file, at iba pa.", 10149 benefits: [""], 10150 idealFor: "" 10151 }, 10152 "gaming": { 10153 summary: "Pinakamainam para sa mga mahilig maglaro.", 10154 benefits: [""], 10155 idealFor: "" 10156 } 10157 }, 10158 "th": { 10159 "entertainment": { 10160 summary: "à¹à¸«à¸¡à¸²à¸°à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸²à¸£à¸ªà¸à¸£à¸µà¸¡à¸¡à¸´à¹à¸, à¸à¸²à¸£à¸à¹à¸à¸à¹à¸§à¹à¸, à¸à¸µà¹à¸¡à¸¥ à¹à¸¥à¸°à¹à¸à¹à¸à¸µà¸¢à¸¥à¸¡à¸µà¹à¸à¸µà¸¢", 10161 benefits: [""], 10162 idealFor: "" 10163 }, 10164 "education": { 10165 summary: "à¹à¸«à¸¡à¸²à¸°à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸²à¸à¸ªà¸£à¹à¸²à¸à¸ªà¸£à¸£à¸à¹, à¸à¸²à¸£à¹à¸à¹à¹à¸à¸ าà¸à¸à¹à¸²à¸¢, à¸à¸²à¸£à¸ªà¸£à¹à¸²à¸à¹à¸à¸à¸ªà¸²à¸£ à¹à¸¥à¸°à¸à¸·à¹à¸à¹", 10166 benefits: [""], 10167 idealFor: "" 10168 }, 10169 "creativeTechnical": { 10170 summary: "à¹à¸«à¸¡à¸²à¸°à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸²à¸£à¸à¸£à¸°à¸¡à¸§à¸¥à¸à¸¥à¸à¸³, สà¹à¸à¸£à¸à¸à¸µà¸, à¸à¸²à¸£à¸à¸³à¹à¸ªà¸à¸ à¹à¸¥à¸°à¸à¸²à¸£à¹à¸à¸£à¸§à¸´à¸à¸µà¹à¸", 10171 benefits: [""], 10172 idealFor: "" 10173 }, 10174 "business": { 10175 summary: "à¹à¸«à¸¡à¸²à¸°à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸²à¸£à¹à¸à¹à¹à¸à¸ าà¸, วิà¸à¸µà¹à¸, à¹à¸ªà¸µà¸¢à¸, à¹à¸à¸¥à¹à¸à¸à¸²à¸à¹à¸«à¸à¹ à¹à¸¥à¸°à¸à¸·à¹à¸à¹", 10176 benefits: [""], 10177 idealFor: "" 10178 }, 10179 "gaming": { 10180 summary: "à¹à¸«à¸¡à¸²à¸°à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸±à¸à¹à¸¥à¹à¸à¹à¸à¸¡à¸à¸±à¸§à¸¢à¸", 10181 benefits: [""], 10182 idealFor: "" 10183 } 10184 }, 10185 "vi": { 10186 "entertainment": { 10187 summary: "Tá»t nhất cho phát trá»±c tuyến, duyá»t web, email và mạng xã há»i.", 10188 benefits: [""], 10189 idealFor: "" 10190 }, 10191 "education": { 10192 summary: "Tá»t nhất cho sáng tạo, chá»nh sá»a ảnh, tạo tà i liá»u và nhiá»u hÆ¡n nữa.", 10193 benefits: [""], 10194 idealFor: "" 10195 }, 10196 "creativeTechnical": { 10197 summary: "Tá»t nhất cho xá» lý vÄn bản, bảng tÃnh, thuyết trình và gá»i video.", 10198 benefits: [""], 10199 idealFor: "" 10200 }, 10201 "business": { 10202 summary: "Tá»t nhất cho chá»nh sá»a ảnh, video, âm thanh, file lá»n và nhiá»u hÆ¡n nữa.", 10203 benefits: [""], 10204 idealFor: "" 10205 }, 10206 "gaming": { 10207 summary: "Tá»t nhất cho game thá»§ nhiá»t huyết.", 10208 benefits: [""], 10209 idealFor: "" 10210 } 10211 } 10212 10213 }, 10214 prefix: { 10215 "us": "Ideal for: ", 10216 "es": "Ideal para: ", 10217 "pt": "Ideal para: ", 10218 "fr": "Idéal pour : ", 10219 "nl": "Ideaal voor: ", 10220 "bg": "ÐÐ¾Ð´Ñ Ð¾Ð´ÑÑ Ð·Ð°: ", 10221 "cs": "Ideálnà pro: ", 10222 "hr": "Idealno za: ", 10223 "da": "Ideel til: ", 10224 "de": "Ideal für: ", 10225 "et": "Ideaalne: ", 10226 "el": "ÎÎ´Î±Î½Î¹ÎºÏ Î³Î¹Î±: ", 10227 "he": "××××××× ×¢××ר: ", 10228 "it": "Ideale per: ", 10229 "kk": "Ò®ÑÑн ÒолайлÑ: ", 10230 "lv": "IdeÄli piemÄrots: ", 10231 "lt": "Idealiai tinka: ", 10232 "hu": "Ideális erre: ", 10233 "ar": "٠ثاÙÙ ÙÙ: ", 10234 "no": "Ideell for: ", 10235 "pl": "Idealne dla: ", 10236 "ro": "Ideal pentru: ", 10237 "sr": "Ðдеално за: ", 10238 "sk": "Ideálne pre: ", 10239 "sl": "Idealno za: ", 10240 "fi": "Ihanteellinen: ", 10241 "sv": "Perfekt för: ", 10242 "tr": "İdeal olan: ", 10243 "uk": "ÐдеалÑно длÑ: ", 10244 "zh": "éç¨äºï¼", 10245 "id": "Ideal untuk: ", 10246 "ja": "ãã«æé©ï¼", 10247 "ko": "ì´ìì ì: ", 10248 "ms": "Sesuai untuk: ", 10249 "fil": "Mainam para sa: ", 10250 "th": "à¹à¸«à¸¡à¸²à¸°à¸ªà¸³à¸«à¸£à¸±à¸: ", 10251 "vi": "Lý tưá»ng cho: " 10252 } 10253 }, 10254 quizEntryContent: { 10255 header: { 10256 "us": "var HP Recommend a new PC for you", 10257 "es": "Deja que HP te recomiende un nuevo PC", 10258 "pt": "Deixe a HP recomendar um novo PC para você", 10259 "fr": "Laissez HP vous recommander un nouveau PC", 10260 "nl": "Laat HP een nieuwe pc voor je aanbevelen", 10261 "bg": "Ðека HP ви пÑепоÑÑÑа нов компÑÑÑÑ", 10262 "cs": "Nechte HP doporuÄit nový poÄÃtaÄ pro vás", 10263 "hr": "Neka HP preporuÄi novo raÄunalo za vas", 10264 "da": "Lad HP anbefale en ny pc til dig", 10265 "de": "Lassen Sie HP einen neuen PC für Sie empfehlen", 10266 "et": "Lase HP-l soovitada sulle uus arvuti", 10267 "el": "ÎÏήÏÏε Ïην HP να ÏÎ±Ï ÏÏοÏείνει Îναν νÎο Ï ÏολογιÏÏή", 10268 "he": "×ª× ×-HP ××××××¥ ×¢× ×××©× ××ש ×¢××ר×", 10269 "it": "Lascia che HP ti consigli un nuovo PC", 10270 "kk": "HP ÑÑзге жаңа ÐÐ Ò±ÑÑнÑÑн", 10271 "lv": "Ä»aujiet HP ieteikt jums jaunu datoru", 10272 "lt": "Leiskite HP rekomenduoti jums naujÄ kompiuterį", 10273 "hu": "Hagyja, hogy a HP új számÃtógépet ajánljon Ãnnek", 10274 "ar": "دع HP ØªÙØµÙ Ø¨Ø¬ÙØ§Ø² Ù٠بÙÙØªØ± Ø¬Ø¯ÙØ¯ ÙÙ", 10275 "no": "La HP anbefale en ny PC for deg", 10276 "pl": "Pozwól HP poleciÄ nowy komputer dla Ciebie", 10277 "ro": "PermiteÈi HP sÄ vÄ recomande un nou PC", 10278 "sr": "Neka HP preporuÄi novi raÄunar za vas", 10279 "sk": "Nechajte HP odporuÄiÅ¥ vám nový poÄÃtaÄ", 10280 "sl": "Naj HP priporoÄi nov raÄunalnik za vas", 10281 "fi": "Anna HP:n suositella sinulle uutta tietokonetta", 10282 "sv": "LÃ¥t HP rekommendera en ny dator för dig", 10283 "tr": "HP'nin size yeni bir bilgisayar önermesine izin verin", 10284 "uk": "ÐозволÑÑе HP ÑекомендÑваÑи вам новий ÐÐ", 10285 "zh": "让 HP ä¸ºæ¨æ¨èä¸å°æ°çµè", 10286 "id": "Biarkan HP merekomendasikan PC baru untuk Anda", 10287 "ja": "HP ã«æ°ãã PC ãããããããã¾ããã", 10288 "ko": "HPê° ìë¡ì´ PC를 ì¶ì²í´ ëë¦¬ê² ìµëë¤", 10289 "ms": "Biarkan HP mencadangkan PC baharu untuk anda", 10290 "fil": "Hayaan ang HP na magrekomenda ng bagong PC para sa iyo", 10291 "th": "à¹à¸«à¹ HP à¹à¸à¸°à¸à¸³à¸à¸µà¸à¸µà¹à¸«à¸¡à¹à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸¸à¸", 10292 "vi": "Hãy Äá» HP Äá» xuất cho bạn má»t máy tÃnh má»i" 10293 }, 10294 description: { 10295 "us": "Answer 3 questions and var HP find it for you.", 10296 "es": "Responde 3 preguntas y deja que HP lo encuentre por ti.", 10297 "pt": "Responda a 3 perguntas e deixe a HP encontrá-lo para você.", 10298 "fr": "Répondez à 3 questions et laissez HP le trouver pour vous.", 10299 "nl": "Beantwoord 3 vragen en laat HP het voor je vinden.", 10300 "bg": "ÐÑговоÑеÑе на 3 вÑпÑоÑа и оÑÑавеÑе HP да го намеÑи за ваÑ.", 10301 "cs": "OdpovÄzte na 3 otázky a nechte HP to najÃt za vás.", 10302 "hr": "Odgovorite na 3 pitanja i neka HP to pronaÄe za vas.", 10303 "da": "Besvar 3 spørgsmÃ¥l, og lad HP finde det for dig.", 10304 "de": "Beantworten Sie 3 Fragen und lassen Sie HP es für Sie finden.", 10305 "et": "Vasta 3 küsimusele ja lase HP-l see sinu jaoks leida.", 10306 "el": "ÎÏανÏήÏÏε Ïε 3 εÏÏÏήÏÎµÎ¹Ï ÎºÎ±Î¹ αÏήÏÏε Ïην HP να Ïο βÏει για εÏάÏ.", 10307 "he": "×¢× × ×¢× 3 ש×××ת ××ª× ×-HP ××צ×× ×ת ×× ×¢××ר×.", 10308 "it": "Rispondi a 3 domande e lascia che HP lo trovi per te.", 10309 "kk": "3 ÑÒ±ÑаÒÒа жаÑап беÑÑÒ£Ñз, HP Ð¾Ð½Ñ ÑÑз Ò¯ÑÑн ÑапÑÑн.", 10310 "lv": "Atbildiet uz 3 jautÄjumiem un ļaujiet HP to atrast jums.", 10311 "lt": "Atsakykite į 3 klausimus ir leiskite HP tai rasti jums.",
10312 "hu": "Válaszoljon 3 kérdésre, és hagyja, hogy a HP megtalálja azt Ãnnek.", 10313 "ar": "أجب ع٠3 Ø£Ø³Ø¦ÙØ© ÙØ¯Ø¹ HP ÙØ¬Ø¯Ùا ÙÙ.", 10314 "no": "Svar pÃ¥ 3 spørsmÃ¥l, og la HP finne det for deg.", 10315 "pl": "Odpowiedz na 3 pytania i pozwól HP znaleÅºÄ to dla Ciebie.", 10316 "ro": "RÄspundeÈi la 3 întrebÄri Èi lÄsaÈi HP sÄ o gÄseascÄ pentru dvs.", 10317 "sr": "Odgovorite na 3 pitanja i neka HP to pronaÄe za vas.", 10318 "sk": "Odpovedzte na 3 otázky a nechajte HP, aby to naÅ¡la za vás.", 10319 "sl": "Odgovorite na 3 vpraÅ¡anja in dovolite, da HP to najde za vas.", 10320 "fi": "Vastaa 3 kysymykseen ja anna HP:n löytää se sinulle.", 10321 "sv": "Svara pÃ¥ 3 frÃ¥gor och lÃ¥t HP hitta det Ã¥t dig.", 10322 "tr": "3 soruyu yanıtlayın ve HP'nin sizin için bulmasına izin verin.", 10323 "uk": "ÐÑдповÑдайÑе на 3 запиÑаннÑ, Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑе HP знайÑи Ñе Ð´Ð»Ñ Ð²Ð°Ñ.", 10324 "zh": "åç3个é®é¢ï¼è®©HPä¸ºæ¨æ¾å°å®ã", 10325 "id": "Jawab 3 pertanyaan dan biarkan HP menemukannya untuk Anda.", 10326 "ja": "3ã¤ã®è³ªåã«çãã¦ãHPã«ãããè¦ã¤ãã¦ãããã¾ãããã", 10327 "ko": "3ê°ì ì§ë¬¸ì ëµíê³ HPê° ê·¸ê²ì ì°¾ìëë¦¬ê² íì¸ì.", 10328 "ms": "Jawab 3 soalan dan biarkan HP mencarinya untuk anda.", 10329 "fil": "Sagutin ang 3 tanong at hayaan ang HP na hanapin ito para sa iyo.", 10330 "th": "à¸à¸à¸à¸à¸³à¸à¸²à¸¡ 3 à¸à¹à¸ à¹à¸¥à¹à¸§à¹à¸«à¹ HP à¸à¹à¸à¸«à¸²à¸ªà¸´à¹à¸à¸à¸±à¹à¸à¹à¸«à¹à¸à¸¸à¸", 10331 "vi": "Trả lá»i 3 câu há»i và Äá» HP tìm nó cho bạn." 10332 }, 10333 cta: { 10334 "us": "Get started", 10335 "es": "Comenzar", 10336 "pt": "Começar", 10337 "fr": "Commencer", 10338 "nl": "Begin", 10339 "bg": "ÐапоÑнеÑе", 10340 "cs": "ZaÄÃt", 10341 "hr": "ZapoÄnite", 10342 "da": "Kom godt i gang", 10343 "de": "Loslegen", 10344 "et": "Alusta", 10345 "el": "ÎεκινήÏÏε", 10346 "he": "×ת××", 10347 "it": "Inizia", 10348 "kk": "ÐаÑÑаÑ", 10349 "lv": "SÄkt", 10350 "lt": "PradÄti", 10351 "hu": "Kezdjen", 10352 "ar": "ابدأ", 10353 "no": "Kom i gang", 10354 "pl": "Zacznij", 10355 "ro": "Ãncepe", 10356 "sr": "PoÄnite", 10357 "sk": "ZaÄnite", 10358 "sl": "ZaÄnite", 10359 "fi": "Aloita", 10360 "sv": "Kom igÃ¥ng", 10361 "tr": "BaÅlayın", 10362 "uk": "ÐоÑаÑи", 10363 "zh": "å¼å§", 10364 "id": "Mulai", 10365 "ja": "å§ãã", 10366 "ko": "ììí기", 10367 "ms": "Mula", 10368 "fil": "Magsimula", 10369 "th": "à¹à¸£à¸´à¹à¸¡à¸à¹à¸", 10370 "vi": "Bắt Äầu" 10371 } 10372 }, 10373 quizBodyContent: { 10374 header: { 10375 "us": "Answer these questions to discover the ideal device for you", 10376 "es": "Responde estas preguntas para descubrir el dispositivo ideal para ti", 10377 "pt": "Responda a estas perguntas para descobrir o dispositivo ideal para você", 10378 "fr": "Répondez à ces questions pour découvrir l'appareil idéal pour vous", 10379 "nl": "Beantwoord deze vragen om het ideale apparaat voor jou te ontdekken", 10380 "bg": "ÐÑговоÑеÑе на Ñези вÑпÑоÑи, за да оÑкÑиеÑе идеалноÑо ÑÑÑÑойÑÑво за ваÑ", 10381 "cs": "OdpovÄzte na tyto otázky a objevte ideálnà zaÅÃzenà pro vás", 10382 "hr": "Odgovorite na ova pitanja kako biste otkrili idealni ureÄaj za vas", 10383 "da": "Besvar disse spørgsmÃ¥l for at finde den ideelle enhed til dig", 10384 "de": "Beantworten Sie diese Fragen, um das ideale Gerät für Sie zu finden", 10385 "et": "Vasta nendele küsimustele, et leida endale ideaalne seade", 10386 "el": "ÎÏανÏήÏÏε Ïε Î±Ï ÏÎÏ ÏÎ¹Ï ÎµÏÏÏήÏÎµÎ¹Ï Î³Î¹Î± να ανακαλÏÏεÏε Ïη ιδανική ÏÏ ÏÎºÎµÏ Î® για εÏάÏ", 10387 "he": "×¢× × ×¢× ×ש×××ת ×××× ××× ××××ת ×ת ×××ש×ר ×××××××× ×¢××ר×", 10388 "it": "Rispondi a queste domande per scoprire il dispositivo ideale per te", 10389 "kk": "СÑзге аÑналÒан Ð¸Ð´ÐµÐ°Ð»Ð´Ñ ÒÒ±ÑÑлÒÑÐ½Ñ ÑÐ°Ð±Ñ Ò¯ÑÑн оÑÑ ÑÒ±ÑаÒÑаÑÒа жаÑап беÑÑÒ£Ñз", 10390 "lv": "Atbildiet uz Å¡iem jautÄjumiem, lai atklÄtu jums ideÄlo ierÄ«ci", 10391 "lt": "Atsakykite į Å¡iuos klausimus, kad atrastumÄte jums idealiausiÄ Ä¯renginį", 10392 "hu": "Válaszoljon ezekre a kérdésekre, hogy megtalálja az Ãn számára ideális eszközt", 10393 "ar": "أجب Ø¹Ù ÙØ°Ù Ø§ÙØ£Ø³Ø¦ÙØ© ÙØ§ÙØªØ´Ø§Ù Ø§ÙØ¬Ùاز اÙ٠ثاÙÙ ÙÙ", 10394 "no": "Svar pÃ¥ disse spørsmÃ¥lene for Ã¥ finne den ideelle enheten for deg", 10395 "pl": "Odpowiedz na te pytania, aby odkryÄ idealne urzÄ dzenie dla siebie", 10396 "ro": "RÄspundeÈi la aceste întrebÄri pentru a descoperi dispozitivul ideal pentru dvs.", 10397 "sr": "Odgovorite na ova pitanja kako biste otkrili idealan ureÄaj za vas", 10398 "sk": "Odpovedzte na tieto otázky, aby ste objavili ideálne zariadenie pre vás", 10399 "sl": "Odgovorite na ta vpraÅ¡anja, da odkrijete idealno napravo za vas", 10400 "fi": "Vastaa näihin kysymyksiin löytääksesi sinulle ihanteellisen laitteen", 10401 "sv": "Svara pÃ¥ dessa frÃ¥gor för att upptäcka den idealiska enheten för dig",
10402 "tr": "Senin için ideal cihazı keÅfetmek için bu soruları yanıtla", 10403 "uk": "ÐÑдповÑдайÑе на ÑÑ Ð·Ð°Ð¿Ð¸ÑаннÑ, Ñоб знайÑи ÑдеалÑний пÑиÑÑÑÑй Ð´Ð»Ñ Ñебе", 10404 "zh": "åçè¿äºé®é¢ï¼åç°é忍ççæ³è®¾å¤", 10405 "id": "Jawab pertanyaan-pertanyaan ini untuk menemukan perangkat ideal untuk Anda", 10406 "ja": "ãããã®è³ªåã«çãã¦ãããªãã«æé©ãªããã¤ã¹ãè¦ã¤ãã¾ããã", 10407 "ko": "ì´ ì§ë¬¸ì ëµíì¬ ë¹ì ìê² ì´ìì ì¸ ì¥ì¹ë¥¼ ì°¾ìë³´ì¸ì", 10408 "ms": "Jawab soalan-soalan ini untuk menemui peranti yang sesuai untuk anda", 10409 "fil": "Sagutin ang mga tanong na ito upang matuklasan ang perpektong device para sa iyo", 10410 "th": "à¸à¸à¸à¸à¸³à¸à¸²à¸¡à¹à¸«à¸¥à¹à¸²à¸à¸µà¹à¹à¸à¸·à¹à¸à¸à¹à¸à¸«à¸²à¸à¸¸à¸à¸à¸£à¸à¹à¸à¸µà¹à¹à¸«à¸¡à¸²à¸°à¸ªà¸¡à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸¸à¸", 10411 "vi": "Trả lá»i những câu há»i nà y Äá» khám phá thiết bá» lý tưá»ng cho bạn" 10412 }, 10413 questions: { 10414 first: { 10415 "us": "Where will the device primarily be used?", 10416 "es": "¿Dónde se utilizará principalmente el dispositivo?", 10417 "pt": "Onde o dispositivo será usado principalmente?", 10418 "fr": "Où l'appareil sera-t-il principalement utilisé ?", 10419 "nl": "Waar zal het apparaat voornamelijk worden gebruikt?", 10420 "bg": "ÐÑде оÑновно Ñе Ñе използва ÑÑÑÑойÑÑвоÑо?", 10421 "cs": "Kde bude zaÅÃzenà primárnÄ použÃváno?", 10422 "hr": "Gdje Äe se ureÄaj prvenstveno koristiti?", 10423 "da": "Hvor vil enheden primært blive brugt?", 10424 "de": "Wo wird das Gerät hauptsächlich verwendet?", 10425 "et": "Kus seadet peamiselt kasutatakse?", 10426 "el": "Î Î¿Ï Î¸Î± ÏÏηÏιμοÏοιείÏαι ÎºÏ ÏίÏÏ Î· ÏÏ ÏÎºÎµÏ Î®;", 10427 "he": "×××× ×××¢×©× ×©×××ש ×¢××§×¨× ×××ש×ר?", 10428 "it": "Dove verrà utilizzato principalmente il dispositivo?", 10429 "kk": "ÒÒ±ÑÑлÒÑ Ð½ÐµÐ³ÑзÑнен Òай жеÑде ÒолданÑладÑ?", 10430 "lv": "Kur ierÄ«ce galvenokÄrt tiks izmantota?", 10431 "lt": "Kur prietaisas bus daugiausia naudojamas?", 10432 "hu": "Hol fogják elsÅsorban használni az eszközt?", 10433 "ar": "Ø£ÙÙ Ø³ÙØªÙ Ø§Ø³ØªØ®Ø¯Ø§Ù Ø§ÙØ¬Ùاز بشÙÙ Ø£Ø³Ø§Ø³ÙØ", 10434 "no": "Hvor vil enheten hovedsakelig bli brukt?", 10435 "pl": "Gdzie urzÄ dzenie bÄdzie gÅównie używane?", 10436 "ro": "Unde va fi utilizat în principal dispozitivul?", 10437 "sr": "Gde Äe se ureÄaj prvenstveno koristiti?", 10438 "sk": "Kde sa bude zariadenie primárne použÃvaÅ¥?", 10439 "sl": "Kje bo naprava veÄinoma uporabljena?", 10440 "fi": "Missä laitetta käytetään pääasiassa?", 10441 "sv": "Var kommer enheten främst att användas?", 10442 "tr": "Cihaz aÄırlıklı olarak nerede kullanılacak?", 10443 "uk": "Ðе пÑиÑÑÑÑй бÑде пеÑеважно викоÑиÑÑовÑваÑиÑÑ?", 10444 "zh": "该设å¤ä¸»è¦å°å¨ä½å¤ä½¿ç¨ï¼", 10445 "id": "Di mana perangkat akan digunakan terutama?", 10446 "ja": "ããã¤ã¹ã¯ä¸»ã«ã©ãã§ä½¿ç¨ããã¾ããï¼", 10447 "ko": "기기ë ì£¼ë¡ ì´ëìì ì¬ì©ë ìì ì ëê¹?", 10448 "ms": "Di manakah peranti akan digunakan terutamanya?", 10449 "fil": "Saan pangunahing gagamitin ang device?", 10450 "th": "à¸à¸¸à¸à¸à¸£à¸à¹à¸à¸°à¸à¸¹à¸à¹à¸à¹à¸à¸²à¸à¸«à¸¥à¸±à¸ ๠à¸à¸µà¹à¹à¸«à¸?", 10451 "vi": "Thiết bá» sẽ chá»§ yếu ÄÆ°á»£c sá» dụng á» Äâu?" 10452 }, 10453 second: { 10454 "us": "How will the device be used?", 10455 "es": "¿Cómo se utilizará el dispositivo?", 10456 "pt": "Como o dispositivo será usado?", 10457 "fr": "Comment l'appareil sera-t-il utilisé ?", 10458 "nl": "Hoe zal het apparaat worden gebruikt?", 10459 "bg": "Ðак Ñе Ñе използва ÑÑÑÑойÑÑвоÑо?", 10460 "cs": "Jak bude zaÅÃzenà použÃváno?", 10461 "hr": "Kako Äe se ureÄaj koristiti?", 10462 "da": "Hvordan vil enheden blive brugt?", 10463 "de": "Wie wird das Gerät verwendet?", 10464 "et": "Kuidas seadet kasutatakse?", 10465 "el": "Î ÏÏ Î¸Î± ÏÏηÏιμοÏοιηθεί η ÏÏ ÏÎºÎµÏ Î®;", 10466 "he": "×××¦× ×××¢×©× ×©×××ש ×××ש×ר?", 10467 "it": "Come verrà utilizzato il dispositivo?", 10468 "kk": "ÒÒ±ÑÑлÒÑ Òалай пайдаланÑладÑ?", 10469 "lv": "KÄ ierÄ«ce tiks izmantota?",
10470 "lt": "Kaip bus naudojamas įrenginys?", 10471 "hu": "Hogyan fogják használni az eszközt?", 10472 "ar": "ÙÙÙ Ø³ÙØªÙ Ø§Ø³ØªØ®Ø¯Ø§Ù Ø§ÙØ¬ÙازØ", 10473 "no": "Hvordan vil enheten bli brukt?", 10474 "pl": "Jak bÄdzie używane urzÄ dzenie?", 10475 "ro": "Cum va fi utilizat dispozitivul?", 10476 "sr": "Kako Äe se ureÄaj koristiti?", 10477 "sk": "Ako sa bude zariadenie použÃvaÅ¥?", 10478 "sl": "Kako bo naprava uporabljena?", 10479 "fi": "Kuinka laitetta käytetään?", 10480 "sv": "Hur kommer enheten att användas?", 10481 "tr": "Cihaz nasıl kullanılacak?", 10482 "uk": "Як бÑде викоÑиÑÑовÑваÑиÑÑ Ð¿ÑиÑÑÑÑй?", 10483 "zh": "该设å¤å°å¦ä½ä½¿ç¨ï¼", 10484 "id": "Bagaimana perangkat akan digunakan?", 10485 "ja": "ããã¤ã¹ã¯ã©ã®ããã«ä½¿ç¨ããã¾ããï¼", 10486 "ko": "기기ë ì´ë»ê² ì¬ì©ë ìì ì ëê¹?", 10487 "ms": "Bagaimanakah peranti akan digunakan?", 10488 "fil": "Paano gagamitin ang device?", 10489 "th": "à¸à¸¸à¸à¸à¸£à¸à¹à¸à¸°à¸à¸¹à¸à¹à¸à¹à¸à¸²à¸à¸à¸¢à¹à¸²à¸à¹à¸£?", 10490 "vi": "Thiết bá» sẽ ÄÆ°á»£c sá» dụng như thế nà o?" 10491 } 10492 10493 , 10494 third: { 10495 "us": "What features matter most to you?", 10496 "es": "¿Qué caracterÃsticas son más importantes para ti?", 10497 "pt": "Quais recursos são mais importantes para você?", 10498 "fr": "Quelles fonctionnalités sont les plus importantes pour vous ?", 10499 "nl": "Welke functies zijn voor jou het belangrijkst?", 10500 "bg": "Ðои ÑÑнкÑии Ñа най-важни за ваÑ?", 10501 "cs": "Na kterých funkcÃch vám nejvÃce záležÃ?", 10502 "hr": "Koje su vam znaÄajke najvažnije?", 10503 "da": "Hvilke funktioner er vigtigst for dig?", 10504 "de": "Welche Funktionen sind für Sie am wichtigsten?", 10505 "et": "Millised funktsioonid on teie jaoks kõige olulisemad?", 10506 "el": "Î Î¿Î¹ÎµÏ Î»ÎµÎ¹ÏÎ¿Ï ÏÎ³Î¯ÎµÏ ÎÏÎ¿Ï Î½ μεγαλÏÏεÏη ÏημαÏία για εÏάÏ;", 10507 "he": "×××× ×ª××× ×ת ×ש×××ת ×× ×××תר?", 10508 "it": "Quali funzionalità sono più importanti per te?", 10509 "kk": "СÑз Ò¯ÑÑн Òандай мүмкÑндÑкÑÐµÑ ÐµÒ£ маңÑздÑ?", 10510 "lv": "Kuras funkcijas jums ir visnozÄ«mÄ«gÄkÄs?", 10511 "lt": "Kurios funkcijos jums yra svarbiausios?", 10512 "hu": "Mely funkciók a legfontosabbak az Ãn számára?", 10513 "ar": "٠ا Ù٠اÙÙ ÙØ²Ø§Øª Ø§ÙØ£Ùثر Ø£ÙÙ ÙØ© باÙÙØ³Ø¨Ø© ÙÙØ", 10514 "no": "Hvilke funksjoner er viktigst for deg?", 10515 "pl": "Które funkcje sÄ dla Ciebie najważniejsze?", 10516 "ro": "Care caracteristici sunt cele mai importante pentru tine?",
10517 "sr": "Koje su funkcije najvažnije za vas?", 10518 "sk": "Na ktorých funkciách vám najviac záležÃ?", 10519 "sl": "Katere funkcije so vam najpomembnejÅ¡e?", 10520 "fi": "Mitkä ominaisuudet ovat sinulle tärkeimpiä?", 10521 "sv": "Vilka funktioner är viktigast för dig?", 10522 "tr": "Sizin için en önemli özellikler nelerdir?", 10523 "uk": "Ð¯ÐºÑ ÑÑнкÑÑÑ Ð´Ð»Ñ Ð²Ð°Ñ Ð½Ð°Ð¹Ð²Ð°Ð¶Ð»Ð¸Ð²ÑÑÑ?", 10524 "zh": "åªäºåè½å¯¹æ¨æéè¦ï¼", 10525 "id": "Fitur apa yang paling penting bagi Anda?", 10526 "ja": "ã©ã®æ©è½ãæãéè¦ã§ããï¼", 10527 "ko": "ì´ë¤ 기ë¥ì´ ê°ì¥ ì¤ìí©ëê¹?", 10528 "ms": "Apakah ciri-ciri yang paling penting bagi anda?", 10529 "fil": "Aling mga tampok ang pinakamahalaga sa iyo?", 10530 "th": "à¸à¸¸à¸à¸ªà¸¡à¸à¸±à¸à¸´à¹à¸à¸à¸µà¹à¸ªà¸³à¸à¸±à¸à¸à¸µà¹à¸ªà¸¸à¸à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸¸à¸?", 10531 "vi": "Những tÃnh nÄng nà o quan trá»ng nhất Äá»i vá»i bạn?" 10532 } 10533 }, 10534 answers: { 10535 setLocation: { 10536 "CAP": "Set location (Desktop)", 10537 "us": "Set location (Desktop)", 10538 "es": "Establecer ubicación (Escritorio)", 10539 "pt": "Definir local (Computador)", 10540 "fr": "Définir lâemplacement (Bureau)", 10541 "nl": "Locatie instellen (Desktop)", 10542 "bg": "Ðадаване на меÑÑоположение (ÐаÑÑолен)", 10543 "cs": "Nastavit polohu (Stolnà PC)", 10544 "hr": "Postavi lokaciju (Stolno raÄunalo)", 10545 "da": "Angiv placering (Stationær)", 10546 "de": "Standort festlegen (PC)", 10547 "et": "Määra asukoht (Lauaarvuti)", 10548 "el": "ÎÏιÏμÏÏ ÏοÏοθεÏÎ¯Î±Ï (ΣÏαθεÏÏÏ)", 10549 "he": "×××ר ×××§×× (× ×××)", 10550 "it": "Imposta posizione (Fisso)", 10551 "kk": "ÐÑналаÑÑÐ´Ñ Ð¾ÑнаÑÑ (Ò®ÑÑелдÑк)", 10552 "lv": "IestatÄ«t atraÅ¡anÄs vietu (Galddators)", 10553 "lt": "Nustatyti vietÄ (Stacionarus)", 10554 "hu": "Hely beállÃtása (Asztali gép)", 10555 "ar": "تعÙÙ٠اÙÙ ÙÙØ¹ (Ø¬ÙØ§Ø² Ù ÙØªØ¨Ù)", 10556 "no": "Angi plassering (Stasjonær)", 10557 "pl": "Ustaw lokalizacjÄ (Stacjonarny)", 10558 "ro": "SeteazÄ locaÈia (Desktop)", 10559 "sr": "Podesi lokaciju (Stoni raÄunar)", 10560 "sk": "NastaviÅ¥ polohu (Stolný PC)", 10561 "sl": "Nastavi lokacijo (Namizni)", 10562 "fi": "Aseta sijainti (Pöytäkone)", 10563 "sv": "Ange plats (Stationär)", 10564 "tr": "Konum ayarla (Masaüstü)", 10565 "uk": "ÐÑÑановиÑи мÑÑÑÐµÐ·Ð½Ð°Ñ Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ (ÐаÑÑÑлÑний)", 10566 "zh": "设置ä½ç½®ï¼å°å¼æºï¼", 10567 "id": "Atur lokasi (PC Meja)", 10568 "ja": "å ´æãè¨å®ï¼ãã¹ã¯ãããï¼", 10569 "ko": "ìì¹ ì¤ì (ë°ì¤í¬í)", 10570 "ms": "Tetapkan lokasi (Komputer Meja)", 10571 "fil": "Itakda ang lokasyon (Desktop)", 10572 "th": "à¸à¸±à¹à¸à¸à¹à¸²à¸à¸³à¹à¸«à¸à¹à¸ (à¹à¸à¸ªà¸à¹à¸à¹à¸à¸)", 10573 "vi": "Äặt vá» trà (Máy bà n)" 10574 } 10575 , 10576 onTheGo: { 10577 "CAP": "On the go (Laptop)", 10578 "us": "On the go (Laptop)", 10579 "es": "En movimiento (portátil)", 10580 "pt": "Em movimento (notebook)", 10581 "fr": "En déplacement (portable)", 10582 "nl": "Onderweg (laptop)", 10583 "bg": "Рдвижение (лапÑоп)", 10584 "cs": "Na cestách (notebook)", 10585 "hr": "U pokretu (laptop)", 10586 "da": "PÃ¥ farten (bærbar)", 10587 "de": "Unterwegs (laptop)", 10588 "et": "Liikvel olles (sülearvuti)", 10589 "el": "Îν κινήÏει (laptop)", 10590 "he": "ת×× ××× ×ª× ××¢× (× ×××)", 10591 "it": "In movimento (portatile)", 10592 "kk": "Ðолда (ноÑÑбÑк)", 10593 "lv": "CeÄ¼Ä (portatÄ«vais)", 10594 "lt": "Kelyje (neÅ¡iojamas)", 10595 "hu": "Ãtközben (laptop)", 10596 "ar": "Ø£Ø«ÙØ§Ø¡ Ø§ÙØªÙÙÙ (ÙØ§Ø¨ØªÙب)", 10597 "no": "PÃ¥ farten (bærbar)", 10598 "pl": "W drodze (laptop)", 10599 "ro": "Ãn miÈcare (laptop)", 10600 "sr": "U pokretu (laptop)", 10601 "sk": "Na cestách (notebook)", 10602 "sl": "Na poti (prenosnik)", 10603 "fi": "Liikkeellä (kannettava)", 10604 "sv": "PÃ¥ sprÃ¥ng (bärbar)", 10605 "tr": "Hareket halinde (dizüstü)", 10606 "uk": "У доÑÐ¾Ð·Ñ (ноÑÑбÑк)", 10607 "zh": "ç§»å¨ä¸ï¼ç¬è®°æ¬ï¼", 10608 "id": "Sedang bepergian (laptop)", 10609 "ja": "å¤åºå ã§ï¼ãã¼ãpcï¼", 10610 "ko": "ì´ë ì¤ (ë ¸í¸ë¶)", 10611 "ms": "Semasa bergerak (komputer riba)", 10612 "fil": "Habang nasa biyahe (laptop)", 10613 "th": "ระหวà¹à¸²à¸à¹à¸à¸´à¸à¸à¸²à¸ (à¹à¸¥à¹à¸à¸à¹à¸à¸)", 10614 "vi": "Khi di chuyá»n (laptop)" 10615 } 10616 , 10617 entertainment: { 10618 "CAP": "Entertainment & Personal", 10619 "us": "Entertainment & Personal", 10620 "es": "Entretenimiento y uso personal", 10621 "pt": "Entretenimento e uso pessoal", 10622 "fr": "Divertissement et usage personnel", 10623 "nl": "Amusement en persoonlijk gebruik", 10624 "bg": "РазвлеÑение и лиÑно ползване", 10625 "cs": "Zábava a osobnà použitÃ", 10626 "hr": "Zabava i osobna upotreba", 10627 "da": "Underholdning og personlig brug", 10628 "de": "Unterhaltung und persönliche Nutzung", 10629 "et": "Meelelahutus ja isiklik kasutus", 10630 "el": "Î¨Ï ÏαγÏγία και ÏÏοÏÏÏική ÏÏήÏη", 10631 "he": "××××ר ×ש×××ש ××ש×", 10632 "it": "Intrattenimento e uso personale",
10633 "kk": "ÐйÑн-ÑаÑÑÒ Ð¶Óне жеке пайдаланÑ", 10634 "lv": "Izklaide un personÄ«ga lietoÅ¡ana", 10635 "lt": "Pramogoms ir asmeniniam naudojimui", 10636 "hu": "Szórakozás és személyes használat", 10637 "ar": "ترÙÙÙ ÙØ§Ø³ØªØ®Ø¯Ø§Ù شخصÙ", 10638 "no": "Underholdning og personlig bruk", 10639 "pl": "Rozrywka i użytki osobiste", 10640 "ro": "Divertisment Èi uz personal", 10641 "sr": "Zabava i liÄna upotreba", 10642 "sk": "Zábava a osobné použitie", 10643 "sl": "Zabava in osebna raba", 10644 "fi": "Viihde ja henkilökohtainen käyttö", 10645 "sv": "UnderhÃ¥llning och personligt bruk", 10646 "tr": "EÄlence ve kiÅisel kullanım", 10647 "uk": "Розваги Ñа оÑобиÑÑе викоÑиÑÑаннÑ", 10648 "zh": "娱ä¹å个人使ç¨", 10649 "id": "Hiburan dan penggunaan pribadi", 10650 "ja": "ã¨ã³ã¿ã¡ã»å人å©ç¨", 10651 "ko": "ìí°í ì¸ë¨¼í¸ ë° ê°ì¸ì©", 10652 "ms": "Hiburan & penggunaan peribadi", 10653 "fil": "Aliwan at personal na gamit", 10654 "th": "à¸à¸§à¸²à¸¡à¸à¸±à¸à¹à¸à¸´à¸à¹à¸¥à¸°à¸à¸²à¸£à¹à¸à¹à¸à¸²à¸à¸ªà¹à¸§à¸à¸à¸±à¸§", 10655 "vi": "Giải trà và sá» dụng cá nhân" 10656 } 10657 , 10658 education: { 10659 "CAP": "Education & Hobbies", 10660 "us": "Education & Hobbies", 10661 "es": "Educación y pasatiempos", 10662 "pt": "Educação e hobbies", 10663 "fr": "Ãducation et loisirs", 10664 "nl": "Onderwijs en hobby's", 10665 "bg": "ÐбÑазование и Ñ Ð¾Ð±Ð¸Ñа", 10666 "cs": "VzdÄlánà a konÃÄky", 10667 "hr": "Obrazovanje i hobiji", 10668 "da": "Uddannelse og hobbyer", 10669 "de": "Bildung und Hobbys", 10670 "et": "Haridus ja hobid", 10671 "el": "ÎκÏÎ±Î¯Î´ÎµÏ Ïη και ÏÏμÏι", 10672 "he": "××× ×× ×ת××××××", 10673 "it": "Istruzione e hobby", 10674 "kk": "ÐÑлÑм жÓне Ñ Ð¾Ð±Ð±Ð¸", 10675 "lv": "IzglÄ«tÄ«ba un hobiji", 10676 "lt": "Å vietimas ir pomÄgiai", 10677 "hu": "Oktatás és hobbi", 10678 "ar": "تعÙÙÙ ÙÙÙØ§Ùات", 10679 "no": "Utdanning og hobbyer", 10680 "pl": "Edukacja i hobby", 10681 "ro": "EducaÈie Èi hobby-uri", 10682 "sr": "Obrazovanje i hobiji", 10683 "sk": "Vzdelanie a záľuby", 10684 "sl": "Izobraževanje in hobiji", 10685 "fi": "Koulutus ja harrastukset", 10686 "sv": "Utbildning och hobbyer", 10687 "tr": "EÄitim ve hobiler", 10688 "uk": "ÐÑвÑÑа Ñа Ñ Ð¾Ð±Ñ", 10689 "zh": "æè²åç±å¥½", 10690 "id": "Pendidikan dan hobi", 10691 "ja": "æè²ã»è¶£å³", 10692 "ko": "êµì¡ ë° ì·¨ë¯¸", 10693 "ms": "Pendidikan & hobi", 10694 "fil": "Edukasyon at libangan", 10695 "th": "à¸à¸²à¸£à¸¨à¸¶à¸à¸©à¸²à¹à¸¥à¸°à¸à¸²à¸à¸à¸à¸´à¹à¸£à¸", 10696 "vi": "Giáo dục và sá» thÃch" 10697 } 10698 , 10699 creativeTechnical: { 10700 "CAP": "Creative & Technical", 10701 "us": "Creative & Technical", 10702 "es": "Uso creativo y técnico", 10703 "pt": "Uso criativo e técnico", 10704 "fr": "Utilisation créative et technique", 10705 "nl": "Creatief en technisch gebruik", 10706 "bg": "ÐÑеаÑивна и ÑÐµÑ Ð½Ð¸ÑеÑка ÑпоÑÑеба", 10707 "cs": "Kreativnà a technické použitÃ", 10708 "hr": "Kreativna i tehniÄka upotreba", 10709 "da": "Kreativ og teknisk brug", 10710 "de": "Kreative und technische Nutzung", 10711 "et": "Loominguline ja tehniline kasutus", 10712 "el": "ÎÎ·Î¼Î¹Î¿Ï Ïγική και ÏεÏνική ÏÏήÏη", 10713 "he": "ש×××ש ×צ××¨×ª× ×××× ×", 10714 "it": "Uso creativo e tecnico", 10715 "kk": "ШÑÒаÑмаÑÑлÑÒ Ð¶Óне ÑÐµÑ Ð½Ð¸ÐºÐ°Ð»ÑÒ ÒолданÑ", 10716 "lv": "RadoÅ¡a un tehniska lietoÅ¡ana", 10717 "lt": "KÅ«rybinis ir techninis naudojimas", 10718 "hu": "KreatÃv és technikai használat", 10719 "ar": "Ø§Ø³ØªØ®Ø¯Ø§Ù Ø¥Ø¨Ø¯Ø§Ø¹Ù ÙØªÙÙÙ", 10720 "no": "Kreativ og teknisk bruk", 10721 "pl": "Użytek kreatywny i techniczny", 10722 "ro": "Utilizare creativÄ Èi tehnicÄ", 10723 "sr": "Kreativna i tehniÄka upotreba", 10724 "sk": "KreatÃvne a technické použitie", 10725 "sl": "Kreativna in tehniÄna uporaba", 10726 "fi": "Luova ja tekninen käyttö", 10727 "sv": "Kreativ och teknisk användning", 10728 "tr": "Yaratıcı ve teknik kullanım", 10729 "uk": "ÐÑеаÑивне Ñа ÑÐµÑ Ð½ÑÑне викоÑиÑÑаннÑ", 10730 "zh": "åæä¸ææ¯ç¨é", 10731 "id": "Penggunaan kreatif dan teknis", 10732 "ja": "ã¯ãªã¨ã¤ãã£ãã»æè¡ç¨é", 10733 "ko": "ì°½ìì ë° ê¸°ì ì ì¬ì©", 10734 "ms": "Penggunaan kreatif & teknikal", 10735 "fil": "Malikhain at teknikal na gamit", 10736 "th": "à¹à¸à¹à¸à¸²à¸à¹à¸à¸´à¸à¸ªà¸£à¹à¸²à¸à¸ªà¸£à¸£à¸à¹à¹à¸¥à¸°à¹à¸à¸à¸à¸´à¸", 10737 "vi": "Sá» dụng sáng tạo & kỹ thuáºt" 10738 } 10739 , 10740 business: { 10741 "CAP": "Business & Professional", 10742 "us": "Business & Professional", 10743 "es": "Uso empresarial y profesional", 10744 "pt": "Uso empresarial e profissional", 10745 "fr": "Usage professionnel et d'affaires", 10746 "nl": "Zakelijk en professioneel gebruik", 10747 "bg": "ÐÐ¸Ð·Ð½ÐµÑ Ð¸ пÑоÑеÑионална ÑпоÑÑеба", 10748 "cs": "Obchodnà a profesionálnà použitÃ", 10749 "hr": "Poslovna i profesionalna upotreba", 10750 "da": "Forretnings- og professionel brug", 10751 "de": "Geschäftliche und professionelle Nutzung", 10752 "et": "Ãri- ja professionaalne kasutus", 10753 "el": "ÎÏαγγελμαÏική και εÏιÏειÏημαÏική ÏÏήÏη", 10754 "he": "ש×××ש ×¢×¡×§× ××קצ××¢×", 10755 "it": "Uso aziendale e professionale",
10756 "kk": "ÐÑкеÑлÑк жÓне кÓÑÑби ÒолданÑ", 10757 "lv": "Biznesa un profesionÄla lietoÅ¡ana", 10758 "lt": "Versliniam ir profesiniam naudojimui", 10759 "hu": "Ãzleti és professzionális használat", 10760 "ar": "Ø§Ø³ØªØ®Ø¯Ø§Ù ØªØ¬Ø§Ø±Ù ÙØ§ØØªØ±Ø§ÙÙ", 10761 "no": "Forretnings- og profesjonell bruk", 10762 "pl": "Użytek biznesowy i profesjonalny", 10763 "ro": "Utilizare profesionalÄ Èi de afaceri", 10764 "sr": "Poslovna i profesionalna upotreba", 10765 "sk": "Obchodné a profesionálne použitie", 10766 "sl": "Poslovna in strokovna uporaba", 10767 "fi": "Liike- ja ammattikäyttö", 10768 "sv": "Affärs- och yrkesanvändning", 10769 "tr": "İŠve profesyonel kullanım", 10770 "uk": "ÐÑÐ·Ð½ÐµÑ Ñа пÑоÑеÑÑйне викоÑиÑÑаннÑ", 10771 "zh": "åå¡ä¸ä¸ä¸ç¨é", 10772 "id": "Penggunaan bisnis dan profesional", 10773 "ja": "ãã¸ãã¹ã»ããç¨é", 10774 "ko": "ì 무 ë° ì 문ê°ì©", 10775 "ms": "Penggunaan perniagaan & profesional", 10776 "fil": "Paggamit sa negosyo at propesyonal", 10777 "th": "à¹à¸à¹à¸à¸²à¸à¸à¸²à¸à¸à¸¸à¸£à¸à¸´à¸à¹à¸¥à¸°à¸¡à¸·à¸à¸à¸²à¸à¸µà¸", 10778 "vi": "Sá» dụng cho kinh doanh & chuyên nghiá»p" 10779 } 10780 , 10781 gaming: { 10782 "CAP": "Gaming", 10783 "us": "Gaming", 10784 "es": "Juegos", 10785 "pt": "Jogos", 10786 "fr": "Jeux vidéo", 10787 "nl": "Gamen", 10788 "bg": "ÐгÑи", 10789 "cs": "Hranà her", 10790 "hr": "Igranje", 10791 "da": "Spil", 10792 "de": "Gaming", 10793 "et": "Mängimine", 10794 "el": "ΠαιÏνίδια", 10795 "he": "×××××× ×", 10796 "it": "Gaming", 10797 "kk": "ÐйÑн", 10798 "lv": "SpÄlÄÅ¡ana", 10799 "lt": "Žaidimai", 10800 "hu": "Játék", 10801 "ar": "Ø£ÙØ¹Ø§Ø¨", 10802 "no": "Spilling", 10803 "pl": "Gry", 10804 "ro": "Gaming", 10805 "sr": "Igranje", 10806 "sk": "Hranie hier", 10807 "sl": "Igranje iger", 10808 "fi": "Pelaaminen", 10809 "sv": "Spel", 10810 "tr": "Oyun", 10811 "uk": "ÐгÑи", 10812 "zh": "游æ", 10813 "id": "Gaming", 10814 "ja": "ã²ã¼ã ", 10815 "ko": "ê²ì", 10816 "ms": "Permainan", 10817 "fil": "Paglalaro", 10818 "th": "à¸à¸²à¸£à¹à¸¥à¹à¸à¹à¸à¸¡", 10819 "vi": "ChÆ¡i game" 10820 } 10821 }, 10822 footer: { 10823 cta: { 10824 "us": "Submit", 10825 "es": "Enviar", 10826 "pt": "Enviar", 10827 "fr": "Soumettre", 10828 "nl": "Indienen", 10829 "bg": "ÐзпÑаÑане", 10830 "cs": "Odeslat", 10831 "hr": "PoÅ¡alji", 10832 "da": "Indsend", 10833 "de": "Einreichen", 10834 "et": "Esita", 10835 "el": "Î¥Ïοβολή", 10836 "he": "ש××", 10837 "it": "Invia", 10838 "kk": "ÐÑбеÑÑ", 10839 "lv": "Iesniegt", 10840 "lt": "Pateikti", 10841 "hu": "Beküldés", 10842 "ar": "إرساÙ", 10843 "no": "Send inn", 10844 "pl": "PrzeÅlij", 10845 "ro": "Trimite", 10846 "sr": "PoÅ¡alji", 10847 "sk": "OdoslaÅ¥", 10848 "sl": "PoÅ¡lji", 10849 "fi": "Lähetä", 10850 "sv": "Skicka in", 10851 "tr": "Gönder", 10852 "uk": "ÐадÑÑлаÑи", 10853 "zh": "æäº¤", 10854 "id": "Kirim", 10855 "ja": "éä¿¡", 10856 "ko": "ì ì¶", 10857 "ms": "Hantar", 10858 "fil": "Isumite", 10859 "th": "สà¹à¸", 10860 "vi": "Gá»i" 10861 }, 10862 currencies: { 10863 "us": '$%price%', 10864 "de": '€%price%', 10865 "ch": 'fr. %price%', 10866 "se": '%price% kr',
10867 "gb": '£%price%', 10868 "au": '$%price%', 10869 "ca": '$%price%', 10870 "cl": '$%price%', 10871 "in": 'â¹ %price%', 10872 "ar": '$ %price%', 10873 "my": 'RM %price%', 10874 "mx": '$%price%', 10875 "sg": '$%price%', 10876 "pe": 'S/.%price%', 10877 "hk": 'HK$ %price%', 10878 "kr": 'â© %price%', 10879 "za": 'R %price%', 10880 "vn": '%price% â«', 10881 "tw": 'å %price%', 10882 "tr": '%price% âº', 10883 "th": '%price% ฿', 10884 "sa": '%price% ï·¼', 10885 "ru": '%price% â½', 10886 "ro": '%price% RON', 10887 "pl": '%price% zÅ', 10888 "ph": 'â± %price%', 10889 "nz": '%price%', 10890 "no": 'kr %price%', 10891 "ma": '%price% .د.Ù .', 10892 "kp": 'â© %price%', 10893 "jp": 'Â¥ %price%', 10894 "il": '⪠%price%', 10895 "id": 'Rp %price%', 10896 "hu": '%price% Ft',
10897 "hr": '⬠%price%', 10898 "dk": 'kr. %price%', 10899 "cz": '%price% KÄ', 10900 "cn": 'Â¥ %price%', 10901 "br": 'R$ %price%', 10902 "bg": '%price% лв', 10903 "an": '⬠%price%' 10904 } 10905 } 10906 }, 10907 offerContent: { 10908 header: { 10909 budgetFriendly: { 10910 "us": "Budget friendly", 10911 "es": "Económico", 10912 "pt": "Econômico", 10913 "fr": "Ãconomique", 10914 "nl": "Budgetvriendelijk", 10915 "bg": "Ðзгоден", 10916 "cs": "CenovÄ dostupný", 10917 "hr": "PristupaÄan", 10918 "da": "Budgetvenlig", 10919 "de": "Preiswert", 10920 "et": "Soodsate hindadega", 10921 "el": "ÎικονομικÏ", 10922 "he": "××××××ª× ×תקצ××", 10923 "it": "Economico", 10924 "kk": "ÐÑджеÑке ÒолайлÑ", 10925 "lv": "Budžetam draudzÄ«gs", 10926 "lt": "Biudžetui palankus", 10927 "hu": "Költségbarát", 10928 "ar": "صدÙÙ ÙÙÙ ÙØ²Ø§ÙÙØ©", 10929 "no": "Budsjettvennlig", 10930 "pl": "PrzystÄpny cenowo", 10931 "ro": "Accesibil", 10932 "sr": "PristupaÄan", 10933 "sk": "Cenovo dostupný", 10934 "sl": "Cenovno ugoden", 10935 "fi": "Edullinen", 10936 "sv": "Budgetvänlig", 10937 "tr": "Bütçe dostu", 10938 "uk": "ÐоÑÑÑпний за ÑÑноÑ", 10939 "zh": "ç»æµå®æ ", 10940 "id": "Ramah anggaran", 10941 "ja": "äºç®ã«åªãã", 10942 "ko": "ìì° ì¹íì ", 10943 "ms": "Mesra bajet", 10944 "fil": "Abot-kayang halaga", 10945 "th": "à¹à¸à¹à¸à¸¡à¸´à¸à¸£à¸à¸±à¸à¸à¸à¸à¸£à¸°à¸¡à¸²à¸", 10946 "vi": "Phù hợp ngân sách" 10947 }, 10948 recommended: { 10949 "us": "Recommended for you", 10950 "es": "Recomendado para ti", 10951 "pt": "Recomendado para você", 10952 "fr": "Recommandé pour vous", 10953 "nl": "Aanbevolen voor jou", 10954 "bg": "ÐÑепоÑÑÑано за ваÑ", 10955 "cs": "DoporuÄeno pro vás", 10956 "hr": "PreporuÄeno za vas", 10957 "da": "Anbefavar til dig", 10958 "de": "Empfohlen für Sie", 10959 "et": "Soovitatav teile", 10960 "el": "Î ÏοÏείνεÏαι για εÏάÏ", 10961 "he": "×××××¥ ×¢××ר×", 10962 "it": "Consigliato per te", 10963 "kk": "СÑзге Ò±ÑÑнÑладÑ", 10964 "lv": "Ieteicams jums", 10965 "lt": "Rekomenduojama jums", 10966 "hu": "Ajánlott önnek", 10967 "ar": "Ù ÙØµÙ ب٠ÙÙ", 10968 "no": "Anbefalt for deg", 10969 "pl": "Polecane dla Ciebie", 10970 "ro": "Recomandat pentru tine", 10971 "sr": "PreporuÄeno za vas", 10972 "sk": "OdporúÄané pre vás", 10973 "sl": "PriporoÄeno za vas", 10974 "fi": "Suositeltu sinulle", 10975 "sv": "Rekommenderat för dig", 10976 "tr": "Sizin için önerilen", 10977 "uk": "Рекомендовано Ð´Ð»Ñ Ð²Ð°Ñ", 10978 "zh": "ä¸ºæ¨æ¨è", 10979 "id": "Direkomendasikan untuk Anda", 10980 "ja": "ããªãã«ãããã", 10981 "ko": "ë¹ì ì ìí ì¶ì²", 10982 "ms": "Disyorkan untuk anda", 10983 "fil": "Inirerekomenda para sa iyo", 10984 "th": "à¹à¸à¸°à¸à¸³à¸ªà¸³à¸«à¸£à¸±à¸à¸à¸¸à¸", 10985 "vi": "ÄÆ°á»£c Äá» xuất cho bạn" 10986 } 10987 , 10988 mostPopular: { 10989 "us": "Most popular", 10990 "es": "Más popular", 10991 "pt": "Mais popular", 10992 "fr": "Le plus populaire", 10993 "nl": "Meest populair", 10994 "bg": "Ðай-попÑлÑÑен", 10995 "cs": "NejoblÃbenÄjÅ¡Ã", 10996 "hr": "Najpopularnije", 10997 "da": "Mest populær", 10998 "de": "Am beliebtesten", 10999 "et": "Kõige populaarsem", 11000 "el": "Πιο δημοÏιλÎÏ", 11001 "he": "××× ×¤×פ××ר×", 11002 "it": "Più popolare", 11003 "kk": "ÐÒ£ ÑанÑмал", 11004 "lv": "VispopulÄrÄkais", 11005 "lt": "Populiariausias", 11006 "hu": "Legnépszerűbb", 11007 "ar": "Ø§ÙØ£Ùثر Ø´Ø¹Ø¨ÙØ©", 11008 "no": "Mest populær", 11009 "pl": "Najpopularniejsze", 11010 "ro": "Cel mai popular", 11011 "sr": "ÐаÑпопÑлаÑниÑи", 11012 "sk": "NajpopulárnejÅ¡Ã", 11013 "sl": "Najbolj priljubljeno", 11014 "fi": "Suosituin", 11015 "sv": "Mest populär", 11016 "tr": "En popüler", 11017 "uk": "ÐайпопÑлÑÑнÑÑий", 11018 "zh": "æå欢è¿", 11019 "id": "Paling populer", 11020 "ja": "æã人æ°ã®ãã", 11021 "ko": "ê°ì¥ ì¸ê¸° ìë", 11022 "ms": "Paling popular", 11023 "fil": "Pinakapopular", 11024 "th": "à¸à¸µà¹à¸à¸´à¸¢à¸¡à¸à¸µà¹à¸ªà¸¸à¸", 11025 "vi": "Phá» biến nhất" 11026 } 11027 11028 }, 11029 cta: { 11030 "us": "Shop now", 11031 "es": "Compra ahora", 11032 "pt": "Compre agora", 11033 "fr": "Achetez maintenant", 11034 "nl": "Koop nu", 11035 "bg": "ÐÑпи Ñега", 11036 "cs": "Kup nynÃ", 11037 "hr": "Kupite sada", 11038 "da": "Køb nu", 11039 "de": "Jetzt kaufen", 11040 "et": "Osta nüüd", 11041 "el": "ÎγοÏάÏÏε ÏÏÏα", 11042 "he": "×§× × ×¢×ש××", 11043 "it": "Acquista ora", 11044 "kk": "ÒазÑÑ ÑаÑÑп алÑÒ£Ñз", 11045 "lv": "PÄrc tagad", 11046 "lt": "Pirkite dabar", 11047 "hu": "Vásároljon most", 11048 "ar": "Ø§Ø´ØªØ±Ù Ø§ÙØ¢Ù", 11049 "no": "Kjøp nÃ¥", 11050 "pl": "Kup teraz", 11051 "ro": "CumpÄrÄ acum", 11052 "sr": "Kupite sada", 11053 "sk": "Kúp teraz", 11054 "sl": "Kupite zdaj", 11055 "fi": "Osta nyt", 11056 "sv": "Köp nu", 11057 "tr": "Hemen satın al", 11058 "uk": "ÐÑпиÑи заÑаз", 11059 "zh": "ç«å³è´ä¹°", 11060 "id": "Beli sekarang", 11061 "ja": "ä»ããè³¼å ¥", 11062 "ko": "ì§ê¸ 구매", 11063 "ms": "Beli sekarang", 11064 "fil": "Bumili ngayon", 11065 "th": "à¸à¸·à¹à¸à¹à¸¥à¸¢", 11066 "vi": "Mua ngay" 11067 } 11068 } 11069}; 11070 11071// --------------- Quiz Code ends Here ----------------- 11072initiateMastiffCall();
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.