Building an Offline-Enabled To-Do List Web App 🚀
Tags: javascript, serviceworke
Published: 2024-04-07 17:02:23

# Building an Offline-Enabled To-Do List Web App

After getting huge success on my previous article. Here is a use case of building an Offline-Enabled Website.
{% post https://dev.to/sh20raj/how-to-make-your-website-used-without-internet-3e3l %}

In today's world, where connectivity isn't always guaranteed, creating web applications that work offline can greatly enhance user experience. In this tutorial, we'll walk through the process of building a simple To-Do List web app that functions both online and offline. We'll be using basic HTML, CSS, and JavaScript, along with a service worker for caching resources.

> [!TIP]
> See [Source Code](https://github.com/SH20RAJ/offline-website) and [Live Preview
](https://sh20raj.github.io/offline-website/)

## Prerequisites
- Basic knowledge of HTML, CSS, and JavaScript
- A text editor
- A browser that supports service workers (most modern browsers)

## Setting Up the Project
Let's start by setting up the basic structure of our project. Create the following files in a new directory:

- `index.html`
- `styles.css`
- `app.js`
- `service-worker.js`

### The HTML Structure (`index.html`)
Our main HTML file will contain the structure of our To-Do List web app. Here's a basic layout:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Offline To-Do List</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <h1>Offline To-Do List</h1>
        <div class="form">
            <input type="text" id="taskInput" placeholder="Add new task...">
            <button onclick="addTask()">Add Task</button>
        </div>
        <ul id="taskList">
            <!-- Tasks will be dynamically added here -->
        </ul>
    </div>
    <script src="app.js"></script>
</body>
</html>
```

### Styling (`styles.css`)
Let's add some basic styles to make our app look presentable:

```css
body {
    font-family: Arial, sans-serif;
    margin: 20px;
}

.container {
    max-width: 600px;
    margin: 0 auto;
}

h1 {
    text-align: center;
}

.form {
    display: flex;
    margin-bottom: 20px;
}

input[type="text"] {
    flex: 1;
    padding: 10px;
}

button {
    padding: 10px 20px;
    background-color: #007bff;
    color: #fff;
    border: none;
    cursor: pointer;
}

button:hover {
    background-color: #0056b3;
}

ul {
    list-style-type: none;
    padding: 0;
}

li {
    margin-bottom: 10px;
}

.completed {
    text-decoration: line-through;
    color: #888;
}
```

### Adding Functionality (`app.js`)
Our JavaScript file will handle the logic for adding tasks, toggling completion, deleting tasks, rendering tasks, and saving tasks to `localStorage`. It will also register the service worker.

```javascript
let tasks = [];

// Check if there are tasks in localStorage
const storedTasks = localStorage.getItem('tasks');
if (storedTasks) {
    tasks = JSON.parse(storedTasks);
    renderTasks();
}

function addTask() {
    const taskInput = document.getElementById('taskInput');
    const taskText = taskInput.value.trim();
    if (taskText !== '') {
        tasks.push({ text: taskText, completed: false });
        taskInput.value = '';
        renderTasks();
        saveTasks();
    }
}

function toggleTask(index) {
    tasks[index].completed = !tasks[index].completed;
    renderTasks();
    saveTasks();
}

function deleteTask(index) {
    tasks.splice(index, 1);
    renderTasks();
    saveTasks();
}

function renderTasks() {
    const taskList = document.getElementById('taskList');
    taskList.innerHTML = '';
    tasks.forEach((task, index) => {
        const li = document.createElement('li');
        li.innerHTML = `
            <span class="${task.completed ? 'completed' : ''}" onclick="toggleTask(${index})">${task.text}</span>
            <button onclick="deleteTask(${index})">Delete</button>
        `;
        taskList.appendChild(li);
    });
}

function saveTasks() {
    localStorage.setItem('tasks', JSON.stringify(tasks));
}

// Service Worker Registration
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
        .then(reg => {
            console.log('Service Worker registered');
        })
        .catch(error => {
            console.error('Service Worker registration failed:', error);
        });
}
```

### Service Worker (`service-worker.js`)
The service worker file is responsible for caching the necessary files and handling requests when the app is offline:

```javascript
const cacheName = 'offline-v1';
const cacheFiles = [
    '/',
    '/index.html',
    '/styles.css',
    '/app.js'
];

self.addEventListener('install', e => {
    console.log('Service Worker: Installed');
    e.waitUntil(
        caches.open(cacheName)
        .then(cache => {
            console.log('Service Worker: Caching Files');
            cache.addAll(cacheFiles);
        })
        .then(() => self.skipWaiting())
    );
});

self.addEventListener('activate', e => {
    console.log('Service Worker: Activated');
    e.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cache => {
                    if (cache !== cacheName) {
                        console.log('Service Worker: Clearing Old Cache');
                        return caches.delete(cache);
                    }
                })
            );
        })
    );
});

self.addEventListener('fetch', e => {
    console.log('Service Worker: Fetching');
    e.respondWith(
        fetch(e.request)
        .then(response => {
            const clone = response.clone();
            caches.open(cacheName)
                .then(cache => {
                    cache.put(e.request, clone);
                });
            return response;
        })
        .catch(() => caches.match(e.request).then(response => response))
    );
});
```

## Conclusion
By following this tutorial, you've learned how to create an offline-enabled To-Do List web app using basic web technologies. Users can add tasks, mark them as completed, and delete them - all while offline. The service worker ensures that the app functions seamlessly even without an internet connection by caching the necessary files.

Feel free to expand upon this project by adding more features like editing tasks, due dates, or even syncing with a backend server when connectivity is restored. This is just the beginning of what you can achieve with offline web applications!

> Download This Article :- https://gist.github.com/SH20RAJ/574a952fe360ca170e81f7447626cc2a

Happy coding! 🚀