├── .gitignore
├── src
├── assets
│ ├── move.png
│ ├── enter.png
│ ├── refresh.png
│ └── trash.png
├── index.js
├── index.html
├── cleardone.js
├── crud.test.js
├── style.css
└── crud.js
├── .babelrc
├── .hintrc
├── .eslintrc.json
├── .stylelintrc.json
├── LICENSE
├── webpack.config.js
├── package.json
├── .github
└── workflows
│ └── linters.yml
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | coverage/
--------------------------------------------------------------------------------
/src/assets/move.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tajemouti/toDoList/HEAD/src/assets/move.png
--------------------------------------------------------------------------------
/src/assets/enter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tajemouti/toDoList/HEAD/src/assets/enter.png
--------------------------------------------------------------------------------
/src/assets/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tajemouti/toDoList/HEAD/src/assets/refresh.png
--------------------------------------------------------------------------------
/src/assets/trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tajemouti/toDoList/HEAD/src/assets/trash.png
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "test": {
4 | "plugins": ["@babel/plugin-transform-modules-commonjs"]
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/.hintrc:
--------------------------------------------------------------------------------
1 | {
2 | "connector": {
3 | "name": "local",
4 | "options": {
5 | "pattern": ["**", "!.git/**", "!node_modules/**"]
6 | }
7 | },
8 | "extends": ["development"],
9 | "formatters": ["stylish"],
10 | "hints": [
11 | "button-type",
12 | "disown-opener",
13 | "html-checker",
14 | "meta-charset-utf-8",
15 | "meta-viewport",
16 | "no-inline-styles:error"
17 | ]
18 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "jest": true
6 | },
7 | "parser": "babel-eslint",
8 | "parserOptions": {
9 | "ecmaVersion": 2018,
10 | "sourceType": "module"
11 | },
12 | "extends": ["airbnb-base"],
13 | "rules": {
14 | "no-shadow": "off",
15 | "no-param-reassign": "off",
16 | "eol-last": "off",
17 | "import/extensions": [ 1, {
18 | "js": "always", "json": "always"
19 | }]
20 | },
21 | "ignorePatterns": [
22 | "dist/",
23 | "build/"
24 | ]
25 | }
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["stylelint-config-standard"],
3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"],
4 | "rules": {
5 | "at-rule-no-unknown": [
6 | true,
7 | {
8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
9 | }
10 | ],
11 | "scss/at-rule-no-unknown": [
12 | true,
13 | {
14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
15 | }
16 | ],
17 | "csstree/validator": true
18 | },
19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"]
20 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import MyTask from './crud.js';
2 | import './style.css';
3 |
4 | const taskInput = document.getElementById('taskInput');
5 | const enterBtn = document.getElementById('enter');
6 | const refreshBtn = document.getElementById('refresh');
7 |
8 | MyTask.displayList();
9 |
10 | taskInput.addEventListener('click', (e) => {
11 | e.preventDefault();
12 | });
13 |
14 | enterBtn.addEventListener('click', (e) => {
15 | e.preventDefault();
16 | if (taskInput.value) {
17 | const description = taskInput.value;
18 | const done = new MyTask(description);
19 | done.addTask();
20 | }
21 | return 0;
22 | });
23 |
24 | document.querySelectorAll('#clear').forEach((link) => {
25 | link.addEventListener('click', (e) => {
26 | e.preventDefault();
27 | MyTask.clearCompleted();
28 | });
29 | });
30 |
31 | refreshBtn.addEventListener('click', (e) => {
32 | e.preventDefault();
33 | MyTask.refresh();
34 | });
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
12 |
13 |
14 |
Today's To Do
15 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/cleardone.js:
--------------------------------------------------------------------------------
1 | const barDone = (e) => {
2 | const clicked = e.target.closest('.checkbox');
3 | if (!clicked) return;
4 | const listNum = +clicked.dataset.btn;
5 | const taskList = document.querySelector(`.task-${listNum}`);
6 | taskList.querySelector('.list').classList.toggle('line');
7 | taskList.querySelector('.square').classList.toggle('active');
8 | taskList.querySelector('.done').classList.toggle('active');
9 | const tasks = JSON.parse(localStorage.getItem('listItems')) || [];
10 | const taskDone = tasks.find((task) => task.index === listNum);
11 | taskDone.completed = !taskDone.completed;
12 | localStorage.setItem('listItems', JSON.stringify(tasks));
13 | };
14 |
15 | const clearDone = () => {
16 | const tasks = JSON.parse(localStorage.getItem('listItems')) || [];
17 | const filtered = tasks.filter((task) => task.completed === false);
18 | let filtOrder = [];
19 | filtered.forEach((task, count) => {
20 | task.index = count;
21 | filtOrder = [...filtOrder, task];
22 | });
23 | localStorage.setItem('listItems', JSON.stringify(filtOrder));
24 | };
25 |
26 | export { barDone, clearDone };
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Ajrass Tajemouti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 |
4 | module.exports = {
5 | mode: 'development',
6 | entry: {
7 | bundle: path.resolve(__dirname, 'src/index.js'),
8 | },
9 | output: {
10 | path: path.resolve(__dirname, 'dist'),
11 | filename: '[name].js',
12 | clean: true,
13 | assetModuleFilename: '[name][ext]',
14 | },
15 | devtool: 'source-map',
16 | devServer: {
17 | static: {
18 | directory: path.resolve(__dirname, 'dist'),
19 | },
20 | port: 9000,
21 | open: true,
22 | hot: true,
23 | compress: true,
24 | historyApiFallback: true,
25 | },
26 | module: {
27 | rules: [
28 | {
29 | test: /\.css$/,
30 | use: [
31 | 'style-loader',
32 | 'css-loader',
33 | ],
34 | },
35 | {
36 | test: /\.js$/,
37 | exclude: /node_modules/,
38 | use: {
39 | loader: 'babel-loader',
40 | options: {
41 | presets: ['@babel/preset-env'],
42 | },
43 | },
44 | },
45 | ],
46 | },
47 | plugins: [
48 | new HtmlWebpackPlugin({
49 | title: 'To-Do List',
50 | filename: 'index.html',
51 | template: 'src/index.html',
52 | }),
53 | ],
54 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todolist",
3 | "version": "1.0.0",
4 | "description": "to do list application",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "jest --coverage",
8 | "build": "webpack",
9 | "dev": "webpack serve"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "@babel/core": "^7.22.9",
16 | "@babel/preset-env": "^7.22.9",
17 | "babel-eslint": "^10.1.0",
18 | "babel-loader": "^9.1.3",
19 | "css-loader": "^6.8.1",
20 | "eslint": "^7.32.0",
21 | "eslint-config-airbnb-base": "^14.2.1",
22 | "eslint-plugin-import": "^2.27.5",
23 | "hint": "^7.1.10",
24 | "html-webpack-plugin": "^5.5.3",
25 | "jest": "^29.6.1",
26 | "jest-environment-jsdom": "^29.6.2",
27 | "jest-localstorage-mock": "^2.4.26",
28 | "jsdom": "^22.1.0",
29 | "style-loader": "^3.3.3",
30 | "stylelint": "^13.13.1",
31 | "stylelint-config-standard": "^21.0.0",
32 | "stylelint-csstree-validator": "^1.9.0",
33 | "stylelint-scss": "^3.21.0",
34 | "webpack": "^5.88.2",
35 | "webpack-cli": "^5.1.4",
36 | "webpack-dev-server": "^4.15.1"
37 | },
38 | "jest": {
39 | "moduleNameMapper": {
40 | "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.js",
41 | "\\.(css|less)$": "identity-obj-proxy"
42 | },
43 | "resetMocks": false,
44 | "setupFiles": [
45 | "jest-localstorage-mock"
46 | ],
47 | "verbose": true,
48 | "testEnvironment": "jest-environment-jsdom"
49 | }
50 | }
--------------------------------------------------------------------------------
/src/crud.test.js:
--------------------------------------------------------------------------------
1 | import MyTask from './crud.js';
2 |
3 | describe('run add test', () => {
4 | document.body.innerHTML = `
5 |
6 |
7 |
Today's To Do
8 |
9 |
10 |
14 |
15 |
16 |
17 |
18 |
19 | `;
20 | const task = 'Repair my RC plane';
21 | const tasksItem = new MyTask(task);
22 |
23 | test('Should add a task to the list', () => {
24 | tasksItem.addTask();
25 | const task = JSON.parse(localStorage.getItem('tasksItem'));
26 | expect(task.length).toBe(1);
27 | });
28 |
29 | test('Should remove a task from the list', () => {
30 | MyTask.removeTask(0);
31 | const task = JSON.parse(localStorage.getItem('tasksItem'));
32 | expect(task.length).toBe(0);
33 | });
34 |
35 | test('Should be able to edit the task', () => {
36 | tasksItem.addTask();
37 | new MyTask('tasksItem').addTask();
38 | const editTask = 'Configure the gyroscope';
39 | MyTask.updateTask(1, editTask);
40 | const task = JSON.parse(localStorage.getItem('tasksItem'));
41 | expect(task[1].description).toBe(editTask);
42 | });
43 |
44 | test('Should update the completed task', () => {
45 | MyTask.completed(1, true);
46 | const task = JSON.parse(localStorage.getItem('tasksItem'));
47 | expect(task[0].completed).toBe(true);
48 | });
49 |
50 | test('Should remove all completed tasks', () => {
51 | MyTask.clearCompleted();
52 | const task = JSON.parse(localStorage.getItem('tasksItem'));
53 | expect(task[0].completed).toBe(false);
54 | });
55 | });
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | padding: 0;
4 | margin: 0;
5 | }
6 |
7 | #container {
8 | width: 60%;
9 | margin: 5% 20%;
10 | border: 1px solid #e2dbdb;
11 | }
12 |
13 | .containers {
14 | display: flex;
15 | justify-content: space-between;
16 | align-items: center;
17 | border-bottom: 1px solid #e2dbdb;
18 | padding: 24px;
19 | }
20 |
21 | #refresh {
22 | background: url('/src/assets/refresh.png');
23 | background-size: contain;
24 | opacity: 0.8;
25 | }
26 |
27 | button {
28 | background: transparent;
29 | border: none;
30 | height: 24px;
31 | width: 24px;
32 | cursor: pointer;
33 | }
34 |
35 | button:active {
36 | transform: scale(1.1);
37 | }
38 |
39 | #enter {
40 | background: url('/src/assets/enter.png');
41 | background-size: contain;
42 | opacity: 0.5;
43 | }
44 |
45 | .list {
46 | padding: 18px;
47 | font-size: 18px;
48 | min-width: 85%;
49 | }
50 |
51 | input {
52 | border: none;
53 | outline: 0;
54 | }
55 |
56 | .list.cross {
57 | text-decoration: line-through;
58 | }
59 |
60 | .containers input {
61 | width: 90%;
62 | padding: 8px;
63 | font-size: 16px;
64 | border: none;
65 | }
66 |
67 | .task {
68 | display: flex;
69 | align-items: center;
70 | border-bottom: 1px solid #e2dbdb;
71 | padding-left: 24px;
72 | position: relative;
73 | }
74 |
75 | .move {
76 | background: url('/src/assets/move.png');
77 | background-size: contain;
78 | position: absolute;
79 | top: 16px;
80 | right: 24px;
81 | }
82 |
83 | .move:hover {
84 | background: url('/src/assets/trash.png');
85 | background-size: contain;
86 | }
87 |
88 | .clear {
89 | padding: 24px;
90 | display: flex;
91 | justify-content: center;
92 | background-color: #e9e3e3;
93 | }
94 |
95 | #clear {
96 | color: #636363;
97 | font-size: 20px;
98 | font-weight: 700;
99 | width: 100%;
100 | }
101 |
--------------------------------------------------------------------------------
/.github/workflows/linters.yml:
--------------------------------------------------------------------------------
1 | name: Linters
2 |
3 | on: pull_request
4 |
5 | env:
6 | FORCE_COLOR: 1
7 |
8 | jobs:
9 | lighthouse:
10 | name: Lighthouse
11 | runs-on: ubuntu-22.04
12 | steps:
13 | - uses: actions/checkout@v3
14 | - uses: actions/setup-node@v3
15 | with:
16 | node-version: "18.x"
17 | - name: Setup Lighthouse
18 | run: npm install -g @lhci/cli@0.11.x
19 | - name: Lighthouse Report
20 | run: lhci autorun --upload.target=temporary-public-storage --collect.staticDistDir=.
21 | webhint:
22 | name: Webhint
23 | runs-on: ubuntu-22.04
24 | steps:
25 | - uses: actions/checkout@v3
26 | - uses: actions/setup-node@v3
27 | with:
28 | node-version: "18.x"
29 | - name: Setup Webhint
30 | run: |
31 | npm install --save-dev hint@7.x
32 | [ -f .hintrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.hintrc
33 | - name: Webhint Report
34 | run: npx hint .
35 | stylelint:
36 | name: Stylelint
37 | runs-on: ubuntu-22.04
38 | steps:
39 | - uses: actions/checkout@v3
40 | - uses: actions/setup-node@v3
41 | with:
42 | node-version: "18.x"
43 | - name: Setup Stylelint
44 | run: |
45 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x
46 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.stylelintrc.json
47 | - name: Stylelint Report
48 | run: npx stylelint "**/*.{css,scss}"
49 | eslint:
50 | name: ESLint
51 | runs-on: ubuntu-22.04
52 | steps:
53 | - uses: actions/checkout@v3
54 | - uses: actions/setup-node@v3
55 | with:
56 | node-version: "18.x"
57 | - name: Setup ESLint
58 | run: |
59 | npm install --save-dev eslint@7.x eslint-config-airbnb-base@14.x eslint-plugin-import@2.x babel-eslint@10.x
60 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.eslintrc.json
61 | - name: ESLint Report
62 | run: npx eslint .
63 | nodechecker:
64 | name: node_modules checker
65 | runs-on: ubuntu-22.04
66 | steps:
67 | - uses: actions/checkout@v3
68 | - name: Check node_modules existence
69 | run: |
70 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 📗 Table of Contents
4 |
5 | - [📖 About the Project](#about-project)
6 | - [🛠 Built With](#built-with)
7 | - [Tech Stack](#tech-stack)
8 | - [Key Features](#key-features)
9 | - [🚀 Live Demo](#live-demo)
10 | - [💻 Getting Started](#getting-started)
11 | - [Setup](#setup)
12 | - [Prerequisites](#prerequisites)
13 | - [Install](#install)
14 | - [Usage](#usage)
15 | - [Run tests](#run-tests)
16 | - [👥 Authors](#authors)
17 | - [🔭 Future Features](#future-features)
18 | - [🤝 Contributing](#contributing)
19 | - [⭐️ Show your support](#support)
20 | - [🙏 Acknowledgements](#acknowledgements)
21 | - [📝 License](#license)
22 |
23 |
24 | # 📖 [To-Do List App]
25 |
26 | **[To-Do List App]** is a learning project in which it is required to implement HTML/JavaScript linters.. And build a meduim fidelity wireframe To-Do List application using ES6 and WebPack framework..
27 |
28 | ## 🛠 Built With
29 | Visual Studia Code, HTML/JavaScript linters, ES6, Webpack.
30 |
31 | ### Tech Stack
32 |
33 |
34 | HTML
35 |
36 |
37 |
38 | JavaScript ES6
39 |
40 |
41 |
42 | CSS
43 |
44 |
45 |
46 | Webpack
47 |
48 |
49 | ### Key Features
50 |
51 | - **[Linters implementation]**
52 | - **[To-Do List application]**
53 | - **[Single Page application]**
54 | - **[JavaScript Modules]**
55 |
56 | (back to top)
57 |
58 | ## 🚀 Live Demo
59 |
60 | - [Live Demo Link](https://tajemouti.github.io/toDoList/dist/)
61 |
62 | (back to top)
63 |
64 | ## 💻 Getting Started
65 |
66 | ### Setup
67 |
68 | In order to use this project.. Clone this repository to your desired folder by pasting this command in your command line interface:
69 |
70 | https://github.com/tajemouti/todolist.git
71 |
72 | ### Prerequisites
73 |
74 | Node.js
75 | ES6
76 | Git
77 | HTML/JavaScript linters
78 | Webpack
79 | Webpack sever
80 |
81 | ### Install
82 |
83 | Install dependencies:
84 |
85 | npm install
86 |
87 |
88 | ### Usage
89 |
90 | -Run
91 |
92 | npm run build
93 |
94 | -then
95 |
96 | npm run dev
97 |
98 |
99 | ### Run tests
100 |
101 | To test this application, run:
102 |
103 | npm test
104 |
105 | (back to top)
106 |
107 |
108 | ## 👥 Authors
109 |
110 | 👤 **Author1**
111 |
112 | - GitHub: [@tajemouti](https://github.com/tajemouti)
113 | - Twitter: [@AjrassTajemouti](https://twitter.com/AjrassTajemouti)
114 | - LinkedIn: [LinkedIn](https://linkedin.com/in/ajrass)
115 |
116 |
117 | ## 🔭 Future Features
118 |
119 | - [ ] **[A medium fedility wire-frame application]**
120 | - [ ] **[Interactive To-Do List application]**
121 | - [ ] **[Secure deployment using GitHub Pages]**
122 |
123 | (back to top)
124 |
125 |
126 | ## 🤝 Contributing
127 |
128 | Contributions, issues, and feature requests are welcome!
129 |
130 | Feel free to check the [issues page](../../issues/).
131 |
132 | (back to top)
133 |
134 |
135 | ## ⭐️ Show your support
136 |
137 | Kindly give this project a star if you like it.
138 |
139 | (back to top)
140 |
141 |
142 | ## 🙏 Acknowledgments
143 |
144 | I would like to thank Microverse.
145 |
146 | (back to top)
147 |
148 |
149 | ## 📝 License
150 |
151 | This project is [MIT](/LICENSE) license.
152 |
153 | (back to top)
154 |
--------------------------------------------------------------------------------
/src/crud.js:
--------------------------------------------------------------------------------
1 | export default class MyTask {
2 | constructor(description) {
3 | this.description = description;
4 | }
5 |
6 | static clearInput = () => {
7 | const taskInput = document.getElementById('taskInput');
8 | taskInput.value = '';
9 | return true;
10 | }
11 |
12 | static getTask = () => {
13 | let listItem = [];
14 | const task = localStorage.getItem('tasksItem');
15 | if (task === null) {
16 | localStorage.setItem('tasksItem', JSON.stringify(listItem));
17 | }
18 | listItem = JSON.parse(localStorage.getItem('tasksItem'));
19 | return listItem;
20 | }
21 |
22 | static getIndex = () => {
23 | const listItem = MyTask.getTask();
24 | let index = 0;
25 | if (listItem === null) {
26 | return index + 1;
27 | }
28 | index = listItem.length + 1;
29 | return index;
30 | }
31 |
32 | static updateIndex = () => {
33 | const listItem = MyTask.getTask();
34 | listItem.forEach((item) => {
35 | const count = listItem.findIndex((obj) => obj === item);
36 | item.index = count + 1;
37 | });
38 | localStorage.setItem('tasksItem', JSON.stringify(listItem));
39 | }
40 |
41 | addTask = () => {
42 | const task = MyTask.getTask();
43 | const index = MyTask.getIndex();
44 | const tasksItem = {
45 | index,
46 | description: this.description,
47 | completed: false,
48 | };
49 |
50 | if (task === null) {
51 | task.push(tasksItem);
52 | localStorage.setItem('tasksItem', JSON.stringify(task));
53 | }
54 | let newlistItem = JSON.parse(localStorage.getItem('tasksItem'));
55 | newlistItem = [...task, tasksItem];
56 | localStorage.setItem('tasksItem', JSON.stringify(newlistItem));
57 | MyTask.clearInput();
58 | MyTask.displayList();
59 | MyTask.updateIndex();
60 | }
61 |
62 | static displayList() {
63 | const listItem = MyTask.getTask();
64 | const taskList = document.getElementById('tasks');
65 | let list = '';
66 | listItem.forEach((tasksItem) => {
67 | list += `
68 |
69 |
70 |
71 | `;
72 | });
73 | taskList.innerHTML = list;
74 | MyTask.addEventListenersToListItems();
75 | MyTask.updateIndex();
76 | MyTask.checkedTask();
77 | }
78 |
79 | static removeTask = (index) => {
80 | const listItem = MyTask.getTask();
81 | listItem.splice(index, 1);
82 | localStorage.setItem('tasksItem', JSON.stringify(listItem));
83 | MyTask.addEventListenersToListItems();
84 | MyTask.displayList();
85 | MyTask.updateIndex();
86 | }
87 |
88 | static updateTask = (index, value) => {
89 | const listItem = MyTask.getTask();
90 | listItem.forEach((item) => {
91 | const count = listItem.findIndex((obj) => obj === item);
92 | if (index === count) {
93 | item.description = value;
94 | }
95 | localStorage.setItem('tasksItem', JSON.stringify(listItem));
96 | });
97 | MyTask.updateIndex();
98 | }
99 |
100 | static completed = (index, value) => {
101 | const listItem = MyTask.getTask();
102 | listItem[index - 1].completed = value;
103 | localStorage.setItem('tasksItem', JSON.stringify(listItem));
104 | MyTask.updateIndex();
105 | }
106 |
107 | static clearCompleted = () => {
108 | const listItem = MyTask.getTask();
109 | const uncompleted = listItem.filter((tasksItem) => tasksItem.completed === false);
110 | localStorage.setItem('tasksItem', JSON.stringify(uncompleted));
111 | MyTask.displayList();
112 | }
113 |
114 | static checkedTask = () => {
115 | const listItem = MyTask.getTask();
116 | listItem.forEach((item) => {
117 | if (item.completed === true) {
118 | document.querySelector(`#\\3${item.index}`).checked = true;
119 | document.querySelector(`#\\3${item.index}`).nextElementSibling.classList.toggle('cross');
120 | }
121 | });
122 | }
123 |
124 | static refresh = () => {
125 | window.location.reload();
126 | }
127 |
128 | static addEventListenersToListItems = () => {
129 | document.querySelectorAll('.checkbox').forEach((link) => {
130 | link.addEventListener('click', (e) => {
131 | link.nextElementSibling.classList.toggle('cross');
132 | MyTask.completed(link.id, e.target.checked);
133 | });
134 | });
135 | document.querySelectorAll('.list').forEach((link, index) => {
136 | link.addEventListener('keyup', (e) => {
137 | e.preventDefault();
138 | MyTask.updateTask(index, e.target.value);
139 | });
140 | });
141 | document.querySelectorAll('.move').forEach((link, index) => {
142 | link.addEventListener('click', (e) => {
143 | e.preventDefault();
144 | MyTask.removeTask(index);
145 | });
146 | });
147 | };
148 | }
--------------------------------------------------------------------------------