Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery ".triggerHandler()" vs. ".trigger()" when multiple elements are selected

The jQuery ".triggerHandler()" mechanism, unlike ".trigger()", only operates on the first element referenced by the jQuery object for which it's called. In other words,

$('.all-over-the-page').triggerHandler("readjust");

will only call the "readjust" handler for the first element with class "all-over-the-page", even if there are many elements on the page with that class. The ".trigger()" method, on the other hand, would affect all of them.

I realize that I can use ".each()" to get around this (or simply write my own substitute that does that for me), but is there some rationale for why the two are different in this respect? It kind-of makes no sense to me. (I understand of course that it almost certainly can't be changed now.)

edit to clarify:

It's probably easier to understand why I'm scratching my head over this if I provide a context in the style of code I've actually got. When I put together code for various "widget" features on a page, that often involves event handlers. A good example is a form of some sort that's got some fields whose relevance is controlled by a checkbox, or radio button, or selector. A common instance of that is the "Shipping Address" checkbox that shows up on a zillion e-commerce sites: if the checkbox is checked, the shipping address is disabled and the billing address is used.

Now consider that some other code may, for its own reasons that are totally independent of the checkbox-control widget, actually do things to the form that may include updating checkbox settings programmatically. In that case, that other widget code may want to use "triggerHandler()" to tell any widgets, "hey I've updated some stuff, so you might want to re-check the current status and adjust if necessary."

Thus, if ".triggerHandler()" would operate on all selected elements, I could use:

 $theForm.find('input, select, textarea').triggerHandler('change');

and all those handlers could run and do whatever they need. As I said, it's easy enough to write:

 $theForm.find('input, select, textarea').each(function() {
   $(this).triggerHandler('change');
 });
like image 900
Pointy Avatar asked Sep 23 '11 14:09

Pointy


1 Answers

"...is there some rationale for why the two are different in this respect?"

I think the idea is that triggerHandler() is meant to be a way of invoking the function you as a handler as though it was any other function.

As such, they made triggerHandler() so that the function is only invoked once, it returns the actual return value of the function, and it doesn't affect the DOM with bubbling or default behaviors.

Of course the function may break if they changed the this value to something other than a DOM element, so they just use the first element matched.

If you're wanting to simply use your function, then I'd probably just keep a reference to it and invoke it directly, or as the argument to .each().

$('.element').each( handler_func );

...as long as you don't need the event object.


EDIT: Or if you want the values returned from the invocation, use .map() instead:

var return_values = $('.element').map( handler_func );

EDIT: With respect to the example provided in the updated question, a good solution may be to take advantage of the extraParameters capability of the trigger()[docs] method so that you can tell the handler to preventDefault() and stopPropagation().

$('.elememts').bind( 'click', function( e, was_code_triggered ) {

    if( was_code_triggered ) {
        e.preventDefault();
        e.stopPropagation();
    }
    // your code
});


// ...


$('.elememts').trigger( 'click', true ); // pass "true" to let handler know
                                         //    it wasn't a DOM event

From the .trigger() docs:

"Note the difference between the extra parameters we're passing here and the eventData parameter to the .bind() method. Both are mechanisms for passing information to an event handler, but the extraParameters argument to .trigger() allows information to be determined at the time the event is triggered, while the eventData argument to .bind() requires the information to be already computed at the time the handler is bound."

like image 130
user113716 Avatar answered Oct 16 '22 03:10

user113716