Welcome to the next exciting step in “JavaScript Deep Dive”! Previously, we mastered managing tasks with arrays and objects. Now, let’s introduce user interactions through functions and event listeners, enabling dynamic task addition directly through user input. But to do that we need to learn couple of interesting javascript concepts.
JavaScript Functions
Functions are reusable blocks of code designed to perform specific tasks. They help reduce repetition and improve readability by breaking complex operations into steps, also making code easier to debug and maintain.
Types of Functions
-
Function Declaration:
These are the most common type of functions. They are defined using thefunction
keyword, followed by the function name, parameters, and the function body.
function addTask(taskName) {
if (!taskName) return; // Early exit
console.log(`Added: ${taskName}`);
}
addTask("Learn React"); // "Added: Learn React"
-
Function Expression:
These functions are defined as part of an expression, usually assigned to a variable. They can be named or anonymous.
const calculateTime = function(task) {
return task.estimate * 1.2; // Add 20% buffer
};
console.log(calculateTime({ estimate: 30 })); // 36
-
Arrow Functions:
Introduced in ES6, arrow functions provide a more concise syntax for writing functions. They are always anonymous.
const formatTask = (task) => `${task.title} [${task.priority}]`;
console.log(formatTask({ title: "Debug", priority: "High" })); // "Debug [High]"
-
Anonymous Functions:
These functions do not have a name. They are often used as callbacks or within function expressions.
tasks.forEach(function(task) {
console.log(task.title);
});
-
Immediately Invoked Function Expression (IIFE):
These functions are defined and executed immediately. They are often used to create a private scope.
(function() {
console.log("IIFE executed");
})();
Function Parameters and Return Statements
Parameters: Function Inputs
Function parameters are the names listed in the function definition. They act as placeholders for the values that will be passed into the function when it is called. Parameters are essentially input variables local to the function’s scope.
// Parameter: 'taskName'
function markComplete(taskName) {
console.log(`${taskName} completed!`);
}
markComplete("Fix login bug"); // Argument: "Fix login bug"
Key Features:
- Default Values: Fallback if no argument passed.
function setReminder(task, urgency = "medium") {
console.log(`Reminder set for ${task} (${urgency})`);
}
setReminder("Pay bills"); // Uses default urgency
- Rest Parameters: Capture unlimited arguments as an array.
function addMultipleTasks(...tasks) {
tasks.forEach(task => console.log(`Added: ${task}`));
}
addMultipleTasks("Email team", "Update UI", "Test API");
// Output:
// "Added: Email team"
// "Added: Update UI"
// "Added: Test API"
- Destructuring: Unpack object properties.
function displayTask({ title, priority }) { // Destructuring
console.log(`${title} [${priority}]`);
}
const myTask = { title: "Debug code", priority: "Critical" };
displayTask(myTask);
Return Statements: Function Outputs
The Return statement is used to specify the value that a function should return after it has completed its execution.
function createTask(title) {
return { id: Date.now(), title }; // Returns new task object
}
const task = createTask("Learn React");
console.log(task); // { id: 162..., title: "Learn React" }
Event Listeners in JavaScript
Event listeners in JavaScript are functions that wait for a specific event to occur on an HTML element and then execute a callback function in response. They are used to make web pages interactive by allowing developers to respond to user actions such as clicks, mouse movements, keyboard inputs, or changes in the state of an HTML element.
Event listeners are attached to HTML elements using the addEventListener() method. This method takes two arguments: the type of event to listen for (e.g., “click”, “mouseover”, “keydown”) and the callback function to execute when the event occurs.
element.addEventListener(eventType, callbackFunction);
Now that we know what event listeners are let’s look at some events and how to add listeners
- Click Events:
const addBtn = document.getElementById('add-btn');
addBtn.addEventListener('click', () => {
console.log("Add new task button clicked!");
// Logic to add task here
});
- Keyboard Events:
taskInput.addEventListener('keydown', (event) => {
if (event.key === "Enter") {
addTask(taskInput.value);
}
});
Event Listeners are common source of memory leaks keep few things find like
- Remove listeners when no longer needed:
button.removeEventListener('click', handleClick);
- Use once option for one-time events:
welcomeBtn.addEventListener('click', showWelcomeMessage, { once: true });
Project: Build a Dynamic Task Manager from Scratch III
Let’s create functionality where users can add tasks via a form, updating the task list dynamically.
Update the HTML to add form
<h1>My Task List</h1>
<form id="task-form">
<input type="text" id="task-input" placeholder="Enter task" required />
<select id="priority-input">
<option value="Critical">Critical</option>
<option value="High">High</option>
<option value="Medium">Medium</option>
<option value="Low">Low</option>
</select>
<button type="submit">Add Task</button>
</form>
<ul id="task-list"></ul>
Add Event Listeners and other relevant changes in the JavaScript <script>
section of the code
<script>
// Initialize tasks array with some initial tasks
const tasks = [
{ id: 1, title: "Buy groceries", priority: "High" },
{ id: 2, title: "Complete JavaScript", priority: "Critical" },
{ id: 3, title: "Read a book", priority: "Medium" }
];
const taskForm = document.getElementById('task-form');
const taskList = document.getElementById('task-list');
// Function to sanitize input
const sanitizeInput = (input) => input.trim().toLowerCase();
// Function to add and display tasks
const addTask = (title, priority) => {
const sanitizedTitle = sanitizeInput(title);
const task = { id: tasks.length + 1, title: sanitizedTitle, priority };
tasks.push(task);
renderTasks();
};
// Function to render tasks to the DOM
const renderTasks = () => {
taskList.innerHTML = '';
tasks.forEach(({ title, priority }) => {
let color;
switch(priority) {
case "Critical": color = "#e74c3c"; break;
case "High": color = "#f39c12"; break;
case "Medium": color = "#3498db"; break;
default: color = "#2ecc71";
}
taskList.innerHTML += `
<li style="color: ${color}">
${title} <span class="priority-badge">${priority}</span>
</li>`;
});
};
renderTasks();
// Event Listener for form submission
taskForm.addEventListener('submit', (event) => {
event.preventDefault(); // Prevent page reload
const title = document.getElementById('task-input').value;
const priority = document.getElementById('priority-input').value;
if (title) {
addTask(title, priority);
taskForm.reset(); // Clear form fields
} else {
alert("Please enter a task!");
}
});
</script>
What we have changed and achieved
-
Added User Input Form: Added a
<form>
with text input and priority dropdown this allows users to dynamically add new tasks. -
Event Driven Architecture: Introduced EventListener in the Form submission handler and handling it well with
preventDefault
to have automatic UI updates -
Modularized Code with Functions: We have added couple of functions
sanitizeInput
which cleans user input,addTask
which handles task creation logic andrenderTasks
which manages DOM updates. These functions can be reused and also separates concerns leading to easier code maintenance.
You’ve now created an interactive task manager allowing users to dynamically add tasks through forms. We also have updated the css to keep it beautiful, take a look at the whole code here
TodoOrNotTodo – Chapter 3 Branch
Continue building your skills and enjoy your JavaScript learning journey with JavaScript Deep Dive!