trigger vs triggerHandler in jQuery

It's never nice to see bugs crop up because libraries and browsers aren't interacting as expected. In this case jQuery can cause a bit of funk with newer versions of Chrome.

  • Last updated: 23 Apr 2014
  • Est. Read Time: 2 mins
  • Tagged: #jquery, #sideeffects

Here’s a Chrome bug that flags some code on change.org that’s stopped working in newer versions of Chrome. The TL;DR is that using jQuery’s trigger instead of triggerHandler can cause problems when a browser provides a function with the same name as the event.

The jQuery docs explain it (emphasis added by yours truly):

Note: For both plain objects and DOM objects other than window, if a triggered event name matches the name of a property on the object, jQuery will attempt to invoke the property as a method if no event handler calls event.preventDefault(). If this behavior is not desired, use .triggerHandler() instead.

I think it’s pretty easy to get this wrong, because the jQuery API isn’t clear on the distinction between trigger and triggerHandler through its function naming, and because – at least in my view – it does something unexpected in trigger by calling functions on objects. It overreaches from jQuery events and into actual host-provided functions. I’m told it’s down to perennial favourites submit and click, which have jQuery events and equivalent browser functions of the same name.

If you’re curious, this is the offending code:

// This will break in newer versions of Chrome.
$(element).trigger('animate');

jQuery fires its own event handlers for animate but then it also calls the browser’s animate function on HTMLElement as well.

Before Web Animations started shipping, trying to call an animate function on elements would’ve been just fine here (because no animate function actually existed), but now we have one there’s a problem. The animate function from Web Animations expects a parameter containing properties to animate, a parameter which jQuery doesn’t provide. Oops.

Incidentally, the same would happen if you called:

$(element).trigger('appendChild');

You actually want triggerHandler, which is just like trigger but without the “call the browser’s function” bit.

Read The Manual, Probably…

It may seem obvious once you understand jQuery’s distinction, but the combination of jQuery’s function naming and assumption that properties are functions to call is something of a footgun.

At least there’s an safety catch via triggerHandler; just be sure to use it!