PageSourceSearch

https://shop.villa-zanders.de/GXModules/Gambio/Hub/Shop/Javascript/PayPalLoader.js?v=1708940671

js villa-zanders.de collected 2026-09-24 22:28:58 UTC 37,793 bytes, 882 lines download raw bytes

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.