Search code examples
javascriptcustom-events

Element event listener callback not working with custom event


Element event listener callback not working with custom event, in the following code, document and window event listeners will be triggered, but not element's (tested on IE11, FF33, and Chrome38, results are the same.) Any idea? Did I misuse custom event?

var el = document.getElementById('some-elem');
el.addEventListener('custom', function (e) {
  console.log("Element got event: " + e.type);
}, false, true);

document.addEventListener('custom', function (e) {
  console.log("document got event: " + e.type);
}, false);

window.addEventListener('custom', function (e) {
  console.log("window got event: " + e.type);
}, false);

var evt = document.createEvent('CustomEvent');
evt.initCustomEvent('custom', true, false);
document.dispatchEvent(evt);
<div id="some-elem"></div>


Solution

  • The problem is that the event never goes through the element, you're firing the event on document. Instead, fire it on the element:

    var el = document.getElementById('some-elem');
    el.addEventListener('custom', function (e) {
      console.log("Element got event: " + e.type);
    }, false, true);
    
    document.addEventListener('custom', function (e) {
      console.log("document got event: " + e.type);
    }, false);
    
    window.addEventListener('custom', function (e) {
      console.log("window got event: " + e.type);
    }, false);
    
    var evt = document.createEvent('CustomEvent');
    evt.initCustomEvent('custom', true, false);
    el.dispatchEvent(evt); // <=== Change is here
    <div id="some-elem"></div>


    Re your comment:

    the object dispatching the event is different from the listening object in my case, does it mean custom event can only be listened on the same object (except window and document)?

    The event has to travel through the element, just like a click has to travel through the element for it to be seen by a click handler on the element. So for instance, if you had a div with the event handler on it, and there was an img inside the div, and you dispatched the event on the img, the handler on the div would trigger because the event bubbles to it (because you made the event bubble-able):

    var el = document.getElementById('some-elem');
    el.addEventListener('custom', function (e) {
      snippet.log("Element got event: " + e.type);
    }, false, true);
    
    document.addEventListener('custom', function (e) {
      snippet.log("document got event: " + e.type);
    }, false);
    
    window.addEventListener('custom', function (e) {
      snippet.log("window got event: " + e.type);
    }, false);
    
    var evt = document.createEvent('CustomEvent');
    evt.initCustomEvent('custom', true, false);
    document.getElementById("some-span").dispatchEvent(evt); // <=== Change is here
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script><!-- snippet.js details: http://meta.stackexchange.com/a/242144/134069 -->
    <div id="some-elem">
      <span id="some-span"></span>
    </div>

    This diagram from the DOM events spec may help with picturing this stuff:

    enter image description here

    The element on which you call dispatchEvent is the "target" element (the dark blue td in that diagram).