Namespace vanilla JavaScript events like in jQuery

3.2k views Asked by At

In jQuery, when you set an event, you are able to namespace it. This means (if you want) you can have multiple resize window events, for example, and be able to unbind them individually without unbinding all events on that selector.

Example of jQuery namespacing:

$(window).on('scroll.myScrollNamespace, function() ...

I'm wondering how I can create a namespace in plain JavaScript. This obviously would not work:

window.addEventListener('resize.myScrollNamespace', function() ...
2

There are 2 answers

1
rsp On BEST ANSWER

If instead of an anonymous function:

window.addEventListener('resize', function () {...});

you use a named function:

window.addEventListener('resize', function myScroll() {...});

then you may be able to use:

window.removeEventListener('resize', myScroll);

Make sure that you have myScroll in scope. When you remove the listeners in a different place than you add them, maybe you should define your functions in some outer scope and use their names in addEventListener in the same way as in the removeEventListener:

function myScroll() {
  // ...
}

window.addEventListener('resize', myScroll);

window.removeEventListener('resize', myScroll);

If you want to be able to remove many listeners at once, then you will have to store them in some array and call removeEventListener for each of its elements.

See the EventTarget.removeEventListener() documentation.

0
Tokimon On

As @rsp answer correctly solves the problem of unbinding the correct handler, it doesn't really answer the problem of namespacing. To handle this you would need to do a bit more coding like this:

function on(elm, evtName, handler) {
  evtName.split('.').reduce(function(evtPart, evt) {
    evt = evt ? evt +'.'+ evtPart : evtPart;
    elm.addEventListener(evt, handler, true);
    return evt;
  }, '');
}

function off(elm, evtName, handler) {
  evtName.split('.').reduce(function(evtPart, evt) {
    evt = evt ? evt +'.'+ evtPart : evtPart;
    elm.removeEventListener(evt, handler, true);
    return evt;
  }, '');
}

// Your handler
function onScroll(e) { ... }

// To bind it
on(window, 'scroll.myScrollNamespace', onScroll);

// To unbind it
off(window, 'scroll.myScrollNamespace', onScroll);

So to sum up: this actually sets several event listeners - one for each part of your namespacing. This functionality is unfortunately not natively supported, but as you can see it can be achieved relatively simple. Just be wary that even though this script support deep namespacing (eg. scroll.parent.child) it would bind a lot of event listeners (3 in this case), and thus is inadvisable.

You could possibly do this more performant, but this gets it done.