// LOBOR FX About Page - Using Global Language Selector + Calculator // Interactive language switching and savings calculator functionality let calculatorFormElements = {}; // Use the same global language selector class class LoborLanguageSelector { constructor() { this.currentLanguage = localStorage.getItem('loborLanguage') || 'es'; this.languageMenuButton = null; this.languageDropdown = null; this.initialized = false; // Bind methods to preserve context this.toggleLanguageMenu = this.toggleLanguageMenu.bind(this); this.selectLanguage = this.selectLanguage.bind(this); this.handleOutsideClick = this.handleOutsideClick.bind(this); this.reinitialize = this.reinitialize.bind(this); } init() { if (this.initialized) { console.log('LanguageSelector already initialized, cleaning up first...'); this.cleanup(); } console.log('Initializing Enhanced Language Selector...'); // Use MutationObserver to detect DOM changes this.observeDOM(); setTimeout(() => { this.setupElements(); this.attachEventListeners(); this.applyCurrentLanguage(); this.initialized = true; console.log('Language Selector initialized successfully'); }, 300); } observeDOM() { // Create an observer to watch for DOM changes (page navigations) if (this.observer) { this.observer.disconnect(); } this.observer = new MutationObserver((mutations) => { let shouldReinit = false; mutations.forEach((mutation) => { if (mutation.type === 'childList') { // Check if navigation elements were added/removed const hasLanguageElements = document.querySelector('#language-menu-button, .language-option'); if (hasLanguageElements && !this.languageMenuButton) { shouldReinit = true; } } }); if (shouldReinit) { console.log('DOM changes detected, reinitializing language selector...'); setTimeout(this.reinitialize, 200); } }); // Start observing this.observer.observe(document.body, { childList: true, subtree: true }); } reinitialize() { if (!this.initialized) { this.init(); } else { this.setupElements(); this.attachEventListeners(); this.applyCurrentLanguage(); } } setupElements() { // Desktop elements this.languageMenuButton = document.getElementById('language-menu-button'); this.languageDropdown = document.getElementById('language-dropdown'); console.log('Desktop - Language button found:', !!this.languageMenuButton); console.log('Desktop - Language dropdown found:', !!this.languageDropdown); } attachEventListeners() { // Remove existing listeners first this.removeEventListeners(); // Desktop dropdown toggle if (this.languageMenuButton) { this.languageMenuButton.addEventListener('click', this.toggleLanguageMenu); console.log('Added click listener to desktop language button'); } // Get all language options (both desktop and mobile) const allLanguageOptions = document.querySelectorAll('.language-option'); console.log('Found language options:', allLanguageOptions.length); // Store references to remove listeners later this.languageOptions = Array.from(allLanguageOptions); // Add listeners to all language options this.languageOptions.forEach((option, index) => { // Add multiple event types for better compatibility option.addEventListener('click', this.selectLanguage, { passive: false }); option.addEventListener('touchstart', this.selectLanguage, { passive: false }); console.log(`Added listeners to language option ${index}:`, option.dataset.lang); }); // Close dropdown when clicking outside (desktop only) document.addEventListener('click', this.handleOutsideClick); console.log('Event listeners attached successfully'); } removeEventListeners() { if (this.languageMenuButton) { this.languageMenuButton.removeEventListener('click', this.toggleLanguageMenu); } if (this.languageOptions) { this.languageOptions.forEach(option => { option.removeEventListener('click', this.selectLanguage); option.removeEventListener('touchstart', this.selectLanguage); }); } document.removeEventListener('click', this.handleOutsideClick); } toggleLanguageMenu(event) { event.preventDefault(); event.stopPropagation(); console.log('Toggle language menu clicked'); if (this.languageDropdown) { const isHidden = this.languageDropdown.classList.contains('hidden'); if (isHidden) { this.languageDropdown.classList.remove('hidden'); console.log('Showing dropdown'); } else { this.languageDropdown.classList.add('hidden'); console.log('Hiding dropdown'); } } } selectLanguage(event) { event.preventDefault(); event.stopPropagation(); let target = event.target; console.log('selectLanguage called, target:', target.tagName, target.textContent?.substring(0, 20)); // Find the closest language-option element while (target && !target.classList.contains('language-option')) { target = target.parentElement; if (!target || target === document.body) { console.log('No language-option found in parent hierarchy'); return; } } if (!target) { console.log('No target found'); return; } const selectedLang = target.dataset.lang; console.log('Language selected:', selectedLang, 'Current:', this.currentLanguage); if (selectedLang && selectedLang !== this.currentLanguage) { this.currentLanguage = selectedLang; localStorage.setItem('loborLanguage', selectedLang); this.updateCurrentLanguageDisplay(); this.switchPageLanguage(); console.log('Language switched to:', this.currentLanguage); // Dispatch custom event for other components to listen window.dispatchEvent(new CustomEvent('languageChanged', { detail: { language: selectedLang } })); } // Close dropdown if it exists (desktop only) if (this.languageDropdown) { this.languageDropdown.classList.add('hidden'); } } updateCurrentLanguageDisplay() { const currentLangElement = document.getElementById('current-language'); if (currentLangElement) { currentLangElement.textContent = this.currentLanguage.toUpperCase(); console.log('Updated language display to:', this.currentLanguage.toUpperCase()); } } switchPageLanguage() { console.log('Switching page language to:', this.currentLanguage); const allSpanishContent = document.querySelectorAll('.es-content'); const allEnglishContent = document.querySelectorAll('.en-content'); console.log('Found Spanish elements:', allSpanishContent.length); console.log('Found English elements:', allEnglishContent.length); if (this.currentLanguage === 'es') { // Show Spanish content allSpanishContent.forEach((element, index) => { element.classList.remove('hidden'); }); // Hide English content allEnglishContent.forEach((element, index) => { element.classList.add('hidden'); }); } else { // Show English content allEnglishContent.forEach((element, index) => { element.classList.remove('hidden'); }); // Hide Spanish content allSpanishContent.forEach((element, index) => { element.classList.add('hidden'); }); } console.log('Language switch completed'); } applyCurrentLanguage() { console.log('Applying current language:', this.currentLanguage); this.updateCurrentLanguageDisplay(); this.switchPageLanguage(); } handleOutsideClick(event) { if (this.languageDropdown && this.languageMenuButton && !this.languageDropdown.contains(event.target) && !this.languageMenuButton.contains(event.target)) { this.languageDropdown.classList.add('hidden'); } } cleanup() { console.log('Cleaning up Language Selector...'); this.removeEventListeners(); if (this.observer) { this.observer.disconnect(); } this.initialized = false; } } // Create and attach to global scope for persistence across page changes if (!window.LoborLanguageSelector) { window.LoborLanguageSelector = new LoborLanguageSelector(); } // Format number with commas for display function formatNumberWithCommas(num) { return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } // Parse number removing commas function parseNumberFromInput(str) { return parseFloat(str.replace(/,/g, '')) || 0; } // Format currency for display function formatCurrency(amount, currency = 'USD') { const formatted = formatNumberWithCommas(Math.round(amount)); return `$${formatted} ${currency}`; } // Calculate savings based on transaction amount function calculateSavings() { const currentLang = window.LoborLanguageSelector?.currentLanguage || 'es'; const transactionAmount = parseNumberFromInput(calculatorFormElements.transactionAmountInput.value); const exchangeRate = parseNumberFromInput(calculatorFormElements.exchangeRateInput.value); // Validate input if (!transactionAmount || transactionAmount <= 0) { const alertMessage = currentLang === 'es' ? 'Por favor ingrese un monto de transacción válido.' : 'Please enter a valid transaction amount.'; alert(alertMessage); calculatorFormElements.transactionAmountInput.focus(); return; } // Calculate costs const bankCostPercentage = 2.2; // 2.2% total cost for traditional banking const loborCostPercentage = 0.8; // 0.8% total cost for LOBOR FX const bankCost = (transactionAmount * bankCostPercentage) / 100; const loborCost = (transactionAmount * loborCostPercentage) / 100; const savings = bankCost - loborCost; // Calculate percentage savings const savingsPercentage = ((savings / bankCost) * 100).toFixed(1); // Estimate annual savings (assuming 12 transactions per year) const annualSavings = savings * 12; // Update results display const savingsAmountElement = document.getElementById('savings-amount'); const bankCostElement = document.getElementById('bank-cost'); const loborCostElement = document.getElementById('lobor-cost'); const transactionDisplayElement = document.getElementById('transaction-display'); const savingsPercentageElement = document.getElementById('savings-percentage'); const annualSavingsElement = document.getElementById('annual-savings'); if (savingsAmountElement) savingsAmountElement.textContent = formatCurrency(savings); if (bankCostElement) bankCostElement.textContent = '~' + formatCurrency(bankCost); if (loborCostElement) loborCostElement.textContent = formatCurrency(loborCost); if (transactionDisplayElement) transactionDisplayElement.textContent = formatCurrency(transactionAmount); if (savingsPercentageElement) savingsPercentageElement.textContent = savingsPercentage + '%'; if (annualSavingsElement) annualSavingsElement.textContent = formatCurrency(annualSavings); // Show results section with animation const resultsSection = document.getElementById('results-section'); if (resultsSection) { resultsSection.classList.remove('hidden'); // Smooth scroll to results setTimeout(() => { resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' }); }, 100); } } // Add input formatting for transaction amount function formatTransactionAmountInput(event) { let value = event.target.value.replace(/[^\d]/g, ''); // Remove non-digits if (value) { value = formatNumberWithCommas(parseInt(value)); } event.target.value = value; } // Add input formatting for exchange rate function formatExchangeRateInput(event) { let value = event.target.value.replace(/[^\d.]/g, ''); // Remove non-digits and non-decimal points // Ensure only one decimal point const decimalCount = (value.match(/\./g) || []).length; if (decimalCount > 1) { value = value.substring(0, value.lastIndexOf('.')); } event.target.value = value; } // Initialize calculator functionality function initCalculator() { // Get form elements calculatorFormElements.transactionAmountInput = document.getElementById('transaction-amount'); calculatorFormElements.exchangeRateInput = document.getElementById('exchange-rate'); calculatorFormElements.calculateButton = document.getElementById('calculate-savings'); calculatorFormElements.resultsSection = document.getElementById('results-section'); // Add event listeners only if elements exist if (calculatorFormElements.calculateButton) { calculatorFormElements.calculateButton.addEventListener('click', calculateSavings); } // Add input formatting if (calculatorFormElements.transactionAmountInput) { calculatorFormElements.transactionAmountInput.addEventListener('input', formatTransactionAmountInput); calculatorFormElements.transactionAmountInput.addEventListener('keypress', function(event) { // Allow only numbers and control keys const char = String.fromCharCode(event.which); if (!char.match(/[0-9]/) && event.which !== 8 && event.which !== 46 && event.which !== 37 && event.which !== 39) { event.preventDefault(); } }); // Enter key support calculatorFormElements.transactionAmountInput.addEventListener('keypress', function(event) { if (event.key === 'Enter') { calculateSavings(); } }); } if (calculatorFormElements.exchangeRateInput) { calculatorFormElements.exchangeRateInput.addEventListener('input', formatExchangeRateInput); calculatorFormElements.exchangeRateInput.addEventListener('keypress', function(event) { if (event.key === 'Enter') { calculateSavings(); } }); } } // Initialize when page loads export function init() { console.log('Initializing About page with global language selector...'); // Initialize or reinitialize the global language selector window.LoborLanguageSelector.init(); // Initialize calculator initCalculator(); // Listen for language change events window.addEventListener('languageChanged', (event) => { console.log('Language changed event received:', event.detail.language); }); } // Cleanup function export function teardown() { console.log('Tearing down About page...'); // Calculator cleanup if (calculatorFormElements.calculateButton) { calculatorFormElements.calculateButton.removeEventListener('click', calculateSavings); } if (calculatorFormElements.transactionAmountInput) { calculatorFormElements.transactionAmountInput.removeEventListener('input', formatTransactionAmountInput); } if (calculatorFormElements.exchangeRateInput) { calculatorFormElements.exchangeRateInput.removeEventListener('input', formatExchangeRateInput); } // Clear references calculatorFormElements = {}; // Don't cleanup the global selector, let it persist }