Update
This commit is contained in:
parent
9fa91da90e
commit
4eda60df2a
@ -32,20 +32,93 @@
|
||||
.dog-calc-section {
|
||||
background: #fdfcfe;
|
||||
border: 1px solid #e8e3ed;
|
||||
border-radius: 8px;
|
||||
border-radius: 8px 8px 0 0;
|
||||
padding: 24px;
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 0;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.dog-calc-section h2 {
|
||||
margin-top: 0;
|
||||
.dog-calc-section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.dog-calc-section h2 {
|
||||
margin: 0;
|
||||
color: #6f3f6d;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Unit Switch */
|
||||
.dog-calc-unit-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.dog-calc-unit-label {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: #635870;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.dog-calc-unit-label.active {
|
||||
color: #6f3f6d;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dog-calc-switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.dog-calc-switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.dog-calc-slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #e8e3ed;
|
||||
transition: 0.3s;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.dog-calc-slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: white;
|
||||
transition: 0.3s;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.dog-calc-switch input:checked + .dog-calc-slider {
|
||||
background-color: #f19a5f;
|
||||
}
|
||||
|
||||
.dog-calc-switch input:checked + .dog-calc-slider:before {
|
||||
transform: translateX(24px);
|
||||
}
|
||||
|
||||
.dog-calc-form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
@ -143,8 +216,8 @@
|
||||
.dog-calc-collapsible {
|
||||
background: #ffffff;
|
||||
border: 1px solid #e8e3ed;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 24px;
|
||||
border-top: none;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
@ -152,17 +225,7 @@
|
||||
.dog-calc-collapsible-header {
|
||||
background: #f8f5fa;
|
||||
padding: 20px 24px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #e8e3ed;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.dog-calc-collapsible-header:hover {
|
||||
background: #f5f1f6;
|
||||
}
|
||||
|
||||
.dog-calc-collapsible-header h3 {
|
||||
@ -172,30 +235,57 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dog-calc-collapsible-arrow {
|
||||
transition: transform 0.2s ease;
|
||||
font-size: 1.2rem;
|
||||
color: #9f5999;
|
||||
}
|
||||
|
||||
.dog-calc-collapsible.active .dog-calc-collapsible-arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.dog-calc-collapsible-content {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.dog-calc-collapsible.active .dog-calc-collapsible-content {
|
||||
max-height: 1000px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dog-calc-collapsible-inner {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.dog-calc-action-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
padding: 20px;
|
||||
background: #f8f5fa;
|
||||
border-left: 1px solid #e8e3ed;
|
||||
border-right: 1px solid #e8e3ed;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.dog-calc-btn {
|
||||
padding: 8px 16px;
|
||||
border: 1px solid #e8e3ed;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: white;
|
||||
color: #6f3f6d;
|
||||
}
|
||||
|
||||
.dog-calc-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dog-calc-btn-share:hover {
|
||||
border-color: #9f5999;
|
||||
color: #9f5999;
|
||||
}
|
||||
|
||||
.dog-calc-btn-embed:hover {
|
||||
border-color: #7fa464;
|
||||
color: #7fa464;
|
||||
}
|
||||
|
||||
.dog-calc-input-group {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
@ -224,9 +314,12 @@
|
||||
|
||||
.dog-calc-footer {
|
||||
text-align: center;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid #e8e3ed;
|
||||
margin-top: 24px;
|
||||
padding: 20px;
|
||||
background: #fdfcfe;
|
||||
border: 1px solid #e8e3ed;
|
||||
border-radius: 0 0 8px 8px;
|
||||
border-top: none;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.dog-calc-footer a {
|
||||
@ -280,6 +373,30 @@
|
||||
.dog-calc-collapsible-header {
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.dog-calc-section-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.dog-calc-section h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dog-calc-unit-switch {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.dog-calc-action-buttons {
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.dog-calc-btn {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@ -346,8 +463,47 @@
|
||||
}
|
||||
|
||||
.dog-calc-footer {
|
||||
background: #24202d;
|
||||
border-color: #433c4f;
|
||||
}
|
||||
|
||||
.dog-calc-unit-label {
|
||||
color: #b8b0c2;
|
||||
}
|
||||
|
||||
.dog-calc-unit-label.active {
|
||||
color: #f5f3f7;
|
||||
}
|
||||
|
||||
.dog-calc-slider {
|
||||
background-color: #433c4f;
|
||||
}
|
||||
|
||||
.dog-calc-action-buttons {
|
||||
background: #312b3b;
|
||||
border-color: #433c4f;
|
||||
}
|
||||
|
||||
.dog-calc-btn {
|
||||
background: #433c4f;
|
||||
border-color: #433c4f;
|
||||
color: #f5f3f7;
|
||||
}
|
||||
|
||||
.dog-calc-btn:hover {
|
||||
background: #524a5f;
|
||||
border-color: #524a5f;
|
||||
}
|
||||
|
||||
.dog-calc-btn-share:hover {
|
||||
border-color: #9f5999;
|
||||
color: #f19a5f;
|
||||
}
|
||||
|
||||
.dog-calc-btn-embed:hover {
|
||||
border-color: #7fa464;
|
||||
color: #7fa464;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@ -355,7 +511,17 @@
|
||||
const widgetTemplate = `
|
||||
<div class="dog-calc-widget">
|
||||
<div class="dog-calc-section">
|
||||
<h2>Dog's Characteristics</h2>
|
||||
<div class="dog-calc-section-header">
|
||||
<h2>Dog's Characteristics</h2>
|
||||
<div class="dog-calc-unit-switch">
|
||||
<span class="dog-calc-unit-label active" id="metricLabel">Metric</span>
|
||||
<label class="dog-calc-switch">
|
||||
<input type="checkbox" id="unitToggle">
|
||||
<span class="dog-calc-slider"></span>
|
||||
</label>
|
||||
<span class="dog-calc-unit-label" id="imperialLabel">Imperial</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dog-calc-form-group">
|
||||
<label for="dogType">Dog Type / Activity Level:</label>
|
||||
@ -376,7 +542,7 @@
|
||||
</div>
|
||||
|
||||
<div class="dog-calc-form-group">
|
||||
<label for="weight">Dog's Weight (kg):</label>
|
||||
<label for="weight" id="weightLabel">Dog's Weight (kg):</label>
|
||||
<input type="number" id="weight" min="0.1" step="0.1" placeholder="Enter weight in kg" aria-describedby="weightHelp">
|
||||
<div id="weightError" class="dog-calc-error dog-calc-hidden">Please enter a valid weight (minimum 0.1 kg)</div>
|
||||
</div>
|
||||
@ -393,15 +559,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dog-calc-collapsible" id="foodCalculator">
|
||||
<div class="dog-calc-collapsible active" id="foodCalculator">
|
||||
<div class="dog-calc-collapsible-header">
|
||||
<h3>How much food is that?</h3>
|
||||
<span class="dog-calc-collapsible-arrow">▼</span>
|
||||
<h3>How much should I feed?</h3>
|
||||
</div>
|
||||
<div class="dog-calc-collapsible-content">
|
||||
<div class="dog-calc-collapsible-inner">
|
||||
<div class="dog-calc-form-group">
|
||||
<label for="foodEnergy">Food Energy Content (kcal/100g):</label>
|
||||
<label for="foodEnergy" id="foodEnergyLabel">Food Energy Content (kcal/100g):</label>
|
||||
<input type="number" id="foodEnergy" min="1" step="1" placeholder="Enter kcal per 100g" aria-describedby="foodEnergyHelp">
|
||||
<div id="foodEnergyError" class="dog-calc-error dog-calc-hidden">Please enter a valid energy content (minimum 1 kcal/100g)</div>
|
||||
</div>
|
||||
@ -438,6 +603,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dog-calc-action-buttons">
|
||||
<button class="dog-calc-btn dog-calc-btn-share" onclick="alert('Share functionality not available in widget mode')">
|
||||
Share
|
||||
</button>
|
||||
<button class="dog-calc-btn dog-calc-btn-embed" onclick="alert('Embed functionality not available in widget mode')">
|
||||
Embed
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="dog-calc-footer">
|
||||
<a href="https://caninenutritionandwellness.com" target="_blank" rel="noopener noreferrer">
|
||||
by caninenutritionandwellness.com
|
||||
@ -451,6 +625,7 @@
|
||||
constructor(container) {
|
||||
this.container = container;
|
||||
this.currentMER = 0;
|
||||
this.isImperial = false;
|
||||
this.init();
|
||||
}
|
||||
|
||||
@ -458,6 +633,7 @@
|
||||
this.injectStyles();
|
||||
this.injectHTML();
|
||||
this.bindEvents();
|
||||
this.updateUnitLabels();
|
||||
}
|
||||
|
||||
injectStyles() {
|
||||
@ -479,7 +655,7 @@
|
||||
const foodEnergyInput = this.container.querySelector('#foodEnergy');
|
||||
const daysInput = this.container.querySelector('#days');
|
||||
const unitSelect = this.container.querySelector('#unit');
|
||||
const collapsibleHeader = this.container.querySelector('.dog-calc-collapsible-header');
|
||||
const unitToggle = this.container.querySelector('#unitToggle');
|
||||
|
||||
if (weightInput) {
|
||||
weightInput.addEventListener('input', () => this.updateCalorieCalculations());
|
||||
@ -500,16 +676,122 @@
|
||||
|
||||
if (unitSelect) unitSelect.addEventListener('change', () => this.updateFoodCalculations());
|
||||
|
||||
if (collapsibleHeader) {
|
||||
collapsibleHeader.addEventListener('click', () => this.toggleCollapsible());
|
||||
if (unitToggle) unitToggle.addEventListener('change', () => this.toggleUnits());
|
||||
}
|
||||
|
||||
toggleUnits() {
|
||||
const toggle = this.container.querySelector('#unitToggle');
|
||||
this.isImperial = toggle.checked;
|
||||
|
||||
this.updateUnitLabels();
|
||||
this.convertExistingValues();
|
||||
this.updateCalorieCalculations();
|
||||
}
|
||||
|
||||
updateUnitLabels() {
|
||||
const metricLabel = this.container.querySelector('#metricLabel');
|
||||
const imperialLabel = this.container.querySelector('#imperialLabel');
|
||||
const weightLabel = this.container.querySelector('#weightLabel');
|
||||
const foodEnergyLabel = this.container.querySelector('#foodEnergyLabel');
|
||||
const weightInput = this.container.querySelector('#weight');
|
||||
const foodEnergyInput = this.container.querySelector('#foodEnergy');
|
||||
const unitSelect = this.container.querySelector('#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";
|
||||
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";
|
||||
foodEnergyInput.step = "0.01";
|
||||
}
|
||||
if (unitSelect) {
|
||||
unitSelect.innerHTML = `
|
||||
<option value="oz">ounces (oz)</option>
|
||||
<option value="lb">pounds (lb)</option>
|
||||
<option value="g">grams (g)</option>
|
||||
<option value="kg">kilograms (kg)</option>
|
||||
`;
|
||||
}
|
||||
} 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 = `
|
||||
<option value="g">grams (g)</option>
|
||||
<option value="kg">kilograms (kg)</option>
|
||||
<option value="oz">ounces (oz)</option>
|
||||
<option value="lb">pounds (lb)</option>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleCollapsible() {
|
||||
const collapsible = this.container.querySelector('.dog-calc-collapsible');
|
||||
if (collapsible) {
|
||||
collapsible.classList.toggle('active');
|
||||
convertExistingValues() {
|
||||
const weightInput = this.container.querySelector('#weight');
|
||||
const foodEnergyInput = this.container.querySelector('#foodEnergy');
|
||||
|
||||
if (weightInput && weightInput.value) {
|
||||
const currentWeight = parseFloat(weightInput.value);
|
||||
if (!isNaN(currentWeight)) {
|
||||
if (this.isImperial) {
|
||||
weightInput.value = this.formatNumber(currentWeight * 2.20462, 1);
|
||||
} else {
|
||||
weightInput.value = this.formatNumber(currentWeight / 2.20462, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foodEnergyInput && foodEnergyInput.value) {
|
||||
const currentEnergy = parseFloat(foodEnergyInput.value);
|
||||
if (!isNaN(currentEnergy)) {
|
||||
if (this.isImperial) {
|
||||
foodEnergyInput.value = this.formatNumber(currentEnergy / 3.52739, 2);
|
||||
} else {
|
||||
foodEnergyInput.value = this.formatNumber(currentEnergy * 3.52739, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getWeightInKg() {
|
||||
const weightInput = this.container.querySelector('#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 = this.container.querySelector('#foodEnergy');
|
||||
if (!foodEnergyInput || !foodEnergyInput.value) return null;
|
||||
|
||||
const energy = parseFloat(foodEnergyInput.value);
|
||||
if (isNaN(energy)) return null;
|
||||
|
||||
return this.isImperial ? energy * 3.52739 : energy;
|
||||
}
|
||||
|
||||
calculateRER(weightKg) {
|
||||
@ -579,23 +861,23 @@
|
||||
}
|
||||
|
||||
updateCalorieCalculations() {
|
||||
const weightInput = this.container.querySelector('#weight');
|
||||
const dogTypeSelect = this.container.querySelector('#dogType');
|
||||
const calorieResults = this.container.querySelector('#calorieResults');
|
||||
const rerValue = this.container.querySelector('#rerValue');
|
||||
const merValue = this.container.querySelector('#merValue');
|
||||
|
||||
if (!weightInput || !dogTypeSelect || !calorieResults || !rerValue || !merValue) {
|
||||
if (!dogTypeSelect || !calorieResults || !rerValue || !merValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
const weight = weightInput.value;
|
||||
const weightKg = this.getWeightInKg();
|
||||
const dogTypeFactor = dogTypeSelect.value;
|
||||
|
||||
this.showError('weightError', false);
|
||||
|
||||
if (!weight || !this.validateInput(weight, 0.1)) {
|
||||
if (weight) this.showError('weightError', true);
|
||||
if (!weightKg || weightKg < 0.1) {
|
||||
const weightInput = this.container.querySelector('#weight');
|
||||
if (weightInput && weightInput.value) this.showError('weightError', true);
|
||||
calorieResults.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
@ -605,7 +887,6 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const weightKg = parseFloat(weight);
|
||||
const factor = parseFloat(dogTypeFactor);
|
||||
|
||||
const rer = this.calculateRER(weightKg);
|
||||
@ -623,26 +904,26 @@
|
||||
updateFoodCalculations() {
|
||||
if (this.currentMER === 0) return;
|
||||
|
||||
const foodEnergyInput = this.container.querySelector('#foodEnergy');
|
||||
const daysInput = this.container.querySelector('#days');
|
||||
const unitSelect = this.container.querySelector('#unit');
|
||||
const dailyFoodResults = this.container.querySelector('#dailyFoodResults');
|
||||
const dailyFoodValue = this.container.querySelector('#dailyFoodValue');
|
||||
const totalFoodDisplay = this.container.querySelector('#totalFoodDisplay');
|
||||
|
||||
if (!foodEnergyInput || !daysInput || !unitSelect || !dailyFoodResults || !dailyFoodValue || !totalFoodDisplay) {
|
||||
if (!daysInput || !unitSelect || !dailyFoodResults || !dailyFoodValue || !totalFoodDisplay) {
|
||||
return;
|
||||
}
|
||||
|
||||
const foodEnergy = foodEnergyInput.value;
|
||||
const energyPer100g = this.getFoodEnergyPer100g();
|
||||
const days = daysInput.value;
|
||||
const unit = unitSelect.value;
|
||||
|
||||
this.showError('foodEnergyError', false);
|
||||
this.showError('daysError', false);
|
||||
|
||||
if (!foodEnergy || !this.validateInput(foodEnergy, 1)) {
|
||||
if (foodEnergy) this.showError('foodEnergyError', true);
|
||||
if (!energyPer100g || energyPer100g < 1) {
|
||||
const foodEnergyInput = this.container.querySelector('#foodEnergy');
|
||||
if (foodEnergyInput && foodEnergyInput.value) this.showError('foodEnergyError', true);
|
||||
dailyFoodResults.style.display = 'none';
|
||||
totalFoodDisplay.value = '';
|
||||
return;
|
||||
@ -654,7 +935,6 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const energyPer100g = parseFloat(foodEnergy);
|
||||
const numDays = parseInt(days);
|
||||
|
||||
const dailyFoodGrams = (this.currentMER / energyPer100g) * 100;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user