پروژه ی ایجاد To-Do List: ثبت Task جدید

15 آبان 1398
پروژه ی ایجاد To-Do List: ثبت Task جدید

ثبت Task جدید

در قسمت قبل با کمک Materialize توانستیم UI پروژه ی خودمان را تکمیل کنیم. در این قسمت باید آماده سازی های جاوا اسکریپتی را انجام بدهیم تا بتوانیم به توسعه ی اصل برنامه برسیم. قدم اول، تعریف متغیرهای مربوط به UI است. منظور من از متغیرهای مربوط به UI، متغیرهایی هستند که به عنصر خاصی در UI (در اینجا HTML) اشاره دارند. ما به این متغیرها نیاز داریم تا بعدا روی آن ها تغییراتی انجام دهیم بنابراین شروع می کنیم:

//  Define UI Variables

const form = document.querySelector('#task-form');
const taskList = document.querySelector('.collection');
const clearBtn = document.querySelector('.clear-tasks');
const filter = document.querySelector('#filter');
const taskInput = document.querySelector('#task');

ما به نوعی با تمام این موارد سرو ار خواهیم داشت. اگر نمی دانید این متغیرها به چه عنصری ارجاع می دهند، می توانید کلاس یا id آن ها را در فایل index.html چک کنید.

حالا باید کاری کنیم که فرم ما قابل ثبت (submit) باشد. برای ثبت کردن فرم می خواهیم یک تابع به نام loadEventListeners داشته باشیم که این کار را برایمان انجام می دهد:

// Load all event listeners
loadEventListeners();

// Load all event listeners
function loadEventListeners() {
    // Add task event
    form.addEventListener('submit', addTask);
}

سوال: در کد بالا ابتدا تابع را صدا زده و سپس آن را تعریف کرده ایم. آیا مشکلی پیش نمی آید؟

پاسخ: خیر، در برخی از زبان های برنامه نویسی با مشکل مواجه می شویم اما زبان جاوا اسکریپت مفهومی به نام hoisting دارد. قبلا در مقاله ی «مبحث Hoisting در جاوا اسکریپت» توضیح داده بودم که:
Hoisting (در فارسی به معنی «بالا بردن/کشیدن» یا «برافراشتن») رفتار پیش فرض جاوا اسکریپت در زمینه ی declaration ها است. بر اساس این قابلیت، جاوا اسکریپت تمام declaration های متغیرها را به بالای سورس کد انتقال می دهد.
همچنین به یاد داشته باشید که در حالت strict mode جاوا اسکریپت اجازه ی چنین کاری را ندارید و تعریف تابع باید حتما قبل از صدا زدن آن صورت بگیرد.

در کد بالا قرار است یک eventlistener را به فرم خود متصل کنیم. Event مورد نظر همان ثبت فرم (submit) است و یک تابع به نام addTask را اجرا می کند. بنابراین تنها کاری که مانده است، تعریف کردن تابع addTask می باشد اما قبل از آن به یک سوال می پردازیم.

سوال: چرا از چنین تابعی استفاده کرده ایم؟ چرا مستقیما تمام eventlistener ها را ننوشته ایم؟ فلسفه ی وجودی تابع loadEventListeners چیست؟

پاسخ: نوشتن تک تک eventlistener ها برنامه ی ما را شلوغ و به هم ریخته می کند. شما می توانید این کار را امتحان کنید و ببینید که پیدا کردن کدهایتان در چنین حالتی سخت تر می شود. البته مشکلی ندارد که شما به روش عادی و دستی کدها را بنویسید اما بهتر است از همین روش ما استفاده کنید. من یک تابع به نام loadEventListeners را ساخته ام که فعلا یک eventlistener را به فرم اضافه می کند (برای ثبت فرم) اما در جلسات بعد کارهای بیشتری داریم و eventlistener های متعددی را به آن اضافه خواهیم کرد. بنابراین به محض اجرای برنامه (باز شدن سایت) تمام eventlistener های موجود به عناصر مورد نظرشان متصل خواهند شد. با نوشتن کدها بدین شکل، تمام eventlistener ها را یکجا و مرتب خواهیم داشت.

خب حالا نوبت تعریف تابع addTask است:

function addTask(e) {

    e.preventDefault();
}

همانطور که بالا تر گفتیم این تابع روی یک event خاص اجرا می شود بنابراین شیء event را به صورت خودکار دریافت می کند که ما برای دریافت آن از حرف e در پارامتر تابع استفاده کرده ایم. این تابع برای submit شدن فرم ما است بنابراین اولین کاری که کرده ایم preventDefault است. تابع preventDefault از رفتار پیش فرض عناصر در HTML جلوگیری می کند؛ در برنامه ی ما preventDefault مانع از submit (ثبت) شدن فرم می شود. چرا مانع ثبت فرم شده ایم؟ به دلیل اینکه می خواهیم اول از همه برخی موارد را بررسی کنیم و کاربر تنها زمانی بتواند فرم را ثبت کند که صحت آن موارد برقرار باشد. برای قدم اول باید مطمئن شویم که فرم ما خالی نیست (یعنی کاربر فرم خالی را ثبت نکند):

function addTask(e) {
    if (taskInput.value === '') {
        alert('Add a task');
    }

    e.preventDefault();
}

taskInput متغیری بود که بالاتر تعریف کرده بودیم:

const taskInput = document.querySelector('#task');

این متغیر همان فیلد فرم ما است. بنابراین گفته ایم اگر taskInput.value (مقدار فیلد) برابر با یک رشته ی خالی باشد (کاربر چیزی وارد نکرده باشد)، یک پنجره ی alert نمایش بده که پیام Add a task را (به معنی «وظیفه ای را اضافه کنید») نمایش بدهد.

اگر الان به مرورگر بروید و بدون اینکه چیزی در فیلد New Task بنویسید، دکمه ی Add a Task را بزنید یک پیام alert نمایش داده می شود اما اگر چیزی درون فیلد باشد هیچ اتفاقی نمی افتد. حالا اگر کاربر چیزی درون فیلد نوشته بود چطور؟ اگر کاربر وظیفه ای را درون فیلد تایپ کرده بود باید آن را به صورت یک <li> به کدهایمان اضافه کنیم. محتوای فایل index.html را یادتان است؟

<ul class="collection"></ul>

بنابراین من می خواهیم عنصر <li> را بسازم و به این ul اضافه کنم. برای این کار می گوییم:

// 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(taskInput.value));

در خط اول ابتدا یک عنصر <li> ساخته ام. در خط دوم یک کلاس برایش تعیین کرده ام که از کلاس های Materialize است (در Materialize اگر میخواهید li های زیبایی داشته باشید باید ul شما دارای کلاس collection و هر li دارای کلاس collection-item باشد). در خط سوم نیز یک textNode ایجاد کرده و به <li> چسبانده ایم به دلیل اینکه می خواهیم هر چیزی که کاربر در فیلد new task تایپ کرد، مقدار متنی li باشد (کاربر است که Task ها یا وظایف را می نویسد).

حالا باید یک لینک (تگ a) داشته باشیم تا با استفاده از آن عناصر <li> مورد نظر را حذف کنیم بنابراین:

// 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);

در خط اول عنصر a را ساخته ام. در خط دوم کلاس مورد نظر materialize را به آن اضافه کرده ام (کلاس secondary-content علامت ضربدر برای حذف را به سمت راست عنصر می برد). در خط سوم innerHTML را روی یک <i> گذاشته ایم که علامت ضربدر را از کتابخانه ی font-awesome انتخاب می کند. در خط آخر این تگ a را به عنصر <li> می چسبانیم.

حالا کدها را تکمیل می کنیم:

  // Append li to ul
  taskList.appendChild(li);

  // Clear input
  taskInput.value = '';

taskList همان متغیری است که به ul ارجاع می دهد و ما عنصر <li> را به آن چسبانده ایم. در نهایت (پس از ثبت task توسط کاربر) می خواهیم فیلد خالی شود بنابراین مقدار آن را خالی کرده ایم. تبریک میگویم، کدهای ما تکمیل شده است!

شما می توانید به مرورگر بروید و با نوشتن مقادیر متفاوت برنامه را تست کنید (البته به یاد داشته باشید که هنوز آن را تکمیل نکرده ایم).

دانلود کدهای این جلسه

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری پروژه‌های مدرن جاوا اسکریپت توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (2 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

علیرضا ترابی
01 مهر 1399
سلام به اقای زورامی عزیز. ممنونم این دوره خوب رو اضافه کردید واقعا نبودش در سایت های فارسی احساس میشد و بنظرم اینطوری خیلی مفاهیم رو بهتر یاد میگیریم مخصوصا با نویسندگی عالی شما که هم متن هاتون ساده و روان هستند و هم جامع و کامل. خیلی خیلی از شما و سایت روکسو متشکرم

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

آیدا
03 آبان 1398
واقعا خوشحالم که این دوره رو گذاشتین آخه جای یک برنامه ی پروژه محور توی آموزشاتون کم بود خیلی داش تئوری میشد

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
09 آبان 1398
سلام دوست عزیز، خوشحالم که براتون مفید بوده!

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.