تا این قسمت توانسته ایم task هایمان را درون local storage ذخیره کنیم تا با reload شدن صفحه از بین نروند. حالا زمان آن است که این مقادیر را از local storage دریافت کرده و در برنامه وارد کنیم. برای انجام این کار ابتدا به یک event-listener احتیاج داریم بنابراین در تابع loadEventListeners خودمان این مورد را نیز اضافه می کنیم:
function loadEventListeners() { // DOM Load Event document.addEventListener('DOMContentLoaded', getTasks); // Add task event form.addEventListener('submit', addTask); // Remove task event taskList.addEventListener('click', removeTask); // Clear task event clearBtn.addEventListener('click', clearTasks); // Filter tasks event filter.addEventListener('keyup', filterTasks); }
همانطور که می بینید منتظر رویداد DOMContentLoaded (به معنی «محتوای DOM بارگذاری شد») هستیم و آن را مستقیما به document متصل کرده ایم. این event-listener تابعی به نام getTasks را اجرا خواهد کرد که باید آن را بنویسیم، بنابراین:
// Get Tasks from LS function getTasks() { let tasks; if (localStorage.getItem('tasks') === null) { tasks = []; } else { tasks = JSON.parse(localStorage.getItem('tasks')); } }
در ابتدا همان کاری را می کنیم که در جلسه ی قبل انجام دادیم؛ اگر درون local storage چیزی بود آن را به متغیر tasks منتسب می کنیم و در غیر این صورت مقدارش را برابر با یک آرایه ی خالی قرار می دهیم. حالا باید بین این task های مختلف گردش کنیم و مقدارشان را دریافت و روی صفحه نمایش دهیم:
// Get Tasks from LS function getTasks() { let tasks; if (localStorage.getItem('tasks') === null) { tasks = []; } else { tasks = JSON.parse(localStorage.getItem('tasks')); } tasks.forEach(function (task) { // Create li element const li = document.createElement('li'); // Add class li.className = 'collection-item'; // Create text node and append to li li.appendChild(document.createTextNode(task)); // Create new link element const link = document.createElement('a'); // Add class link.className = 'delete-item secondary-content'; // Add icon html link.innerHTML = '<i class="fa fa-remove"></i>'; // Append the link to li li.appendChild(link); // Append li to ul taskList.appendChild(li); }); }
توضیحات کد:
در این کد می خواهیم بین مقادیر مختلف در local storage گردش کنیم و برای هر مقدار یک <li> بسازیم تا درون Task list ما نمایش داده شود بنابراین کدهای جلسات قبل برای ساخت <li> را از تابع addTask کپی کرده ایم و درون تابع جدیدمان قرار داده ایم. تنها مقداری که تغییر داده ایم در قسمت Create text node and append to li است که آن را از taskInput.value به task تغییر داده ایم چرا که هنوز کاربر چیزی تایپ نکرده و اصلا taskInput ای نداریم. به عنوان یادآوری، به صورت خلاصه و به ترتیب خطوط کدهای درون forEach این کار ها را انجام می دهند:
حالا مشکلی در حذف این موارد داریم. به طور مثال اگر من روی علامت ضربدر کلیک کنم و یکی از task ها را حذف کنم، پس از refresh کردن صفحه دوباره برمی گردد و در اصل از local storage حذف نمی شود. برای حل این مشکل باید هنگام حذف یک task، آن را از local storage نیز حذف کنیم. اگر یادتان باشد تابعی به نام removeTasks وجود داشت که کار حذف این موارد را انجام می داد:
// Remove Task function removeTask(e) { if (e.target.parentElement.classList.contains('delete-item')) { if (confirm('Are You Sure?')) { e.target.parentElement.parentElement.remove(); } } }
ما باید درون همین تابع کدهای حذف از local storage را نیز بنویسیم، بنابراین:
// Remove Task function removeTask(e) { if (e.target.parentElement.classList.contains('delete-item')) { if (confirm('Are You Sure?')) { e.target.parentElement.parentElement.remove(); // remove from LS removeTaskFromLocalStorage(e.target.parentElement.parentElement); } } }
برای تمیز بودن کدها، فقط نام تابع را درون removeTasks نوشته ام تا همزمان با اجرایش removeTaskFromLocalStorage را نیز اجرا کند. همچنین زمانی که می گوییم مورد x را حذف کن باید مشخص کنیم این x دقیقا چیست اما از آنجایی که id خاصی برای <li> هایمان نداریم باید از مقدار e.target.parentElement.parentElement استفاده کنیم که آن را به تابع هم پاس داده ایم. حالا بیرون از تابع removeTasks، تابع جدید را کدنویسی می کنیم:
// Remove from LS function removeTaskFromLocalStorage(taskItem) { let tasks; if (localStorage.getItem('tasks') === null) { tasks = []; } else { tasks = JSON.parse(localStorage.getItem('tasks')); } tasks.forEach(function (task, index) { if (taskItem.textContent === task) { tasks.splice(index, 1); } }); localStorage.setItem('tasks', JSON.stringify(tasks)); }
توضیحات کد:
اولین کاری که انجام می دهیم ایجاد متغیر tasks است تا بدانیم چیزی در local storage وجود دارد یا خیر. از آنجایی که این کد عینا تکرار موارد قبلی است می توانید آن را از توابع دیگر کپی کنید و مشکلی نخواهیم داشت. در مرحله ی بعد با استفاده از یک حلقه ی forEach بین موارد موجود در local storage (که در اینجا می شود همان متغیر tasks) گردش کرده ایم. درون آن یک شرط if داریم که می گوید اگر taskItem.textContent (یعنی خود متن task - مثلا roxo.ir در مثال خودمان) برابر با task بود، میدانیم که باید حذفش کنیم. task در هر گردش برابر یکی از مقادیر موجود در local storage است؛ به زبان ساده تر اگر مقدار حذف شده (متن <li>) برابر با مقدار موجود در local storage باشد، باید آن مقدار نیز از local storage حذف شود. برای حذف کردن این مقدار از تابع splice استفاده کرده ایم. یادتان باشد که حلقه ی forEach به صورت پارامتر دوم index فعلی در هر گردش را نیز به شما می دهد بنابراین می توانیم از آن استفاده کنیم تا به Splice بگوییم index موردنظر را پیدا کن و سپس 1 مورد را حذف کن. توجه داشته باشید که تا این قسمت برای خودمان task را حذف کرده ایم و هنوز چیزی به local storage نگفته ایم بنابراین بدون هیچ تغییری باقی مانده است. در نهایت باید Local storage را دوباره تنظیم کنیم تا به روز رسانی شود.
حالا اگر roxo.ir را حذف کنیم و صفحه را refresh کنیم هیچ مشکلی نخواهیم داشت. شما می توانید کد را خودتان تست نمایید:
آخرین کاری که باید انجام دهیم اضافه کردن کارایی به دکمه ی Clear Tasks می باشد. اگر task ها را با استفاده از این دکمه حذف کنیم، از local storage حذف نمی شوند، بنابراین باید درون تابع clearTasks کدهای این مورد را نیز اضافه کنیم:
// Clear Tasks function clearTasks() { // taskList.innerHTML = ''; // Faster while (taskList.firstChild) { taskList.removeChild(taskList.firstChild); } // Clear from LS clearTasksFromLocalStorage(); }
تابعی به نام clearTasksFromLocalStorage نوشته ایم بنابراین باید خارج از تابع clearTasks آن را تعریف کنیم:
// Clear Tasks from LS function clearTasksFromLocalStorage() { localStorage.clear(); }
صدا زدن دستور clear روی localStorage تمام local storage را حذف می کند.
با شما تبریک میگویم! شما با موفقیت برنامه ی مدرن to-do list را تمام کردید!
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.