Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function addSimultaneousEventListeners(eventNames, callback, options) {
- const defaultOptions = {
- inOrder: true, // the events should be fired in the order specified in eventNames array or not
- tolerance: 500, // the tolerance time between the first and the last event in milliseconds,
- // you can rarely fire two events at the exact moment
- }
- // merge default options with user options
- const mergedOptions = {
- ...defaultOptions,
- ...options
- };
- const inOrder = mergedOptions.inOrder;
- const tolerance = mergedOptions.tolerance;
- eventNames = Object.freeze(eventNames); // make array immutable
- let eventList = [];
- eventNames.forEach((eventName) => {
- document.addEventListener(eventName, listener);
- })
- function listener(e) {
- eventList.push(e);
- // trim eventList size
- if (eventList.length > eventNames.length) {
- eventList = eventList.slice(eventList.length - eventNames.length);
- }
- // console.log("eventList: " + eventList.reduce((string, event) => {
- // return string + event.type + "@" + Math.round(event.timeStamp) + ", ";
- // }, ""));
- const eventStack = eventNames.slice(); // copy array
- if (eventList.length === eventNames.length) {
- const firstEvent = eventList[0];
- for (let i = 0; i < eventList.length; i++) {
- const currentEvent = eventList[i];
- let currentEventName;
- if (inOrder) {
- currentEventName = eventNames[i];
- } else {
- const eventIndex = eventStack.indexOf(currentEvent.type);
- if (eventIndex >= 0) {
- currentEventName = currentEvent.type;
- eventStack.splice(eventIndex, 1);
- } else {
- return; // not the right events fired
- }
- }
- if (currentEvent.type !== currentEventName || !approximatelyEqual(firstEvent.timeStamp, currentEvent.timeStamp)) {
- return; // not the right event type or both events are NOT fired at the same time
- }
- }
- // eventList will be in order when inOrder is true
- // otherwise it will be the order the user fired them
- // you should always test for event types
- callback(eventList);
- }
- }
- // test if a and b are equal within the tolerance range
- function approximatelyEqual(a, b) {
- return (Math.abs(a - b) <= tolerance);
- }
- }
- // Demo: detect keydown, click, and contextmenu fire at about the same time in that order
- addSimultaneousEventListeners(["keydown", "click", "contextmenu"], // events registered
- (eventList) => { // listener
- console.log("you pressed a key, left clicked, and right clicked the document!");
- console.log("eventList: ", eventList);
- },
- { // options
- inOrder: true
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement