When doing $(element).on('customevent',function(){});, every element that binds the customevent will also trigger. This works roughly as a Pub/Sub, and it appears that there is no order or priority. What I want to do is, to implement my own callback queue, but, with ajustable priority (like what Wordpress has, you can set the hooks priorities). So a higher number have a bigger priority, and a number 0 will be a common and executed last.
Given the example $(element).on_priority(10, 'customevent', function(){}); and $(element).on_priority(0, 'customevent', function(){});, the 10 priority will execute the same customevent first, and might or not cancel the execution of the 0 priority event.
How can I implement that? I'm having trouble trying to visualize the flow of the callbacks
So far, I thought like this:
var callbacks = {
'customevent': {},
'customevent2': {
0: [{element: $element, fn: function(), data:{}}, {element: $element, fn: function(), data:{}}],
10: [{element: $element, fn: function(), data:{}}],
20: [{element: $element, fn: function(), data:{}}]
}
};
Is the right direction? Performance wise it shouldn't be much of a hit, the problem is iterating the object over and over. The problem with this is that I wouldn't be able to unregister a previously set event or set the order (or even reorder) the callback array inside each priority
I'd just suggest an array of callback objects that you could encapsulate in its own object. The object has methods for add, remove and execute. Add, adds a given callback in priority order. Remove finds a callback and removes it. Execute calls each callback in priority order, but stopping further execution of callbacks if any callback returns false.
Traversing the callbacks in priority order is simple (you just go from begin to end of the array) because the callbacks are kept in sorted order in the array.
function sortedCallbacks() {
this.list = [];
}
sortedCallbacks.prototype = {
// add callback to the list
add: function(fn, priority, data) {
var list = this.list;
var callbackObj = {fn: fn, priority: priority, data: data};
for (var i = 0; i < list.length; i++) {
// if our new priority is greater, then insert it here
if (priority > list[i].priority) {
list.splice(i, 0, callbackObj);
return;
}
}
// if the list was either empty or no priorities in the list were less than
// the new priority, then just add this onto the end of the list
list.push(callbackObj);
},
// remove callback from the list
remove: function(fn, priority) {
var list = this.list;
for (var i = 0; i < list.length; i++) {
if (list[i].fn === fn && list[i].priority === priority) {
list.splice(i, 1);
return;
}
}
},
// change priority or data or both
change: function(fn, oldPriority, newPriority, data) {
this.remove(fn, oldPriority);
this.add(fn, newPriority, data);
}
// execute callbacks in order
execute: function(/* args for callback passed here */) {
// execute in priority order
var list = this.list, retVal, args;
for (var i = 0; i < list.length; i++) {
args = [].slice.call(arguments, 0);
// add the data for this callback to any arguments that were passed to execute
args.unshift(list[i].data);
retVal = list[i].fn.apply(this, args);
// if callback returns false, then stop further callback execution
if (retVal === false) {
return;
}
}
}
};
Sample usage:
// create callbacks object and add some callbacks to it
var callbacks = new sortedCallbacks();
callbacks.add(fn1, 4, "whatever");
callbacks.add(fn2, 9, "hello");
callbacks.add(fn8, -1, "nothing");
// execute the callbacks and pass them each a value
callbacks.execute(elem.value)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With