Reputation: 4531
I have a list of event names which I need to listen to stored in an array, like so:
var events = ['A', 'B'];
Now, I'm unsure which event will be triggered first and it could be very inconsistent (depends on the HTTP requests that they await) so I can never safely listen to only one of them. So, I need to somehow "cross-listen" to all of them in order to trigger my original callback.
So my idea was to do the following:
So this would result in 4 listners, which would look something like this (pseudo-code):
var callback = function() { console.log('The callback'); };
Event.on('A', function () {
Event.on('B', callback);
});
Event.on('B', function () {
Event.on('A', callback);
});
So I believe this would solve my issue (there's probably another problem that I'm not seeing here though).
The issue is, I can make this work when there are only 2 events I need to listen to. But what about when I have 3-4 events I want to "cross-listen" to? Lets say we have ['A', 'B', 'C', 'D']
. This would obviously require looping through the events. This part is what's confusing me and I'm not sure how to proceed. This would need to register a nice combination of events.
This needs to be done in JavaScript.
My imagination and logic is limited in this case.
Upvotes: 1
Views: 641
Reputation: 579
A bit late, but you can make a function that wraps your callback and reuse it to attach multiple eventlisteners and count until all have occurred. This way you can also add events to cancel out others, say keyup cancels keydown.
const K = a => _b => a
const makeEventTrigger = (fn) => {
let lastTarget,
required = 0,
active = 0;
return (enable, qualifier = K(true)) => {
required = enable ? required + 1 : required;
return (event) => {
if(!qualifier(event)) {
return
}
const isLastTarget =
lastTarget && lastTarget.isEqualNode(event.currentTarget);
if (!enable) {
lastTarget = isLastTarget ? null : lastTarget;
active = Math.max(0, active - 1);
return;
}
if (!isLastTarget) {
lastTarget = event.currentTarget;
active = Math.min(required, active + 1);
return active === required && fn();
}
};
};
};
let changeTitleCol = () =>
(document.querySelector("h1").style.color =
"#" + Math.random().toString(16).slice(-6));
let addTriggerForColorChange = makeEventTrigger(changeTitleCol);
let isSpace = e => e.key === " " || e.code === "Space"
document
.querySelector("button")
.addEventListener("mousedown", addTriggerForColorChange(true));
document
.querySelector("button")
.addEventListener("mouseup", addTriggerForColorChange(false));
document.addEventListener("keydown", addTriggerForColorChange(true, isSpace));
document.addEventListener("keyup", addTriggerForColorChange(false));
<h1>Multiple Event sources!</h1>
<div>
<button id="trigger-A">klik me and press space</button>
</div>
Upvotes: 0
Reputation: 8423
I was thinking something like this:
var callback = function() { console.log('The callback'); };
var events = {
'click': false,
'mouseover': false,
'mouseout': false
};
for(prop in events) {
$('.evt-button').on(prop, function(evt) {
if(events[evt.type] === false) {
console.log('First ' + evt.type + ' event');
events[evt.type] = true;
checkAll();
}
});
}
function checkAll() {
var anyFalse = false;
for(prop in events) {
if(events.hasOwnProperty(prop)) {
if(events[prop] === false) {
anyFalse = true;
break;
}
}
}
if(!anyFalse) {
callback();
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button class="evt-button">The button</button>
Upvotes: 1
Reputation: 26143
There's lots of ways to do what you're asking, but to keep it simple you could have an array of event names, as you already do, and simply remove them as they occur, checking to see if the array is empty each time. Like this...
var events = ['A', 'B'];
var callback = function() { console.log('The callback'); };
var eventOccured = function(eventName) {
// if the event name is in the array, remove it...
var idx = events.indexOf(eventName);
if (idx !== -1) {
events.splice(events.indexOf(idx), 1);
}
// if the event array is empty then we've handled everything...
calback();
};
Event.on('A', function () {
// do whatever you need in the event handler
eventOccured("A");
});
Event.on('B', function () {
// do whatever you need in the event handler
eventOccured("B");
});
Upvotes: 0