2

I'm looking for a way to achieve the following. I could build some mechanism to do this, I'm asking for something built-in or a really simple way, if it exists and I'm missing it.

Edit: Please note that I'm talking about events in random objects, not in DOM elements. The events order cannot be managed using the parent, etc. as suggested in the possible duplicate.

Edit 2: Maybe an after-all-handlers-have-been-called callback? Or an always-last-to-be-executed handler?

Given:

var someObject={};
$(someObject).on("event",function() { console.log('Default handler'); });
...
$(someObject).on("event",function() { console.log('Other handler'); });

When doing:

$(someObject).triggerHandler("event");

The output is:

Default handler
Other handler

We all know this. The problem is: What if I would want to make the first event the "default" handler, to be executed if there aren't other event handlers (not a problem there) or if the other handlers didn't stop the event propagation (here is the problem).

I'm looking for a way to be able to do something like:

$(someObject).on("event",function(ev) { ev.preventDefault(); });

and prevent the first event handler from executing. In this example is not working given the execution order. Reversing the execution order is not the correct way to do it.

TL;DR

Is it possible to set a default handler, one to be called in case there's no other handlers and the event hasn't been canceled?

Edit 3: To give you a better idea, the current approach is the following (names are made up for this example):

var eventCanceled=false;
function doTheEvent() {
    $(someObject).triggerHandler("event");
    if(!eventCanceled) defaultEventHandler();
}
//To be called inside the handlers to stop the default handler
function cancelTheEvent() {
    eventCanceled=true;
}

I just want to get rid of this and be able to use triggerHandler directly.

Gabriel
  • 2,170
  • 1
  • 17
  • 20
  • Possible duplicate of [Priority when more than one event handler is bound to an element](http://stackoverflow.com/questions/8779657/priority-when-more-than-one-event-handler-is-bound-to-an-element) – Alon Eitan May 29 '16 at 18:17
  • Not exactly, note that I'm talking about random objects, not DOM elements. – Gabriel May 29 '16 at 18:19
  • Instead of having two same-named event-names `"event"` `"event"` have you thought about changing to `"default"` and `"event"` – Roko C. Buljan May 29 '16 at 18:30
  • Is unknow how many events handlers there will be. In that case the last one should call `triggerHandler("default")`... but each handler won't know if it's the last or not. – Gabriel May 29 '16 at 18:35

4 Answers4

1

Hope this is what you are looking for. This is called observer pattern.

var someObj = {};
someObj.eventCallbackList = {};
someObj.createEventObject = function(name) {
  return {
    type: name,
    preventDefault: function() {
      this.callDefault = false;
    },
    callDefault: true
  }
}
someObj.on = function(eventName, callback, defaultFlag) {
  if (!this.eventCallbackList[eventName]) {
    // there can be multiple other handlers
    this.eventCallbackList[eventName] = {
      other: [],
      default: null
    };
  }

  if (defaultFlag) {
    this.eventCallbackList[eventName]['default'] = callback;
  } else {
    this.eventCallbackList[eventName]['other'].push(callback);

  }
}

someObj.triggerHandler = function(eventName) {
  var event = this.createEventObject(eventName);
  var callbacks = this.eventCallbackList[eventName];

  if (callbacks) {
    if (callbacks['other']) {
      for (var i = 0; i < callbacks['other'].length; i++) {
        callbacks['other'][i](event);
      }
    }

    if (event.callDefault && callbacks['default']) {
      callbacks['default'](event);

    }
  }


}




// Test 

someObj.on('myCustomEvent', function(event) {
  console.log('OtherHandler');
  event.preventDefault();
});

someObj.on('myCustomEvent', function(event) {
  console.log('default');
}, true);

$(document).on('click', function() {
  someObj.triggerHandler('myCustomEvent');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
rishabh dev
  • 1,711
  • 1
  • 15
  • 26
  • Although you're not using jQuery's methods, it's a really good option, thank you. – Gabriel May 29 '16 at 19:57
  • There is no way you can use jquery here. jquery does not provide event handling on objects. They are only for dom. – rishabh dev May 29 '16 at 19:59
  • jQuery does provide event handling on objects. But it's not the point, I was not complaining it was just a comment, good work, thank you. – Gabriel May 29 '16 at 20:02
  • Do you have any reference where I can read more about it @Gabriel. Thanks. – rishabh dev May 29 '16 at 20:04
  • They work just like any other events, with `on()` and `triggerHandler()`. You can find plenty of info at this forums or at jquery.com. – Gabriel May 30 '16 at 02:40
0

you can add a parameter to set what codes you want to execute inside your triggerHandler function.

you can refer to this thread in adding parameter. jQuery: receive extraParameters from triggerHandler()

Community
  • 1
  • 1
Jeric Cruz
  • 1,899
  • 1
  • 14
  • 29
0

While there is a way to detect if the preventDefault() was called, there is no such thing as a "default handler". Event handlers are executed in the order they are registered. So the first one registered is the first one executed.

If your "default handler" doesn't need to be executed synchronously, you could delay the "default handler" to be executed after all the other handlers are done and in any of the other handlers revert that if necessary:

var defaultHandlerTimeout;
$element.on('event', function() {
  defaultHandlerTimeout = setTimeout(function() {
    // your actual handler
  });
});

$element.on('event', function() {
  // prevent the "default handler" from being executed
  clearTimeout(defaultHandlerTimeout);
});
rodneyrehm
  • 13,442
  • 1
  • 40
  • 56
0

jQuery does store all of it's events internally and you can access specific element events using $._data(elem,'events').

Whether this will help your situation or not I'm not sure but is worth digging into. Personally i've never found the need to use it.

See https://stackoverflow.com/a/2518441/1175966

Community
  • 1
  • 1
charlietfl
  • 170,828
  • 13
  • 121
  • 150