D.R. D.R. - 1 month ago 7
jQuery Question

Trigger event only if not prevented by any handler?

I currently have a JavaScript component which triggers a DOM event using JQuery like so:

$(document).trigger('myevent', mydata);


Other components register an event handler and update themselves accordingly when receiving the event.

Now, I want to extend this functionality in such a way, that any of the registered components should have the chance to prevent those updates (i.e., reject the event).

I thought of having two events instead:

$(document).trigger('myevent-before', mydata);
if( ??? )
$(document).trigger('myevent', mydata);


Components which like to reject the update would register for the
myevent-before
and return some kind of information in order to prevent the triggering side from triggering the actual
myevent
.

Is this the way to go?


  • If yes, how to formulate the if clause? Does
    trigger()
    return some indicator if any of the called event handlers returned false?

  • If no, what's the way to do such a thing in JavaScript?






Example 1:


  1. Main Component: Hey, does anyone have a problem with an upcoming update?

  2. Component A: No.

  3. Component B: No.

  4. Main Component: OK, then I'll trigger the actual update!



Example 2:


  1. Main Component: Hey, does anyone have a problem with an upcoming update?

  2. Component A: No.

  3. Component B: Yes.

  4. Main Component: Oh, ok, no update it is.



(note that there might be more than 2 components registered of course)

Answer

It is possible to do this with plain Javascript. Not sure if it's possible with jQuery as well.

var input = document.getElementById( 'input' );
var makered = document.getElementById( 'makered' );

makered.addEventListener( 'click', function( e ) {
  var beforeMakeRedEvent = new Event( 'before-make-red', { cancelable: true } );
  input.dispatchEvent( beforeMakeRedEvent );
  if( beforeMakeRedEvent.defaultPrevented ) {
    console.log( 'Sorry, unable to make it red!' );
  }
  else {
    console.log( 'Making it red! Yeeehaawww!' );
  }
} );

input.addEventListener( 'before-make-red', function( e) {
  if( this.value == 1 ) {
    e.preventDefault();  
  }
} );
<input id="input" value="5">
<button id="makered">Make red</button>

Here's the above example translated to jQuery:

$( '#makered' ).on( 'click', function( e ) {
  var beforeMakeRedEvent = jQuery.Event( 'before-make-red' );
  $( '#input' ).trigger( beforeMakeRedEvent );
  if( beforeMakeRedEvent.isDefaultPrevented() ) {
    console.log( 'Sorry, unable to make it red!' );
  }
  else {
    console.log( 'Making it red! Yeeehaawww!' );
  }
} );

$( '#input' ).on( 'before-make-red', function( e ) {
  if( this.value == 1 ) {
    e.preventDefault();
  }
} );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input id="input" value="5">
<button id="makered">Make red</button>