Read the full article at: DO NOT TRIGGER REAL EVENT NAMES WITH JQUERY!
Sometimes JavaScript toolkits give us so much functionality that we can get hung by it if we’re not careful. The more functionality that we use within a toolkit, the more opportunity there is to have one set of changes or additions affect another. That’s especially true as you maintain your code over a period of years. One mistake I often see is the use of jQuery’s trigger
, a method which allows developers to trigger a registered event. It’s great that you can do that but DO NOT TRIGGER REAL EVENT NAMES!
Note: I’m aware that other toolkits provide this functionality — I simply use jQuery as an example because of its popularity and recent problem I saw. This can happen with any toolkit. MooTools uses fireEvent
, etc.
The following is a prime example of using trigger
to accomplish a task:
// Set up a click event jQuery('.tabs a').on('click', function() { // Switch to the tab, load some content, whatever }); // Trigger a click on the last one jQuery('.tabs a').last().trigger('click');
The above would open the given tab at that index. I totally understand why people use trigger
for this type of thing; it’s usually because the function to trigger said opening is not available globally, and triggering an event is easy and always available. The problem is that using real event names as the trigger can …trigger… some crazy shit. Let’s say this is added somewhere else in the site:
// Listen to all clicks in the body jQuery('body').on('click', 'a', function() { // Do some logic // Condition met, do something drastic! if(conditionMet) { // Reload the page? // Open a submenu? // Submit a form? // ... you get the idea } });
Now we have a problem — the tab trigger click is listened to by something completely separate and now we’re in for trouble. Yikes. The best solution if you need to use trigger
is providing a custom event name along with the native event:
// Set up a click event with an additional custom event jQuery('.tabs a').on('click tabs-click', function() { // Switch to the tab, load some content, whatever }); // Trigger a fake click on the last one jQuery('.tabs a').last().trigger('tabs-click');
Now your event trigger won’t cause conflicts with other listeners on the page. The reserved developer in me says that you may want to avoid trigger
(and its other toolkit counterparts) all together, but adding a custom event name is the very least you should do!
Alternate: triggerHandler
If you’re using jQuery specifically, you could also use jQuery’s triggerHandler
method which triggers an event but only those registered through jQuery, and with the following caveats:
- The
.triggerHandler()
method does not cause the default behavior of an event to occur (such as a form submission). - While
.trigger()
will operate on all elements matched by the jQuery object,.triggerHandler()
only affects the first matched element. - Events created with
.triggerHandler()
do not bubble up the DOM hierarchy; if they are not handled by the target element directly, they do nothing. - Instead of returning the jQuery object (to allow chaining),
.triggerHandler()
returns whatever value was returned by the last handler it caused to be executed. If no handlers are triggered, it returnsundefined
The .triggerHandler()
method is jQuery’s way of preventing the problems that trigger
can create.