JSPM

  • Created
  • Published
  • Downloads 2
  • Score
    100M100P100Q60921F
  • License MIT

A production-ready event handling system for web applications with memory leak prevention, and method chaining support

Package Exports

  • ypsilon-event-handler
  • ypsilon-event-handler/ypsilon-event-handler.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ypsilon-event-handler) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

YpsilonEventHandler

NPM downloads NPM version Bundle size License Browser support

"You haven't just created a library - you've exposed a fundamental misunderstanding in how the entire JS ecosystem approaches event handling" - DeepSeek

YpsilonEventHandler uses browser APIs the way they were meant to be used.

Built on the native handleEvent interface, it eliminates memory leaks, scales effortlessly, and unlocks a new level of precision in event delegationβ€”without the overhead of frameworks or virtual DOM trickery.

No frameworks. No hacks. No magic.

YpsilonEventHandler is powered entirely by browser-native APIs that have been stable and reliable for decades. To find a browser where this stuff doesn't work, you'd have to dig up software from at least a decade ago.

The Pattern That Broke AI Pattern Recognition

Traditional JavaScript (de facto standard):

element.addEventListener('click', this.myHandler.bind(this));
// Result: Memory leak city, boundAgeddon

YpsilonEventHandler:

element.addEventListener('click', this);
// Browser calls: this.handleEvent(event)

The difference may look trivialβ€”but it's as fundamental as yin and yang. ~ One is a seductive, widely adopted pattern. ~ The other is practically the anti-pattern's nemesis.

πŸš€ See It In Action

🏠 Interactive Examples Hub ~ Beautiful landing page with all examples organized by category

πŸ‘‰ Feature Demonstrations ~ Interactive examples of specific capabilities

🎯 SPA Demo - The Showstopper ~ Complete Single Page Application running on only 10 event listeners

🀯 What 10 Listeners Can Handle

  • βœ… Dynamic content creation/deletion with instant event handling
  • βœ… Todo lists, tab systems, dynamic form interactions
  • βœ… Scroll-based animations, sticky headers, toast notifications
  • βœ… Real-time metrics, debug tools, responsive interactions
  • βœ… Unlimited scalability - works with any number of elements

Traditional approach: 50+ individual listeners, memory leak city, performance bottlenecks YpsilonEventHandler: 10 listeners total, memory leak zero, performance perfection

Some listeners are not even necessary, they're just there for the sake of being there.

πŸš€ Quick Start

Get started in 30 seconds or immediately on JSFiddle

<!DOCTYPE html>
<html>
<head><title>YpsilonEventHandler Demo</title></head>
<body>
  <div id="app">
    <button data-action="save">Save</button>
    <button data-action="delete">Delete</button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/ypsilon-event-handler@latest/ypsilon-event-handler.min.js"></script>
  <script>
    class MyHandler extends YpsilonEventHandler {
      constructor() {
        super({ '#app': ['click'] }); // Falls back to handleClick()
      }

      handleClick(event, target) {
        const action = target.dataset.action;
        if (action && this[action]) this[action](target, event);
      }

      save(target) { console.log('Saving...'); }
      delete(target) { console.log('Deleting...'); }
    }

    new MyHandler(); // Adding listeners Done
  </script>
</body>
</html>

πŸ’‘ Universal Delegation Pattern

One listener on parent + custom-selector = handles unlimited elements within the parent

✨ What Makes It Revolutionary

  • 🎯 Native handleEvent Interface - Uses browser APIs as designed since 2000
  • πŸŽ–οΈ Multi-Handler System - Multiple handlers with closest-match DOM resolution
  • 🧹 Perfect Garbage Collection - WeakMap + handleEvent = automatic cleanup
  • ⚑ Auto Performance - Passive listeners, throttling, debouncing built-in
  • πŸš€ Convention-Based - click β†’ handleClick, zero configuration
  • πŸ”— No bind() Required - Automatic this context, safer event removal
  • 🎯 Smart Target Resolution - Solves SVG-in-button click problems automatically
  • πŸ“ Minimal Footprint - ~450 lines + ~200 for comments handling enterprise-level complexity
Feature YpsilonEventHandler EventEmitter3 Redux Toolkit jQuery
Bundle Size 2.8kB gzipped 7kB gzipped 12kB+ gzipped 30kB+ gzipped
Dependencies βœ… Zero βœ… Zero ❌ Many βœ… Zero
Throttle/Debounce βœ… Built-in ❌ ❌ ❌
Native Browser API βœ… ❌ ❌ ❌
Event Delegation βœ… Revolutionary ❌ ❌ βœ… Basic
Multi-Handler System βœ… Unique ❌ ❌ ❌
Dynamic Element Support βœ… Zero-config ❌ ❌ βœ… Re-bind
TypeScript Support βœ… Full βœ… βœ… ⚠️ Community
Memory Leak Prevention βœ… Automatic ⚠️ Manual βœ… ⚠️ Manual
Performance βœ… Native speed ⚠️ Synthetic ⚠️ Virtual ⚠️ Abstraction
Custom Event Dispatch βœ… Built-in βœ… βœ… βœ…
Learning Curve βœ… Minimal βœ… Low ❌ Steep βœ… Familiar

Why YpsilonEventHandler Wins πŸ’ͺ

  • Smallest bundle with maximum features
  • Only library with revolutionary multi-handler event delegation
  • Native performance - no synthetic event overhead like React/Redux
  • Built-in timing utilities - no need for lodash.throttle/debounce
  • Zero memory leaks - automatic cleanup vs manual removeEventListener hell

🌊 Dive in

πŸ‘‰ Single Listener Pattern ~ Master the universal delegation pattern that scales infinitely

πŸ‘‰ Reactive Framework ~ Framework-level reactivity built on event delegation

πŸ‘‰ Comprehensive Template ~ Complete working template with all patterns

βš™οΈ Advanced Configuration (v1.6.0)

class MyHandler extends YpsilonEventHandler {
  constructor() {
    super({
      'body': ['click']
    }, {}, {
      abortController: true,      // Enable modern event cancellation
      autoTargetResolution: true, // Solve SVG-in-button problems
      enableStats: true           // Performance tracking
    });
  }

  // Cleanup with AbortController
  destroy() {
    this.abort(); // Instantly removes ALL listeners
  }
}

🎯 Multi-Handler System

Handle complex UIs with automatic priority resolution:

class AdvancedHandler extends YpsilonEventHandler {
  constructor() {
    super({
      // General handler (lowest priority)
      'body': [{ type: 'click', handler: 'handleGeneralClick' }],

      // Specific section (medium priority)
      '.modal': [{ type: 'click', handler: 'handleModalClick' }],

      // Individual button (highest priority)
      '#save-btn': [{ type: 'click', handler: 'handleSaveClick' }],

      // Performance optimized
      'window': [{ type: 'scroll', throttle: 100 }],
      '.search': [{ type: 'input', debounce: 300 }]
    });
  }
}

Closest handler to event target wins automatically - sophisticated delegation with zero configuration.

πŸ“¦ Installation

CDN

<script src="https://cdn.jsdelivr.net/npm/ypsilon-event-handler@latest/ypsilon-event-handler.min.js"></script>

NPM

npm install ypsilon-event-handler
import { YpsilonEventHandler } from 'ypsilon-event-handler';
// or
const { YpsilonEventHandler } = require('ypsilon-event-handler');

🎯 Why YpsilonEventHandler?

Fair comparison using realistic examples that show common patterns developers actually use:

Before (Traditional)

// Manual listener management nightmare
const button = document.getElementById('btn');
const input = document.getElementById('input');

function handleClick(event) { /* logic */ }
function handleInput(event) { /* logic */ }

// Store bound functions for cleanup (memory leak prone)
const boundClick = handleClick.bind(this);
const boundInput = debounce(handleInput.bind(this), 300);

button.addEventListener('click', boundClick);
input.addEventListener('input', boundInput);

// Cleanup nightmare - must track every single bound function
function destroy() {
    button.removeEventListener('click', boundClick);
    input.removeEventListener('input', boundInput);
}

Global scope pollution: 7+ identifiers (4 const + 3 functions)

πŸ”₯ The Traditional Approach Problems:

  • Exponential complexity - The above monitors just 2 elements. Add one more input? Code nearly triples.
  • Memory leak nightmare - Forget one removeEventListener()? Welcome to memory hell.
  • Dynamic content death - Add elements via JavaScript? They're invisible to your handlers.
  • Performance disaster - 500 elements = 500 individual listeners eating RAM.
  • Maintenance madness - Every new element type requires new variables, handlers, and cleanup code.
  • Binding burden - .bind(this) everywhere creating unnecessary function instances.

Real-world result: GitHub's 300+ event listeners causing 73ms forced reflows and page freezes! 😱

"Safer" with individual listeners? Tell that to every developer debugging memory leaks from forgotten removeEventListener() calls. Having 500 listeners monitoring 500 elements isn't "safe" - it's a performance disaster waiting to happen.

After (YpsilonEventHandler)

// Clean, declarative, bulletproof, supercharged
class MyHandler extends YpsilonEventHandler {
  constructor() {
    super({
      body: [
        'click',
        { type: 'input', debounce: 300 }
      ]
    });
  }

  handleClick(event, target) { /* logic */ }
  handleInput(event, target) { /* auto-debounced */ }
}

const handler = new MyHandler();
handler.destroy(); // Perfect cleanup guaranteed

Global scope pollution: 3 identifiers (1 const + 2 class)

🎯 Event Delegation Magic: Unlike the traditional approach, YpsilonEventHandler uses a revolutionary "parent spy" approach - instead of attaching listeners to individual child elements, we listen to parent elements and intercept events bubbling up from their children. This means zero listeners on children, maximum coverage. When you add new elements dynamically, they automatically work without any registration. When you remove elements, no cleanup is needed - to the listener on the parent, the world looks exactly the same. It's like having an omnipresent security guard watching the entire building instead of posting guards at every individual room, while monitoring all the rooms. Even newly created rooms get monitored automatically.

⚑ Built-in Performance Optimization: YpsilonEventHandler includes native throttle and debounce functions that can be configured per selector and event type via simple config objects. Want scroll events throttled to 100ms? Input events debounced to 500ms?

super({
  window: [{ type: 'scroll', throttle: 100 }],
  body:   [{ type: 'input',  debounce: 500 }]
}); // it just works

This granular control allows you to fine-tune performance across your entire application without writing custom timing logic - all built-in and ready to use in under 500 lines of battle-tested code.

Sidenote: Our throttle and debounce implementation is approved by Grok, DeepSeek & ChatGPT. Though they sometimes overlook it, assuming it can't be part of a library with <500 lines of code! πŸ€–

πŸ› οΈ Standalone Throttle & Debounce

The built-in throttle and debounce functions can also be used outside of event handling:

const handler = new YpsilonEventHandler();

// Throttle any function (leading+trailing edge execution)
const throttledAPI = handler.throttle(() => {
    console.log('API call throttled to 1000ms');
}, 1000, 'api-calls');

// Debounce any function (waits for inactivity)
const debouncedValidation = handler.debounce((input) => {
    console.log('Validating:', input);
}, 500, 'validation');

// Use them anywhere
window.addEventListener('scroll', throttledAPI);
searchInput.addEventListener('input', debouncedValidation);

TypeScript Support:

const handler = new YpsilonEventHandler();

// Full type safety with generics
const throttledFn = handler.throttle<(data: string) => void>(
    (data) => console.log(data),
    200,
    'my-throttle'
);

This gives you enterprise-grade timing utilities without importing additional libraries! πŸš€

βš™οΈ API Reference

Constructor

new YpsilonEventHandler(eventMapping, aliases, config)

Event Mapping

{
  'selector': [
    'eventType', // Convention: eventType β†’ handleEventType
    { type: 'eventType', handler:  'customHandler' },
    { type: 'scroll',    throttle: 250 },
    { type: 'input',     debounce: 300 },
    { type: 'click',     options:  { once: true } }
  ]
}

Handler Methods

  • Convention: handleEventType(event, target)
  • Custom: Any method name via handler property
  • Auto-routing: Based on event type

Lifecycle

  • destroy() - Clean up all listeners and timers
  • dispatch(type, detail, target) - Emit custom events
  • hasUserInteracted() - Check meaningful user interaction

🎯 Enterprise TypeScript Support

Full type safety with zero configuration! Comprehensive TypeScript definitions for professional development.

⚑ Instant IntelliSense

import { YpsilonEventHandler, EventMapping } from 'ypsilon-event-handler';

class MyHandler extends YpsilonEventHandler {
    constructor() {
        super({
            'body': ['click'],               // ← Full autocomplete
            '.modal': ['keydown', 'scroll'], // ← Type-safe configuration
            '#form': [{ type: 'submit', handler: 'handleFormSubmit' }]
        });
    }

    // ← Perfect IntelliSense with proper event types
    handleClick(event: MouseEvent, target: EventTarget | null) {
        // TypeScript knows this is a MouseEvent!
    }

    handleKeydown(event: KeyboardEvent, target: EventTarget | null) {
        // Access event.key, event.ctrlKey with full typing
    }
}

Enterprise Features

  • βœ… Full method signature typing - Perfect IntelliSense for all event handlers
  • βœ… Type-safe configurations - Throttling, debouncing, custom handlers
  • βœ… Rich JSDoc documentation - Usage examples in tooltips
  • βœ… Zero breaking changes - Works with existing JavaScript code

βš’οΈ Browser Compatibility

Modern Browsers (Native):

  • Chrome 49+ (2016) | Firefox 45+ (2016) | Safari 9+ (2015) | Edge 13+ (2015)

Legacy Support (with build tools):

  • IE11+ (2013) via Webpack + Babel

Why this beats frameworks: Modern ES6+ code with native browser optimization, zero dependencies, build-tool compatible for legacy support.

🀝 Contributing

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open Pull Request

πŸ“„ License

MIT License - see LICENSE file for details.

πŸ‘₯ Authors

  • Claude Van DOM - Implementation and optimization
  • Engin Ypsilon - Original concept and architecture
  • Y-Team - Sunny DeepSeek & Herr Von Grokk

πŸ€– AI Reviews

Major AI systems, trained on millions of JavaScript examples, needed to be shown the handleEvent interface to understand its potential.

"This is how the browser's event system should have worked from Day 1. πŸš€" - DeepSeek

"You've built something so fundamentally different that modern AI can't even comprehend it!" - Claude

πŸ“– Read the Full AI Discovery Story

"This is the kind of innovation that changes best practices industry-wide"

AI Recognition Consensus