To-Do List

A stylish dark-themed to-do list with keyboard toggle (Right Shift), due dates, cool animations, favorite tasks, and help instructions

  1. // ==UserScript==
  2. // @name To-Do List
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description A stylish dark-themed to-do list with keyboard toggle (Right Shift), due dates, cool animations, favorite tasks, and help instructions
  6. // @author GREGDGamer1
  7. // @match *://*/*
  8. // @grant none
  9. // @license You can modify as long as you credit me
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // Append Google Fonts link for Fredoka
  16. const fontLink = document.createElement('link');
  17. fontLink.href = 'https://fonts.googleapis.com/css2?family=Fredoka:wght@400&display=swap';
  18. fontLink.rel = 'stylesheet';
  19. document.head.appendChild(fontLink);
  20.  
  21. // Append Font Awesome for icons
  22. const fontAwesomeLink = document.createElement('link');
  23. fontAwesomeLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css';
  24. fontAwesomeLink.rel = 'stylesheet';
  25. document.head.appendChild(fontAwesomeLink);
  26.  
  27. // Styles for the modal (dark theme by default)
  28. const styles = `
  29. body {
  30. font-family: 'Fredoka', sans-serif;
  31. margin: 0;
  32. padding: 0;
  33. background-color: #181818;
  34. color: #ffffff;
  35. }
  36. #blur-background {
  37. position: fixed;
  38. top: 0;
  39. left: 0;
  40. right: 0;
  41. bottom: 0;
  42. background: rgba(0, 0, 0, 0.5);
  43. z-index: 1000;
  44. display: none;
  45. }
  46. #todo-modal {
  47. position: fixed;
  48. top: 50%;
  49. left: 50%;
  50. transform: translate(-50%, -100%);
  51. background-color: #2c2c2c;
  52. padding: 20px;
  53. box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
  54. border-radius: 10px;
  55. z-index: 1001;
  56. width: 300px;
  57. opacity: 0;
  58. transition: transform 0.4s ease, opacity 0.4s ease;
  59. display: none;
  60. }
  61. #todo-modal.show {
  62. display: block;
  63. transform: translate(-50%, -50%) scale(1);
  64. opacity: 1;
  65. }
  66. ul {
  67. list-style-type: none;
  68. padding: 0;
  69. }
  70. li {
  71. padding: 10px;
  72. border: 1px solid #444;
  73. margin: 5px 0;
  74. border-radius: 5px;
  75. opacity: 0;
  76. transform: translateX(-20px);
  77. transition: opacity 0.3s ease, transform 0.3s ease;
  78. cursor: pointer;
  79. }
  80. li.show {
  81. opacity: 1;
  82. transform: translateX(0);
  83. }
  84. li.fade-out {
  85. opacity: 0;
  86. transform: scale(0.9);
  87. transition: opacity 0.3s ease, transform 0.3s ease;
  88. }
  89. .favorite-icon {
  90. cursor: pointer;
  91. margin-right: 10px;
  92. }
  93. .help-icon {
  94. position: absolute;
  95. top: 10px;
  96. right: 10px;
  97. cursor: pointer;
  98. font-size: 18px;
  99. color: #ffffff;
  100. transition: transform 0.3s ease, color 0.3s ease; /* Add color transition */
  101. }
  102. .help-icon:hover {
  103. transform: scale(1.5); /* Scale up on hover */
  104. color: #ffdd57; /* Change color on hover */
  105. }
  106. .help-modal {
  107. position: fixed;
  108. top: 50%;
  109. left: 50%;
  110. transform: translate(-50%, -50%);
  111. background-color: #333;
  112. color: white;
  113. padding: 20px;
  114. border-radius: 10px;
  115. box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
  116. z-index: 1002;
  117. display: none;
  118. width: 300px;
  119. opacity: 0;
  120. transition: opacity 0.4s ease;
  121. }
  122. .help-modal.show {
  123. display: block;
  124. opacity: 1;
  125. }
  126. input, input[type="date"] {
  127. width: calc(100% - 22px);
  128. padding: 10px;
  129. margin-bottom: 10px;
  130. border: 1px solid #444;
  131. border-radius: 5px;
  132. background-color: #444;
  133. color: #ffffff;
  134. font-family: 'Fredoka', sans-serif;
  135. }
  136. button {
  137. width: 100%;
  138. padding: 10px;
  139. border: none;
  140. border-radius: 5px;
  141. cursor: pointer;
  142. transition: background 0.3s, transform 0.2s;
  143. font-family: 'Fredoka', sans-serif;
  144. }
  145. button:hover {
  146. transform: translateY(-2px);
  147. }
  148. button.add-task {
  149. background-color: #28a745;
  150. color: white;
  151. }
  152. button.add-task:hover {
  153. background-color: #218838;
  154. }
  155. button.clear-tasks {
  156. background-color: #dc3545;
  157. color: white;
  158. margin-top: 10px;
  159. }
  160. button.clear-tasks:hover {
  161. background-color: #c82333;
  162. }
  163. button.export-tasks, button.import-tasks {
  164. background-color: #007bff;
  165. color: white;
  166. margin-top: 10px;
  167. }
  168. button.export-tasks:hover, button.import-tasks:hover {
  169. background-color: #0056b3;
  170. }
  171. select {
  172. width: calc(100% - 22px);
  173. padding: 10px;
  174. margin-bottom: 10px;
  175. border: 1px solid #444;
  176. border-radius: 5px;
  177. background-color: #444;
  178. color: #ffffff;
  179. font-family: 'Fredoka', sans-serif;
  180. }
  181. `;
  182.  
  183. // Append styles to the head
  184. const styleSheet = document.createElement("style");
  185. styleSheet.type = "text/css";
  186. styleSheet.innerText = styles;
  187. document.head.appendChild(styleSheet);
  188.  
  189. // Create blur background
  190. const blurBackground = document.createElement('div');
  191. blurBackground.id = 'blur-background';
  192. document.body.appendChild(blurBackground);
  193.  
  194. // Create modal
  195. const todoModal = document.createElement('div');
  196. todoModal.id = 'todo-modal';
  197. document.body.appendChild(todoModal);
  198.  
  199. // Help modal
  200. const helpModal = document.createElement('div');
  201. helpModal.className = 'help-modal';
  202. document.body.appendChild(helpModal);
  203. const helpTitle = document.createElement('h3');
  204. helpTitle.textContent = 'Help Instructions';
  205. helpModal.appendChild(helpTitle);
  206. const helpText = document.createElement('p');
  207. helpText.innerHTML = `
  208. <strong>Instructions:</strong><br>
  209. 1. Use the input field to add a new task.<br>
  210. 2. Set a due date (optional) using the date picker.<br>
  211. 3. Choose a category for your task.<br>
  212. 4. Click the star icon to mark tasks as favorites.<br>
  213. 5. Double-click the star in the task to edit it.(then dont click the input or else youll remove it, its automaticly focused)<br>
  214. 6. Click on a task to remove it from the list.<br>
  215. 7. Use the export/import buttons to backup tasks.<br>
  216. 8. Press the right Shift key to toggle this to-do list.<br>
  217. 9. some websites break the menu or the menu will break them
  218. `;
  219. helpModal.appendChild(helpText);
  220. const helpCloseButton = document.createElement('button');
  221. helpCloseButton.textContent = 'Close';
  222. helpModal.appendChild(helpCloseButton);
  223. helpCloseButton.onclick = () => {
  224. helpModal.classList.remove('show');
  225. helpModal.style.display = 'none';
  226. helpIcon.classList.remove('animate'); // Remove animation class when closed
  227. };
  228.  
  229. const title = document.createElement('h2');
  230. title.textContent = 'To-Do List';
  231. todoModal.appendChild(title);
  232.  
  233. // Help icon
  234. const helpIcon = document.createElement('span');
  235. helpIcon.className = 'help-icon';
  236. helpIcon.innerHTML = '?';
  237. helpIcon.onclick = () => {
  238. helpModal.classList.add('show');
  239. helpModal.style.display = 'block';
  240. helpModal.style.opacity = 1;
  241. helpIcon.classList.add('animate'); // Add animation class when opened
  242. };
  243. todoModal.appendChild(helpIcon);
  244.  
  245. const todoList = document.createElement('ul');
  246. todoModal.appendChild(todoList);
  247.  
  248. const input = document.createElement('input');
  249. input.type = 'text';
  250. input.placeholder = 'Add a new task';
  251. todoModal.appendChild(input);
  252.  
  253. const dueDateInput = document.createElement('input');
  254. dueDateInput.type = 'date';
  255. todoModal.appendChild(dueDateInput);
  256.  
  257. const categorySelect = document.createElement('select');
  258. const categories = ['Work', 'Personal', 'School', 'Other'];
  259. categories.forEach(category => {
  260. const option = document.createElement('option');
  261. option.value = category;
  262. option.textContent = category;
  263. categorySelect.appendChild(option);
  264. });
  265. todoModal.appendChild(categorySelect);
  266.  
  267. const addButton = document.createElement('button');
  268. addButton.className = 'add-task';
  269. addButton.textContent = 'Add Task';
  270. todoModal.appendChild(addButton);
  271.  
  272. const clearButton = document.createElement('button');
  273. clearButton.className = 'clear-tasks';
  274. clearButton.textContent = 'Clear All Tasks';
  275. todoModal.appendChild(clearButton);
  276.  
  277. const exportButton = document.createElement('button');
  278. exportButton.className = 'export-tasks';
  279. exportButton.textContent = 'Export Tasks';
  280. todoModal.appendChild(exportButton);
  281.  
  282. const importButton = document.createElement('button');
  283. importButton.className = 'import-tasks';
  284. importButton.textContent = 'Import Tasks';
  285. todoModal.appendChild(importButton);
  286.  
  287. // Load tasks from localStorage
  288. function loadTasks() {
  289. const tasks = JSON.parse(localStorage.getItem('todoTasks')) || [];
  290. tasks.forEach(task => addTaskToList(task.text, task.dueDate, task.category));
  291. }
  292.  
  293. // Save tasks to localStorage
  294. function saveTasks() {
  295. const tasks = Array.from(todoList.children).map(li => {
  296. const text = li.querySelector('.task-text').textContent;
  297. const dueDate = li.querySelector('.task-date') ? li.querySelector('.task-date').textContent : '';
  298. const category = li.querySelector('.task-category') ? li.querySelector('.task-category').textContent : '';
  299. return { text, dueDate, category: category.replace(' (Category: ', '').replace(')', '') };
  300. });
  301. localStorage.setItem('todoTasks', JSON.stringify(tasks));
  302. }
  303.  
  304. // Add a task to the list
  305. function addTaskToList(task, dueDate, category) {
  306. const listItem = document.createElement('li');
  307.  
  308. const favoriteIcon = document.createElement('i');
  309. favoriteIcon.className = 'favorite-icon fas fa-star'; // Font Awesome star icon
  310. favoriteIcon.onclick = (event) => {
  311. event.stopPropagation(); // Prevent task click event
  312. favoriteIcon.classList.toggle('fas');
  313. favoriteIcon.classList.toggle('far'); // Toggle filled and outlined star
  314. saveTasks();
  315. };
  316.  
  317. const taskText = document.createElement('span');
  318. taskText.className = 'task-text';
  319. taskText.textContent = task;
  320.  
  321. const taskDate = document.createElement('span');
  322. taskDate.className = 'task-date';
  323. taskDate.textContent = dueDate ? ` (Due: ${new Date(dueDate).toLocaleDateString()})` : '';
  324.  
  325. const taskCategory = document.createElement('span');
  326. taskCategory.className = 'task-category';
  327. taskCategory.textContent = category ? ` (Category: ${category})` : '';
  328.  
  329. // Add click event to remove the task
  330. listItem.onclick = () => {
  331. listItem.classList.add('fade-out');
  332. setTimeout(() => {
  333. todoList.removeChild(listItem);
  334. saveTasks();
  335. }, 300);
  336. };
  337.  
  338. // Add double-click event for editing tasks
  339. listItem.ondblclick = () => {
  340. const currentText = taskText.textContent;
  341. const editInput = document.createElement('input');
  342. editInput.type = 'text';
  343. editInput.value = currentText;
  344. listItem.replaceChild(editInput, taskText);
  345.  
  346. editInput.onblur = () => {
  347. const newText = editInput.value.trim();
  348. if (newText) {
  349. taskText.textContent = newText;
  350. listItem.replaceChild(taskText, editInput);
  351. saveTasks();
  352. } else {
  353. listItem.replaceChild(taskText, editInput);
  354. }
  355. };
  356.  
  357. editInput.focus();
  358. };
  359.  
  360. listItem.appendChild(favoriteIcon); // Append favorite icon
  361. listItem.appendChild(taskText);
  362. listItem.appendChild(taskDate);
  363. listItem.appendChild(taskCategory);
  364. todoList.appendChild(listItem);
  365.  
  366. // Trigger animation
  367. setTimeout(() => listItem.classList.add('show'), 10);
  368.  
  369. // Save tasks to localStorage
  370. saveTasks();
  371. }
  372.  
  373. // Event listeners
  374. addButton.onclick = () => {
  375. const taskValue = input.value.trim();
  376. const dueDateValue = dueDateInput.value;
  377. const categoryValue = categorySelect.value;
  378. if (taskValue) {
  379. addTaskToList(taskValue, dueDateValue, categoryValue);
  380. input.value = '';
  381. dueDateInput.value = '';
  382. }
  383. };
  384.  
  385. clearButton.onclick = () => {
  386. while (todoList.firstChild) {
  387. todoList.removeChild(todoList.firstChild);
  388. }
  389. saveTasks();
  390. };
  391.  
  392. // Export tasks function
  393. exportButton.onclick = () => {
  394. const tasks = JSON.parse(localStorage.getItem('todoTasks')) || [];
  395. const blob = new Blob([JSON.stringify(tasks, null, 2)], { type: 'application/json' });
  396. const url = URL.createObjectURL(blob);
  397.  
  398. const a = document.createElement('a');
  399. a.href = url;
  400. a.download = 'tasks.json';
  401. document.body.appendChild(a);
  402. a.click();
  403. document.body.removeChild(a);
  404. URL.revokeObjectURL(url);
  405. };
  406.  
  407. // Import tasks function
  408. importButton.onclick = () => {
  409. const inputFile = document.createElement('input');
  410. inputFile.type = 'file';
  411. inputFile.accept = '.json';
  412. inputFile.onchange = (event) => {
  413. const file = event.target.files[0];
  414. if (file) {
  415. const reader = new FileReader();
  416. reader.onload = (e) => {
  417. try {
  418. const tasks = JSON.parse(e.target.result);
  419. clearTasks(); // Clear current tasks
  420. tasks.forEach(task => {
  421. addTaskToList(task.text, task.dueDate, task.category);
  422. });
  423. } catch (error) {
  424. alert('Error importing tasks. Please ensure the file is valid.');
  425. }
  426. };
  427. reader.readAsText(file);
  428. }
  429. };
  430. inputFile.click();
  431. };
  432.  
  433. // Function to clear tasks (for import)
  434. function clearTasks() {
  435. while (todoList.firstChild) {
  436. todoList.removeChild(todoList.firstChild);
  437. }
  438. saveTasks();
  439. }
  440.  
  441. // Keyboard toggle for the modal with animation
  442. document.addEventListener('keydown', (event) => {
  443. if (event.key === 'Shift' && event.code === 'ShiftRight') {
  444. const isVisible = todoModal.classList.toggle('show');
  445. blurBackground.style.display = isVisible ? 'block' : 'none';
  446.  
  447. // Apply fade animation
  448. if (isVisible) {
  449. todoModal.style.display = 'block';
  450. setTimeout(() => {
  451. todoModal.style.opacity = 1;
  452. todoModal.style.transform = 'translate(-50%, -50%) scale(1)';
  453. }, 10);
  454. } else {
  455. todoModal.style.opacity = 0;
  456. todoModal.style.transform = 'translate(-50%, -50%) scale(0)';
  457. setTimeout(() => {
  458. todoModal.style.display = 'none';
  459. }, 400);
  460. }
  461. }
  462. });
  463.  
  464. // Load existing tasks on startup
  465. loadTasks();
  466.  
  467. })();
  468. // ==UserScript==
  469. // @name Advanced School Helper To-Do List backup
  470. // @namespace http://tampermonkey.net/
  471. // @version 2.9
  472. // @description A stylish dark-themed to-do list with keyboard toggle (Right Shift), due dates, cool animations, right-click editing, favorite tasks, and help instructions
  473. // @author GREGDGamer1
  474. // @match *://*/*
  475. // @grant none
  476. // ==/UserScript==
  477.  
  478. (function() {
  479. 'use strict';
  480.  
  481. // Append Google Fonts link for Fredoka
  482. const fontLink = document.createElement('link');
  483. fontLink.href = 'https://fonts.googleapis.com/css2?family=Fredoka:wght@400&display=swap';
  484. fontLink.rel = 'stylesheet';
  485. document.head.appendChild(fontLink);
  486.  
  487. // Append Font Awesome for icons
  488. const fontAwesomeLink = document.createElement('link');
  489. fontAwesomeLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css';
  490. fontAwesomeLink.rel = 'stylesheet';
  491. document.head.appendChild(fontAwesomeLink);
  492.  
  493. // Styles for the modal (dark theme by default)
  494. const styles = `
  495. body {
  496. font-family: 'Fredoka', sans-serif;
  497. margin: 0;
  498. padding: 0;
  499. background-color: #181818;
  500. color: #ffffff;
  501. }
  502. #blur-background {
  503. position: fixed;
  504. top: 0;
  505. left: 0;
  506. right: 0;
  507. bottom: 0;
  508. background: rgba(0, 0, 0, 0.5);
  509. z-index: 1000;
  510. display: none;
  511. }
  512. #todo-modal {
  513. position: fixed;
  514. top: 50%;
  515. left: 50%;
  516. transform: translate(-50%, -100%);
  517. background-color: #2c2c2c;
  518. padding: 20px;
  519. box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
  520. border-radius: 10px;
  521. z-index: 1001;
  522. width: 300px;
  523. opacity: 0;
  524. transition: transform 0.4s ease, opacity 0.4s ease;
  525. display: none;
  526. }
  527. #todo-modal.show {
  528. display: block;
  529. transform: translate(-50%, -50%) scale(1);
  530. opacity: 1;
  531. }
  532. ul {
  533. list-style-type: none;
  534. padding: 0;
  535. }
  536. li {
  537. padding: 10px;
  538. border: 1px solid #444;
  539. margin: 5px 0;
  540. border-radius: 5px;
  541. opacity: 0;
  542. transform: translateX(-20px);
  543. transition: opacity 0.3s ease, transform 0.3s ease;
  544. cursor: pointer;
  545. }
  546. li.show {
  547. opacity: 1;
  548. transform: translateX(0);
  549. }
  550. li.fade-out {
  551. opacity: 0;
  552. transform: scale(0.9);
  553. transition: opacity 0.3s ease, transform 0.3s ease;
  554. }
  555. .favorite-icon {
  556. cursor: pointer;
  557. margin-right: 10px;
  558. }
  559. .help-icon {
  560. position: absolute;
  561. top: 10px;
  562. right: 10px;
  563. cursor: pointer;
  564. font-size: 18px;
  565. color: #ffffff;
  566. transition: transform 0.3s ease, color 0.3s ease; /* Add color transition */
  567. }
  568. .help-icon:hover {
  569. transform: scale(1.5); /* Scale up on hover */
  570. color: #ffdd57; /* Change color on hover */
  571. }
  572. .help-modal {
  573. position: fixed;
  574. top: 50%;
  575. left: 50%;
  576. transform: translate(-50%, -50%);
  577. background-color: #333;
  578. color: white;
  579. padding: 20px;
  580. border-radius: 10px;
  581. box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
  582. z-index: 1002;
  583. display: none;
  584. width: 300px;
  585. opacity: 0;
  586. transition: opacity 0.4s ease;
  587. }
  588. .help-modal.show {
  589. display: block;
  590. opacity: 1;
  591. }
  592. input, input[type="date"] {
  593. width: calc(100% - 22px);
  594. padding: 10px;
  595. margin-bottom: 10px;
  596. border: 1px solid #444;
  597. border-radius: 5px;
  598. background-color: #444;
  599. color: #ffffff;
  600. font-family: 'Fredoka', sans-serif;
  601. }
  602. button {
  603. width: 100%;
  604. padding: 10px;
  605. border: none;
  606. border-radius: 5px;
  607. cursor: pointer;
  608. transition: background 0.3s, transform 0.2s;
  609. font-family: 'Fredoka', sans-serif;
  610. }
  611. button:hover {
  612. transform: translateY(-2px);
  613. }
  614. button.add-task {
  615. background-color: #28a745;
  616. color: white;
  617. }
  618. button.add-task:hover {
  619. background-color: #218838;
  620. }
  621. button.clear-tasks {
  622. background-color: #dc3545;
  623. color: white;
  624. margin-top: 10px;
  625. }
  626. button.clear-tasks:hover {
  627. background-color: #c82333;
  628. }
  629. button.export-tasks, button.import-tasks {
  630. background-color: #007bff;
  631. color: white;
  632. margin-top: 10px;
  633. }
  634. button.export-tasks:hover, button.import-tasks:hover {
  635. background-color: #0056b3;
  636. }
  637. select {
  638. width: calc(100% - 22px);
  639. padding: 10px;
  640. margin-bottom: 10px;
  641. border: 1px solid #444;
  642. border-radius: 5px;
  643. background-color: #444;
  644. color: #ffffff;
  645. font-family: 'Fredoka', sans-serif;
  646. }
  647. `;
  648.  
  649. // Append styles to the head
  650. const styleSheet = document.createElement("style");
  651. styleSheet.type = "text/css";
  652. styleSheet.innerText = styles;
  653. document.head.appendChild(styleSheet);
  654.  
  655. // Create blur background
  656. const blurBackground = document.createElement('div');
  657. blurBackground.id = 'blur-background';
  658. document.body.appendChild(blurBackground);
  659.  
  660. // Create modal
  661. const todoModal = document.createElement('div');
  662. todoModal.id = 'todo-modal';
  663. document.body.appendChild(todoModal);
  664.  
  665. // Help modal
  666. const helpModal = document.createElement('div');
  667. helpModal.className = 'help-modal';
  668. document.body.appendChild(helpModal);
  669. const helpTitle = document.createElement('h3');
  670. helpTitle.textContent = 'Help Instructions';
  671. helpModal.appendChild(helpTitle);
  672. const helpText = document.createElement('p');
  673. helpText.innerHTML = `
  674. <strong>Instructions:</strong><br>
  675. 1. Use the input field to add a new task.<br>
  676. 2. Set a due date (optional) using the date picker.<br>
  677. 3. Choose a category for your task.<br>
  678. 4. Click the star icon to mark tasks as favorites.<br>
  679. 5. Double-click the star in the task to edit it.(then dont click the input or else youll remove it, its automaticly focused)<br>
  680. 6. Click on a task to remove it from the list.<br>
  681. 7. Use the export/import buttons to backup tasks.<br>
  682. 8. Press the right Shift key to toggle this to-do list.<br>
  683. 9. some websites break the menu or the menu will break them
  684. `;
  685. helpModal.appendChild(helpText);
  686. const helpCloseButton = document.createElement('button');
  687. helpCloseButton.textContent = 'Close';
  688. helpModal.appendChild(helpCloseButton);
  689. helpCloseButton.onclick = () => {
  690. helpModal.classList.remove('show');
  691. helpModal.style.display = 'none';
  692. helpIcon.classList.remove('animate'); // Remove animation class when closed
  693. };
  694.  
  695. const title = document.createElement('h2');
  696. title.textContent = 'To-Do List';
  697. todoModal.appendChild(title);
  698.  
  699. // Help icon
  700. const helpIcon = document.createElement('span');
  701. helpIcon.className = 'help-icon';
  702. helpIcon.innerHTML = '?';
  703. helpIcon.onclick = () => {
  704. helpModal.classList.add('show');
  705. helpModal.style.display = 'block';
  706. helpModal.style.opacity = 1;
  707. helpIcon.classList.add('animate'); // Add animation class when opened
  708. };
  709. todoModal.appendChild(helpIcon);
  710.  
  711. const todoList = document.createElement('ul');
  712. todoModal.appendChild(todoList);
  713.  
  714. const input = document.createElement('input');
  715. input.type = 'text';
  716. input.placeholder = 'Add a new task';
  717. todoModal.appendChild(input);
  718.  
  719. const dueDateInput = document.createElement('input');
  720. dueDateInput.type = 'date';
  721. todoModal.appendChild(dueDateInput);
  722.  
  723. const categorySelect = document.createElement('select');
  724. const categories = ['Work', 'Personal', 'School', 'Other'];
  725. categories.forEach(category => {
  726. const option = document.createElement('option');
  727. option.value = category;
  728. option.textContent = category;
  729. categorySelect.appendChild(option);
  730. });
  731. todoModal.appendChild(categorySelect);
  732.  
  733. const addButton = document.createElement('button');
  734. addButton.className = 'add-task';
  735. addButton.textContent = 'Add Task';
  736. todoModal.appendChild(addButton);
  737.  
  738. const clearButton = document.createElement('button');
  739. clearButton.className = 'clear-tasks';
  740. clearButton.textContent = 'Clear All Tasks';
  741. todoModal.appendChild(clearButton);
  742.  
  743. const exportButton = document.createElement('button');
  744. exportButton.className = 'export-tasks';
  745. exportButton.textContent = 'Export Tasks';
  746. todoModal.appendChild(exportButton);
  747.  
  748. const importButton = document.createElement('button');
  749. importButton.className = 'import-tasks';
  750. importButton.textContent = 'Import Tasks';
  751. todoModal.appendChild(importButton);
  752.  
  753. // Load tasks from localStorage
  754. function loadTasks() {
  755. const tasks = JSON.parse(localStorage.getItem('todoTasks')) || [];
  756. tasks.forEach(task => addTaskToList(task.text, task.dueDate, task.category));
  757. }
  758.  
  759. // Save tasks to localStorage
  760. function saveTasks() {
  761. const tasks = Array.from(todoList.children).map(li => {
  762. const text = li.querySelector('.task-text').textContent;
  763. const dueDate = li.querySelector('.task-date') ? li.querySelector('.task-date').textContent : '';
  764. const category = li.querySelector('.task-category') ? li.querySelector('.task-category').textContent : '';
  765. return { text, dueDate, category: category.replace(' (Category: ', '').replace(')', '') };
  766. });
  767. localStorage.setItem('todoTasks', JSON.stringify(tasks));
  768. }
  769.  
  770. // Add a task to the list
  771. function addTaskToList(task, dueDate, category) {
  772. const listItem = document.createElement('li');
  773.  
  774. const favoriteIcon = document.createElement('i');
  775. favoriteIcon.className = 'favorite-icon fas fa-star'; // Font Awesome star icon
  776. favoriteIcon.onclick = (event) => {
  777. event.stopPropagation(); // Prevent task click event
  778. favoriteIcon.classList.toggle('fas');
  779. favoriteIcon.classList.toggle('far'); // Toggle filled and outlined star
  780. saveTasks();
  781. };
  782.  
  783. const taskText = document.createElement('span');
  784. taskText.className = 'task-text';
  785. taskText.textContent = task;
  786.  
  787. const taskDate = document.createElement('span');
  788. taskDate.className = 'task-date';
  789. taskDate.textContent = dueDate ? ` (Due: ${new Date(dueDate).toLocaleDateString()})` : '';
  790.  
  791. const taskCategory = document.createElement('span');
  792. taskCategory.className = 'task-category';
  793. taskCategory.textContent = category ? ` (Category: ${category})` : '';
  794.  
  795. // Add click event to remove the task
  796. listItem.onclick = () => {
  797. listItem.classList.add('fade-out');
  798. setTimeout(() => {
  799. todoList.removeChild(listItem);
  800. saveTasks();
  801. }, 300);
  802. };
  803.  
  804. // Add double-click event for editing tasks
  805. listItem.ondblclick = () => {
  806. const currentText = taskText.textContent;
  807. const editInput = document.createElement('input');
  808. editInput.type = 'text';
  809. editInput.value = currentText;
  810. listItem.replaceChild(editInput, taskText);
  811.  
  812. editInput.onblur = () => {
  813. const newText = editInput.value.trim();
  814. if (newText) {
  815. taskText.textContent = newText;
  816. listItem.replaceChild(taskText, editInput);
  817. saveTasks();
  818. } else {
  819. listItem.replaceChild(taskText, editInput);
  820. }
  821. };
  822.  
  823. editInput.focus();
  824. };
  825.  
  826. listItem.appendChild(favoriteIcon); // Append favorite icon
  827. listItem.appendChild(taskText);
  828. listItem.appendChild(taskDate);
  829. listItem.appendChild(taskCategory);
  830. todoList.appendChild(listItem);
  831.  
  832. // Trigger animation
  833. setTimeout(() => listItem.classList.add('show'), 10);
  834.  
  835. // Save tasks to localStorage
  836. saveTasks();
  837. }
  838.  
  839. // Event listeners
  840. addButton.onclick = () => {
  841. const taskValue = input.value.trim();
  842. const dueDateValue = dueDateInput.value;
  843. const categoryValue = categorySelect.value;
  844. if (taskValue) {
  845. addTaskToList(taskValue, dueDateValue, categoryValue);
  846. input.value = '';
  847. dueDateInput.value = '';
  848. }
  849. };
  850.  
  851. clearButton.onclick = () => {
  852. while (todoList.firstChild) {
  853. todoList.removeChild(todoList.firstChild);
  854. }
  855. saveTasks();
  856. };
  857.  
  858. // Export tasks function
  859. exportButton.onclick = () => {
  860. const tasks = JSON.parse(localStorage.getItem('todoTasks')) || [];
  861. const blob = new Blob([JSON.stringify(tasks, null, 2)], { type: 'application/json' });
  862. const url = URL.createObjectURL(blob);
  863.  
  864. const a = document.createElement('a');
  865. a.href = url;
  866. a.download = 'tasks.json';
  867. document.body.appendChild(a);
  868. a.click();
  869. document.body.removeChild(a);
  870. URL.revokeObjectURL(url);
  871. };
  872.  
  873. // Import tasks function
  874. importButton.onclick = () => {
  875. const inputFile = document.createElement('input');
  876. inputFile.type = 'file';
  877. inputFile.accept = '.json';
  878. inputFile.onchange = (event) => {
  879. const file = event.target.files[0];
  880. if (file) {
  881. const reader = new FileReader();
  882. reader.onload = (e) => {
  883. try {
  884. const tasks = JSON.parse(e.target.result);
  885. clearTasks(); // Clear current tasks
  886. tasks.forEach(task => {
  887. addTaskToList(task.text, task.dueDate, task.category);
  888. });
  889. } catch (error) {
  890. alert('Error importing tasks. Please ensure the file is valid.');
  891. }
  892. };
  893. reader.readAsText(file);
  894. }
  895. };
  896. inputFile.click();
  897. };
  898.  
  899. // Function to clear tasks (for import)
  900. function clearTasks() {
  901. while (todoList.firstChild) {
  902. todoList.removeChild(todoList.firstChild);
  903. }
  904. saveTasks();
  905. }
  906.  
  907. // Keyboard toggle for the modal with animation
  908. document.addEventListener('keydown', (event) => {
  909. if (event.key === 'Shift' && event.code === 'ShiftRight') {
  910. const isVisible = todoModal.classList.toggle('show');
  911. blurBackground.style.display = isVisible ? 'block' : 'none';
  912.  
  913. // Apply fade animation
  914. if (isVisible) {
  915. todoModal.style.display = 'block';
  916. setTimeout(() => {
  917. todoModal.style.opacity = 1;
  918. todoModal.style.transform = 'translate(-50%, -50%) scale(1)';
  919. }, 10);
  920. } else {
  921. todoModal.style.opacity = 0;
  922. todoModal.style.transform = 'translate(-50%, -50%) scale(0)';
  923. setTimeout(() => {
  924. todoModal.style.display = 'none';
  925. }, 400);
  926. }
  927. }
  928. });
  929.  
  930. // Load existing tasks on startup
  931. loadTasks();
  932.  
  933. })();