/** * Shashof Pro - Full Widget Logic v13.0 * This version includes a definitive fix for the custom dropdown visual update issue. */ class ShashofFullConverter { constructor(widget, data, strings) { this.widget = widget; this.rates = data.rates; this.strings = strings; this.fromCurrency = data.default_from; this.toCurrency = data.default_to; this.elements = { amountInput: this.widget.querySelector('.shashof-pro-amount'), fromDropdown: this.widget.querySelector('.shashof-custom-select[data-type="from"]'), toDropdown: this.widget.querySelector('.shashof-custom-select[data-type="to"]'), swapButton: this.widget.querySelector('.shashof-pro-swap-btn'), convertButton: this.widget.querySelector('.shashof-pro-convert-btn'), resultArea: this.widget.querySelector('.shashof-pro-result-area'), resultValue: this.widget.querySelector('.shashof-pro-result-value'), resultRate: this.widget.querySelector('.shashof-pro-result-rate'), }; this.init(); } init() { this.createCustomDropdowns(); this.addEventListeners(); this.performConversion(); } createCustomDropdowns() { this.buildDropdown(this.elements.fromDropdown, this.fromCurrency); this.buildDropdown(this.elements.toDropdown, this.toCurrency); } buildDropdown(container, defaultValue) { if (!container) return; const selectedValueDiv = container.querySelector('.selected-value'); const optionsList = container.querySelector('.options-list'); const flags = { usd: 'πŸ‡ΊπŸ‡Έ', sar: 'πŸ‡ΈπŸ‡¦', eur: 'πŸ‡ͺπŸ‡Ί', yer_sanaa: 'πŸ‡ΎπŸ‡ͺ', yer_aden: 'πŸ‡ΎπŸ‡ͺ' }; optionsList.innerHTML = ''; // Clear previous options for (const code in this.strings.currencies) { const li = document.createElement('li'); li.dataset.value = code; li.innerHTML = `${flags[code] || '🏳️'} ${this.strings.currencies[code]}`; optionsList.appendChild(li); } this.setDropdownValue(container, defaultValue); selectedValueDiv.addEventListener('click', (e) => { e.stopPropagation(); this.closeAllDropdowns(container); container.classList.toggle('open'); }); optionsList.addEventListener('click', (e) => { const li = e.target.closest('li'); if (li) { const value = li.dataset.value; if (container.dataset.type === 'from') { this.fromCurrency = value; } else { this.toCurrency = value; } this.setDropdownValue(container, value); this.performConversion(); } }); } setDropdownValue(container, value) { if (!container || !value) return; const selectedValueDiv = container.querySelector('.selected-value'); const flags = { usd: 'πŸ‡ΊπŸ‡Έ', sar: 'πŸ‡ΈπŸ‡¦', eur: 'πŸ‡ͺπŸ‡Ί', yer_sanaa: 'πŸ‡ΎπŸ‡ͺ', yer_aden: 'πŸ‡ΎπŸ‡ͺ' }; // This is the visual update selectedValueDiv.innerHTML = `${flags[value] || '🏳️'} ${this.getCurrencyName(value)}`; // This is the data update container.dataset.value = value; this.closeAllDropdowns(); } closeAllDropdowns(exceptThisOne = null) { const allDropdowns = this.widget.querySelectorAll('.shashof-custom-select'); allDropdowns.forEach(dropdown => { if (dropdown !== exceptThisOne) { dropdown.classList.remove('open'); } }); } addEventListeners() { this.elements.convertButton.addEventListener('click', () => this.performConversion()); this.elements.swapButton.addEventListener('click', () => this.swapCurrencies()); this.elements.amountInput.addEventListener('keyup', e => { if (e.key === 'Enter') this.performConversion(); }); document.addEventListener('click', () => this.closeAllDropdowns()); } performConversion() { this.setLoading(true); try { const amount = parseFloat(this.elements.amountInput.value) || 0; const fromCurrency = this.fromCurrency; const toCurrency = this.toCurrency; if (amount <= 0) { this.updateResult('--', this.strings.error_amount, 'error'); return; } if (fromCurrency === toCurrency) { const rateInfo = this.strings.rate_info.replace('{from}', this.getCurrencyName(fromCurrency)).replace('{rate}', '1.00').replace('{to}', this.getCurrencyName(toCurrency)); this.updateResult(this.formatNumber(amount), rateInfo); return; } const conversionRate = this.calculateRate(fromCurrency, toCurrency); if (conversionRate) { const finalResult = amount * conversionRate; const rateInfo = this.strings.rate_info.replace('{from}', this.getCurrencyName(fromCurrency)).replace('{rate}', this.formatNumber(conversionRate, 4)).replace('{to}', this.getCurrencyName(toCurrency)); this.updateResult(this.formatNumber(finalResult), rateInfo); } else { const errorMsg = this.strings.error_unavailable.replace('{from}', this.getCurrencyName(fromCurrency)).replace('{to}', this.getCurrencyName(toCurrency)); this.updateResult('N/A', errorMsg, 'error'); } } catch (error) { console.error("Shashof Pro Error:", error); this.updateResult('Error', 'An unexpected error occurred.', 'error'); } finally { setTimeout(() => this.setLoading(false), 200); } } swapCurrencies() { const tempFrom = this.fromCurrency; this.fromCurrency = this.toCurrency; this.toCurrency = tempFrom; this.setDropdownValue(this.elements.fromDropdown, this.fromCurrency); this.setDropdownValue(this.elements.toDropdown, this.toCurrency); this.performConversion(); } calculateRate(from, to) { if (from === to) return 1; const directKey = `${from}_to_${to}`; if (this.rates[directKey] !== undefined) return this.rates[directKey]; const inverseKey = `${to}_to_${from}`; if (this.rates[inverseKey] !== undefined && this.rates[inverseKey] !== 0) return 1 / this.rates[inverseKey]; const fromRateInYer = this.getRateAgainstBase(from); const toRateInYer = this.getRateAgainstBase(to); if (fromRateInYer !== null && toRateInYer !== null && toRateInYer !== 0) return fromRateInYer / toRateInYer; return null; } getRateAgainstBase(currency) { if (currency === 'yer_sanaa') return 1; const directToBaseKey = `${currency}_to_yer_sanaa`; if (this.rates[directToBaseKey] !== undefined) return this.rates[directToBaseKey]; if (currency === 'yer_aden' && this.rates['yer_sanaa_to_yer_aden'] !== undefined && this.rates['yer_sanaa_to_yer_aden'] !== 0) return 1 / this.rates['yer_sanaa_to_yer_aden']; return null; } updateResult(value, text, state = 'success') { this.elements.resultValue.textContent = value; this.elements.resultRate.textContent = text; this.elements.resultArea.className = 'shashof-pro-result-area'; this.elements.resultArea.classList.add(state, 'visible'); } setLoading(isLoading) { this.elements.convertButton.classList.toggle('loading', isLoading); this.elements.convertButton.disabled = isLoading; const btnText = this.elements.convertButton.querySelector('.btn-text'); if (btnText) btnText.textContent = isLoading ? this.strings.calculating : this.strings.convert; } getCurrencyName(code) { return this.strings.currencies[code] || code; } formatNumber(num, precision = 2) { return num.toLocaleString('en-US', { minimumFractionDigits: precision, maximumFractionDigits: precision }); } } window.addEventListener('load', () => { if (typeof window.shashofProData === 'object' && typeof window.shashofProStrings === 'object') { const fullWidgets = document.querySelectorAll('.shashof-pro-converter'); fullWidgets.forEach(widget => { const widgetId = widget.dataset.widgetId; const data = window.shashofProData[widgetId]; const strings = window.shashofProStrings[widgetId]; if (data && strings) { new ShashofFullConverter(widget, data, strings); } }); } });