MDL-61138 javascript: stop duplicate custom events firing

This commit is contained in:
Ryan Wyllie 2018-03-21 15:04:55 +08:00
parent 6d4bc5bd34
commit 90d8c85ec3
2 changed files with 57 additions and 11 deletions

View File

@ -1 +1 @@
define(["jquery","core/key_codes"],function(a,b){var c={activate:"cie:activate",keyboardActivate:"cie:keyboardactivate",escape:"cie:escape",down:"cie:down",up:"cie:up",home:"cie:home",end:"cie:end",next:"cie:next",previous:"cie:previous",asterix:"cie:asterix",scrollLock:"cie:scrollLock",scrollTop:"cie:scrollTop",scrollBottom:"cie:scrollBottom",ctrlPageUp:"cie:ctrlPageUp",ctrlPageDown:"cie:ctrlPageDown",enter:"cie:enter"},d=function(a,b){return b=b||[],!(!b.length||b.indexOf(a)===-1)},e=function(a){return a.shiftKey||a.metaKey||a.altKey||a.ctrlKey},f=function(b,c,d){b.off("keydown."+c).on("keydown."+c,function(b){e(b)||b.keyCode==d&&a(b.target).trigger(c,[{originalEvent:b}])})},g=function(d){d.off("click.cie.activate").on("click.cie.activate",function(b){a(b.target).trigger(c.activate,[{originalEvent:b}])}),d.off("keydown.cie.activate").on("keydown.cie.activate",function(d){e(d)||d.keyCode!=b.enter&&d.keyCode!=b.space||a(d.target).trigger(c.activate,[{originalEvent:d}])})},h=function(d){d.off("keydown.cie.keyboardactivate").on("keydown.cie.keyboardactivate",function(d){e(d)||d.keyCode!=b.enter&&d.keyCode!=b.space||a(d.target).trigger(c.keyboardActivate,[{originalEvent:d}])})},i=function(a){f(a,c.escape,b.escape)},j=function(a){f(a,c.down,b.arrowDown)},k=function(a){f(a,c.up,b.arrowUp)},l=function(a){f(a,c.home,b.home)},m=function(a){f(a,c.end,b.end)},n=function(d){var e="rtl"==a("html").attr("dir")?b.arrowLeft:b.arrowRight;f(d,c.next,e)},o=function(d){var e="rtl"==a("html").attr("dir")?b.arrowRight:b.arrowLeft;f(d,c.previous,e)},p=function(a){f(a,c.asterix,b.asterix)},q=function(a){a.off("scroll.cie.scrollTop").on("scroll.cie.scrollTop",function(b){var d=a.scrollTop();0===d&&a.trigger(c.scrollTop,[{originalEvent:b}])})},r=function(a){a.off("scroll.cie.scrollBottom").on("scroll.cie.scrollBottom",function(b){var d=a.scrollTop(),e=a.innerHeight(),f=a[0].scrollHeight;d+e>=f&&a.trigger(c.scrollBottom,[{originalEvent:b}])})},s=function(a){a.off("DOMMouseScroll.cie.DOMMouseScrollLock mousewheel.cie.mousewheelLock").on("DOMMouseScroll.cie.DOMMouseScrollLock mousewheel.cie.mousewheelLock",function(b){var d=a.scrollTop(),e=a[0].scrollHeight,f=a.height(),g="DOMMouseScroll"==b.type?b.originalEvent.detail*-40:b.originalEvent.wheelDelta,h=g>0;return!h&&-g>e-f-d?(a.scrollTop(e),b.stopPropagation(),b.preventDefault(),b.returnValue=!1,a.trigger(c.scrollLock,[{originalEvent:b}]),!1):!(h&&g>d)||(a.scrollTop(0),b.stopPropagation(),b.preventDefault(),b.returnValue=!1,a.trigger(c.scrollLock,[{originalEvent:b}]),!1)})},t=function(d){d.off("keydown.cie.ctrlpageup").on("keydown.cie.ctrlpageup",function(d){d.ctrlKey&&d.keyCode==b.pageUp&&a(d.target).trigger(c.ctrlPageUp,[{originalEvent:d}])})},u=function(d){d.off("keydown.cie.ctrlpagedown").on("keydown.cie.ctrlpagedown",function(d){d.ctrlKey&&d.keyCode==b.pageDown&&a(d.target).trigger(c.ctrlPageDown,[{originalEvent:d}])})},v=function(a){f(a,c.enter,b.enter)},w=function(){var a={};return a[c.activate]=g,a[c.keyboardActivate]=h,a[c.escape]=i,a[c.down]=j,a[c.up]=k,a[c.home]=l,a[c.end]=m,a[c.next]=n,a[c.previous]=o,a[c.asterix]=p,a[c.scrollLock]=s,a[c.scrollTop]=q,a[c.scrollBottom]=r,a[c.ctrlPageUp]=t,a[c.ctrlPageDown]=u,a[c.enter]=v,a},x=function(b,c){b=a(b),c=c||[],b.length&&c.length&&a.each(w(),function(a,e){d(a,c)&&e(b)})};return{define:x,events:c}});
define(["jquery","core/key_codes"],function(a,b){var c={activate:"cie:activate",keyboardActivate:"cie:keyboardactivate",escape:"cie:escape",down:"cie:down",up:"cie:up",home:"cie:home",end:"cie:end",next:"cie:next",previous:"cie:previous",asterix:"cie:asterix",scrollLock:"cie:scrollLock",scrollTop:"cie:scrollTop",scrollBottom:"cie:scrollBottom",ctrlPageUp:"cie:ctrlPageUp",ctrlPageDown:"cie:ctrlPageDown",enter:"cie:enter"},d={},e=function(a,b){return b=b||[],!(!b.length||b.indexOf(a)===-1)},f=function(a){return a.shiftKey||a.metaKey||a.altKey||a.ctrlKey},g=function(b,c){var e="";return c.hasOwnProperty("originalEvent")?(e="triggeredCustom_"+b,c.originalEvent.hasOwnProperty(e)?void 0:(c.originalEvent[e]=!0,void a(c.target).trigger(b,[{originalEvent:c}]))):(e=""+b+c.type+c.timeStamp,void(d.hasOwnProperty(e)||(d[e]=!0,a(c.target).trigger(b,[{originalEvent:c}]))))},h=function(a,b,c){a.off("keydown."+b).on("keydown."+b,function(a){f(a)||a.keyCode==c&&g(b,a)})},i=function(a){a.off("click.cie.activate").on("click.cie.activate",function(a){g(c.activate,a)}),a.off("keydown.cie.activate").on("keydown.cie.activate",function(a){f(a)||a.keyCode!=b.enter&&a.keyCode!=b.space||g(c.activate,a)})},j=function(a){a.off("keydown.cie.keyboardactivate").on("keydown.cie.keyboardactivate",function(a){f(a)||a.keyCode!=b.enter&&a.keyCode!=b.space||g(c.keyboardActivate,a)})},k=function(a){h(a,c.escape,b.escape)},l=function(a){h(a,c.down,b.arrowDown)},m=function(a){h(a,c.up,b.arrowUp)},n=function(a){h(a,c.home,b.home)},o=function(a){h(a,c.end,b.end)},p=function(d){var e="rtl"==a("html").attr("dir")?b.arrowLeft:b.arrowRight;h(d,c.next,e)},q=function(d){var e="rtl"==a("html").attr("dir")?b.arrowRight:b.arrowLeft;h(d,c.previous,e)},r=function(a){h(a,c.asterix,b.asterix)},s=function(a){a.off("scroll.cie.scrollTop").on("scroll.cie.scrollTop",function(b){var d=a.scrollTop();0===d&&g(c.scrollTop,b)})},t=function(a){a.off("scroll.cie.scrollBottom").on("scroll.cie.scrollBottom",function(b){var d=a.scrollTop(),e=a.innerHeight(),f=a[0].scrollHeight;d+e>=f&&g(c.scrollBottom,b)})},u=function(a){a.off("DOMMouseScroll.cie.DOMMouseScrollLock mousewheel.cie.mousewheelLock").on("DOMMouseScroll.cie.DOMMouseScrollLock mousewheel.cie.mousewheelLock",function(b){var d=a.scrollTop(),e=a[0].scrollHeight,f=a.height(),h="DOMMouseScroll"==b.type?b.originalEvent.detail*-40:b.originalEvent.wheelDelta,i=h>0;return!i&&-h>e-f-d?(a.scrollTop(e),b.stopPropagation(),b.preventDefault(),b.returnValue=!1,g(c.scrollLock,b),!1):!(i&&h>d)||(a.scrollTop(0),b.stopPropagation(),b.preventDefault(),b.returnValue=!1,g(c.scrollLock,b),!1)})},v=function(a){a.off("keydown.cie.ctrlpageup").on("keydown.cie.ctrlpageup",function(a){a.ctrlKey&&a.keyCode==b.pageUp&&g(c.ctrlPageUp,a)})},w=function(a){a.off("keydown.cie.ctrlpagedown").on("keydown.cie.ctrlpagedown",function(a){a.ctrlKey&&a.keyCode==b.pageDown&&g(c.ctrlPageDown,a)})},x=function(a){h(a,c.enter,b.enter)},y=function(){var a={};return a[c.activate]=i,a[c.keyboardActivate]=j,a[c.escape]=k,a[c.down]=l,a[c.up]=m,a[c.home]=n,a[c.end]=o,a[c.next]=p,a[c.previous]=q,a[c.asterix]=r,a[c.scrollLock]=u,a[c.scrollTop]=s,a[c.scrollBottom]=t,a[c.ctrlPageUp]=v,a[c.ctrlPageDown]=w,a[c.enter]=x,a},z=function(b,c){b=a(b),c=c||[],b.length&&c.length&&a.each(y(),function(a,d){e(a,c)&&d(b)})};return{define:z,events:c}});

View File

@ -44,6 +44,10 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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
@ -77,6 +81,48 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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.
*
@ -90,7 +136,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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);
}
}
});
@ -106,12 +152,12 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
*/
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);
}
}
});
@ -129,7 +175,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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);
}
}
});
@ -250,7 +296,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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);
}
});
};
@ -270,7 +316,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
var scrollHeight = element[0].scrollHeight;
if (scrollTop + innerHeight >= scrollHeight) {
element.trigger(events.scrollBottom, [{originalEvent: e}]);
triggerEvent(events.scrollBottom, e);
}
});
};
@ -302,7 +348,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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) {
@ -312,7 +358,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
e.preventDefault();
e.returnValue = false;
// Fire the scroll lock event.
element.trigger(events.scrollLock, [{originalEvent: e}]);
triggerEvent(events.scrollLock, e);
return false;
}
@ -333,7 +379,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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);
}
}
});
@ -351,7 +397,7 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
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);
}
}
});