1/* -------------------------------------------------------------- 2 PayPalLoader.js 2023-04-12 3 Gambio GmbH 4 http://www.gambio.de 5 Copyright (c) 2023 Gambio GmbH 6 Released under the GNU General Public License (Version 2) 7 [http://www.gnu.org/licenses/gpl-2.0.html] 8 -------------------------------------------------------------- 9*/ 10 11 12(function() { 13 if (window.NodeList && !NodeList.prototype.forEach) { 14 NodeList.prototype.forEach = Array.prototype.forEach; 15 } 16 17 let currentScript = document.currentScript; 18 19 let consoleInfo = function(...params) { 20 if (typeof payPalButtonSettings.developmentMode !== 'boolean' || payPalButtonSettings.developmentMode === false) { 21 return; 22 } 23 console.info('PayPalLoader', ...params); 24 } 25 26 let handleAntiqueBrowser = function() { 27 consoleInfo('Sorry, antique browser not supported.'); 28 29 let pppay = document.querySelector('li.gambio_hub-PayPal2Hub'); 30 if (pppay) { 31 pppay.remove(); 32 } 33 } 34 35 let initDisplayModeECS_ButtonReplace = function() { 36 let paypalButtonContainer = document.querySelector('#paypal-button-container'), 37 footerTotalRow = document.querySelector('table.order-total tr.footer.total'), 38 newTotalRow = document.createElement('tr'), 39 newTotalRowCell = document.createElement('td'); 40 newTotalRowCell.colSpan = '2'; 41 newTotalRowCell.style.width = '100%'; 42 newTotalRowCell.style.borderTop = 'none'; 43 newTotalRowCell.appendChild(paypalButtonContainer); 44 newTotalRow.appendChild(newTotalRowCell); 45 footerTotalRow.parentNode.appendChild(newTotalRow); 46 footerTotalRow.querySelectorAll('td').forEach(function(td) { 47 td.style.paddingBottom = '15px'; 48 }); 49 }; 50 51 let initDisplayModeECS = function() { 52 if(window.location.search.match(/(\?|&)display_mode=ecs($|&)/)) { 53 let checkoutButtons = document.querySelector('div.checkout-buttons'); 54 if(checkoutButtons) { 55 checkoutButtons.style.display = 'none'; 56 } 57 let checkoutSubmitButton = document.querySelector('div.shopping-cart-button a.button-submit'); 58 if(checkoutSubmitButton === null) { 59 checkoutSubmitButton = document.querySelector('tr.checkout-button'); 60 } 61 if(checkoutSubmitButton) { 62 checkoutSubmitButton.style.display = 'none'; 63 } 64 let shoppingCartButton = document.querySelector('div.shopping-cart-button'); 65 if(shoppingCartButton) { 66 shoppingCartButton.classList.add('paypal-ecs-mode'); 67 } 68 let ppiContainer = document.querySelector('div.paypalinstallmentcontainer'); 69 if(ppiContainer) { 70 ppiContainer.style.display = 'none'; 71 } 72 initDisplayModeECS_ButtonReplace(); 73 } 74 } 75 76 let initJSSDKPayPalButtonECS = function(amount) { 77 if (amount === undefined) { 78 amount = payPalButtonSettings.cartAmount; 79 } 80 consoleInfo('initJSSDKPayPalButtonECS cart amount: ' + amount); 81 if (amount < 0.01) { 82 consoleInfo('ECS: not showing, cart amount too low'); 83 return; 84 } 85 let buttonContainer = document.querySelector('#paypal-button-container'); 86 if (!buttonContainer) { 87 return; 88 } 89 let ecsIntro = document.querySelector('div.ecs_intro'); 90 if (document.querySelector('tr.checkout-button .button-disabled') !== null) { 91 if (ecsIntro) { 92 ecsIntro.style.display = 'none'; 93 } 94 buttonContainer.style.display = 'none'; 95 } else { 96 if (ecsIntro) { 97 ecsIntro.style.display = 'block'; 98 } 99 buttonContainer.style.display = 'block'; 100 initDisplayModeECS(); 101 } 102 103 paypal.Buttons({ 104 style: payPalButtonSettings.style, 105 createOrder: function(data, actions) { 106 return fetch(payPalButtonSettings.createOrderUrl, { 107 method: 'post', 108 headers: { 109 'Content-Type': 'application/json' 110 } 111 }) 112 .then((res) => { return res.json() }) 113 .then((orderdata) => { 114 consoleInfo('order created: ' + orderdata.id, orderdata); 115 return orderdata.id; 116 }); 117 }, 118 onApprove: function(data, actions) { 119 consoleInfo('Approved data:', data); 120 return fetch(payPalButtonSettings.approvedOrderUrl + '&orderId=' + data.orderID, { 121 method: 'post', 122 headers: { 123 'Content-Type': 'application/json' 124 }, 125 body: JSON.stringify(data) 126 }) 127 .then((res) => { return res.json(); }) 128 .then((responsedata) => { 129 consoleInfo('response data:', responsedata); 130 document.location = payPalButtonSettings.checkoutUrl; 131 }); 132 }, 133 onError: function(err) { 134 let ppButtonContainer = document.querySelector('#paypal-button-container'); 135 let ecsIntro = document.querySelector('div.ecs_intro'); 136 if(ppButtonContainer) {
137 let errorMessage = document.querySelector('div.paypal-error'); 138 if(!errorMessage) { 139 errorMessage = document.createElement('div'); 140 errorMessage.classList.add('paypal-error'); 141 errorMessage.classList.add('alert'); 142 errorMessage.classList.add('alert-warning'); 143 errorMessage.style.textAlign = 'left'; 144 errorMessage.style.color = '#555'; 145 } 146 errorMessage.innerText = payPalText.paypalUnavailable + ' '; 147 let shoppingCartButton = document.querySelector('div.shopping-cart-button'); 148 if(shoppingCartButton && shoppingCartButton.classList.contains('paypal-ecs-mode')) { 149 let linkUrl = window.location.toString().replace('display_mode=ecs', 'display_mode=normal'); 150 let continueLink = document.createElement('a'); 151 continueLink.setAttribute('href', linkUrl); 152 continueLink.innerText = payPalText.errorContinue; 153 errorMessage.append(continueLink); 154 } 155 ppButtonContainer.parentNode.append(errorMessage); 156 ppButtonContainer.style.display = 'none'; 157 } 158 if(ecsIntro) { 159 ecsIntro.style.display = 'none'; 160 } 161 } 162 }).render('#paypal-button-container'); 163 164 let observerTarget = document.querySelector('#paypal-button-container'); 165 let observer = new MutationObserver(function(mutations, observer) { 166 mutations.forEach(function(mutation) { 167 if(mutation.removedNodes.length > 0) { 168 consoleInfo('re-init PayPal buttons'); 169 let totalSumCell = document.querySelector('tr.total.sum td:nth-child(2)'); 170 if (totalSumCell) { 171 let amount = parseFloat(totalSumCell.textContent.replace(/[^0-9]/g, '')) / 100; 172 initJSSDKPayPalButtonECS(amount); 173 initInstallmentBanners(amount); 174 } else { 175 initJSSDKPayPalButtonECS(); 176 initInstallmentBanners(); 177 } 178 } 179 }); 180 }); 181 observer.observe(observerTarget, {childList: true}); 182 }; 183 184 185 let addButtonContainerDecoration = function(buttonContainer, continueButtonBlock) 186 { 187 buttonContainer.style.width = 'auto'; 188 buttonContainer.style.textAlign = 'center'; 189 buttonContainer.style.fontStyle = 'italic'; 190 if (payPalText.continueToPayPal) { 191 let labelToButtonDistance = 3; 192 let lineHeight = '-' + window.getComputedStyle(continueButtonBlock).lineHeight; 193 buttonContainer.style.marginTop = 'calc(' + lineHeight + ' - ' + labelToButtonDistance + 'px)'; 194 let continueLabel = document.createElement('span'); 195 continueLabel.classList.add('paypal-continue-label'); 196 continueLabel.textContent = payPalText.continueToPayPal 197 continueLabel.style.paddingBottom = labelToButtonDistance + 'px'; 198 buttonContainer.appendChild(continueLabel) ; 199 } 200 } 201 202 203 let initJSSDKPayPalButtonECM = function(continueButtonBlock) 204 { 205 let paypalButtonContainer = document.createElement('div'); 206 207 paypalButtonContainer.id = 'paypal-button-container'; 208 paypalButtonContainer.style.display = 'none'; 209 addButtonContainerDecoration(paypalButtonContainer, continueButtonBlock); 210 continueButtonBlock.appendChild(paypalButtonContainer); 211 212 paypal.Buttons({ 213 fundingSource: 'paypal', 214 style: payPalButtonSettings.style, 215 createOrder: function(data, actions) { 216 return fetch(payPalButtonSettings.createOrderUrl, { 217 method: 'post', 218 headers: { 219 'Content-Type': 'application/json' 220 } 221 }) 222 .then((res) => { return res.json() }) 223 .then((orderdata) => { 224 consoleInfo('order created: ' + orderdata.id, orderdata); 225 return orderdata.id; 226 }); 227 }, 228 onApprove: function(data, actions) { 229 document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID; 230 document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID; 231 document.querySelector('#checkout_payment').submit(); 232 } 233 }).render('#paypal-button-container'); 234 235 return paypalButtonContainer; 236 } 237 238 let initPayLaterButton = function(continueButtonBlock) 239 { 240 let payLaterItem = document.querySelector('li.gambio_hub-PayPal2Hub-paylater'); 241 if (payLaterItem === null) { 242 return null; 243 } 244 245 let paylaterButton = paypal.Buttons({ 246 fundingSource: 'paylater', 247 style: payPalButtonSettings.style, 248 createOrder: function(data, actions) { 249 return fetch(payPalButtonSettings.createOrderUrl, { 250 method: 'post', 251 headers: { 252 'Content-Type': 'application/json' 253 } 254 }) 255 .then((res) => { return res.json() }) 256 .then((orderdata) => { 257 consoleInfo('order created: ' + orderdata.id, orderdata); 258 return orderdata.id; 259 }); 260 }, 261 onApprove: function(data, actions) { 262 document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID; 263 document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID; 264 document.querySelector('#checkout_payment').submit(); 265 } 266 }); 267 268 if (paylaterButton.isEligible()) { 269 let paylaterButtonId = 'paypal-paylater-button-container', 270 paylaterButtonContainer = document.createElement('div'); 271 paylaterButtonContainer.id = paylaterButtonId; 272 paylaterButtonContainer.style.display = 'none'; 273 addButtonContainerDecoration(paylaterButtonContainer, continueButtonBlock); 274 continueButtonBlock.appendChild(paylaterButtonContainer); 275 paylaterButton.render('#' + paylaterButtonId); 276 consoleInfo('PayPal Paylater: eligible and initialized'); 277 return paylaterButtonContainer; 278 } else { 279 consoleInfo('PayPal Paylater: not eligible'); 280 payLaterItem.remove(); 281 } 282 283 return null; 284 } 285 286 287 let initSepaButton = function(continueButtonBlock) 288 { 289 let sepaItem = document.querySelector('li.gambio_hub-PayPal2Hub-sepa'); 290 if (sepaItem === null) { 291 return null; 292 } 293 let sepaButtonStyle = payPalButtonSettings.style; 294 if (sepaButtonStyle.color === 'gold' || sepaButtonStyle.color === 'blue') { 295 sepaButtonStyle.color = 'silver'; 296 } 297 298 let sepaButton = paypal.Buttons({ 299 fundingSource: 'sepa', 300 style: payPalButtonSettings.style, 301 createOrder: function(data, actions) { 302 return fetch(payPalButtonSettings.createOrderUrl, { 303 method: 'post', 304 headers: { 305 'Content-Type': 'application/json' 306 } 307 }) 308 .then((res) => { return res.json() }) 309 .then((orderdata) => { 310 consoleInfo('order created: ' + orderdata.id, orderdata); 311 return orderdata.id; 312 }); 313 }, 314 onApprove: function(data, actions) { 315 document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID; 316 document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID; 317 document.querySelector('#checkout_payment').submit(); 318 } 319 }); 320 321 if (sepaButton.isEligible()) { 322 let sepaButtonId = 'paypal-sepa-button-container', 323 sepaButtonContainer = document.createElement('div'); 324 sepaButtonContainer.id = sepaButtonId; 325 sepaButtonContainer.style.display = 'none'; 326 addButtonContainerDecoration(sepaButtonContainer, continueButtonBlock); 327 continueButtonBlock.appendChild(sepaButtonContainer); 328 sepaButton.render('#' + sepaButtonId); 329 consoleInfo('PayPal SEPA: eligible and initialized'); 330 return sepaButtonContainer; 331 } else { 332 consoleInfo('PayPal SEPA: not eligible'); 333 sepaItem.remove(); 334 } 335 336 return null; 337 } 338 339 340 let initCreditCardButton = function(continueButtonBlock) 341 { 342 let brandedCreditCardsItem = document.querySelector('li.gambio_hub-PayPal2Hub-creditcardbutton'); 343 if (brandedCreditCardsItem === null) { 344 return null; 345 } 346 347 let cardButtonStyle = payPalButtonSettings.style; 348 cardButtonStyle.color = 'black'; 349 cardButtonStyle.shape = 'pill'; 350 351 let creditCardButton = paypal.Buttons({ 352 fundingSource: 'card', 353 style: cardButtonStyle, 354 createOrder: function(data, actions) { 355 return fetch(payPalButtonSettings.createOrderUrl, { 356 method: 'post', 357 headers: { 358 'Content-Type': 'application/json' 359 } 360 }) 361 .then((res) => { return res.json() }) 362 .then((orderdata) => { 363 consoleInfo('order created: ' + orderdata.id, orderdata); 364 return orderdata.id; 365 }); 366 }, 367 onApprove: function(data, actions) { 368 document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID; 369 document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID; 370 document.querySelector('#checkout_payment').submit(); 371 } 372 }); 373 374 consoleInfo(creditCardButton); 375 376 if (creditCardButton.isEligible()) { 377 consoleInfo('Eligible for branded cc payments'); 378 let creditCardButtonId = 'paypal-creditcard-button-container', 379 creditCardButtonContainer = document.createElement('div'); 380 creditCardButtonContainer.id = creditCardButtonId; 381 creditCardButtonContainer.style.display = 'none'; 382 addButtonContainerDecoration(creditCardButtonContainer, continueButtonBlock); 383 continueButtonBlock.appendChild(creditCardButtonContainer); 384 creditCardButton.render('#' + creditCardButtonId); 385 return creditCardButtonContainer; 386 } else { 387 consoleInfo('NOT eligible for branded cc payments'); 388 brandedCreditCardsItem.remove(); 389 } 390 391 return null; 392 } 393 394 395 let initHostedCreditCard = function() { 396 let theLabel = document.querySelector('#ppcc-card-holder-field').closest('label'), 397 theDiv = document.createElement('div'); 398 399 theDiv.classList.add('payment-module-container'); 400 theLabel.parentNode.appendChild(theDiv); 401 while(theLabel.hasChildNodes()) { 402 theDiv.appendChild(theLabel.firstChild); 403 } 404 theLabel.remove(); 405 406 let theListItem = document.querySelector('li.gambio_hub-PayPal2Hub-creditcard'); 407 theListItem.style.cursor = 'pointer'; 408 theListItem.addEventListener('click', function() {
409 $(this).find('input:radio:not(:disabled):not(.placeholder-radio)').first().prop('checked', true).trigger('change'); 410 }); 411 412 let cardHolderField = document.querySelector('#ppcc-card-holder-field'), 413 fieldStyle = getComputedStyle(cardHolderField), 414 orderIdElement = document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]'); 415 416 paypal.HostedFields.render({ 417 createOrder: function() { 418 return fetch(payPalButtonSettings.createOrderUrl, { 419 method: 'post', 420 headers: { 421 'Content-Type': 'application/json' 422 } 423 }) 424 .then((res) => { 425 return res.json() 426 }) 427 .then((orderdata) => { 428 orderIdElement.value = orderdata.id; 429 consoleInfo('credit card order created: ' + orderdata.id, orderdata); 430 return orderdata.id; 431 }); 432 }, 433 styles: { 434 'input': { 435 'color': fieldStyle.color, 436 'font-size': fieldStyle.fontSize, 437 'font-family': fieldStyle.fontFamily, 438 'padding': fieldStyle.padding, 439 'line-height': fieldStyle.lineHeight 440 }, 441 '.valid': { 442 'color': 'green' 443 }, 444 '.invalid': { 445 'color': 'red' 446 } 447 }, 448 fields: { 449 number: { 450 'selector': '#ppcc-card-number', 451 'placeholder': '4111111111111111', 452 }, 453 cvv: { 454 'selector': '#ppcc-cvv', 455 'placeholder': '123', 456 }, 457 expirationDate: { 458 'selector': '#ppcc-expiration-date', 459 'placeholder': 'MM/YY', 460 } 461 } 462 }).then(function(cardFields) { 463 consoleInfo('PayPal: CC fields initialized', cardFields); 464 let paymentForm = document.querySelector('#checkout_payment'); 465 let cardFieldsSubmitted = false; 466 paymentForm.addEventListener('submit', function(event) { 467 if (cardFieldsSubmitted === false && paymentForm.payment.value === 'gambio_hub-PayPal2Hub-creditcard') { 468 event.preventDefault(); 469 let billingAddressData = JSON.parse(document.querySelector('#ppcc-billingaddress').textContent); 470 cardFields.submit({ 471 cardholderName: paymentForm.ppcc_card_holder.value, 472 billingAddress: billingAddressData, 473 contingencies: ['SCA_WHEN_REQUIRED'] 474 }).then(function() { 475 // OK 476 consoleInfo('cardFields submitted'); 477 cardFieldsSubmitted = true; 478 paymentForm.submit(); 479 }).catch(function(err) { 480 orderIdElement.value = ''; 481 consoleInfo(err); 482 alert(payPalText.errorCheckData); 483 document.querySelector('input[name="payment"]:checked').scrollIntoView(false); 484 }); 485 } 486 }); 487 }); 488 } 489 490 let initCheckoutPayment = function() { 491 let continueButtonBlock = document.querySelector('#checkout_payment div.continue_button'), 492 continueButton = continueButtonBlock.querySelector('input[type="submit"]'), 493 continueButtonDisplay = continueButton.style.display, 494 paypalButtonContainer = document.createElement('div'), 495 plusContainer = document.querySelector('#gambiohub-ppplus'), 496 ccForm = document.querySelector('div.paypal-cc-form'), 497 orderIdElement = document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]'); 498
499 if (plusContainer === null && ccForm !== null) { 500 consoleInfo('PayPal: Credit Card form found on page.'); 501 let hostedFieldsEligible = paypal.HostedFields.isEligible(); 502 let brandedCreditCardsOption = document.querySelector('li.gambio_hub-PayPal2Hub-creditcardbutton'); 503 if (hostedFieldsEligible) { 504 consoleInfo('PayPal: eligible for hosted fields'); 505 if (brandedCreditCardsOption) { 506 brandedCreditCardsOption.remove(); 507 } 508 509 initHostedCreditCard(); 510 } 511 else { 512 consoleInfo('PayPal: NOT eligible for hosted fields'); 513 let ccListItem = document.querySelector('li.gambio_hub-PayPal2Hub-creditcard'); 514 ccListItem.remove(); 515 } 516 } 517 518 if (plusContainer === null && !payPalButtonSettings.paymentApproved) { 519 let backButtonBlock = continueButtonBlock.parentElement.querySelector('div.back_button'); 520 if (backButtonBlock !== null && backButtonBlock.classList.contains('col-xs-6')) { 521 backButtonBlock.classList.remove('col-xs-6'); 522 backButtonBlock.classList.add('col-xs-4'); 523 continueButtonBlock.classList.remove('col-xs-6'); 524 continueButtonBlock.classList.add('col-xs-8'); 525 let backButton = backButtonBlock.querySelector('a.btn'); 526 payPalButtonSettings.style.height = parseInt(getComputedStyle(backButton).height); 527 } 528 529 let paypalButtonContainer = initJSSDKPayPalButtonECM(continueButtonBlock); 530 let paylaterButtonContainer = initPayLaterButton(continueButtonBlock); 531 let creditCardButtonContainer = initCreditCardButton(continueButtonBlock); 532 let sepaButtonContainer = initSepaButton(continueButtonBlock); 533 534 let paymentItemClickListener = function() { 535 let selected_payment = this.querySelector('input[name="payment"]'); 536 if (null !== selected_payment) { 537 if (selected_payment.value === 'gambio_hub-PayPal2Hub' || 538 (selected_payment.value === 'gambio_hub' && selected_payment.dataset.module_code 539 === 'PayPal2Hub')) { 540 continueButton.style.display = 'none'; 541 paypalButtonContainer.style.display = 'block'; 542 if (paylaterButtonContainer !== null) { 543 paylaterButtonContainer.style.display = 'none'; 544 } 545 if (creditCardButtonContainer !== null) { 546 creditCardButtonContainer.style.display = 'none'; 547 } 548 if (sepaButtonContainer !== null) { 549 sepaButtonContainer.style.display = 'none'; 550 } 551 } 552 else if(selected_payment.value === 'gambio_hub-PayPal2Hub-paylater' && paylaterButtonContainer !== null) { 553 continueButton.style.display = 'none'; 554 paypalButtonContainer.style.display = 'none'; 555 paylaterButtonContainer.style.display = 'block'; 556 if (creditCardButtonContainer !== null) { 557 creditCardButtonContainer.style.display = 'none'; 558 } 559 if (sepaButtonContainer !== null) { 560 sepaButtonContainer.style.display = 'none'; 561 } 562 } else if(selected_payment.value === 'gambio_hub-PayPal2Hub-sepa' && sepaButtonContainer !== null) { 563 continueButton.style.display = 'none'; 564 paypalButtonContainer.style.display = 'none'; 565 if (paylaterButtonContainer !== null) { 566 paylaterButtonContainer.style.display = 'none'; 567 } 568 if (creditCardButtonContainer !== null) { 569 creditCardButtonContainer.style.display = 'none'; 570 } 571 sepaButtonContainer.style.display = 'block'; 572 } else if(selected_payment.value === 'gambio_hub-PayPal2Hub-creditcardbutton' && creditCardButtonContainer !== null) { 573 continueButton.style.display = 'none'; 574 paypalButtonContainer.style.display = 'none'; 575 creditCardButtonContainer.style.display = 'block'; 576 if (paylaterButtonContainer !== null) { 577 paylaterButtonContainer.style.display = 'none'; 578 } 579 if (sepaButtonContainer !== null) { 580 sepaButtonContainer.style.display = 'none'; 581 } 582 } else { 583 continueButton.style.display = continueButtonDisplay; 584 paypalButtonContainer.style.display = 'none'; 585 if (paylaterButtonContainer !== null) { 586 paylaterButtonContainer.style.display = 'none'; 587 } 588 if (creditCardButtonContainer !== null) { 589 creditCardButtonContainer.style.display = 'none'; 590 } 591 if (sepaButtonContainer !== null) { 592 sepaButtonContainer.style.display = 'none'; 593 } 594 } 595 } 596 }; 597 598 let paymentItems = document.querySelectorAll('#checkout_payment input[name="payment"], #checkout_payment li.list-group-item');
599 paymentItems.forEach(function(paymentItem) { 600 paymentItem.addEventListener('click', paymentItemClickListener) 601 }); 602 603 let paymentListEntries = document.querySelectorAll('#checkout_payment li'); 604 paymentListEntries.forEach(function(paymentOption) { 605 if (paymentOption.querySelector('input[name="payment"]:checked') || paymentListEntries.length === 1) { 606 paymentOption.dispatchEvent(new Event('click')); 607 } 608 }); 609 } 610 } 611 612 /**** 613 **** Installment Banners 614 */ 615 616 let initInstallmentBanners = function(amount) { 617 consoleInfo('Initialising PayPal Installments banners', 'CartAmount = ' + payPalBannerSettings.cartAmount); 618 let banners = document.querySelectorAll('.paypal-installments'); 619 banners.forEach(function(bannerElement) { 620 let position = bannerElement.dataset.ppinstPos; 621 consoleInfo('found banner on position ' + position); 622 if (payPalBannerSettings.positions && payPalBannerSettings.positions[position]) { 623 consoleInfo('settings found for position ' + position, payPalBannerSettings.positions[position]); 624 if (payPalBannerSettings.positions[position].style.layout === 'none') { 625 consoleInfo('position disabled: ' + position); 626 return; 627 } 628 629 if (amount === undefined) { 630 amount = 0.00; 631 } 632 if (payPalBannerSettings.cartAmount) { 633 amount += payPalBannerSettings.cartAmount; 634 } 635 if (payPalBannerSettings.productsPrice) { 636 amount += payPalBannerSettings.productsPrice; 637 } else { 638 let p = document.querySelector('div.current-price-container'); 639 if(p) { 640 let priceText = p.innerText; 641 priceText = priceText.replace(/.*?[\d,.]+\s+\D{1,3}.*?([\d,.]+\s+\D{1,3})/s, '$1'); 642 amount += 0.01 * parseFloat(priceText.replace(/.*?(((\d{1,3}[.,])+)(\d{2})).*/, '$1').replace(/[.,]/g, '')); 643 consoleInfo('Product amount for banner: ' + amount); 644 } 645 } 646 if (amount < 99) { 647 consoleInfo('Not showing PayPal Installments banner for amount ' + amount); 648 return; 649 } 650 651 if(bannerElement.classList.contains('paypal-installments-cartbottom')) { 652 let observerTarget = document.querySelector('div.shopping-cart-button'); 653 if (observerTarget) { 654 let cartSumElement = document.querySelector('tr.total.sum td:nth-child(2)'); 655 let amountString = '0'; 656 if(cartSumElement) { 657 amountString = cartSumElement.textContent.trim(); 658 } else { 659 cartSumElement = document.querySelector('tr.footer.total td:nth-child(2)'); 660 if(cartSumElement) { 661 amountString = cartSumElement.textContent.trim() 662 .replace(/(\n|\t|\.|\,)/g, '') 663 .replace(/.*?([0-9.,]+)\s+EUR.*/, '$1'); 664 } 665 } 666 amount = 0.01 * parseInt(amountString.replace(/[^0-9]/g, '')); 667 consoleInfo('cart amount ' + amount); 668 669 let observer = new MutationObserver(function(mutations, observer) { 670 mutations.forEach(function(mutation) { 671 if(mutation.removedNodes.length > 0) { 672 consoleInfo('re-init PayPal installments banner'); 673 initInstallmentBanners(); 674 } 675 }); 676 }); 677 observer.observe(observerTarget, {childList: true}); 678 } 679 } 680 681 paypal.Messages({ 682 amount: amount, 683 currency: payPalBannerSettings.currency, 684 style: payPalBannerSettings.positions[position].style, 685 placement: payPalBannerSettings.positions[position].placement 686 }).render(bannerElement) 687 .then(function() { 688 let legacyInstallmentContainer = document.querySelector('.paypalinstallmentcontainer'); 689 if(legacyInstallmentContainer) { 690 legacyInstallmentContainer.remove(); 691 } 692 }); 693 } 694 }); 695 }; 696 697 let paypalSdkLoaded = function() { 698 consoleInfo('PayPalSDK loaded'); 699 if(window.location.pathname.match(/shopping_cart.php/)) { 700 consoleInfo('Initializing ECS button'); 701 initJSSDKPayPalButtonECS(); 702 } 703 if(window.location.pathname.match(/checkout_payment.php/)) { 704 consoleInfo('Initializing PayPal on payment page'); 705 initCheckoutPayment(); 706 } 707 initInstallmentBanners(); 708 }; 709 710 let disableJavascriptFeatures = function(disable = true) { 711 /* 712 let pppay = document.querySelector('ul:not(.paypal3-plus-checkout) li.gambio_hub-PayPal2Hub'); 713 if (pppay) { 714 consoleInfo('Removing PayPal payment option'); 715 pppay.remove(); 716 } 717 */ 718 719 let newStyle = disable ? 'none' : 'block'; 720 721 let ecsButton = document.querySelector('div#paypal-newbutton'); 722 if (ecsButton) { 723 ecsButton.style.display = newStyle; 724 } 725 726 let ccPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-creditcard'); 727 if (ccPaymentOption) { 728 ccPaymentOption.style.display = newStyle; 729 } 730 731 let puiPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-pui'); 732 if (puiPaymentOption) { 733 puiPaymentOption.style.display = newStyle; 734 } 735 736 let paylaterPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-paylater'); 737 if (paylaterPaymentOption) { 738 paylaterPaymentOption.style.display = newStyle; 739 } 740 741 let sepaPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-sepa'); 742 if (sepaPaymentOption) { 743 sepaPaymentOption.style.display = newStyle; 744 } 745 746 let ecmPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub'); 747 if (ecmPaymentOption && disable) { 748 let paypalModeInput = document.createElement('input'); 749 paypalModeInput.type = 'hidden'; 750 paypalModeInput.name = 'PayPalMode'; 751 paypalModeInput.value = 'sdkless'; 752 ecmPaymentOption.appendChild(paypalModeInput); 753 } 754 } 755 756 let disablePayPalOptions = function(disable = true) { 757 let paymentOptions = document.querySelectorAll('#checkout_payment li.list-group-item'); 758 paymentOptions.forEach((paymentOption, key, parent) => { 759 paymentOption.classList.forEach((className) => { 760 if (className.match(/.*PayPal2Hub.*/)) { 761 if (disable) { 762 paymentOption.querySelector('input[name="payment"]').setAttribute('disabled', 'disabled'); 763 paymentOption.style.opacity = '0.5'; 764 } else { 765 paymentOption.querySelector('input[name="payment"]').removeAttribute('disabled'); 766 paymentOption.style.opacity = '1'; 767 } 768 } 769 }); 770 }); 771 }; 772 773 let enablePayPalOptions = function() { 774 disablePayPalOptions(false); 775 } 776 777 778 let readyCallback = function() { 779 consoleInfo('readyCallback start'); 780 let jssrc = ''; 781 if (typeof (payPalButtonSettings) !== 'undefined' && payPalButtonSettings.jssrc) { 782 jssrc = payPalButtonSettings.jssrc; 783 } else if (typeof (payPalBannerSettings) !== 'undefined' && payPalBannerSettings.jssrc) { 784 jssrc = payPalBannerSettings.jssrc; 785 } 786 let pageHasBanners = document.querySelectorAll('.paypal-installments').length > 0; 787 let isCheckoutPage = window.location.pathname.match(/shopping_cart.php/) || 788 window.location.pathname.match(/checkout_payment.php/); 789 790 let consentGiven = undefined; 791 let purposeId = null; 792 let consentDataElement = document.getElementById('paypalconsent'); 793 if (consentDataElement !== null) { 794 let consentData = JSON.parse(consentDataElement.textContent); 795 purposeId = consentData.purpose_id; 796 let gxConsentsString = document.cookie.split('; ').find((row) => row.startsWith('GXConsents=')); 797 let gxConsents = gxConsentsString ? gxConsentsString.split('=')[1] : null; 798 if (gxConsents) { 799 let gxConsentsData = JSON.parse(gxConsents); 800 consentGiven = gxConsentsData.purposeConsents[''+purposeId]; 801 } 802 } 803 804 if (jssrc && (pageHasBanners || isCheckoutPage) && typeof(window.paypal) === 'undefined') { 805 let loadTimeout = null; 806 807 let onPayPalSdkLoad = function() { 808 clearTimeout(loadTimeout); 809 paypalSdkLoaded(); 810 disableJavascriptFeatures(false); 811 enablePayPalOptions(); 812 }; 813 let onPayPalSdkError = function() { 814 consoleInfo('ERROR loading PayPal Javascript - blocked?'); 815 consoleInfo('PayPal JSSDK unavailable, disabling features'); 816 disableJavascriptFeatures(); 817 enablePayPalOptions(); 818 }; 819 window.initPayPalJSSDK = function() { 820 if (typeof(window.paypal) !== 'undefined') { 821 return; 822 } 823 let jssdk = document.createElement('script'); 824 jssdk.src = payPalButtonSettings.jssrc ? payPalButtonSettings.jssrc : payPalBannerSettings.jssrc; 825 826 let acdcIdentity = document.querySelector('#paypal_cc_i
826dentity'); 827 if (acdcIdentity !== null) { 828 let clientIdentity = JSON.parse(acdcIdentity.textContent); 829 if (typeof clientIdentity.client_token !== 'undefined') { 830 jssdk.dataset.clientToken = clientIdentity.client_token; 831 } 832 } 833 jssdk.onerror = onPayPalSdkError; 834 jssdk.onload = onPayPalSdkLoad; 835 836 if(document.currentScript) { 837 document.currentScript.parentNode.insertBefore(jssdk, document.currentScript); 838 } else { 839 document.querySelector('script:last-of-type').parentNode.appendChild(jssdk); 840 } 841 } 842 843 disablePayPalOptions(); 844 if (purposeId !== null) { 845 consoleInfo("External PayPal Javascript is managed by CookieConsent, purpose " + purposeId); 846 if (window.PayPalAsOilClearToLoad) { 847 consoleInfo('OIL has cleared PayPal to load'); 848 window.initPayPalJSSDK(); 849 } else { 850 consoleInfo('OIL has not yet cleared PayPal to load'); 851 disableJavascriptFeatures(); 852 window.addEventListener('PayPalClearedToLoad', evt => { 853 consoleInfo('OIL has cleared PayPal to load (Event)'); 854 window.initPayPalJSSDK(); 855 }); 856 if (isCheckoutPage) { 857 consoleInfo('on checkout page; waiting 5s for OIL') 858 loadTimeout = setTimeout(onPayPalSdkError, 5000); 859 } 860 } 861 } else { 862 console.info("Not using CookieConsent integration for PayPal, loading directly"); 863 window.initPayPalJSSDK(); 864 } 865 } else { 866 consoleInfo('PayPal JSSDK unavailable or not required, disabling features'); 867 disableJavascriptFeatures(); 868 } 869 consoleInfo('readyCallback end'); 870 }; 871 872 let mainCallback = ("fetch" in window) ? readyCallback : handleAntiqueBrowser; 873 874 if(document.readyState === 'complete' || (document.readyState !== 'loading' && !document.documentElement.doScroll)) { 875 consoleInfo('Readystate complete'); 876 mainCallback(); 877 } else { 878 consoleInfo('Adding EventListener for DOMContentLoaded'); 879 document.addEventListener('DOMContentLoaded', mainCallback); 880 } 881 882}());
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.