├── .gitignore ├── app_screenshot.png ├── .babelrc ├── src ├── modules │ ├── constructor.js │ ├── clear.js │ ├── ToDo.js │ ├── store.js │ └── interface.js ├── index.js ├── test │ ├── add.test.js │ └── edit.test.js ├── index.html └── style.css ├── .hintrc ├── .eslintrc.json ├── .stylelintrc.json ├── webpack.config.js ├── README.md ├── MIT.md ├── package.json ├── dist ├── index.html ├── main.js └── runtime.js └── .github └── workflows └── linters.yml /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /app_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luccamicale/To-Do-List-/HEAD/app_screenshot.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "plugins": ["@babel/plugin-transform-modules-commonjs"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/modules/constructor.js: -------------------------------------------------------------------------------- 1 | export default class ToDos { 2 | constructor(value, completed, index) { 3 | this.value = value; 4 | this.completed = false; 5 | this.index = index; 6 | } 7 | } -------------------------------------------------------------------------------- /src/modules/clear.js: -------------------------------------------------------------------------------- 1 | export default function clearTasks() { 2 | const toDos = JSON.parse(localStorage.getItem('toDos')); 3 | const filter = toDos.filter((toDo) => toDo.completed === false); 4 | localStorage.setItem('toDos', JSON.stringify(filter)); 5 | } -------------------------------------------------------------------------------- /src/modules/ToDo.js: -------------------------------------------------------------------------------- 1 | import Interface from './interface.js'; 2 | import Store from './store.js'; 3 | import ToDos from './constructor.js'; 4 | 5 | export default function add(task) { 6 | const completed = 'asd'; 7 | const toIndex = Store.getToDos().length + 1; 8 | const toDo = new ToDos(task, completed, toIndex); 9 | Interface.addTask(toDo); 10 | Store.addTask(toDo); 11 | } -------------------------------------------------------------------------------- /.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": null, 6 | "scss/at-rule-no-unknown": [ 7 | true, 8 | { 9 | "ignoreAtRules": [ 10 | "tailwind", 11 | "apply", 12 | "variants", 13 | "responsive", 14 | "screen" 15 | ] 16 | } 17 | ] 18 | }, 19 | "csstree/validator": true, 20 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css"] 21 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './style.css'; 2 | import add from './modules/ToDo.js'; 3 | import interfaces from './modules/interface.js'; 4 | import Store from './modules/store.js'; 5 | 6 | document.addEventListener('DOMContentLoaded', interfaces.displayTasks); 7 | document.querySelector('#form-section').addEventListener('submit', (e) => { 8 | e.preventDefault(); 9 | const text = document.getElementById('input-task').value; 10 | add(text); 11 | }); 12 | document.querySelector('#addBtn').addEventListener('click', add); 13 | 14 | const clearAll = document.querySelector('.clearCompleted'); 15 | clearAll.addEventListener('click', () => { 16 | Store.clearAll(); 17 | window.location.reload(); 18 | }); -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | 4 | module.exports = { 5 | mode: 'development', 6 | entry: './src/index.js', 7 | devServer: { 8 | static: './dist', 9 | }, 10 | plugins: [ 11 | new HtmlWebpackPlugin({ 12 | template: './src/index.html', 13 | }), 14 | ], 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.css$/i, 19 | use: ['style-loader', 'css-loader'], 20 | }, 21 | ], 22 | }, 23 | 24 | output: { 25 | filename: '[name].js', 26 | path: path.resolve(__dirname, 'dist'), 27 | 28 | clean: true, 29 | }, 30 | optimization: { 31 | runtimeChunk: 'single', 32 | }, 33 | }; -------------------------------------------------------------------------------- /src/test/add.test.js: -------------------------------------------------------------------------------- 1 | import add from '../modules/ToDo.js'; 2 | 3 | // eslint-disable-next-line linebreak-style 4 | describe('adding', () => { 5 | document.body.innerHTML = `
6 |
7 | 8 | 9 |
10 |
11 |
12 | `; 15 | test('Should add one element ', () => { 16 | add('Hello'); 17 | const list = document.querySelectorAll('textarea'); 18 | expect(list).toHaveLength(1); 19 | }); 20 | 21 | test('Should remove one element ', () => { 22 | const deleteBtn = document.querySelector('.delete'); 23 | deleteBtn.click(); 24 | const listElement = document.querySelectorAll('textarea'); 25 | expect(listElement).toHaveLength(0); 26 | }); 27 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # To Do List 2 | 3 | I creted my website in To do list. Now my website is very simple, but in the next project I will add the more functions- 4 | 5 | 6 | ## Built With 7 | 8 | - HTMl 9 | - wepack 10 | - CSS 11 | - Javascript 12 | 13 | ## Live Demo (if available) 14 | 15 | [Live Demo Link](https://livedemo.com) 16 | 17 | 18 | 19 | ## Authors 20 | 21 | 👤 **Lucca Micale** 22 | 23 | - GitHub: [@luccamicale] 24 | - Twitter: [@luccamicale_] 25 | - LinkedIn: [luccamicale] 26 | 27 | 👤 **Daniel Carrera** 28 | ​ 29 | - GitHub: [@carreraprogrammer](https://github.com/carreraprogrammer) 30 | - Twitter: [@carreraprogrammer](https://twitter.com/carreraprog) 31 | - LinkedIn: [Daniel Carrera] (https://www.linkedin.com/in/daniel-carrera-paz-85a917244/) 32 | 33 | ## 🤝 Contributing 34 | 35 | Contributions, issues, and feature requests are welcome! 36 | 37 | Feel free to check the [issues page](../../issues/). 38 | 39 | ## Show your support 40 | 41 | Give a ⭐️ if you like this project! 42 | 43 | ## Acknowledgments 44 | 45 | - Hat tip to anyone whose code was used 46 | - Inspiration 47 | - etc 48 | 49 | ## 📝 License 50 | 51 | This project is [MIT](./LICENSE) licensed. -------------------------------------------------------------------------------- /MIT.md: -------------------------------------------------------------------------------- 1 | ## Copyright 2021, [YOUR NAME] 2 | 3 | ###### Please delete this line and the next one 4 | ###### APP TYPE can be a webpage/website, a web app, a software and so on 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this [APP TYPE] and associated documentation files, to deal in the [APP TYPE] without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the [APP TYPE], and to permit persons to whom the [APP TYPE] is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the [APP TYPE]. 9 | 10 | THE [APP TYPE] IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE [APP TYPE] OR THE USE OR OTHER DEALINGS IN THE [APP TYPE]. 11 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | To Do List 9 | 10 | 11 | 12 | 13 |
14 |
15 | Today's To Do 16 |
17 |
18 |
19 | 20 | 21 |
22 |
23 |
24 |
    25 | 26 |
27 |
28 | 29 |
30 | 31 |
32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /src/test/edit.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable linebreak-style */ 2 | import add from '../modules/ToDo.js'; 3 | import Store from '../modules/store.js'; 4 | import clearTasks from '../modules/clear.js'; 5 | 6 | describe('editing', () => { 7 | document.body.innerHTML = `
8 |
9 | 10 | 11 |
12 |
13 |
14 | `; 17 | test('Should edit one element when is called', () => { 18 | add('Hello'); 19 | const editBtn = document.querySelector('.edit'); 20 | editBtn.click(); 21 | const list = document.querySelector('.text-area'); 22 | list.value = 'asd'; 23 | expect(list.value).toBe('asd'); 24 | }); 25 | 26 | test('Update item complete status', () => { 27 | const obj = { 28 | value: 'hello', 29 | completed: true, 30 | index: 1, 31 | }; 32 | expect(Store.check(obj.completed, 1)).toBe(true); 33 | }); 34 | 35 | test('This function should clear all elements', () => { 36 | const obj2 = { 37 | value: 'clear', 38 | completed: true, 39 | index: 1, 40 | }; 41 | clearTasks(obj2); 42 | expect(JSON.parse(localStorage.getItem('toDos'))).toEqual([]); 43 | }); 44 | }); -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | width: 50%; 5 | border: 1px solid; 6 | background-color: antiquewhite; 7 | } 8 | 9 | input { 10 | border: none; 11 | outline: none; 12 | } 13 | 14 | .box { 15 | display: flex; 16 | justify-content: space-between; 17 | align-items: center; 18 | padding: 1.2em; 19 | gap: 1em; 20 | } 21 | 22 | .clearbtn { 23 | background-color: #eee; 24 | } 25 | 26 | .clr-all:hover { 27 | background-color: #302b2b; 28 | } 29 | 30 | .size { 31 | width: 100%; 32 | } 33 | 34 | .input-task { 35 | width: 100%; 36 | border-color: transparent; 37 | padding-block: 1em; 38 | } 39 | 40 | .form { 41 | display: flex; 42 | } 43 | 44 | .container > * { 45 | border-bottom: 1px solid #80808040; 46 | padding-inline: 1em; 47 | } 48 | 49 | input:focus { 50 | outline: none; 51 | } 52 | 53 | .task-list { 54 | display: flex; 55 | flex-direction: column; 56 | padding: 0; 57 | } 58 | 59 | .title { 60 | margin-top: 1em; 61 | display: flex; 62 | } 63 | 64 | .ul-container li { 65 | display: flex; 66 | align-items: center; 67 | gap: 0.7em; 68 | padding: 0.5em; 69 | } 70 | 71 | .fa-solid { 72 | margin-left: auto; 73 | } 74 | 75 | .clearCompleted { 76 | width: 100%; 77 | padding: 1em; 78 | } 79 | 80 | .toDoList li { 81 | border-bottom: 1px solid #80808040; 82 | } 83 | 84 | #text-field { 85 | width: 100%; 86 | height: 30px; 87 | } 88 | 89 | #clear-btn { 90 | width: 100%; 91 | height: 35px; 92 | text-align: center; 93 | margin-top: 10px; 94 | } 95 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-demo", 3 | "version": "1.0.0", 4 | "description": "![](https://img.shields.io/badge/Microverse-blueviolet)", 5 | "private": true, 6 | "scripts": { 7 | "test": "jest", 8 | "start": "webpack serve --open", 9 | "build": "webpack" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "@babel/plugin-transform-modules-commonjs": "^7.18.6", 16 | "babel-eslint": "^10.1.0", 17 | "css-loader": "^6.7.1", 18 | "eslint": "^7.32.0", 19 | "eslint-config-airbnb-base": "^14.2.1", 20 | "eslint-plugin-import": "^2.26.0", 21 | "global-jsdom": "^8.6.0", 22 | "hint": "^7.1.3", 23 | "html-webpack-plugin": "^5.5.0", 24 | "jest": "^29.2.0", 25 | "jsdom": "^20.0.1", 26 | "style-loader": "^3.3.1", 27 | "stylelint": "^13.13.1", 28 | "stylelint-config-standard": "^21.0.0", 29 | "stylelint-csstree-validator": "^1.9.0", 30 | "stylelint-scss": "^3.21.0", 31 | "webpack": "^5.74.0", 32 | "webpack-cli": "^4.10.0", 33 | "webpack-dev-server": "^4.11.1" 34 | }, 35 | "dependencies": { 36 | "jest-environment-jsdom": "^29.2.0", 37 | "lodash": "^4.17.21" 38 | }, 39 | "jest": { 40 | "testEnvironment": "jsdom", 41 | "verbose": true 42 | }, 43 | "main": "webpack.config.js", 44 | "repository": { 45 | "type": "git", 46 | "url": "git+https://github.com/luccamicale/To-Do-List-.git" 47 | }, 48 | "bugs": { 49 | "url": "https://github.com/luccamicale/To-Do-List-/issues" 50 | }, 51 | "homepage": "https://github.com/luccamicale/To-Do-List-#readme" 52 | } 53 | -------------------------------------------------------------------------------- /src/modules/store.js: -------------------------------------------------------------------------------- 1 | export default class Store { 2 | static getToDos() { 3 | let toDos; 4 | if (localStorage.getItem('toDos') === null) { 5 | toDos = []; 6 | } else { 7 | toDos = JSON.parse(localStorage.getItem('toDos')); 8 | } 9 | 10 | return toDos; 11 | } 12 | 13 | static addTask(toDo) { 14 | const toDos = Store.getToDos(); 15 | toDos.push(toDo); 16 | localStorage.setItem('toDos', JSON.stringify(toDos)); 17 | } 18 | 19 | static deleteTask(element) { 20 | const toDos = Store.getToDos(); 21 | toDos.forEach((toDo, id) => { 22 | if (toDo.index === element) { 23 | toDos.splice(id, 1); 24 | } 25 | }); 26 | toDos.forEach((toDo, i) => { 27 | toDo.index = i + 1; 28 | }); 29 | localStorage.setItem('toDos', JSON.stringify(toDos)); 30 | } 31 | 32 | static editTask(value, idx) { 33 | const toDos = Store.getToDos(); 34 | toDos.forEach((toDo) => { 35 | if (toDo.index === parseInt(idx, 10)) { 36 | toDo.value = value; 37 | } 38 | }); 39 | localStorage.setItem('toDos', JSON.stringify(toDos)); 40 | } 41 | 42 | static check(check, idx) { 43 | const toDos = Store.getToDos(); 44 | toDos.forEach((toDo) => { 45 | if (toDo.index === parseInt(idx, 10)) { 46 | toDo.completed = check; 47 | } 48 | }); 49 | localStorage.setItem('toDos', JSON.stringify(toDos)); 50 | return check; 51 | } 52 | 53 | static clearAll() { 54 | const toDos = Store.getToDos(); 55 | const filter = toDos.filter((toDo) => toDo.completed === false); 56 | 57 | toDos.forEach((toDo, i) => { 58 | toDo.index = i + 1; 59 | }); 60 | localStorage.setItem('toDos', JSON.stringify(filter)); 61 | } 62 | } -------------------------------------------------------------------------------- /src/modules/interface.js: -------------------------------------------------------------------------------- 1 | import Store from './store.js'; 2 | 3 | export default class Interface { 4 | static displayTasks() { 5 | const toDos = Store.getToDos(); 6 | toDos.forEach((toDo) => Interface.addTask(toDo)); 7 | } 8 | 9 | static addTask(toDo) { 10 | const ulList = document.getElementById('toDoList'); 11 | const task = document.createElement('li'); 12 | 13 | const check = document.createElement('input'); 14 | check.type = 'checkbox'; 15 | check.id = 'completed'; 16 | check.checked = toDo.completed; 17 | 18 | check.addEventListener('click', (e) => { 19 | toDo.completed = e.target.checked; 20 | Store.check(toDo.completed, toDo.index); 21 | }); 22 | 23 | const text = document.createElement('textarea'); 24 | text.id = 'task-value'; 25 | text.readOnly = true; 26 | text.classList.add('text-area'); 27 | text.value = toDo.value; 28 | 29 | const editBtn = document.createElement('button'); 30 | editBtn.id = toDo.index; 31 | editBtn.classList.add('edit'); 32 | editBtn.innerHTML = 'Edit'; 33 | 34 | task.appendChild(check); 35 | task.appendChild(text); 36 | task.appendChild(editBtn); 37 | 38 | editBtn.addEventListener('click', () => { 39 | text.removeAttribute('readonly'); 40 | editBtn.innerHTML = 'Save'; 41 | text.focus(); 42 | editBtn.addEventListener('click', () => { 43 | text.setAttribute('readonly', true); 44 | editBtn.innerHTML = 'Edit'; 45 | Store.editTask(text.value, toDo.index); 46 | }); 47 | }); 48 | 49 | const deleteBtn = document.createElement('button'); 50 | deleteBtn.innerHTML = ``; 51 | ulList.appendChild(task); 52 | task.appendChild(deleteBtn); 53 | deleteBtn.addEventListener('click', () => { 54 | deleteBtn.parentElement.remove(); 55 | Store.deleteTask(toDo.index); 56 | }); 57 | } 58 | 59 | static deleteTask(el) { 60 | if (el.classList.contains('delete')) { 61 | el.parentElement.remove(); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Todo List 2022 with LocalStorage 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |

23 | What's up, 24 |

25 |
26 | 27 | 28 | 29 |
30 |

CREATE A TODO

31 |
32 |

What's on your todo?

33 | 38 | 39 |

Pick a category

40 |
41 | 46 | 51 |
52 | 53 | 54 |
55 |
56 | 57 | 58 | 59 |
60 |

TODO LIST

61 |
62 |
63 | 64 | 65 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /.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@v2 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: "12.x" 17 | - name: Setup Lighthouse 18 | run: npm install -g @lhci/cli@0.7.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@v2 26 | - uses: actions/setup-node@v1 27 | with: 28 | node-version: "12.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@v2 40 | - uses: actions/setup-node@v1 41 | with: 42 | node-version: "12.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@v2 54 | - uses: actions/setup-node@v1 55 | with: 56 | node-version: "12.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@v2 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 -------------------------------------------------------------------------------- /dist/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). 3 | * This devtool is neither made for production nor for readable output files. 4 | * It uses "eval()" calls to create a separate source file in the browser devtools. 5 | * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) 6 | * or disable the default devtool with "devtool: false". 7 | * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). 8 | */ 9 | (self["webpackChunkwebpack_demo"] = self["webpackChunkwebpack_demo"] || []).push([["main"],{ 10 | 11 | /***/ "./src/index.js": 12 | /*!**********************!*\ 13 | !*** ./src/index.js ***! 14 | \**********************/ 15 | /***/ (() => { 16 | 17 | eval("window.addEventListener('load', () => {\r\n\ttodos = JSON.parse(localStorage.getItem('todos')) || [];\r\n\tconst nameInput = document.querySelector('#name');\r\n\tconst newTodoForm = document.querySelector('#new-todo-form');\r\n\r\n\tconst username = localStorage.getItem('username') || '';\r\n\r\n\tnameInput.value = username;\r\n\r\n\tnameInput.addEventListener('change', (e) => {\r\n\t\tlocalStorage.setItem('username', e.target.value);\r\n\t})\r\n\r\n\tnewTodoForm.addEventListener('submit', e => {\r\n\t\te.preventDefault();\r\n\r\n\t\tconst todo = {\r\n\t\t\tcontent: e.target.elements.content.value,\r\n\t\t\tcategory: e.target.elements.category.value,\r\n\t\t\tdone: false,\r\n\t\t\tcreatedAt: new Date().getTime()\r\n\t\t}\r\n\r\n\t\ttodos.push(todo);\r\n\r\n\t\tlocalStorage.setItem('todos', JSON.stringify(todos));\r\n\r\n\t\t// Reset the form\r\n\t\te.target.reset();\r\n\r\n\t\tDisplayTodos()\r\n\t})\r\n\r\n\tDisplayTodos()\r\n})\r\n\r\nfunction DisplayTodos () {\r\n\tconst todoList = document.querySelector('#todo-list');\r\n\ttodoList.innerHTML = \"\";\r\n\r\n\ttodos.forEach(todo => {\r\n\t\tconst todoItem = document.createElement('div');\r\n\t\ttodoItem.classList.add('todo-item');\r\n\r\n\t\tconst label = document.createElement('label');\r\n\t\tconst input = document.createElement('input');\r\n\t\tconst span = document.createElement('span');\r\n\t\tconst content = document.createElement('div');\r\n\t\tconst actions = document.createElement('div');\r\n\t\tconst edit = document.createElement('button');\r\n\t\tconst deleteButton = document.createElement('button');\r\n\r\n\t\tinput.type = 'checkbox';\r\n\t\tinput.checked = todo.done;\r\n\t\tspan.classList.add('bubble');\r\n\t\tif (todo.category == 'personal') {\r\n\t\t\tspan.classList.add('personal');\r\n\t\t} else {\r\n\t\t\tspan.classList.add('business');\r\n\t\t}\r\n\t\tcontent.classList.add('todo-content');\r\n\t\tactions.classList.add('actions');\r\n\t\tedit.classList.add('edit');\r\n\t\tdeleteButton.classList.add('delete');\r\n\r\n\t\tcontent.innerHTML = ``;\r\n\t\tedit.innerHTML = 'Edit';\r\n\t\tdeleteButton.innerHTML = 'Delete';\r\n\r\n\t\tlabel.appendChild(input);\r\n\t\tlabel.appendChild(span);\r\n\t\tactions.appendChild(edit);\r\n\t\tactions.appendChild(deleteButton);\r\n\t\ttodoItem.appendChild(label);\r\n\t\ttodoItem.appendChild(content);\r\n\t\ttodoItem.appendChild(actions);\r\n\r\n\t\ttodoList.appendChild(todoItem);\r\n\r\n\t\tif (todo.done) {\r\n\t\t\ttodoItem.classList.add('done');\r\n\t\t}\r\n\t\t\r\n\t\tinput.addEventListener('change', (e) => {\r\n\t\t\ttodo.done = e.target.checked;\r\n\t\t\tlocalStorage.setItem('todos', JSON.stringify(todos));\r\n\r\n\t\t\tif (todo.done) {\r\n\t\t\t\ttodoItem.classList.add('done');\r\n\t\t\t} else {\r\n\t\t\t\ttodoItem.classList.remove('done');\r\n\t\t\t}\r\n\r\n\t\t\tDisplayTodos()\r\n\r\n\t\t})\r\n\r\n\t\tedit.addEventListener('click', (e) => {\r\n\t\t\tconst input = content.querySelector('input');\r\n\t\t\tinput.removeAttribute('readonly');\r\n\t\t\tinput.focus();\r\n\t\t\tinput.addEventListener('blur', (e) => {\r\n\t\t\t\tinput.setAttribute('readonly', true);\r\n\t\t\t\ttodo.content = e.target.value;\r\n\t\t\t\tlocalStorage.setItem('todos', JSON.stringify(todos));\r\n\t\t\t\tDisplayTodos()\r\n\r\n\t\t\t})\r\n\t\t})\r\n\r\n\t\tdeleteButton.addEventListener('click', (e) => {\r\n\t\t\ttodos = todos.filter(t => t != todo);\r\n\t\t\tlocalStorage.setItem('todos', JSON.stringify(todos));\r\n\t\t\tDisplayTodos()\r\n\t\t})\r\n\r\n\t})\r\n}\n\n//# sourceURL=webpack://webpack-demo/./src/index.js?"); 18 | 19 | /***/ }) 20 | 21 | }, 22 | /******/ __webpack_require__ => { // webpackRuntimeModules 23 | /******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId)) 24 | /******/ var __webpack_exports__ = (__webpack_exec__("./src/index.js")); 25 | /******/ } 26 | ]); -------------------------------------------------------------------------------- /dist/runtime.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). 3 | * This devtool is neither made for production nor for readable output files. 4 | * It uses "eval()" calls to create a separate source file in the browser devtools. 5 | * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) 6 | * or disable the default devtool with "devtool: false". 7 | * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). 8 | */ 9 | /******/ (() => { // webpackBootstrap 10 | /******/ "use strict"; 11 | /******/ var __webpack_modules__ = ({}); 12 | /************************************************************************/ 13 | /******/ // The module cache 14 | /******/ var __webpack_module_cache__ = {}; 15 | /******/ 16 | /******/ // The require function 17 | /******/ function __webpack_require__(moduleId) { 18 | /******/ // Check if module is in cache 19 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 20 | /******/ if (cachedModule !== undefined) { 21 | /******/ return cachedModule.exports; 22 | /******/ } 23 | /******/ // Create a new module (and put it into the cache) 24 | /******/ var module = __webpack_module_cache__[moduleId] = { 25 | /******/ // no module.id needed 26 | /******/ // no module.loaded needed 27 | /******/ exports: {} 28 | /******/ }; 29 | /******/ 30 | /******/ // Execute the module function 31 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 32 | /******/ 33 | /******/ // Return the exports of the module 34 | /******/ return module.exports; 35 | /******/ } 36 | /******/ 37 | /******/ // expose the modules object (__webpack_modules__) 38 | /******/ __webpack_require__.m = __webpack_modules__; 39 | /******/ 40 | /************************************************************************/ 41 | /******/ /* webpack/runtime/chunk loaded */ 42 | /******/ (() => { 43 | /******/ var deferred = []; 44 | /******/ __webpack_require__.O = (result, chunkIds, fn, priority) => { 45 | /******/ if(chunkIds) { 46 | /******/ priority = priority || 0; 47 | /******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1]; 48 | /******/ deferred[i] = [chunkIds, fn, priority]; 49 | /******/ return; 50 | /******/ } 51 | /******/ var notFulfilled = Infinity; 52 | /******/ for (var i = 0; i < deferred.length; i++) { 53 | /******/ var [chunkIds, fn, priority] = deferred[i]; 54 | /******/ var fulfilled = true; 55 | /******/ for (var j = 0; j < chunkIds.length; j++) { 56 | /******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) { 57 | /******/ chunkIds.splice(j--, 1); 58 | /******/ } else { 59 | /******/ fulfilled = false; 60 | /******/ if(priority < notFulfilled) notFulfilled = priority; 61 | /******/ } 62 | /******/ } 63 | /******/ if(fulfilled) { 64 | /******/ deferred.splice(i--, 1) 65 | /******/ var r = fn(); 66 | /******/ if (r !== undefined) result = r; 67 | /******/ } 68 | /******/ } 69 | /******/ return result; 70 | /******/ }; 71 | /******/ })(); 72 | /******/ 73 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ 74 | /******/ (() => { 75 | /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 76 | /******/ })(); 77 | /******/ 78 | /******/ /* webpack/runtime/jsonp chunk loading */ 79 | /******/ (() => { 80 | /******/ // no baseURI 81 | /******/ 82 | /******/ // object to store loaded and loading chunks 83 | /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched 84 | /******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded 85 | /******/ var installedChunks = { 86 | /******/ "runtime": 0 87 | /******/ }; 88 | /******/ 89 | /******/ // no chunk on demand loading 90 | /******/ 91 | /******/ // no prefetching 92 | /******/ 93 | /******/ // no preloaded 94 | /******/ 95 | /******/ // no HMR 96 | /******/ 97 | /******/ // no HMR manifest 98 | /******/ 99 | /******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0); 100 | /******/ 101 | /******/ // install a JSONP callback for chunk loading 102 | /******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { 103 | /******/ var [chunkIds, moreModules, runtime] = data; 104 | /******/ // add "moreModules" to the modules object, 105 | /******/ // then flag all "chunkIds" as loaded and fire callback 106 | /******/ var moduleId, chunkId, i = 0; 107 | /******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { 108 | /******/ for(moduleId in moreModules) { 109 | /******/ if(__webpack_require__.o(moreModules, moduleId)) { 110 | /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; 111 | /******/ } 112 | /******/ } 113 | /******/ if(runtime) var result = runtime(__webpack_require__); 114 | /******/ } 115 | /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); 116 | /******/ for(;i < chunkIds.length; i++) { 117 | /******/ chunkId = chunkIds[i]; 118 | /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { 119 | /******/ installedChunks[chunkId][0](); 120 | /******/ } 121 | /******/ installedChunks[chunkId] = 0; 122 | /******/ } 123 | /******/ return __webpack_require__.O(result); 124 | /******/ } 125 | /******/ 126 | /******/ var chunkLoadingGlobal = self["webpackChunkwebpack_demo"] = self["webpackChunkwebpack_demo"] || []; 127 | /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); 128 | /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); 129 | /******/ })(); 130 | /******/ 131 | /************************************************************************/ 132 | /******/ 133 | /******/ 134 | /******/ })() 135 | ; --------------------------------------------------------------------------------