/** * Dog Calorie Calculator * Calculates dog's daily calorie requirements and food amounts * by Canine Nutrition and Wellness */ class DogCalorieCalculator { constructor() { this.currentMER = 0; this.isImperial = false; this.init(); } init() { this.bindEvents(); this.updateUnitLabels(); } bindEvents() { const weightInput = document.getElementById('weight'); const dogTypeSelect = document.getElementById('dogType'); const foodEnergyInput = document.getElementById('foodEnergy'); const daysInput = document.getElementById('days'); const unitSelect = document.getElementById('unit'); const unitToggle = document.getElementById('unitToggle'); if (weightInput) weightInput.addEventListener('input', () => this.updateCalorieCalculations()); if (weightInput) weightInput.addEventListener('blur', () => this.validateWeight()); if (dogTypeSelect) dogTypeSelect.addEventListener('change', () => this.updateCalorieCalculations()); if (foodEnergyInput) foodEnergyInput.addEventListener('input', () => this.updateFoodCalculations()); if (foodEnergyInput) foodEnergyInput.addEventListener('blur', () => this.validateFoodEnergy()); if (daysInput) daysInput.addEventListener('input', () => this.updateFoodCalculations()); if (daysInput) daysInput.addEventListener('blur', () => this.validateDays()); if (unitSelect) unitSelect.addEventListener('change', () => this.updateFoodCalculations()); if (unitToggle) unitToggle.addEventListener('change', () => this.toggleUnits()); } calculateRER(weightKg) { return 70 * Math.pow(weightKg, 0.75); } calculateMER(rer, factor) { return rer * factor; } validateInput(value, min = 0, isInteger = false) { const num = parseFloat(value); if (isNaN(num) || num < min) return false; if (isInteger && !Number.isInteger(num)) return false; return true; } showError(elementId, show = true) { const errorElement = document.getElementById(elementId); if (errorElement) { if (show) { errorElement.classList.remove('dog-calculator-hidden'); } else { errorElement.classList.add('dog-calculator-hidden'); } } } convertUnits(grams, unit) { switch (unit) { case 'kg': return grams / 1000; case 'oz': return grams / 28.3495; case 'lb': return grams / 453.592; default: return grams; } } formatNumber(num, decimals = 0) { return num.toFixed(decimals).replace(/\.?0+$/, ''); } toggleUnits() { const toggle = document.getElementById('unitToggle'); this.isImperial = toggle.checked; this.updateUnitLabels(); this.convertExistingValues(); this.updateCalorieCalculations(); } updateUnitLabels() { const metricLabel = document.getElementById('metricLabel'); const imperialLabel = document.getElementById('imperialLabel'); const weightLabel = document.getElementById('weightLabel'); const foodEnergyLabel = document.getElementById('foodEnergyLabel'); const weightInput = document.getElementById('weight'); const foodEnergyInput = document.getElementById('foodEnergy'); const unitSelect = document.getElementById('unit'); if (metricLabel && imperialLabel) { metricLabel.classList.toggle('active', !this.isImperial); imperialLabel.classList.toggle('active', this.isImperial); } if (this.isImperial) { if (weightLabel) weightLabel.textContent = "Dog's Weight (lbs):"; if (weightInput) { weightInput.placeholder = "Enter weight in lbs"; weightInput.min = "0.2"; // ~0.1kg in lbs weightInput.step = "0.1"; } if (foodEnergyLabel) foodEnergyLabel.textContent = "Food Energy Content (kcal/oz):"; if (foodEnergyInput) { foodEnergyInput.placeholder = "Enter kcal per oz"; foodEnergyInput.min = "0.03"; // ~1 kcal/100g in kcal/oz foodEnergyInput.step = "0.01"; } if (unitSelect) { unitSelect.innerHTML = ` `; } } else { if (weightLabel) weightLabel.textContent = "Dog's Weight (kg):"; if (weightInput) { weightInput.placeholder = "Enter weight in kg"; weightInput.min = "0.1"; weightInput.step = "0.1"; } if (foodEnergyLabel) foodEnergyLabel.textContent = "Food Energy Content (kcal/100g):"; if (foodEnergyInput) { foodEnergyInput.placeholder = "Enter kcal per 100g"; foodEnergyInput.min = "1"; foodEnergyInput.step = "1"; } if (unitSelect) { unitSelect.innerHTML = ` `; } } } convertExistingValues() { const weightInput = document.getElementById('weight'); const foodEnergyInput = document.getElementById('foodEnergy'); if (weightInput && weightInput.value) { const currentWeight = parseFloat(weightInput.value); if (!isNaN(currentWeight)) { if (this.isImperial) { // Convert kg to lbs weightInput.value = this.formatNumber(currentWeight * 2.20462, 1); } else { // Convert lbs to kg weightInput.value = this.formatNumber(currentWeight / 2.20462, 1); } } } if (foodEnergyInput && foodEnergyInput.value) { const currentEnergy = parseFloat(foodEnergyInput.value); if (!isNaN(currentEnergy)) { if (this.isImperial) { // Convert kcal/100g to kcal/oz foodEnergyInput.value = this.formatNumber(currentEnergy / 3.52739, 2); } else { // Convert kcal/oz to kcal/100g foodEnergyInput.value = this.formatNumber(currentEnergy * 3.52739, 0); } } } } getWeightInKg() { const weightInput = document.getElementById('weight'); if (!weightInput || !weightInput.value) return null; const weight = parseFloat(weightInput.value); if (isNaN(weight)) return null; return this.isImperial ? weight / 2.20462 : weight; } getFoodEnergyPer100g() { const foodEnergyInput = document.getElementById('foodEnergy'); if (!foodEnergyInput || !foodEnergyInput.value) return null; const energy = parseFloat(foodEnergyInput.value); if (isNaN(energy)) return null; return this.isImperial ? energy * 3.52739 : energy; } validateWeight() { const weight = document.getElementById('weight')?.value; if (weight && !this.validateInput(weight, 0.1)) { this.showError('weightError', true); } else { this.showError('weightError', false); } } validateFoodEnergy() { const energy = document.getElementById('foodEnergy')?.value; if (energy && !this.validateInput(energy, 1)) { this.showError('foodEnergyError', true); } else { this.showError('foodEnergyError', false); } } validateDays() { const days = document.getElementById('days')?.value; if (days && !this.validateInput(days, 1, true)) { this.showError('daysError', true); } else { this.showError('daysError', false); } } updateCalorieCalculations() { const dogTypeSelect = document.getElementById('dogType'); const calorieResults = document.getElementById('calorieResults'); const rerValue = document.getElementById('rerValue'); const merValue = document.getElementById('merValue'); if (!dogTypeSelect || !calorieResults || !rerValue || !merValue) { return; } const weightKg = this.getWeightInKg(); const dogTypeFactor = dogTypeSelect.value; this.showError('weightError', false); if (!weightKg || weightKg < 0.1) { if (weightKg !== null) this.showError('weightError', true); calorieResults.style.display = 'none'; return; } if (!dogTypeFactor) { calorieResults.style.display = 'none'; return; } const factor = parseFloat(dogTypeFactor); const rer = this.calculateRER(weightKg); const mer = this.calculateMER(rer, factor); this.currentMER = mer; rerValue.textContent = this.formatNumber(rer, 0) + ' cal/day'; merValue.textContent = this.formatNumber(mer, 0) + ' cal/day'; calorieResults.style.display = 'block'; this.updateFoodCalculations(); } updateFoodCalculations() { if (this.currentMER === 0) return; const daysInput = document.getElementById('days'); const unitSelect = document.getElementById('unit'); const dailyFoodResults = document.getElementById('dailyFoodResults'); const dailyFoodValue = document.getElementById('dailyFoodValue'); const totalFoodDisplay = document.getElementById('totalFoodDisplay'); if (!daysInput || !unitSelect || !dailyFoodResults || !dailyFoodValue || !totalFoodDisplay) { return; } const energyPer100g = this.getFoodEnergyPer100g(); const days = daysInput.value; const unit = unitSelect.value; this.showError('foodEnergyError', false); this.showError('daysError', false); const minEnergy = this.isImperial ? 0.03 : 1; if (!energyPer100g || energyPer100g < minEnergy) { if (energyPer100g !== null) this.showError('foodEnergyError', true); dailyFoodResults.style.display = 'none'; totalFoodDisplay.value = ''; return; } if (!days || !this.validateInput(days, 1, true)) { if (days) this.showError('daysError', true); totalFoodDisplay.value = ''; return; } const numDays = parseInt(days); const dailyFoodGrams = (this.currentMER / energyPer100g) * 100; const totalFoodGrams = dailyFoodGrams * numDays; dailyFoodValue.textContent = this.formatNumber(dailyFoodGrams, 1) + ' g/day'; dailyFoodResults.style.display = 'block'; const convertedAmount = this.convertUnits(totalFoodGrams, unit); const unitLabel = unit === 'g' ? 'g' : unit === 'kg' ? 'kg' : unit === 'oz' ? 'oz' : 'lb'; const decimals = unit === 'g' ? 0 : unit === 'kg' ? 2 : 1; totalFoodDisplay.value = this.formatNumber(convertedAmount, decimals) + ' ' + unitLabel; } } // Global function for collapsible functionality (no longer used) function toggleCollapsible(id) { // Food section is now always expanded } // Initialize calculator when DOM is ready document.addEventListener('DOMContentLoaded', function() { new DogCalorieCalculator(); // Initialize share URL const shareUrlInput = document.getElementById('shareUrl'); if (shareUrlInput) { shareUrlInput.value = window.location.href; } // Update embed codes with current domain updateEmbedCodes(); }); // Share and Embed Functions function showShareOptions() { const modal = document.getElementById('shareModal'); if (modal) { modal.style.display = 'block'; document.body.style.overflow = 'hidden'; } } function closeShareModal() { const modal = document.getElementById('shareModal'); if (modal) { modal.style.display = 'none'; document.body.style.overflow = 'auto'; } } function showEmbedModal() { const modal = document.getElementById('embedModal'); if (modal) { modal.style.display = 'block'; document.body.style.overflow = 'hidden'; } } function closeEmbedModal() { const modal = document.getElementById('embedModal'); if (modal) { modal.style.display = 'none'; document.body.style.overflow = 'auto'; } } // Share functions function shareToFacebook() { const url = encodeURIComponent(window.location.href); const text = encodeURIComponent('Check out this Dog Calorie Calculator!'); window.open(`https://www.facebook.com/sharer/sharer.php?u=${url}"e=${text}`, '_blank'); } function shareToTwitter() { const url = encodeURIComponent(window.location.href); const text = encodeURIComponent('Calculate your dog\'s daily calorie needs with this helpful tool!'); window.open(`https://twitter.com/intent/tweet?url=${url}&text=${text}`, '_blank'); } function shareToLinkedIn() { const url = encodeURIComponent(window.location.href); window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${url}`, '_blank'); } function shareViaEmail() { const subject = encodeURIComponent('Dog Calorie Calculator'); const body = encodeURIComponent(`Check out this helpful Dog Calorie Calculator:\n\n${window.location.href}\n\nIt helps calculate your dog's daily calorie needs based on their weight and activity level.`); window.location.href = `mailto:?subject=${subject}&body=${body}`; } function copyShareLink() { const shareUrlInput = document.getElementById('shareUrl'); if (shareUrlInput) { shareUrlInput.select(); shareUrlInput.setSelectionRange(0, 99999); // For mobile devices try { document.execCommand('copy'); // Update button to show success const copyBtn = document.querySelector('.dog-calculator-share-copy'); if (copyBtn) { const originalHTML = copyBtn.innerHTML; copyBtn.innerHTML = ' Copied!'; copyBtn.style.background = '#7fa464'; setTimeout(() => { copyBtn.innerHTML = originalHTML; copyBtn.style.background = ''; }, 2000); } } catch (err) { console.error('Failed to copy text: ', err); } } } // Embed functions function updateEmbedCodes() { const currentDomain = window.location.origin; const currentPath = window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')); const baseUrl = currentDomain + currentPath; const widgetCode = document.getElementById('widgetCode'); const iframeCode = document.getElementById('iframeCode'); if (widgetCode) { widgetCode.textContent = `\n
`; } if (iframeCode) { iframeCode.textContent = ``; } } function copyEmbedCode(type) { const codeElement = type === 'widget' ? document.getElementById('widgetCode') : document.getElementById('iframeCode'); const button = event.target.closest('.dog-calculator-copy-btn'); if (codeElement && button) { const textArea = document.createElement('textarea'); textArea.value = codeElement.textContent; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; textArea.style.top = '-999999px'; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { document.execCommand('copy'); textArea.remove(); // Update button to show success const originalHTML = button.innerHTML; button.innerHTML = ' Copied'; button.classList.add('copied'); setTimeout(() => { button.innerHTML = originalHTML; button.classList.remove('copied'); }, 2000); } catch (err) { console.error('Failed to copy text: ', err); textArea.remove(); } } } // Close modals when clicking outside window.addEventListener('click', function(event) { const shareModal = document.getElementById('shareModal'); const embedModal = document.getElementById('embedModal'); if (event.target === shareModal) { closeShareModal(); } else if (event.target === embedModal) { closeEmbedModal(); } }); // Close modals with Escape key window.addEventListener('keydown', function(event) { if (event.key === 'Escape') { closeShareModal(); closeEmbedModal(); } });