Bug Tracker

Ticket #11047 (closed bug: patchwelcome)

Opened 3 years ago

Last modified 14 months ago

If you trigger a custom event you can NOT catch it using the addEventListener function

Reported by: anonymous Owned by:
Priority: undecided Milestone: None
Component: unfiled Version: 1.7.1
Keywords: Cc:
Blocking: Blocked by:

Description

The trigger function should also dispatch custom events such that code using addEventListener can catch the custom event. However, that is not happening. In fact, that is the only of the 8 combinations listed below that does not work. We should fix this to allow better interoperability between jQuery event functions and W3C DOM event functions.

  1. PASS: If you trigger a DOM event you can catch it using the bind function
  2. PASS: If you trigger a DOM event you can catch it using the addEventListener function
  3. PASS: If you trigger a custom event you can catch it using the bind function
  4. FAIL: If you trigger a custom event you can NOT catch it using the addEventListener function
  5. PASS: If you dispatch a DOM event you can catch it using the bind function
  6. PASS: If you dispatch a DOM event you can catch it using the addEventListener function
  7. PASS: If you dispatch a custom event you can catch it using the bind function
  8. PASS: If you dispatch a custom event you can catch it using the addEventListener function

The code below shows all the combinations listed above, including the failing case. It reproes under all major browsers in Windows 7. There is also a jsFiddle at:  http://jsfiddle.net/Jqeza/3/

<html>
<head>
  <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
  <button id="idButtonTrigger" onmouseover="TriggerEvent()">Hover to Trigger Event</button>
  <button id="idButtonDispatch" onmouseover="DispatchEvent()">Hover to Dispatch Event</button>
  <p>ClickListener: <a id="idClickListener"></a></p>
  <p>ClickBind: <a id="idClickBind"></a></p>
  <p>CustomListener: <a id="idCustomListener"></a></p>
  <p>CustomBind: <a id="idCustomBind"></a></p>

  <script type="text/javascript">

    document.addEventListener('click', function(event) {
      document.getElementById('idClickListener').innerHTML = "Fired!";
      $('#idClickListener').fadeIn('slow').fadeOut('slow');
    });

    $(document).bind('click', function(event) {
      document.getElementById('idClickBind').innerHTML = "Fired!";
      $('#idClickBind').fadeIn('slow').fadeOut('slow');
    });

    document.addEventListener('custom', function(event) {
      document.getElementById('idCustomListener').innerHTML = "Fired!";
      $('#idCustomListener').fadeIn('slow').fadeOut('slow');
    });

    $(document).bind('custom', function(event) {
      document.getElementById('idCustomBind').innerHTML = "Fired!";
      $('#idCustomBind').fadeIn('slow').fadeOut('slow');
    });

    function TriggerEvent() {
      $('#idButtonTrigger').trigger('click');
      $('#idButtonTrigger').trigger('custom'); // CANNOT catch with addEventListener
    }

    function DispatchEvent() {
      var clickEvent = document.createEvent("MouseEvents");
      clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      document.getElementById('idButtonDispatch').dispatchEvent(clickEvent);

      var customEvent = document.createEvent('Event');
      customEvent.initEvent('custom', true, true);
      document.getElementById('idButtonDispatch').dispatchEvent(customEvent);
    }

  </script>
</body>
</html>

Change History

comment:1 Changed 3 years ago by dmethvin

  • Status changed from new to closed
  • Resolution set to patchwelcome

jQuery's event system is a level *above* the native one, we're not trying to shim the browser functionality.

For example case 2, we actually "fail" that for custom event names. The only reason it works for most browser events is that calling the corresponding DOM method name fires the event.

Doing what you describe is pretty difficult, especially when you take IE<9 into account with .attachEvent/.fireEvent. Your examples aren't doing that so they aren't cross-browser compatible. And you have to still retain the current semantics (like optional trigger data) to avoid breaking all the thousands of sites and plugins out there.

Experiment with it in your own branch and see if you agree it's pretty tough.

comment:2 Changed 3 years ago by anonymous

All that's being said here is that the trigger method should do a dispatchEvent (where supported) on custom events so that listeners using addEventListener can catch the custom event. For instance, something similar to the following piece of code at the end of the trigger method would be enough.

if (isCustomEvent(event) && elem.dispatchEvent) {
  var customEvent = document.createEvent('Event');  
  customEvent.initEvent(event.type, true, true);  
  if (data != null) {
    customEvent.data = data;
  }
  elem.dispatchEvent(customEvent);  
}

Where isCustomEvent(event) is a function that would return true if the event type is not one of the standard DOM events. This way, clients that are written purely using W3C's DOM Event model could still listen to custom events (in addition to standard DOM Events) fired by jQuery without having to modify any code (and without having to take a dependency on jQuery either).

comment:3 Changed 3 years ago by dmethvin

do a dispatchEvent (where supported)

In general we haven't tried to implement functionality that only works on some browsers (and some events) but not all, since someone will immediately file a bug that it doesn't work right.

Where isCustomEvent(event) is a function that would return true if the event type is not one of the standard DOM events.

Can you post a cross-browser implementation of that?

comment:4 Changed 22 months ago by nelson@…

comment:5 Changed 14 months ago by anonymous

You can use this plugin which has a method betterTrigger  https://github.com/sandeep45/betterTrigger

Note: See TracTickets for help on using tickets.