PageSourceSearch

https://www.zweirad-dineiger.com/GXModules/Gambio/Hub/Shop/Javascript/PayPalLoader-bust_1771317833.js

js zweirad-dineiger.com collected 2026-10-08 16:30:01 UTC 43,061 bytes, 1,014 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: async function(data, actions) {
106                return await createOrderWithOrWithoutVault()
107            },
108			onApprove: function(data, actions) {
109				consoleInfo('Approved data:', data);
110				return fetch(payPalButtonSettings.approvedOrderUrl + '&orderId=' + data.orderID, {
111					method: 'post',
112					headers: {
113						'Content-Type': 'application/json'
114					},
115					body: JSON.stringify(data)
116				})
117					.then((res) => { return res.json(); })
118					.then((responsedata) => {
119						consoleInfo('response data:', responsedata);
120						document.location = payPalButtonSettings.checkoutUrl;
121					});
122			},
123			onError: function(err) {
124				let ppButtonContainer = document.querySelector('#paypal-button-container');
125				let ecsIntro = document.querySelector('div.ecs_intro');
126				if(ppButtonContainer) {
127					let errorMessage = document.querySelector('div.paypal-error');
128					if(!errorMessage) {
129						errorMessage = document.createElement('div');
130						errorMessage.classList.add('paypal-error');
131						errorMessage.classList.add('alert');
132						errorMessage.classList.add('alert-warning');
133						errorMessage.style.textAlign = 'left';
134						errorMessage.style.color = '#555';
135					}
136					errorMessage.innerText = payPalText.paypalUnavailable + ' ';
137					let shoppingCartButton = document.querySelector('div.shopping-cart-button');
138					if(shoppingCartButton && shoppingCartButton.classList.contains('paypal-ecs-mode')) {
139						let linkUrl = window.location.toString().replace('display_mode=ecs', 'display_mode=normal');
140						let continueLink = document.createElement('a');
141						continueLink.setAttribute('href', linkUrl);
142						continueLink.innerText = payPalText.errorContinue;
143						errorMessage.append(continueLink);
144					}
145					ppButtonContainer.parentNode.append(errorMessage);
146					ppButtonContainer.style.display = 'none';
147				}
148				if(ecsIntro) {
149					ecsIntro.style.display = 'none';
150				}
151			}
152		}).render('#paypal-button-container');
153
154		let observerTarget = document.querySelector('#paypal-button-container');
155		let observer = new MutationObserver(function(mutations, observer) {
156			mutations.forEach(function(mutation) {
157				if(mutation.removedNodes.length > 0) {
158					consoleInfo('re-init PayPal buttons');
159                    let totalSumCell = document.querySelector('tr.total.sum td:nth-child(2)');
160                    if (totalSumCell) {
161                        let amount = parseFloat(totalSumCell.textContent.replace(/[^0-9]/g, '')) / 100;
162                        initJSSDKPayPalButtonECS(amount);
163                        initInstallmentBanners(amount);
164                    } else {
165                        initJSSDKPayPalButtonECS();
166                        initInstallmentBanners();
167                    }
168				}
169			});
170		});
171		observer.observe(observerTarget, {childList: true});
172        appendVaultCheckbox(buttonContainer)
173	};
174
175    
176    let addButtonContainerDecoration = function(buttonContainer, continueButtonBlock)
177    {
178        buttonContainer.style.width = 'auto';
179        buttonContainer.style.textAlign = 'center';
180        buttonContainer.style.fontStyle = 'italic';
181        if (payPalText.continueToPayPal) {
182            let labelToButtonDistance = 3;
183            let lineHeight = '-' + window.getComputedStyle(continueButtonBlock).lineHeight;
184            buttonContainer.style.marginTop = 'calc(' + lineHeight + ' - ' + labelToButtonDistance + 'px)';
185            let continueLabel = document.createElement('span');
186            continueLabel.classList.add('paypal-continue-label');
187            continueLabel.textContent = payPalText.continueToPayPal
188            continueLabel.style.paddingBottom = labelToButtonDistance + 'px'; 
189            buttonContainer.appendChild(continueLabel) ;
190        }
191    }
192    
193    
194	let initJSSDKPayPalButtonECM = function(continueButtonBlock)
195	{
196        let paypalButtonContainer = document.createElement('div');
197        
198        paypalButtonContainer.id = 'paypal-button-container';
199        paypalButtonContainer.style.display = 'none';
200        addButtonContainerDecoration(paypalButtonContainer, continueButtonBlock);
201        continueButtonBlock.appendChild(paypalButtonContainer);
202		paypal.Buttons({
203            fundingSource: 'paypal',
204			style: payPalButtonSettings.style,
205			createOrder: async function(data, actions) {
206                return await createOrderWithOrWithoutVault(payPalButtonSettings.usePayNow)
207			},
208			onApprove: function(data, actions) {
209				document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID;
210				document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID;
211                document.querySelector('#checkout_payment input[name="PayPal2HubPaymentInitiator"]').value = 'ecm';
212				document.querySelector('#checkout_payment').submit();
213			}
214		}).render('#paypal-button-container');
215        appendVaultCheckbox(paypalButtonContainer)
216        return paypalButtonContainer;
217	}
218
219    /**
220     * Show save payment option.
221     * @param paypalButtonContainer
222     * @returns {*}
223     */
224    function appendVaultCheckbox(paypalButtonContainer) {
225        if (payPalButtonSettings.useVault !== true) {
226            //no enable vault
227            return;
228        }
229        // only enable for shop enable vault and customer has'not using vault yet.
230        if (!isCustomerUsingVaultToken()) {
231            // Checkbox already exists in the container
232            if (paypalButtonContainer.querySelector('#paypal-vaulting-checkbox')) {
233                return;
234            }
235            const labelTexts = {
236                "en_US": "Save PayPal account for future payments",
237                "de_DE": "Für zukünftige Einkäufe speichern"
238            }
239            const divTag = document.createElement('div');
240            divTag.id = 'paypal-vaulting-div'
241            divTag.style.marginTop = '3px'  
242            const checkbox = document.createElement('input');
243            checkbox.type = 'checkbox';
244            checkbox.id = 'paypal-vaulting-checkbox';
245            checkbox.value = true;
246            // Create the label
247            const label = document.createElement('label');
248            label.htmlFor = 'paypal-vaulting-checkbox';
249            label.style.display = 'inline'
250            label.style.marginLeft = '3px'
251            label.textContent = labelTexts[payPalButtonSettings.locale] || labelTexts["de_DE"];
252        
253            // Append the checkbox and label to the DOM (e.g., to the body)
254            divTag.appendChild(checkbox);
255            divTag.appendChild(label);
256            paypalButtonContainer.appendChild(divTag)
257        } else {
258            appendCustomVaultCss()
259        }
260    }
261
262    /**
263     * Append some customer css class for vault
264     */
265    function appendCustomVaultCss() {
266        try {
267            const paypalContainer = document.getElementById('paypal-button-container');
268            if (!paypalContainer) return;
269
270            const isShoppingCart = document.querySelector('.shopping-cart-button');
271            const isCheckout = document.querySelector('.continue_button');
272
273            if (isShoppingCart) {
274                paypalContainer.classList.add('paypal-shopping-cart-vault');
275            } else if (isCheckout) {
276                paypalContainer.classList.add('paypal-checkout-vault');
277
278                const continueButton = document.querySelector('.continue_button');
279                const backButton = document.querySelector('.back_button');
280                if (continueButton) {
281                    continueButton.classList.add('continue_button_vault');
282                }
283                if (backButton) {
284                    backButton.classList.add('back_button_vault');
285                }
286            }
287        } catch (error) {
288            console.error('Error appending custom vault CSS:', error);
289        }
290    }
291
292
293    /**
294     * Check customer is using vault token
295     * @returns {boolean}
296     */
297    function isCustomerUsingVaultToken() {
298        const vaultToken = payPalButtonSettings.vaultToken;
299        
300        return vaultToken !== null && typeof vaultToken !== 'undefined' && vaultToken !== "";
301    }
302
303
304    /**
305     * Separate a function create order with or without vault for paypal button
306     * @returns {Promise<*>}
307     */
308    async function createOrderWithOrWithoutVault(payNow = false) {
309        const url = new URL(payPalButtonSettings.createOrderUrl);
310        if (payNow === true || payNow === 'true') {
311            url.searchParams.set('payNow', 'true');
312        }
313        const vaultCheckbox = document.getElementById('paypal-vaulting-checkbox');
314        let shouldVault = ((vaultCheckbox && vaultCheckbox.checked) || isCustomerUsingVaultToken());
315        if (payPalButtonSettings.useVault === true && shouldVault === true) {
316            url.searchParams.set('vault', 'true');
317            url.searchParams.set('payment_method', 'paypal');
318        }
319        const response = await fetch(url.toString(), {
320            method: 'POST',
321            headers: {
322                'Content-Type': 'application/json'
323            }
324        });
325        const data = await response.json();
326        return data.id;
327    }
328
329    
330    let initPayLaterButton = function(continueButtonBlock)
331    {
332        let payLaterItem = document.querySelector('li.gambio_hub-PayPal2Hub-paylater');
333        if (payLaterItem === null) {
334            return null;
335        }
336    
337        let paylaterButton = paypal.Buttons({
338            fundingSource: 'paylater',
339            style: payPalButtonSettings.style,
340            createOrder: function(data, actions) {
341                return fetch(payPalButtonSettings.createOrderUrl, {
342                    method: 'post',
343                    headers: {
344                        'Content-Type': 'application/json'
345                    }
346                })
347                    .then((res) => { return res.json() })
348                    .then((orderdata) => {
349                        consoleInfo('order created: ' + orderdata.id, orderdata);
350                        return orderdata.id;
351                    });
352            },
353            onApprove: function(data, actions) {
354                document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID;
355                document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID;
356                document.querySelector('#checkout_payment').submit();
357            }
358        });
359    
360        if (paylaterButton.isEligible()) {
361            let paylaterButtonId = 'paypal-paylater-button-container',
362                paylaterButtonContainer = document.createElement('div');
363            paylaterButtonContainer.id = paylaterButtonId;
364            paylaterButtonContainer.style.display = 'none';
365            addButtonContainerDecoration(paylaterButtonContainer, continueButtonBlock);
366            continueButtonBlock.appendChild(paylaterButtonContainer);
367            paylaterButton.render('#' + paylaterButtonId);
368            consoleInfo('PayPal Paylater: eligible and initialized');
369            return paylaterButtonContainer;
370        } else {
371            consoleInfo('PayPal Paylater: not eligible');
372            payLaterItem.remove();
373        }
374        
375        return null;
376    }
377    
378    
379    let initSepaButton = function(continueButtonBlock)
380    {
381        let sepaItem = document.querySelector('li.gambio_hub-PayPal2Hub-sepa');
382        if (sepaItem === null) {
383            return null;
384        }
385        let sepaButtonStyle = payPalButtonSettings.style;
386        if (sepaButtonStyle.color === 'gold' || sepaButtonStyle.color === 'blue') {
387            sepaButtonStyle.color = 'silver';
388        }
389        
390        let sepaButton = paypal.Buttons({
391            fundingSource: 'sepa',
392            style: payPalButtonSettings.style,
393            createOrder: function(data, actions) {
394                return fetch(payPalButtonSettings.createOrderUrl, {
395                    method: 'post',
396                    headers: {
397                        'Content-Type': 'application/json'
398                    }
399                })
400                    .then((res) => { return res.json() })
401                    .then((orderdata) => {
402                        consoleInfo('order created: ' + orderdata.id, orderdata);
403                        return orderdata.id;
404                    });
405            },
406            onApprove: function(data, actions) {
407                document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID;
408                document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID;
409                document.querySelector('#checkout_payment').submit();
410            }
411        });
412        
413        if (sepaButton.isEligible()) {
414            let sepaButtonId = 'paypal-sepa-button-container',
415                sepaButtonContainer = document.createElement('div');
416            sepaButtonContainer.id = sepaButtonId;
417            sepaButtonContainer.style.display = 'none';
418            addButtonContainerDecoration(sepaButtonContainer, continueButtonBlock);
419            continueButtonBlock.appendChild(sepaButtonContainer);
420            sepaButton.render('#' + sepaButtonId);
421            consoleInfo('PayPal SEPA: eligible and initialized');
422            return sepaButtonContainer;
423        } else {
424            consoleInfo('PayPal SEPA: not eligible');
425            sepaItem.remove();
426        }
427        
428        return null;
429    }
430    
431    
432    let initCreditCardButton = function(continueButtonBlock)
433    {
434        let brandedCreditCardsItem = document.querySelector('li.gambio_hub-PayPal2Hub-creditcardbutton');
435        if (brandedCreditCardsItem === null) {
436            return null;
437        }
438        
439        let cardButtonStyle = payPalButtonSettings.style;
440        cardButtonStyle.color = 'black';
441        cardButtonStyle.shape = 'pill';
442
443        let creditCardButton = paypal.Buttons({
444            fundingSource: 'card',
445            style: cardButtonStyle,
446            createOrder: function(data, actions) {
447                return fetch(payPalButtonSettings.createOrderUrl, {
448                    method: 'post',
449                    headers: {
450                        'Content-Type': 'application/json'
451                    }
452                })
453                    .then((res) => { return res.json() })
454                    .then((orderdata) => {
455                        consoleInfo('order created: ' + orderdata.id, orderdata);
456                        return orderdata.id;
457                    });
458            },
459            onApprove: function(data, actions) {
460                document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]').value = data.orderID;
461                document.querySelector('#checkout_payment input[name="PayPal2HubPayerId"]').value = data.payerID;
462                document.querySelector('#checkout_payment').submit();
463            }
464        });
465        
466        consoleInfo(creditCardButton);
467        
468        if (creditCardButton.isEligible()) {
469            consoleInfo('Eligible for branded cc payments');
470            let creditCardButtonId = 'paypal-creditcard-button-container',
471                creditCardButtonContainer = document.createElement('div');
472            creditCardButtonContainer.id = creditCardButtonId;
473            creditCardButtonContainer.style.display = 'none';
474            addButtonContainerDecoration(creditCardButtonContainer, continueButtonBlock);
475            continueButtonBlock.appendChild(creditCardButtonContainer);
476            creditCardButton.render('#' + creditCardButtonId);
477            return creditCardButtonContainer;
478        } else {
479            consoleInfo('NOT eligible for branded cc payments');
480            brandedCreditCardsItem.remove();
481        }
482        
483        return null;
484    }
485    
486
487    let initHostedCreditCard = function() {
488        let theLabel = document.querySelector('#ppcc-card-holder-field').closest('label'),
489            theDiv = document.createElement('div');
490    
491        theDiv.classList.add('payment-module-container');
492        theLabel.parentNode.appendChild(theDiv);
493        while(theLabel.hasChildNodes()) {
494            theDiv.appendChild(theLabel.firstChild);
495        }
496        theLabel.remove();
497        
498        let theListItem = document.querySelector('li.gambio_hub-PayPal2Hub-creditcard');
499        theListItem.style.cursor = 'pointer';
500        theListItem.addEventListener('click', function() {
501            $(this).find('input:radio:not(:disabled):not(.placeholder-radio)').first().prop('checked', true).trigger('change');
502        });
503    
504        let cardHolderField = document.querySelector('#ppcc-card-holder-field'),
505            fieldStyle = getComputedStyle(cardHolderField),
506            orderIdElement = document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]');
507    
508        paypal.HostedFields.render({
509            createOrder: function() {
510                return fetch(payPalButtonSettings.createOrderUrl, {
511                    method: 'post',
512                    headers: {
513                        'Content-Type': 'application/json'
514                    }
515                })
516                    .then((res) => {
517                        return res.json()
518                    })
519                    .then((orderdata) => {
520                        orderIdElement.value = orderdata.id;
521                        consoleInfo('credit card order created: ' + orderdata.id, orderdata);
522                        return orderdata.id;
523                    });
524            },
525            styles: {
526                'input': {
527                    'color': fieldStyle.color,
528                    'font-size': fieldStyle.fontSize,
529                    'font-family': fieldStyle.fontFamily,
530                    'padding': fieldStyle.padding,
531                    'line-height': fieldStyle.lineHeight
532                },
533                '.valid': {
534                    'color': 'green'
535                },
536                '.invalid': {
537                    'color': 'red'
538                }
539            },
540            fields: {
541                number: {
542                    'selector': '#ppcc-card-number',
543                    'placeholder': '4111111111111111',
544                },
545                cvv: {
546                    'selector': '#ppcc-cvv',
547                    'placeholder': '123',
548                },
549                expirationDate: {
550                    'selector': '#ppcc-expiration-date',
551                    'placeholder': 'MM/YY',
552                }
553            }
554        }).then(function(cardFields) {
555            consoleInfo('PayPal: CC fields initialized', cardFields);
556            let paymentForm = document.querySelector('#checkout_payment');
557            let cardFieldsSubmitted = false;
558            paymentForm.addEventListener('submit', function(event) {
559                if (cardFieldsSubmitted === false && paymentForm.payment.value === 'gambio_hub-PayPal2Hub-creditcard') {
560                    event.preventDefault();
561                    let billingAddressData = JSON.parse(document.querySelector('#ppcc-billingaddress').textContent);
562                    cardFields.submit({
563                        cardholderName: paymentForm.ppcc_card_holder.value,
564                        billingAddress: billingAddressData,
565                        contingencies: ['SCA_WHEN_REQUIRED']
566                    }).then(function() {
567                        // OK
568                        consoleInfo('cardFields submitted');
569                        cardFieldsSubmitted = true;
570                        paymentForm.submit();
571                    }).catch(function(err) {
572                        orderIdElement.value = '';
573                        consoleInfo(err);
574                        alert(payPalText.errorCheckData);
575                        document.querySelector('input[name="payment"]:checked').scrollIntoView(false);
576                    });
577                }
578            });
579        });
580    }
581    let initLoadingButton = function (continueButtonBlock) {
582        const loadingButtonId = 'loading-button-container'
583        let loadingButtonContainer = document.createElement('div');
584        loadingButtonContainer.id = loadingButtonId;
585        loadingButtonContainer.style.display = 'none';
586        loadingButtonContainer.style.width = 'auto';
587        loadingButtonContainer.style.verticalAlign = 'inherit'
588        loadingButtonContainer.style.backgroundImage = "url(https://cdn.gambiohub.com/sdk/images/loading.gif)"
589        loadingButtonContainer.style.backgroundSize = "contain"
590        loadingButtonContainer.style.backgroundRepeat = "no-repeat"
591        loadingButtonContainer.style.backgroundPosition = "center"
592        let parentHeight = continueButtonBlock.clientHeight;
593        loadingButtonContainer.style.height = parentHeight + 'px';
594        window.addEventListener('showLoadingButton', evt => {
595            loadingButtonContainer.style.display = 'block';
596        });
597        window.addEventListener('hideLoadingButton', evt => {
598            loadingButtonContainer.style.display = 'none';
599        });
600        continueButtonBlock.appendChild(loadingButtonContainer);
601    }
602
603    let initAlternativePaymentMethod =  function ()  {
604        try {
605            let loader = new PayPalAlternativePaymentMethodLoader.PayPalAlternativePaymentMethodLoader();
606            return loader.load();
607        } catch (err) {
608            consoleInfo(err)
609            return [];
610        }
611
612    }
613    
614	let initCheckoutPayment = function() {
615		let continueButtonBlock = document.querySelector('#checkout_payment div.continue_button'),
616			continueButton = continueButtonBlock.querySelector('input[type="submit"]'),
617			continueButtonDisplay = continueButton.style.display,
618			paypalButtonContainer = document.createElement('div'),
619			plusContainer = document.querySelector('#gambiohub-ppplus'),
620            ccForm = document.querySelector('div.paypal-cc-form'),
621            orderIdElement = document.querySelector('#checkout_payment input[name="PayPal2HubOrderId"]'),
622            ccCardHolderFieldForm = document.querySelector('#paypal-cardfields-form-container');
623        
624        if (plusContainer === null && ccForm !== null && ccCardHolderFieldForm === null) {
625            consoleInfo('PayPal: Credit Card form found on page.');
626            let hostedFieldsEligible = paypal.HostedFields.isEligible();
627            let brandedCreditCardsOption = document.querySelector('li.gambio_hub-PayPal2Hub-creditcardbutton');
628            if (hostedFieldsEligible) {
629                consoleInfo('PayPal: eligible for hosted fields');
630                if (brandedCreditCardsOption) {
631                    brandedCreditCardsOption.remove();
632                }
633                
634                initHostedCreditCard();
635            }
636            else {
637                consoleInfo('PayPal: NOT eligible for hosted fields');
638                let ccListItem = document.querySelector('li.gambio_hub-PayPal2Hub-creditcard');
639                if (ccListItem) {
640                    ccListItem.remove();
641                }
642            }
643        }
644
645		if (plusContainer === null && !payPalButtonSettings.paymentApproved) {
646            let backButtonBlock = continueButtonBlock.parentElement.querySelector('div.back_button');
647            if (backButtonBlock !== null && backButtonBlock.classList.contains('col-xs-6')) {
648                backButtonBlock.classList.remove('col-xs-6');
649                backButtonBlock.classList.add('col-xs-4');
650                continueButtonBlock.classList.remove('col-xs-6');
651                continueButtonBlock.classList.add('col-xs-8');
652                let backButton = backButtonBlock.querySelector('a.btn');
653                let height = parseInt(getComputedStyle(backButton).height);
654                if (isNaN(height)) {
655                    height = 25; // fallback
656                }
657
658                if (height < 25) height = 25;
659                if (height > 50) height = 50;
660                payPalButtonSettings.style.height = height;
661            }
662            let promises = initAlternativePaymentMethod();
663            initJSSDKPayPalButtonECM(continueButtonBlock);
664            initPayLaterButton(continueButtonBlock);
665            initCreditCardButton(continueButtonBlock);
666            initSepaButton(continueButtonBlock);
667            initLoadingButton(continueButtonBlock);
668            let payPalContainerButtonConfig = [
669                {
670                    'value' : 'gambio_hub-PayPal2Hub',
671                    'container' : 'paypal-button-container'
672                },
673                {
674                    'value' : 'gambio_hub-PayPal2Hub-paylater',
675                    'container' : 'paypal-paylater-button-container'
676                },
677                {
678                    'value' : 'gambio_hub-PayPal2Hub-sepa',
679                    'container' : 'paypal-sepa-button-container'
680                },
681                {
682                    'value' : 'gambio_hub-PayPal2Hub-creditcardbutton',
683                    'container' : 'paypal-creditcard-button-container'
684                },
685                {
686                    'value' : 'loading-button-container',
687                    'container' : 'loading-button-container'
688                },
689            ];
690			let paymentItemClickListener = function() {
691				let selected_payment = this.querySelector('input[name="payment"]');
692                if (null !== selected_payment) {
693                    let showDefaultButton = true;
694                    let selectedPaymentValue = selected_payment.value;
695                    if (selectedPaymentValue === 'gambio_hub' && selected_payment.dataset.module_code === 'PayPal2Hub') {
696                        selectedPaymentValue = 'gambio_hub-PayPal2Hub'
697                    }
698                    payPalContainerButtonConfig.forEach((item) => {
699                        let button =  document.getElementById(item.container);
700                        if (button) {
701                            if (item.value === selectedPaymentValue) {
702                                showDefaultButton = false;
703                                button.style.display = 'block'
704                                continueButton.style.display = 'none';
705                            } else  {
706                                button.style.display = 'none'
707                            }
708                        }
709                    });
710                    if (showDefaultButton === true) {
711                        continueButton.style.display = continueButtonDisplay;
712                    }
713                }
714			};
715
716            Promise.allSettled(promises).then((results) => {
717                results.forEach((result) => {
718                    if (result.status === 'fulfilled' && result.value) {
719                        payPalContainerButtonConfig.push(result.value)
720                    }
721                })
722                let paymentItems = document.querySelectorAll('#checkout_payment input[name="payment"], #checkout_payment li.list-group-item');
723                paymentItems.forEach(function(paymentItem) {
724                    paymentItem.addEventListener('click', paymentItemClickListener)
725                });
726
727                let paymentListEntries = document.querySelectorAll('#checkout_payment li');
728                paymentListEntries.forEach(function(paymentOption) {
729                    if (paymentOption.querySelector('input[name="payment"]:checked') || paymentListEntries.length === 1) {
730                        paymentOption.dispatchEvent(new Event('click'));
731                    }
732                });
733            });
734		}
735	}
736
737	/****
738	 ****  Installment Banners
739 	 */
740
741	let initInstallmentBanners = function(amount) {
742		consoleInfo('Initialising PayPal Installments banners', 'CartAmount = ' + payPalBannerSettings.cartAmount);
743		let banners = document.querySelectorAll('.paypal-installments');
744		banners.forEach(function(bannerElement) {
745			let position = bannerElement.dataset.ppinstPos;
746			consoleInfo('found banner on position ' + position);
747			if (payPalBannerSettings.positions && payPalBannerSettings.positions[position]) {
748				consoleInfo('settings found for position ' + position, payPalBannerSettings.positions[position]);
749				if (payPalBannerSettings.positions[position].style.layout === 'none') {
750					consoleInfo('position disabled: ' + position);
751					return;
752				}
753
754				if (amount === undefined) {
755                    amount = 0.00;
756                }
757				if (payPalBannerSettings.cartAmount) {
758					amount += payPalBannerSettings.cartAmount;
759				}
760                if (payPalBannerSettings.productsPrice) {
761                    amount += payPalBannerSettings.productsPrice;
762                } else {
763					let p = document.querySelector('div.current-price-container');
764					if(p) {
765						let priceText = p.innerText;
766						priceText = priceText.replace(/.*?[\d,.]+\s+\D{1,3}.*?([\d,.]+\s+\D{1,3})/s, '$1');
767						amount += 0.01 * parseFloat(priceText.replace(/.*?(((\d{1,3}[.,])+)(\d{2})).*/, '$1').replace(/[.,]/g, ''));
768						consoleInfo('Product amount for banner: ' + amount);
769					}
770                }
771				if (amount < 99) {
772					consoleInfo('Not showing PayPal Installments banner for amount ' + amount);
773                    return;
774				}
775
776				if(bannerElement.classList.contains('paypal-installments-cartbottom')) {
777					let observerTarget = document.querySelector('div.shopping-cart-button');
778					if (observerTarget) {
779						let cartSumElement = document.querySelector('tr.total.sum td:nth-child(2)');
780						let amountString = '0';
781						if(cartSumElement) {
782							amountString = cartSumElement.textContent.trim();
783						} else {
784							cartSumElement = document.querySelector('tr.footer.total td:nth-child(2)');
785							if(cartSumElement) {
786								amountString = cartSumElement.textContent.trim()
787									.replace(/(\n|\t|\.|\,)/g, '')
788									.replace(/.*?([0-9.,]+)\s+EUR.*/, '$1');
789							}
790						}
791                        amount = 0.01 * parseInt(amountString.replace(/[^0-9]/g, ''));
792						consoleInfo('cart amount ' + amount);
793
794						let observer = new MutationObserver(function(mutations, observer) {
795							mutations.forEach(function(mutation) {
796								if(mutation.removedNodes.length > 0) {
797									consoleInfo('re-init PayPal installments banner');
798									initInstallmentBanners();
799								}
800							});
801						});
802						observer.observe(observerTarget, {childList: true});
803					}
804				}
805
806				paypal.Messages({
807					amount: amount,
808					currency: payPalBannerSettings.currency,
809					style: payPalBannerSettings.positions[position].style,
810					placement: payPalBannerSettings.positions[position].placement
811				}).render(bannerElement)
812                    .then(function() {
813                        let legacyInstallmentContainer = document.querySelector('.paypalinstallmentcontainer');
814                        if(legacyInstallmentContainer) {
815                            legacyInstallmentContainer.remove();
816                        }
817                    });
818			}
819		});
820	};
821
822	let paypalSdkLoaded = function() {
823		consoleInfo('PayPalSDK loaded');
824		if(window.location.pathname.match(/shopping_cart.php/)) {
825			consoleInfo('Initializing ECS button');
826			initJSSDKPayPalButtonECS();
827		}
828		if(window.location.pathname.match(/checkout_payment.php/)) {
829			consoleInfo('Initializing PayPal on payment page');
830			initCheckoutPayment();
831		}
832		initInstallmentBanners();
833	};
834
835    let disableJavascriptFeatures = function(disable = true) {
836        /*
837        let pppay = document.querySelector('ul:not(.paypal3-plus-checkout) li.gambio_hub-PayPal2Hub');
838        if (pppay) {
839            consoleInfo('Removing PayPal payment option');
840            pppay.remove();
841        }
842        */
843
844        let newStyle = disable ? 'none' : 'block';
845        
846        let ecsButton = document.querySelector('div#paypal-newbutton');
847        if (ecsButton) {
848            ecsButton.style.display = newStyle;
849        }
850
851        let ccPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-creditcard');
852        if (ccPaymentOption) {
853            ccPaymentOption.style.display = newStyle;
854        }
855        
856        let puiPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-pui');
857        if (puiPaymentOption) {
858            puiPaymentOption.style.display = newStyle;
859        }
860        
861        let paylaterPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-paylater');
862        if (paylaterPaymentOption) {
863            paylaterPaymentOption.style.display = newStyle;
864        }
865    
866        let sepaPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub-sepa');
867        if (sepaPaymentOption) {
868            sepaPaymentOption.style.display = newStyle;
869        }
870    
871        let ecmPaymentOption = document.querySelector('#checkout_payment li.gambio_hub-PayPal2Hub');
872        if (ecmPaymentOption && disable) {
873            let paypalModeInput = document.createElement('input');
874            paypalModeInput.type = 'hidden';
875            paypalModeInput.name = 'PayPalMode';
876            paypalModeInput.value = 'sdkless';
877            ecmPaymentOption.appendChild(paypalModeInput);
878        }
879    }
880    
881    let disablePayPalOptions = function(disable = true) {
882        let paymentOptions = document.querySelectorAll('#checkout_payment li.list-group-item');
883        paymentOptions.forEach((paymentOption, key, parent) => {
884            paymentOption.classList.forEach((className) => {
885                if (className.match(/.*PayPal2Hub.*/)) {
886                    if (disable) {
887                        paymentOption.querySelector('input[name="payment"]').setAttribute('disabled', 'disabled');
888                        paymentOption.style.opacity = '0.5';
889                    } else {
890                        paymentOption.querySelector('input[name="payment"]').removeAttribute('disabled');
891                        paymentOption.style.opacity = '1';
892                    }
893                }
894            });
895        });
896    };
897    
898    let enablePayPalOptions = function() {
899        disablePayPalOptions(false);
900    }
901    
902    
903	let readyCallback = function() {
904        consoleInfo('readyCallback start');
905		let jssrc = '';
906        if (typeof (payPalButtonSettings) !== 'undefined' && payPalButtonSettings.jssrc) {
907            jssrc = payPalButtonSettings.jssrc;
908        } else if (typeof (payPalBannerSettings) !== 'undefined' && payPalBannerSettings.jssrc) {
909            jssrc = payPalBannerSettings.jssrc;
910        }
911        let pageHasBanners = document.querySelectorAll('.paypal-installments').length > 0;
912        let isCheckoutPage = window.location.pathname.match(/shopping_cart.php/) ||
913            window.location.pathname.match(/checkout_payment.php/);
914        
915        let consentGiven = undefined;
916        let purposeId = null;
917        let consentDataElement = document.getElementById('paypalconsent');
918        if (consentDataElement !== null) {
919            let consentData = JSON.parse(consentDataElement.textContent);
920            purposeId = consentData.purpose_id;
921            let gxConsentsString = document.cookie.split('; ').find((row) => row.startsWith('GXConsents='));
922            let gxConsents = gxConsentsString ? gxConsentsString.split('=')[1] : null;
923            if (gxConsents) {
924                let gxConsentsData = JSON.parse(gxConsents);
925                consentGiven = gxConsentsData.purposeConsents[''+purposeId];
926            }
927        }
928        
929        if (jssrc && (pageHasBanners || isCheckoutPage) && typeof(window.paypal) === 'undefined') {
930            let loadTimeout = null;
931            
932            let onPayPalSdkLoad = function() {
933                clearTimeout(loadTimeout);
934                paypalSdkLoaded();
935                disableJavascriptFeatures(false);
936                enablePayPalOptions();
937            };
938            let onPayPalSdkError = function() {
939                consoleInfo('ERROR loading PayPal Javascript - blocked?');
940                consoleInfo('PayPal JSSDK unavailable, disabling features');
941                disableJavascriptFeatures();
942                enablePayPalOptions();
943            };
944            window.initPayPalJSSDK = function() {
945                if (typeof(window.paypal) !== 'undefined') {
946                    return;
947                }
948                let jssdk = document.createElement('script');
949                jssdk.src = payPalButtonSettings.jssrc ? payPalButtonSettings.jssrc : payPalBannerSettings.jssrc;
950                if (payPalButtonSettings.useVault === true && isCustomerUsingVaultToken()) {
951                    jssdk.setAttribute('data-user-id-token', payPalButtonSettings.vaultToken);
952                }
953                if (
954                    payPalButtonSettings.partnerAttributionId !== null &&
955                    payPalButtonSettings.partnerAttributionId !== undefined) {
956                    jssdk.setAttribute('data-partner-attribution-id', payPalButtonSettings.partnerAttributionId);
957                }
958                let acdcIdentity = document.querySelector('#paypal_cc_i
958dentity');
959                if (acdcIdentity !== null) {
960                    let clientIdentity = JSON.parse(acdcIdentity.textContent);
961                    if (typeof clientIdentity.client_token !== 'undefined') {
962                        jssdk.dataset.clientToken = clientIdentity.client_token;
963                    }
964                }
965                jssdk.onerror = onPayPalSdkError;
966                jssdk.onload = onPayPalSdkLoad;
967    
968                if(document.currentScript) {
969                    document.currentScript.parentNode.insertBefore(jssdk, document.currentScript);
970                } else {
971                    document.querySelector('script:last-of-type').parentNode.appendChild(jssdk);
972                }
973            }
974            
975            disablePayPalOptions();
976            if (purposeId !== null) {
977                consoleInfo("External PayPal Javascript is managed by CookieConsent, purpose " + purposeId);
978                if (window.PayPalAsOilClearToLoad) {
979                    consoleInfo('OIL has cleared PayPal to load');
980                    window.initPayPalJSSDK();
981                } else {
982                    consoleInfo('OIL has not yet cleared PayPal to load');
983                    disableJavascriptFeatures();
984                    window.addEventListener('PayPalClearedToLoad', evt => {
985                        consoleInfo('OIL has cleared PayPal to load (Event)');
986                        window.initPayPalJSSDK();
987                    });
988                    if (isCheckoutPage) {
989                        consoleInfo('on checkout page; waiting 5s for OIL')
990                        loadTimeout = setTimeout(onPayPalSdkError, 5000);
991                    }
992                }
993            } else {
994                console.info("Not using CookieConsent integration for PayPal, loading directly");
995                window.initPayPalJSSDK();
996            }
997		} else {
998			consoleInfo('PayPal JSSDK unavailable or not required, disabling features');
999            disableJavascriptFeatures();
1000		}
1001        consoleInfo('readyCallback end');
1002	};
1003
1004	let mainCallback = ("fetch" in window) ? readyCallback : handleAntiqueBrowser;
1005	
1006	if(document.readyState === 'complete' || (document.readyState !== 'loading' && !document.documentElement.doScroll)) {
1007        consoleInfo('Readystate complete');
1008		mainCallback();
1009	} else {
1010        consoleInfo('Adding EventListener for DOMContentLoaded');
1011		document.addEventListener('DOMContentLoaded', mainCallback);
1012	}
1013	
1014}());

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.