94- آموزش جاوااسکریپت | پروژه عملی: قسمت 7 از 12- محاسبه و نمایش مجموع کالریها در Calorie Tracker
در این بخش، منطق محاسبه مجموع کالریها را به Item Controller اضافه میکنیم و مقدار نهایی را بعد از ثبت هر آیتم و همچنین هنگام اجرای اولیه برنامه در رابط کاربری نمایش میدهیم.
تا اینجا امکان افزودن آیتمهای غذایی به برنامه را پیادهسازی کردهایم. حالا باید مجموع کالریها را نیز بهروزرسانی کنیم تا هر بار که یک آیتم جدید ثبت میشود، مقدار کل کالریها در رابط کاربری نمایش داده شود.
در این بخش، دو کار اصلی انجام میدهیم:
- محاسبه مجموع کالریها در
Item Controller - نمایش مقدار مجموع در
UI Controller
دریافت مجموع کالریها بعد از افزودن آیتم
بعد از اینکه آیتم جدید ثبت و به لیست اضافه شد، باید مجموع کالریها را دوباره محاسبه کنیم و آن را در رابط کاربری نمایش دهیم.
بهروزرسانی تابع itemAddSubmit
در App Controller، بعد از افزودن آیتم به لیست، مجموع کالریها را از Item Controller میگیریم و به UI Controller میفرستیم.
const itemAddSubmit = function (e) {
const input = UICtrl.getItemInput();
if (input.name !== '' && input.calories !== '') {
const newItem = ItemCtrl.addItem(input.name, input.calories);
UICtrl.addListItem(newItem);
// دریافت مجموع کالریها
const totalCalories = ItemCtrl.getTotalCalories();
// نمایش مجموع کالریها در رابط کاربری
UICtrl.showTotalCalories(totalCalories);
UICtrl.clearInput();
}
e.preventDefault();
};
ساخت متد getTotalCalories در Item Controller
برای محاسبه مجموع کالریها، باید روی آرایه items پیمایش کنیم و کالری هر آیتم را به مقدار کل اضافه کنیم.
کد متد getTotalCalories
getTotalCalories: function () {
let total = 0;
data.items.forEach(function (item) {
total += item.calories;
});
data.totalCalories = total;
return data.totalCalories;
}
توضیح عملکرد getTotalCalories
این متد به شکل زیر عمل میکند:
1. تعریف مقدار اولیه
ابتدا یک متغیر برای نگهداری مجموع تعریف میکنیم:
let total = 0;
2. پیمایش روی آیتمها
سپس با forEach روی تمام آیتمها حرکت میکنیم:
data.items.forEach(function (item) {
total += item.calories;
});
در هر تکرار، مقدار کالری آیتم فعلی به مجموع اضافه میشود.
3. ذخیره مجموع در state
در ادامه، مجموع محاسبهشده را داخل data.totalCalories قرار میدهیم:
data.totalCalories = total;
4. برگرداندن نتیجه
در نهایت، مقدار مجموع کالریها بازگردانده میشود:
return data.totalCalories;
نمایش مجموع کالریها در رابط کاربری
حالا که مجموع کالریها محاسبه میشود، باید آن را در رابط کاربری نمایش دهیم.
افزودن selector جدید در UI Controller
ابتدا selector مربوط به نمایش مجموع کالریها را به UISelectors اضافه میکنیم.
const UISelectors = {
itemList: '#item-list',
addBtn: '.add-btn',
itemNameInput: '#item-name',
itemCaloriesInput: '#item-calories',
totalCalories: '.total-calories'
};
نکته
در فایل index.html، این مقدار داخل یک عنصر با کلاس total-calories قرار دارد. بنابراین selector ما به صورت زیر تعریف میشود:
totalCalories: '.total-calories'
ساخت متد showTotalCalories
در UI Controller یک متد جدید میسازیم تا مقدار مجموع کالریها را داخل DOM نمایش دهد.
showTotalCalories: function (totalCalories) {
document.querySelector(UISelectors.totalCalories).textContent = totalCalories;
}
توضیح
این متد مقدار textContent عنصر مربوط به مجموع کالریها را به عدد جدید تغییر میدهد. در نتیجه، هر بار که مجموع تغییر کند، رابط کاربری هم فوراً بهروزرسانی میشود.
نمایش مجموع کالریها هنگام اجرای اولیه برنامه
بهتر است هنگام اجرای برنامه نیز مجموع کالریها محاسبه و نمایش داده شود.
در حال حاضر چون هنوز از Local Storage استفاده نمیکنیم، این مقدار معمولاً برابر 0 است؛ اما بهتر است ساختار برنامه را از همین حالا کامل نگه داریم.
بهروزرسانی متد init
در App Controller، داخل متد init نیز مجموع کالریها را دریافت و نمایش میدهیم.
init: function () {
const items = ItemCtrl.getItems();
if (items.length === 0) {
UICtrl.hideList();
} else {
UICtrl.populateItemList(items);
}
const totalCalories = ItemCtrl.getTotalCalories();
UICtrl.showTotalCalories(totalCalories);
loadEventListeners();
}
نتیجه اجرای این بخش
بعد از این تغییرات:
- با افزودن هر آیتم جدید، مجموع کالریها دوباره محاسبه میشود
- مقدار جدید بلافاصله در رابط کاربری نمایش داده میشود
- هنگام اجرای اولیه برنامه نیز مقدار مجموع نمایش داده میشود
- ساختار برنامه برای اتصال به
Local Storageدر بخشهای بعدی آماده خواهد بود
نسخه کامل کد این بخش
app.js
// Storage Controller
// Item Controller
const ItemCtrl = (function () {
const Item = function (id, name, calories) {
this.id = id;
this.name = name;
this.calories = calories;
};
const data = {
items: [],
currentItem: null,
totalCalories: 0
};
return {
getItems: function () {
return data.items;
},
addItem: function (name, calories) {
let id;
if (data.items.length > 0) {
id = data.items[data.items.length - 1].id + 1;
} else {
id = 0;
}
calories = parseInt(calories);
const newItem = new Item(id, name, calories);
data.items.push(newItem);
return newItem;
},
getTotalCalories: function () {
let total = 0;
data.items.forEach(function (item) {
total += item.calories;
});
data.totalCalories = total;
return data.totalCalories;
},
logData: function () {
return data;
}
};
})();
// UI Controller
const UICtrl = (function () {
const UISelectors = {
itemList: '#item-list',
addBtn: '.add-btn',
itemNameInput: '#item-name',
itemCaloriesInput: '#item-calories',
totalCalories: '.total-calories'
};
return {
populateItemList: function (items) {
let html = '';
items.forEach(function (item) {
html += `
<li class="collection-item" id="item-${item.id}">
<strong>${item.name}: </strong>
<em>${item.calories} Calories</em>
<a href="#" class="secondary-content">
<i class="edit-item fa fa-pencil"></i>
</a>
</li>
`;
});
document.querySelector(UISelectors.itemList).innerHTML = html;
},
getItemInput: function () {
return {
name: document.querySelector(UISelectors.itemNameInput).value,
calories: document.querySelector(UISelectors.itemCaloriesInput).value
};
},
addListItem: function (item) {
document.querySelector(UISelectors.itemList).style.display = 'block';
const li = document.createElement('li');
li.className = 'collection-item';
li.id = `item-${item.id}`;
li.innerHTML = `
<strong>${item.name}: </strong>
<em>${item.calories} Calories</em>
<a href="#" class="secondary-content">
<i class="edit-item fa fa-pencil"></i>
</a>
`;
document
.querySelector(UISelectors.itemList)
.insertAdjacentElement('beforeend', li);
},
showTotalCalories: function (totalCalories) {
document.querySelector(UISelectors.totalCalories).textContent = totalCalories;
},
clearInput: function () {
document.querySelector(UISelectors.itemNameInput).value = '';
document.querySelector(UISelectors.itemCaloriesInput).value = '';
},
hideList: function () {
document.querySelector(UISelectors.itemList).style.display = 'none';
},
getSelectors: function () {
return UISelectors;
}
};
})();
// App Controller
const App = (function (ItemCtrl, UICtrl) {
const loadEventListeners = function () {
const UISelectors = UICtrl.getSelectors();
document
.querySelector(UISelectors.addBtn)
.addEventListener('click', itemAddSubmit);
};
const itemAddSubmit = function (e) {
const input = UICtrl.getItemInput();
if (input.name !== '' && input.calories !== '') {
const newItem = ItemCtrl.addItem(input.name, input.calories);
UICtrl.addListItem(newItem);
const totalCalories = ItemCtrl.getTotalCalories();
UICtrl.showTotalCalories(totalCalories);
UICtrl.clearInput();
}
e.preventDefault();
};
return {
init: function () {
const items = ItemCtrl.getItems();
if (items.length === 0) {
UICtrl.hideList();
} else {
UICtrl.populateItemList(items);
}
const totalCalories = ItemCtrl.getTotalCalories();
UICtrl.showTotalCalories(totalCalories);
loadEventListeners();
}
};
})(ItemCtrl, UICtrl);
App.init();
جمعبندی
در این بخش، منطق محاسبه و نمایش مجموع کالریها را به برنامه اضافه کردیم.
در این مرحله:
- متد
getTotalCaloriesرا درItem Controllerساختیم - مجموع کالری همه آیتمها را با
forEachمحاسبه کردیم - مقدار مجموع را در
data.totalCaloriesذخیره کردیم - متد
showTotalCaloriesرا درUI Controllerافزودیم - بعد از ثبت هر آیتم، مجموع کالریها را در UI نمایش دادیم
- هنگام اجرای اولیه برنامه نیز مقدار مجموع را مقداردهی کردیم
در بخش بعدی، وارد مدیریت وضعیت ویرایش میشویم تا با کلیک روی آیکن ویرایش، فرم به حالت Edit State برود و امکان بهروزرسانی آیتمها فراهم شود.