├── .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 |
18 | 19 | 20 |
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 |
11 | 12 | 13 |
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 | } --------------------------------------------------------------------------------