{"_id":"@avatijs/listener","_rev":"1-ee59e0e65ca5263859ba7ec4d5162181","name":"@avatijs/listener","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@avatijs/listener","version":"0.1.0","author":{"url":"https://khaled.ee/","name":"Khaled Sameer","email":"khaled.smq@hotmail.com"},"license":"MIT","_id":"@avatijs/listener@0.1.0","maintainers":[{"name":"khaledsqm","email":"khaled.smq@hotmail.com"}],"homepage":"https://avati.io/","bugs":{"url":"https://github.com/KhaledSMQ/avati/issues","email":"khaled.smq@hotmail.com"},"dist":{"shasum":"72f5d24d36813a430d6ef2e665e963a66643e59e","tarball":"https://registry.npmjs.org/@avatijs/listener/-/listener-0.1.0.tgz","fileCount":2,"integrity":"sha512-APBf3BdHBSLjy74vJTyfJoJw5p4s/b7Bau57D/IJJVLhALZWJMmkokpJ3wMDy7sYRQxBA8p7LgHPQbTB9ZIQ9A==","signatures":[{"sig":"MEUCIQCX1UaFjZRsH3E9aLte1C/s7sZxEno8KAHoD/jilcfN8gIgZez5FesPueW8MW21uKtGw3WEkueHqVI0xkHVE0CXxmA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14933},"main":"dist/index.cjs.js","types":"dist/index.d.ts","module":"dist/index.esm.js","browser":"dist/index.umd.js","gitHead":"9f15041f42232ccefd6b2357b81056ccfc85228a","scripts":{"dev":"webpack --mode development --watch --config-name umd --config-name esm --config-name cjs","lint":"eslint src --ext .ts,.tsx","test":"jest","build":"webpack --mode production --config-name umd --config-name esm --config-name cjs"},"_npmUser":{"name":"khaledsqm","email":"khaled.smq@hotmail.com"},"repository":{"url":"git+https://github.com/KhaledSMQ/avati.git","type":"git","directory":"packages/listener"},"_npmVersion":"10.9.0","description":"Event listen manager package part of Avati project","directories":{},"_nodeVersion":"20.14.0","browserslist":["last 1 version and not Explorer 10","Explorer 11","iOS >= 9","Android >= 4.4"],"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@avatijs/debounce":"^0.1.0","@avatijs/throttle":"^0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/listener_0.1.0_1732139680316_0.4403882513661259","host":"s3://npm-registry-packages"}},"0.1.1":{"name":"@avatijs/listener","version":"0.1.1","description":"Listener package part of Avati project","main":"./dist/cjs/index.js","module":"./dist/esm/index.js","types":"./dist/types/index.d.ts","browser":"./dist/umd/index.js","unpkg":"./dist/umd/index.min.js","jsdelivr":"./dist/umd/index.min.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js","default":"./dist/umd/index.js"},"./package.json":"./package.json"},"sideEffects":false,"engines":{"node":">=18.20.5"},"bundlesize":[{"path":"./dist/esm/index.js","maxSize":"3 kB","compression":"brotli"},{"path":"./dist/cjs/index.js","maxSize":"3 kB","compression":"brotli"},{"path":"./dist/umd/*.js","maxSize":"3 kB","compression":"brotli"}],"scripts":{"build":"npm run clean && npm run build:types && npm run build:prod","build:dev":"webpack --mode development --progress","build:prod":"webpack --mode production","build:types":"tsc --emitDeclarationOnly","build:deps":"npm run build -w @avatijs/debounce && npm run build -w @avatijs/throttle && npm run build -w @avatijs/memoize","watch":"webpack --mode=development --watch","watch:silent":"webpack --mode=development --watch --silent","clean":"rimraf dist","prepublishOnly":"npm run build","test":"jest --config jest.config.js","typecheck":"tsc --noEmit","size":"webpack --mode production --json > stats.json && webpack-bundle-analyzer stats.json","analyze:deps":"madge --circular --extensions ts ./src/index.ts","size:check":"bundlesize","size:watch":"bundlesize --watch","size:compression":"bundlesize --compression","check-deps":"depcheck --config .depcheckrc","analyze":"npm run analyze:size && npm run analyze:deps && npm run analyze:duplicates","analyze:size":"webpack --mode production --json > stats.json && webpack-bundle-analyzer stats.json","analyze:detailed":"webpack --config webpack.analysis.config.js","analyze:duplicates":"jscpd src","analyze:why":"webpack --mode production --display-reasons","analyze:tree":"webpack --mode production --display-used-exports","analyze:modules":"webpack --mode production --display-modules","analyze:full":"webpack --mode production --stats detailed"},"author":{"name":"Khaled Sameer","email":"khaled.smq@hotmail.com","url":"https://khaled.ee/"},"homepage":"https://avati.io/","bugs":{"url":"https://github.com/KhaledSMQ/avati/issues","email":"khaled.smq@hotmail.com"},"repository":{"type":"git","url":"git+https://github.com/KhaledSMQ/avati.git","directory":"packages/listener"},"license":"MIT","publishConfig":{"access":"public"},"keywords":["avati","scheduler","batch","task-queue","priority-queue","async","typescript","debounce","debouncer","throttle","throttling","delay","function control","rate limit","rate limiting","utility","helper","JavaScript","timing","event handling","event control","performance","optimization","function delay","input control","API calls"],"devDependencies":{"@types/jest":"^29.5.14","@types/node":"^22.9.1","@typescript-eslint/eslint-plugin":"^8.15.0","@typescript-eslint/parser":"^8.15.0","bundlesize":"^0.18.2","depcheck":"^1.4.7","dependency-cruiser":"^16.6.0","eslint":"^8.57.1","jest":"^29.7.0","jscpd":"^4.0.5","madge":"^8.0.0","rimraf":"^6.0.1","source-map-explorer":"^2.5.3","terser-webpack-plugin":"^5.3.10","ts-jest":"^29.2.5","ts-loader":"^9.5.1","typescript":"^5.6.3","webpack":"^5.96.1","webpack-bundle-analyzer":"^4.10.2","webpack-cli":"^5.1.4"},"dependencies":{"@avatijs/debounce":"^0.1.2","@avatijs/memoize":"^0.1.2","@avatijs/throttle":"^0.1.2"},"_id":"@avatijs/listener@0.1.1","gitHead":"45902cf3fc3c657b7e7d4055600c78870d4dbabb","_nodeVersion":"20.14.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-e/0XbufwtzVpi7ahV3Lh3sEwPFmvdNZVYMLx+nEvGTS4zXqIUbvjilaTANtB4pzFFX0aIs5OVdqnsGxAogKCWg==","shasum":"3bc07f4a1daf243b96ce27abb4a42665cf821372","tarball":"https://registry.npmjs.org/@avatijs/listener/-/listener-0.1.1.tgz","fileCount":19,"unpackedSize":273893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDmdBViwT54ea0byN4CZJVxzSE/t0KU7zOYRMVvfW4HHAiEAr1HqyKjtNrfFyj7T3A8W3PSelvs8A8gkIyclxHHFSXs="}]},"_npmUser":{"name":"khaledsqm","email":"khaled.smq@hotmail.com"},"directories":{},"maintainers":[{"name":"khaledsqm","email":"khaled.smq@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/listener_0.1.1_1732354319212_0.955781730290274"},"_hasShrinkwrap":false}},"time":{"created":"2024-11-20T21:54:40.178Z","modified":"2024-11-23T09:31:59.644Z","0.1.0":"2024-11-20T21:54:40.473Z","0.1.1":"2024-11-23T09:31:59.443Z"},"bugs":{"url":"https://github.com/KhaledSMQ/avati/issues","email":"khaled.smq@hotmail.com"},"author":{"name":"Khaled Sameer","email":"khaled.smq@hotmail.com","url":"https://khaled.ee/"},"license":"MIT","homepage":"https://avati.io/","repository":{"type":"git","url":"git+https://github.com/KhaledSMQ/avati.git","directory":"packages/listener"},"description":"Listener package part of Avati project","maintainers":[{"name":"khaledsqm","email":"khaled.smq@hotmail.com"}],"readme":"# EventListenerManager HTML Showcases\n\nBelow are practical HTML examples demonstrating how to use the `EventListenerManager` in a web page. Each example illustrates different features and use cases, such as debouncing, throttling, asynchronous callbacks, error handling, and metadata attachment.\n\n---\n\n## **Prerequisites**\n\nTo use the `EventListenerManager` in your HTML files, you need to include it in your project. Assuming you have the compiled JavaScript version of the `EventListenerManager`, you can include it using a `<script>` tag.\n\nFor demonstration purposes, we'll assume the `EventListenerManager` is available in a file named `EventListenerManager.js`.\n\n---\n\n## **1. Basic Usage**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Basic Usage</title>\n</head>\n<body>\n  <button id=\"myButton\">Click Me</button>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    // Wait for the DOM to load\n    document.addEventListener('DOMContentLoaded', () => {\n      const button = document.getElementById('myButton');\n\n      function handleClick(event) {\n        alert('Button clicked!');\n      }\n\n      // Add an event listener using EventListenerManager\n      const eventId = eventManager.add(button, 'click', handleClick);\n\n      // Optionally, remove the event listener after some time\n      setTimeout(() => {\n        eventManager.remove(eventId);\n        console.log('Event listener removed');\n      }, 10000); // Removes the listener after 10 seconds\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- We include the `EventListenerManager.js` script in the HTML file.\n- We use `eventManager.add()` to attach a click event listener to the button.\n- After 10 seconds, we remove the event listener using `eventManager.remove()`.\n\n---\n\n## **2. Debouncing Input Events**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Debounce Example</title>\n  <style>\n    #output {\n      margin-top: 20px;\n    }\n  </style>\n</head>\n<body>\n  <input type=\"text\" id=\"searchInput\" placeholder=\"Type to search...\" />\n  <div id=\"output\"></div>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const input = document.getElementById('searchInput');\n      const output = document.getElementById('output');\n\n      function handleInput(event) {\n        const query = event.target.value;\n        output.textContent = `Searching for: ${query}`;\n      }\n\n      // Debounce the input event handler\n      eventManager.add(input, 'input', handleInput, { debounce: 500 });\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- As the user types in the input field, the `handleInput` function is called after the user stops typing for 500 milliseconds.\n- This reduces the number of times the search function is called, which is especially useful when making API requests.\n\n---\n\n## **3. Throttling Scroll Events**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Throttle Example</title>\n  <style>\n    body {\n      height: 2000px;\n    }\n    #scrollPosition {\n      position: fixed;\n      top: 10px;\n      left: 10px;\n      background: rgba(255, 255, 255, 0.8);\n      padding: 5px;\n    }\n  </style>\n</head>\n<body>\n  <div id=\"scrollPosition\">Scroll Y: 0</div>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const scrollDisplay = document.getElementById('scrollPosition');\n\n      function handleScroll() {\n        scrollDisplay.textContent = `Scroll Y: ${window.scrollY}`;\n      }\n\n      // Throttle the scroll event handler\n      eventManager.add(window, 'scroll', handleScroll, { throttle: 100 });\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- The `handleScroll` function updates the displayed scroll position.\n- By throttling the scroll event handler to 100 milliseconds, we limit the number of times the function is called during scrolling, improving performance.\n\n---\n\n## **4. Using Async Callbacks**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Async Callback Example</title>\n</head>\n<body>\n  <form id=\"myForm\">\n    <input type=\"text\" name=\"data\" placeholder=\"Enter some data\" required />\n    <button type=\"submit\">Submit</button>\n  </form>\n  <div id=\"status\"></div>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const form = document.getElementById('myForm');\n      const status = document.getElementById('status');\n\n      async function handleSubmit(event) {\n        event.preventDefault();\n        status.textContent = 'Submitting...';\n\n        // Simulate an asynchronous operation (e.g., network request)\n        await new Promise((resolve) => setTimeout(resolve, 2000));\n\n        status.textContent = 'Form submitted successfully!';\n      }\n\n      // Add an async event listener\n      eventManager.add(form, 'submit', handleSubmit, { async: true });\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- The `handleSubmit` function is asynchronous and simulates a network request.\n- The `async` option ensures that any errors in the async function are caught and can be handled appropriately.\n\n---\n\n## **5. Error Handling with onError**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Error Handling Example</title>\n</head>\n<body>\n  <button id=\"errorButton\">Click Me</button>\n  <div id=\"errorMessage\" style=\"color: red;\"></div>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const button = document.getElementById('errorButton');\n      const errorMessage = document.getElementById('errorMessage');\n\n      function handleClick() {\n        // Simulate an error\n        throw new Error('Something went wrong!');\n      }\n\n      function handleError(error) {\n        errorMessage.textContent = `Error: ${error.message}`;\n      }\n\n      // Add event listener with error handling\n      eventManager.add(button, 'click', handleClick, { onError: handleError });\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- When the button is clicked, the `handleClick` function throws an error.\n- The `onError` handler catches the error and displays an error message to the user.\n\n---\n\n## **6. Attaching Metadata to Events**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Metadata Example</title>\n</head>\n<body>\n  <button id=\"metaButton\">Click Me</button>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const button = document.getElementById('metaButton');\n\n      function handleClick(event) {\n        if (event.metadata) {\n          console.log('Event ID:', event.metadata.eventId);\n          console.log('Timestamp:', new Date(event.metadata.timestamp));\n          console.log('Original Callback:', event.metadata.originalCallback);\n        }\n        alert('Button clicked!');\n      }\n\n      // Add event listener with metadata\n      eventManager.add(button, 'click', handleClick, { metadata: true });\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- The `handleClick` function accesses metadata attached to the event object.\n- This can be useful for logging or debugging purposes.\n\n---\n\n## **7. Using once() for One-Time Event Listeners**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Once Example</title>\n</head>\n<body>\n  <button id=\"onceButton\">Click Me Once</button>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const button = document.getElementById('onceButton');\n\n      function handleClick() {\n        alert('This will only appear once!');\n      }\n\n      // Add a one-time event listener\n      eventManager.once(button, 'click', handleClick);\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- The `handleClick` function will only be called once, after which the event listener is automatically removed.\n\n---\n\n## **8. Automatic Cleanup with addWithCleanup**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Cleanup Example</title>\n</head>\n<body>\n  <button id=\"cleanupButton\">Click Me</button>\n  <button id=\"removeListenerButton\">Remove Listener</button>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const clickButton = document.getElementById('cleanupButton');\n      const removeButton = document.getElementById('removeListenerButton');\n\n      function handleClick() {\n        alert('Button clicked!');\n      }\n\n      // Add event listener with cleanup\n      const cleanup = eventManager.addWithCleanup(clickButton, 'click', handleClick);\n\n      // Remove the event listener when the remove button is clicked\n      removeButton.addEventListener('click', () => {\n        cleanup();\n        alert('Event listener removed');\n      });\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- The `addWithCleanup` method provides a convenient way to remove event listeners without tracking the `eventId`.\n- Clicking the \"Remove Listener\" button calls the cleanup function, removing the event listener from the \"Click Me\" button.\n\n---\n\n## **9. Combining Debounce and Async Callbacks**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Debounce and Async Example</title>\n</head>\n<body>\n  <input type=\"text\" id=\"searchInput\" placeholder=\"Type to search...\" />\n  <div id=\"results\"></div>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const input = document.getElementById('searchInput');\n      const results = document.getElementById('results');\n\n      async function handleInput(event) {\n        const query = event.target.value;\n        if (!query) {\n          results.textContent = '';\n          return;\n        }\n        results.textContent = 'Searching...';\n\n        // Simulate an asynchronous search operation\n        await new Promise((resolve) => setTimeout(resolve, 1000));\n\n        results.textContent = `Results for \"${query}\"`;\n      }\n\n      // Debounce the async input handler\n      eventManager.add(input, 'input', handleInput, { debounce: 500, async: true });\n    });\n  </script>\n</body>\n</html>\n```\n\n### **Explanation**\n\n- This example demonstrates combining debouncing with an asynchronous callback.\n- The search operation is debounced to reduce unnecessary function calls and handle asynchronous operations smoothly.\n\n---\n\n## **10. Throttling with noLeading and noTrailing Options**\n\n### **HTML**\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>EventListenerManager - Throttle Options Example</title>\n  <style>\n    body {\n      height: 2000px;\n    }\n    #scrollInfo {\n      position: fixed;\n      top: 10px;\n      left: 10px;\n      background: rgba(255, 255, 255, 0.8);\n      padding: 5px;\n    }\n  </style>\n</head>\n<body>\n  <div id=\"scrollInfo\">Scroll Y: 0</div>\n\n  <!-- Include the EventListenerManager script -->\n  <script src=\"EventListenerManager.js\"></script>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      const scrollInfo = document.getElementById('scrollInfo');\n\n      function handleScroll() {\n        scrollInfo.textContent = `Scroll Y: ${window.scrollY}`;\n      }\n\n      // Throttle with no leading call\n      eventManager.add(window, 'scroll', handleScroll, {\n        throttle: 200,\n        noLeading: true,\n      });\n\n      // Uncomment the following code to throttle with no trailing call\n      /*\n      eventManager.add(window, 'scroll', handleScroll, {\n        throttle: 200,\n        noTrailing: true,\n      });\n      */\n    });\n  </script>\n</body>\n</html>\n```\n\n\n\n\n## Changelog\n\nPlease see [CHANGELOG](./CHANGELOG.md) for more information what has changed recently.\n\n## Contributing\n\nI welcome contributions from developers of all experience levels. If you have an idea, found a bug, or want to improve something, I encourage you to get involved!\n\n### How to Contribute\n1. Read [Contributing Guide](https://github.com/KhaledSMQ/avati/blob/master/Contributing.md) for details on how to get started.\n2. Fork the repository and make your changes.\n3. Submit a pull request, and we’ll review it as soon as possible.\n\n## License\n\n[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/KhaledSMQ/avati/blob/master/LICENSE)\n\nAvati is open-source and distributed under the [MIT License](https://github.com/KhaledSMQ/avati/blob/master/LICENSE).\n\n---\n<div align=\"center\">\n\n[![Follow on Twitter](https://img.shields.io/twitter/follow/KhaledSMQ.svg?style=social)](https://x.com/khaledsmq_)\n[![Follow on LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue.svg)](https://www.linkedin.com/in/khaledsmq/)\n[![Follow on Medium](https://img.shields.io/badge/Medium-Follow-black.svg)](https://medium.com/@khaled.smq)\n[![Made with ❤️](https://img.shields.io/badge/Made%20with-❤️-red.svg)](https://github.com/KhaledSMQ)\n[![Star on GitHub](https://img.shields.io/github/stars/KhaledSMQ/avati.svg?style=social)](https://github.com/KhaledSMQ/avati/stargazers)\n[![Follow on GitHub](https://img.shields.io/github/followers/KhaledSMQ.svg?style=social&label=Follow)](https://github.com/KhaledSMQ)\n\n</div>\n","readmeFilename":"README.md","keywords":["avati","scheduler","batch","task-queue","priority-queue","async","typescript","debounce","debouncer","throttle","throttling","delay","function control","rate limit","rate limiting","utility","helper","JavaScript","timing","event handling","event control","performance","optimization","function delay","input control","API calls"]}