MATIN MOLKARA
SERIES: JavaScript — PART 94 OF 108

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 برود و امکان به‌روزرسانی آیتم‌ها فراهم شود.

// 0 comments
#JavaScript#Calorie Tracker#Total Calories#DOM Manipulation#UI Controller#Item Controller#State Management#آموزش جاوااسکریپت#پروژه جاوااسکریپت

نظرات (0)

نظر خود را بنویسید