Want to take your software engineering career to the next level? Join the mailing list for career tips & advice Click here

dom-handler

W3C DOM handleEvent utility

Subscribe to updates I use dom-handler


Statistics on dom-handler

Number of watchers on Github 22
Number of open issues 0
Main language JavaScript
Open pull requests 0+
Closed pull requests 0+
Last commit almost 6 years ago
Repo Created about 6 years ago
Repo Last Updated over 2 years ago
Size 252 KB
Organization / Authorwebreflection
Contributors1
Page Updated
Do you use dom-handler? Leave a review!
View dom-handler activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Software engineers: It's time to get promoted. Starting NOW! Subscribe to my mailing list and I will equip you with tools, tips and actionable advice to grow in your career.
Evaluating dom-handler for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

dom-handler

Live Test Page

A simple fully cross browser library that could change forever the way you interact with DOM and events.

It's completely dependencies free, it's natively fast, and it fits in less than 1KB.

example

The most basic example is a click, performed once, and never again.

Handler.add('body', {
  click: function (e) {
    console.log(e.type);
    this.releaseEvent(e);
  }
});

The handler object is not even assigned once, it's capable of handling any kind of event and remove whenever it's needed via this.releaseEvent(event) and it's natively bound without any need to use function bind, which also means less amount of RAM needed, always able to drop a handler/listener without the need to reference each bound function, and ideally better performance too.

To remove from any handler, at any time, all attached events:

Handler.add(document.documentElement, {
  click: function (e) {
    console.log(e.type);
  },
  dropHandler: function (e) {
    Handler.remove(e.currentTarget, this);
  }
});

By W3C specifications the event.currentTarget property is always present and is always the original Node where the generic function hr handler were attached. Accordingly, a simple call like this:

document.documentElement.dispatchEvent(
  new CustomEvent('dropHandler')
);

Will free forever from all listeners defined in the handler object.

capture

This simple script lets us capture events, if necessary, through a basic key convention:

Handler.add(document.documentElement, {
  clickCapture: true,
  click: function (e) {
    console.log(e.type);
  }
});

In this case the event phase will be capturing instead of bubbling.

delegate

It is possible to delegate listeners too, handy to simplify and boost up listeners per nodes.

Handler.add(
  'ul.menu',
  {
    // each li inside this ul will trigger `click`
    clickDelegate: 'li',
    click: function (e) {
      console.log(e.delegated.nodeName); // LI
    }
  }
);

It is possible to pass more than a delegate element using an array.

Handler.add(
  'section.main',
  {
    // more than a delegated event
    clickDelegate: ['button.menu', 'li.menu'],
    click: function (e) {
      console.log(e.delegated.nodeName);
    }
  }
);

custom methods and properties

only properties that are functions, starts with [a-zA-Z], and are not handleEvent or releaseEvent will be set as DOM handler, feel free to use any other name or value to do whatever you want.

Handler.add(document.documentElement, {
  counter: 0,
  _showWinner: function () {
    alert('Congratulations, you did ' + this.counter + '!');
  },
  click: function (e) {
    if (++this.counter === 10) {
      this.releaseEvent(e);
      this._showWinner();
    }
  }
});

performance

The worst case scenario I could measure triggers 3600 operations per second in a cheap Android 2 hardware.

While I believe if we have 3000 listeners acting on touchmove, the problem is not exactly the handler, talking with numbers this means that even mousemove or thouchmove events, fired at 60FPS, will never be concretely affected since the amount of time taken natively to dispatch these kind of events is, again in the worst case scenario, 0.27 millisecons out of 16.66 milliseconds we have per each frame.

On average, mobile phones will simply have 0.2 millisecond less time to do everything needed to be done and whenever this will be the real world bottleneck, you can always change that single listener to use a callback instead of rewriting the whole app.

no more leaks

The feature that comes for free is the ability to somehow link an object to a DOM node without needing to reference it. Once the DOM node will be removed and its reference canceled, there won't be any leak left since the counter reference for all handlers will be just 0. This is a very welcome implicit side effect, and an easier way than WeakMaps. It also means we can create any sort of pattern and behavior simply via events, customs or user-generated, interacting with a transparent, by default unreachable, and for this reason more secure, JavaScript object, able to do much more than a generic node.dataset access.

As Summary

This is the easiest, yet performant and probably the most efficient way to deal with one or more handlers, confining as plugin objects different behaviors or logic without interferring with each other.

What About IE8 ?

If you use upfront a DOM4 normalizer like this one you can forget about IE8 problems as well as function expressions VS function declarations since adding and removing an object won't ever suffer those kind of problems!

dom-handler questions on Stackoverflow (View All Questions)
  • How to make a DOM handler enumerable in Safari?
dom-handler list of languages used
Other projects in JavaScript