ctrlPageDown: 'cie:ctrlPageDown',
enter: 'cie:enter',
};
+ // Static cache of jQuery events that have been handled. This should
+ // only be populated by JavaScript generated events (which will keep it
+ // fairly small).
+ var triggeredEvents = {};
/**
* Check if the caller has asked for the given event type to be
return (e.shiftKey || e.metaKey || e.altKey || e.ctrlKey);
};
+ /**
+ * Trigger the custom event for the given jQuery event.
+ *
+ * This function will only fire the custom event if one hasn't already been
+ * fired for the jQuery event.
+ *
+ * This is to prevent multiple custom event handlers triggering multiple
+ * custom events for a single jQuery event as it bubbles up the stack.
+ *
+ * @param {string} eventName The name of the custom event
+ * @param {event} e The jQuery event
+ * @return {void}
+ */
+ var triggerEvent = function(eventName, e) {
+ var eventTypeKey = "";
+
+ if (!e.hasOwnProperty('originalEvent')) {
+ // This is a jQuery event generated from JavaScript not a browser event so
+ // we need to build the cache key for the event.
+ eventTypeKey = "" + eventName + e.type + e.timeStamp;
+
+ if (!triggeredEvents.hasOwnProperty(eventTypeKey)) {
+ // If we haven't seen this jQuery event before then fire a custom
+ // event for it and remember the event for later.
+ triggeredEvents[eventTypeKey] = true;
+ $(e.target).trigger(eventName, [{originalEvent: e}]);
+ }
+ return;
+ }
+
+ eventTypeKey = "triggeredCustom_" + eventName;
+ if (!e.originalEvent.hasOwnProperty(eventTypeKey)) {
+ // If this is a jQuery event generated by the browser then set a
+ // property on the original event to track that we've seen it before.
+ // The property is set on the original event because it's the only part
+ // of the jQuery event that is maintained through multiple event handlers.
+ e.originalEvent[eventTypeKey] = true;
+ $(e.target).trigger(eventName, [{originalEvent: e}]);
+ return;
+ }
+ };
+
/**
* Register a keyboard event that ignores modifier keys.
*
element.off('keydown.' + event).on('keydown.' + event, function(e) {
if (!isModifierPressed(e)) {
if (e.keyCode == keyCode) {
- $(e.target).trigger(event, [{originalEvent: e}]);
+ triggerEvent(event, e);
}
}
});
*/
var addActivateListener = function(element) {
element.off('click.cie.activate').on('click.cie.activate', function(e) {
- $(e.target).trigger(events.activate, [{originalEvent: e}]);
+ triggerEvent(events.activate, e);
});
element.off('keydown.cie.activate').on('keydown.cie.activate', function(e) {
if (!isModifierPressed(e)) {
if (e.keyCode == keyCodes.enter || e.keyCode == keyCodes.space) {
- $(e.target).trigger(events.activate, [{originalEvent: e}]);
+ triggerEvent(events.activate, e);
}
}
});
element.off('keydown.cie.keyboardactivate').on('keydown.cie.keyboardactivate', function(e) {
if (!isModifierPressed(e)) {
if (e.keyCode == keyCodes.enter || e.keyCode == keyCodes.space) {
- $(e.target).trigger(events.keyboardActivate, [{originalEvent: e}]);
+ triggerEvent(events.keyboardActivate, e);
}
}
});
element.off('scroll.cie.scrollTop').on('scroll.cie.scrollTop', function(e) {
var scrollTop = element.scrollTop();
if (scrollTop === 0) {
- element.trigger(events.scrollTop, [{originalEvent: e}]);
+ triggerEvent(events.scrollTop, e);
}
});
};
var scrollHeight = element[0].scrollHeight;
if (scrollTop + innerHeight >= scrollHeight) {
- element.trigger(events.scrollBottom, [{originalEvent: e}]);
+ triggerEvent(events.scrollBottom, e);
}
});
};
e.preventDefault();
e.returnValue = false;
// Fire the scroll lock event.
- element.trigger(events.scrollLock, [{originalEvent: e}]);
+ triggerEvent(events.scrollLock, e);
return false;
} else if (up && delta > scrollTop) {
e.preventDefault();
e.returnValue = false;
// Fire the scroll lock event.
- element.trigger(events.scrollLock, [{originalEvent: e}]);
+ triggerEvent(events.scrollLock, e);
return false;
}
element.off('keydown.cie.ctrlpageup').on('keydown.cie.ctrlpageup', function(e) {
if (e.ctrlKey) {
if (e.keyCode == keyCodes.pageUp) {
- $(e.target).trigger(events.ctrlPageUp, [{originalEvent: e}]);
+ triggerEvent(events.ctrlPageUp, e);
}
}
});
element.off('keydown.cie.ctrlpagedown').on('keydown.cie.ctrlpagedown', function(e) {
if (e.ctrlKey) {
if (e.keyCode == keyCodes.pageDown) {
- $(e.target).trigger(events.ctrlPageDown, [{originalEvent: e}]);
+ triggerEvent(events.ctrlPageDown, e);
}
}
});