##### `reef-aquarium.js` Unchanged from the previous version, as the DOM issue is likely due to rendering rather than the script logic. console.log('reef-aquarium.js loaded successfully'); jQuery(document).ready(function($) { console.log('jQuery and document ready'); // Debug DOM content console.log('DOM content check:', { reefAquariumApp: $('#reef-aquarium-app').length, logbookSection: $('#logbook-section').length, trendParameter: $('#trend-parameter').length, trendResult: $('#trend-result').length }); const featureSelect = $('#feature-select'); const logbookSection = $('#logbook-section'); const calculatorSection = $('#calculator-section'); const emailNotificationSection = $('#email-notification-section'); if (!featureSelect.length || !logbookSection.length) { console.error('Critical elements not found:', { featureSelect: featureSelect.length, logbookSection: logbookSection.length }); return; } // Feature selection featureSelect.on('change', function() { console.log('Feature changed to:', this.value); logbookSection.hide(); calculatorSection.hide(); emailNotificationSection.hide(); if (this.value === 'logbook') { logbookSection.show(); if ($('#trend-parameter').length && $('#trend-result').length) { displayTrend(); } else { console.warn('Trend elements not ready yet'); } displayLogs(); } else if (this.value === 'calculator') { calculatorSection.show(); } else if (this.value === 'email-notification') { emailNotificationSection.show(); } }); // Function to initialize the app function initializeApp(attempt = 1, maxAttempts = 5) { console.log(`Initial load attempt ${attempt}`); logbookSection.show(); if ($('#trend-parameter').length && $('#trend-result').length) { displayTrend(); displayLogs(); } else if (attempt < maxAttempts) { console.warn('Trend elements not found during initial load, retrying...'); setTimeout(() => initializeApp(attempt + 1, maxAttempts), 500); } else { console.error('Failed to find trend elements after maximum attempts'); } } // Start the initialization process setTimeout(() => initializeApp(), 500); // Backup DOM-ready event listener $(window).on('load', function() { console.log('Window load event triggered'); if ($('#trend-parameter').length && $('#trend-result').length) { displayTrend(); displayLogs(); } else { console.error('Trend elements still not found on window load'); } }); // Save Log functionality window.saveLog = function() { console.log('saveLog function called'); const logElements = { iodine: $('#log-iodine'), strontium: $('#log-strontium'), iron: $('#log-iron'), boron: $('#log-boron'), silica: $('#log-silica'), pH: $('#log-pH') }; if (Object.values(logElements).some(el => el.length === 0)) { console.error('One or more log input elements not found:', logElements); alert('Error: Some input fields are missing. Please check the page structure.'); return; } const log = { iodine: logElements.iodine.val() || '', strontium: logElements.strontium.val() || '', iron: logElements.iron.val() || '', boron: logElements.boron.val() || '', silica: logElements.silica.val() || '', pH: logElements.pH.val() || '', date: new Date().toISOString().split('T')[0] }; if (!log.iodine && !log.strontium && !log.iron && !log.boron && !log.silica && !log.pH) { alert('Please enter at least one parameter value.'); return; } let logs = JSON.parse(localStorage.getItem('reefLogs') || '[]'); logs.push(log); localStorage.setItem('reefLogs', JSON.stringify(logs)); displayLogs(); alert('Log saved successfully!'); console.log('Log saved:', log); }; function displayLogs() { console.log('displayLogs function called'); const logEntries = $('#log-entries'); if (logEntries.length === 0) { console.error('log-entries element not found'); return; } const logs = JSON.parse(localStorage.getItem('reefLogs') || '[]'); logEntries.html(logs.map(log => `

${log.date}: Iodine: ${log.iodine || 'N/A'}, Strontium: ${log.strontium || 'N/A'}, Iron: ${log.iron || 'N/A'}, Boron: ${log.boron || 'N/A'}, Silica: ${log.silica || 'N/A'}, pH: ${log.pH || 'N/A'}

`).join('')); console.log('Logs displayed:', logs.length, 'entries'); } // Display Parameter Trends window.displayTrend = function() { console.log('displayTrend function called'); const trendParameter = $('#trend-parameter'); const trendResult = $('#trend-result'); if (trendParameter.length === 0 || trendResult.length === 0) { console.error('trend-parameter or trend-result element not found:', { trendParameter: trendParameter.length, trendResult: trendResult.length }); return; } const parameter = trendParameter.val(); if (!parameter) { trendResult.html('

Please select a parameter.

'); return; } const logs = JSON.parse(localStorage.getItem('reefLogs') || '[]'); if (logs.length === 0) { trendResult.html('

No data available for trends.

'); return; } const recentLogs = logs.slice(-5); const values = recentLogs.map(log => parseFloat(log[parameter]) || 0).filter(val => !isNaN(val)); if (values.length > 0) { const avg = values.reduce((sum, val) => sum + val, 0) / values.length; const trend = values[values.length - 1] > values[0] ? 'increasing' : 'decreasing'; trendResult.html(`

Recent ${parameter} trend: ${trend}. Average: ${avg.toFixed(2)}

`); } else { trendResult.html('

No valid data for this parameter.

'); } console.log('Trend displayed for:', parameter); }; // Calculator functionality window.calculateAdjustment = function() { console.log('calculateAdjustment function called'); const calcElements = { parameter: $('#calc-parameter'), tankVolume: $('#calc-tank-volume'), tankUnit: $('#calc-tank-unit'), current: $('#calc-current'), target: $('#calc-target'), product: $('#calc-product'), results: $('#calc-results') }; if (Object.values(calcElements).some(el => el.length === 0)) { console.error('One or more calculator elements not found:', calcElements); alert('Error: Some calculator fields are missing. Please check the page structure.'); return; } const parameter = calcElements.parameter.val(); const tankVolume = parseFloat(calcElements.tankVolume.val()) || 0; const unit = calcElements.tankUnit.val(); const current = parseFloat(calcElements.current.val()) || 0; const target = parseFloat(calcElements.target.val()) || 0; const product = calcElements.product.val(); if (tankVolume <= 0 || isNaN(current) || isNaN(target)) { calcElements.results.html('

Please enter valid numeric values for volume, current level, and target level.

'); return; } const liters = unit === 'gallons' ? tankVolume * 3.78541 : tankVolume; let message = 'No adjustment calculated'; if (parameter === 'calcium') { const diff = target - current; if (product === 'calcium_carbonate') { const grams = (diff * liters * 0.0535).toFixed(2); message = `Add: ${grams} gm\nDissolve in water and add slowly.`; } else if (product === 'calcium_chloride') { const grams = (diff * liters * 0.036).toFixed(2); message = `Add: ${grams} gm\nDissolve in water and add slowly.`; } } else if (parameter === 'alkalinity') { const diff = target - current; if (product === 'sodium_bicarbonate') { const grams = (diff * liters * 2.8).toFixed(2); message = `Add: ${grams} gm\nDissolve in water and add slowly.`; } } else if (parameter === 'magnesium') { const diff = target - current; if (product === 'magnesium_sulfate') { const grams = (diff * liters * 0.071).toFixed(2); message = `Add: ${grams} gm\nDissolve in water and add slowly.`; } } calcElements.results.html(`

${parameter.toUpperCase()} Adjustment: ${message}

`); console.log('Adjustment calculated:', { parameter, message }); // Auto-save to log book const log = { [parameter]: current, date: new Date().toISOString().split('T')[0] }; let logs = JSON.parse(localStorage.getItem('reefLogs') || '[]'); logs.push(log); localStorage.setItem('reefLogs', JSON.stringify(logs)); displayLogs(); }; // Reset Calculator functionality window.resetCalculator = function() { console.log('resetCalculator function called'); const calcElements = { tankVolume: $('#calc-tank-volume'), tankUnit: $('#calc-tank-unit'), current: $('#calc-current'), target: $('#calc-target'), results: $('#calc-results') }; if (Object.values(calcElements).some(el => el.length === 0)) { console.error('One or more reset elements not found:', calcElements); return; } calcElements.tankVolume.val(''); calcElements.tankUnit.val('liters'); calcElements.current.val(''); calcElements.target.val(''); calcElements.results.html(''); }; // Email Notification functionality window.saveEmailSettings = function() { console.log('saveEmailSettings function called'); const email = $('#email-address').val(); const frequency = $('#notification-frequency').val(); const status = $('#email-status'); if (!email || !email.includes('@')) { status.html('

Please enter a valid email address.

'); return; } localStorage.setItem('emailSettings', JSON.stringify({ email, frequency })); status.html(`

Notifications set to ${frequency} for ${email}.

`); }; // Trend parameter change $('#trend-parameter').on('change', function() { if ($('#trend-parameter').length && $('#trend-result').length) { displayTrend(); } else { console.warn('Trend elements not ready for change event'); } }); });XML-RPC server accepts POST requests only.