Autosave Form Inputs and Display Saved Entries

Autosaves and displays entries from a single input field. Entries can be recovered or deleted. Dropdown only shows when clicking on the input field

当前为 2024-08-13 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Autosave Form Inputs and Display Saved Entries
  3. // @namespace http://tampermonkey.net/
  4. // @version 2024-08-13
  5. // @description Autosaves and displays entries from a single input field. Entries can be recovered or deleted. Dropdown only shows when clicking on the input field
  6. // @author Lawrence d'Aniello
  7. // @match https://example.com/* // Customize to match your target website
  8. // @license MIT
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16.  
  17. let inputField;
  18. let searchButton;
  19. let savedInputEntries = JSON.parse(localStorage.getItem('savedInputEntries')) || [];
  20.  
  21.  
  22. function initScript() {
  23.  
  24. // Example selectors - change these to match the specific site
  25. const inputField = document.querySelector('input[type="text"]'); // Change CSS selector to match your input field
  26. const searchButton = document.querySelector('button'); // Change CSS selector to match your search button
  27.  
  28.  
  29. if (!inputField || !searchButton) {
  30. setTimeout(initScript, 1000);
  31. return;
  32. }
  33.  
  34.  
  35. inputField.setAttribute('autocomplete', 'off');
  36. setupEventListeners();
  37. }
  38.  
  39.  
  40. function setupEventListeners() {
  41. inputField.addEventListener('focus', displaySavedInputEntries);
  42. document.addEventListener('click', handleClick);
  43. inputField.addEventListener('input', hideSavedInputEntries);
  44. if (searchButton) {
  45. searchButton.addEventListener('click', forceInputSave);
  46. }
  47. window.addEventListener('beforeunload', forceInputSave);
  48.  
  49.  
  50. inputField.addEventListener('keydown', (event) => {
  51. if (event.key === 'Enter') {
  52. forceInputSave();
  53. }
  54. });
  55. }
  56.  
  57.  
  58. function forceInputSave() {
  59. const currentValue = inputField.value.trim();
  60. if (currentValue && !savedInputEntries.includes(currentValue)) {
  61. savedInputEntries.unshift(currentValue);
  62. if (savedInputEntries.length > 15) {
  63. savedInputEntries.pop();
  64. }
  65. localStorage.setItem('savedInputEntries', JSON.stringify(savedInputEntries));
  66. }
  67. hideSavedInputEntries(); // Ensure dropdown is hidden after saving
  68. }
  69.  
  70.  
  71. function displaySavedInputEntries() {
  72. hideSavedInputEntries();
  73.  
  74.  
  75. const dropdown = document.createElement('ul');
  76. dropdown.id = 'savedInputEntriesDropdown';
  77. dropdown.style.cssText = `
  78. list-style-type: none;
  79. padding: 5px;
  80. border: 1px solid #ccc;
  81. position: absolute;
  82. background-color: #fff;
  83. z-index: 1000;
  84. max-height: 150px;
  85. overflow-y: auto;
  86. `;
  87.  
  88.  
  89. const inputRect = inputField.getBoundingClientRect();
  90. dropdown.style.left = `${inputRect.left}px`;
  91. dropdown.style.top = `${inputRect.bottom + window.scrollY}px`;
  92. dropdown.style.width = `${inputRect.width}px`;
  93.  
  94.  
  95. savedInputEntries.forEach(entry => {
  96. const listItem = document.createElement('li');
  97. listItem.style.cssText = `
  98. display: flex;
  99. justify-content: space-between;
  100. padding: 5px;
  101. cursor: pointer;
  102. position: relative;
  103. transition: background-color 0.3s, color 0.3s;
  104. `;
  105. listItem.textContent = entry;
  106.  
  107.  
  108. const deleteButton = document.createElement('button');
  109. deleteButton.textContent = '✖';
  110. deleteButton.style.cssText = `
  111. display: none;
  112. background: none;
  113. border: none;
  114. color: red;
  115. cursor: pointer;
  116. position: absolute;
  117. right: 10px;
  118. top: 50%;
  119. transform: translateY(-50%);
  120. `;
  121.  
  122.  
  123. listItem.appendChild(deleteButton);
  124.  
  125.  
  126. listItem.addEventListener('mouseover', () => {
  127. listItem.style.backgroundColor = '#f0f0f0';
  128. listItem.style.color = '#333';
  129. deleteButton.style.display = 'inline';
  130. });
  131.  
  132.  
  133. listItem.addEventListener('mouseout', () => {
  134. listItem.style.backgroundColor = '#fff';
  135. listItem.style.color = '#000';
  136. deleteButton.style.display = 'none';
  137. });
  138.  
  139.  
  140. deleteButton.addEventListener('click', (event) => {
  141. event.stopPropagation();
  142. deleteEntry(entry);
  143. });
  144.  
  145.  
  146. listItem.addEventListener('click', () => {
  147. inputField.value = entry;
  148. hideSavedInputEntries();
  149. inputField.focus();
  150. });
  151.  
  152.  
  153. dropdown.appendChild(listItem);
  154. });
  155.  
  156.  
  157. document.body.appendChild(dropdown);
  158. }
  159.  
  160.  
  161. function hideSavedInputEntries() {
  162. const existingDropdown = document.getElementById('savedInputEntriesDropdown');
  163. if (existingDropdown) {
  164. existingDropdown.remove();
  165. }
  166. }
  167.  
  168.  
  169. function handleClick(event) {
  170. if (event.target !== inputField && !inputField.contains(event.target)) {
  171. hideSavedInputEntries();
  172. } else if (event.target === inputField) {
  173. displaySavedInputEntries();
  174. }
  175. }
  176.  
  177.  
  178. function deleteEntry(entryToDelete) {
  179. savedInputEntries = savedInputEntries.filter(entry => entry !== entryToDelete);
  180. localStorage.setItem('savedInputEntries', JSON.stringify(savedInputEntries));
  181. displaySavedInputEntries(); // Update dropdown to reflect deletion
  182. }
  183.  
  184.  
  185. // Start the script
  186. initScript();
  187. })();