mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-70075 core: Listen for change
in accessibleChange event
The accessibleChange custom interaction event was only listening for blur and focus, however some OS/browser combinations do not emit these events until the element is explicitly blurred. This is notably different on Firefox on some Operating Systems. Recent changes in MDL-68167 explicitly moved the user participants page filter module to use the accessibleChange event, which means that the selections are now only triggered on an explicit blur when using Firefox. This highlight a bug whereby, when the mouse is used to make a selection, the event is not triggered until the element is blurred. This change modifies the accessibleChange event to ignore the `change` event where it was triggered by the keyboard and where that keybaord event was not a [return] or [escape] keypress, but to otherwise respect the native change event.
This commit is contained in:
parent
3caa6bfbe1
commit
189a4c8f8e
@ -1,2 +1,2 @@
|
||||
define ("core/custom_interaction_events",["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",accessibleChange:"cie:accessibleChange"},d={},e=function(a,b){b=b||[];if(b.length&&-1!==b.indexOf(a)){return!0}return!1},f=function(a){return a.shiftKey||a.metaKey||a.altKey||a.ctrlKey},g=function(b,c){var e="";if(!c.hasOwnProperty("originalEvent")){e=""+b+c.type+c.timeStamp;if(!d.hasOwnProperty(e)){d[e]=!0;a(c.target).trigger(b,[{originalEvent:c}])}return}e="triggeredCustom_"+b;if(!c.originalEvent.hasOwnProperty(e)){c.originalEvent[e]=!0;a(c.target).trigger(b,[{originalEvent:c}])}},h=function(a,b,c){a.off("keydown."+b).on("keydown."+b,function(a){if(!f(a)){if(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){if(!f(a)){if(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){if(!f(a)){if(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();if(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;if(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?-40*b.originalEvent.detail:b.originalEvent.wheelDelta,i=0<h;if(!i&&-h>e-f-d){a.scrollTop(e);b.stopPropagation();b.preventDefault();b.returnValue=!1;g(c.scrollLock,b);return!1}else if(i&&h>d){a.scrollTop(0);b.stopPropagation();b.preventDefault();b.returnValue=!1;g(c.scrollLock,b);return!1}return!0})},v=function(a){a.off("keydown.cie.ctrlpageup").on("keydown.cie.ctrlpageup",function(a){if(a.ctrlKey){if(a.keyCode==b.pageUp){g(c.ctrlPageUp,a)}}})},w=function(a){a.off("keydown.cie.ctrlpagedown").on("keydown.cie.ctrlpagedown",function(a){if(a.ctrlKey){if(a.keyCode==b.pageDown){g(c.ctrlPageDown,a)}}})},x=function(a){h(a,c.enter,b.enter)},y=function(d){var e=-1!==navigator.userAgent.indexOf("Macintosh"),f="ontouchstart"in window||"msMaxTouchPoints"in navigator&&0<navigator.msMaxTouchPoints;if(e||f){d.on("change",function(a){g(c.accessibleChange,a)})}else{var h=d.get()[0];h.addEventListener("focus",function(b){a(b.target).data("initValue",b.target.value)},!0);h.addEventListener("blur",function(b){var d=a(b.target).data("initValue");a(b.target).removeData("initValue");if(b.target.value!==d){g(c.accessibleChange,b)}},!0);d.on("keydown",function(d){if(d.which===b.enter&&d.target.value!==a(d.target).data("initValue")){g(c.accessibleChange,d)}else if(d.which===b.escape){d.target.value=a(d.target).data("initValue")}});d.on("click",function(b){var d=a(b.target).data("initValue");if("undefined"!=typeof d&&d!=b.target.value){g(c.accessibleChange,b)}})}},z=function(){var a={};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[c.accessibleChange]=y;return a};return{define:function define(b,c){b=a(b);c=c||[];if(!b.length||!c.length){return}a.each(z(),function(a,d){if(e(a,c)){d(b)}})},events:c}});
|
||||
define ("core/custom_interaction_events",["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",accessibleChange:"cie:accessibleChange"},d={},e=function(a,b){b=b||[];if(b.length&&-1!==b.indexOf(a)){return!0}return!1},f=function(a){return a.shiftKey||a.metaKey||a.altKey||a.ctrlKey},g=function(b,c){var e="";if(!c.hasOwnProperty("originalEvent")){e=""+b+c.type+c.timeStamp;if(!d.hasOwnProperty(e)){d[e]=!0;a(c.target).trigger(b,[{originalEvent:c}])}return}e="triggeredCustom_"+b;if(!c.originalEvent.hasOwnProperty(e)){c.originalEvent[e]=!0;a(c.target).trigger(b,[{originalEvent:c}])}},h=function(a,b,c){a.off("keydown."+b).on("keydown."+b,function(a){if(!f(a)){if(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){if(!f(a)){if(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){if(!f(a)){if(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();if(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;if(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?-40*b.originalEvent.detail:b.originalEvent.wheelDelta,i=0<h;if(!i&&-h>e-f-d){a.scrollTop(e);b.stopPropagation();b.preventDefault();b.returnValue=!1;g(c.scrollLock,b);return!1}else if(i&&h>d){a.scrollTop(0);b.stopPropagation();b.preventDefault();b.returnValue=!1;g(c.scrollLock,b);return!1}return!0})},v=function(a){a.off("keydown.cie.ctrlpageup").on("keydown.cie.ctrlpageup",function(a){if(a.ctrlKey){if(a.keyCode==b.pageUp){g(c.ctrlPageUp,a)}}})},w=function(a){a.off("keydown.cie.ctrlpagedown").on("keydown.cie.ctrlpagedown",function(a){if(a.ctrlKey){if(a.keyCode==b.pageDown){g(c.ctrlPageDown,a)}}})},x=function(a){h(a,c.enter,b.enter)},y=function(a){var d=-1!==navigator.userAgent.indexOf("Macintosh"),e="ontouchstart"in window||"msMaxTouchPoints"in navigator&&0<navigator.msMaxTouchPoints;if(d||e){a.on("change",function(a){g(c.accessibleChange,a)})}else{var f=function(a){a.dataset.initValue=a.value},h=function(a){if("initValue"in a.dataset){a.value=a.dataset.initValue}},i=function(a){if(!("initValue"in a.target.dataset)){return}if(a.target.value!==a.target.dataset.initValue){a.target.dataset.initValue=a.target.value;g(c.accessibleChange,a)}},j=a.get()[0];j.addEventListener("focus",function(a){f(a.target)},!0);j.addEventListener("blur",function(a){i(a)},!0);a.on("keydown",function(a){if(a.which===b.enter){i(a)}else if(a.which===b.escape){h(a.target);a.target.dataset.ignoreChange=!0}else{a.target.dataset.ignoreChange=!0}});a.on("change",function(a){if(a.target.dataset.ignoreChange){return}i(a)});a.on("keyup",function(a){delete a.target.dataset.ignoreChange});a.on("click",function(a){i(a)})}},z=function(){var a={};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[c.accessibleChange]=y;return a};return{define:function define(b,c){b=a(b);c=c||[];if(!b.length||!c.length){return}a.each(z(),function(a,d){if(e(a,c)){d(b)}})},events:c}});
|
||||
//# sourceMappingURL=custom_interaction_events.min.js.map
|
||||
|
File diff suppressed because one or more lines are too long
@ -427,35 +427,95 @@ define(['jquery', 'core/key_codes'], function($, keyCodes) {
|
||||
var onMac = navigator.userAgent.indexOf('Macintosh') !== -1;
|
||||
var touchEnabled = ('ontouchstart' in window) || (('msMaxTouchPoints' in navigator) && (navigator.msMaxTouchPoints > 0));
|
||||
if (onMac || touchEnabled) {
|
||||
// On Mac devices, and touch-enabled devices, the change event seems to be handled correctly and
|
||||
// consistently at this time.
|
||||
element.on('change', function(e) {
|
||||
triggerEvent(events.accessibleChange, e);
|
||||
});
|
||||
} else {
|
||||
// Some browsers have non-normalised behaviour for handling the selection of values in a <select> element.
|
||||
// When using Chrome on Linux (and possibly others), a 'change' event is fired when pressing the Escape key.
|
||||
// When using Firefox on Linux (and possibly others), a 'change' event is fired when navigating through the
|
||||
// list with a keyboard.
|
||||
//
|
||||
// To normalise these behaviours:
|
||||
// - the initial value is stored in a data attribute when focusing the element
|
||||
// - the current value is checked against the stored initial value when and the accessibleChange event fired when:
|
||||
// --- blurring the element
|
||||
// --- the 'Enter' key is pressed
|
||||
// --- the element is clicked
|
||||
// --- the 'change' event is fired, except where it is from a keyboard interaction
|
||||
//
|
||||
// To facilitate the change event keyboard interaction check, the 'keyDown' handler sets a flag to ignore
|
||||
// the change event handler which is unset on the 'keyUp' event.
|
||||
//
|
||||
// Unfortunately we cannot control this entirely as some browsers (Chrome) trigger a change event when
|
||||
// pressign the Escape key, and this is considered to be the correct behaviour.
|
||||
// Chrome https://bugs.chromium.org/p/chromium/issues/detail?id=839717
|
||||
//
|
||||
// Our longer-term solution to this should be to switch away from using <select> boxes as a single-select,
|
||||
// and make use of a dropdown of action links like the Bootstrap Dropdown menu.
|
||||
var setInitialValue = function(target) {
|
||||
target.dataset.initValue = target.value;
|
||||
};
|
||||
var resetToInitialValue = function(target) {
|
||||
if ('initValue' in target.dataset) {
|
||||
target.value = target.dataset.initValue;
|
||||
}
|
||||
};
|
||||
var checkAndTriggerAccessibleChange = function(e) {
|
||||
if (!('initValue' in e.target.dataset)) {
|
||||
// Some browsers trigger click before focus, therefore it is possible that initValue is undefined.
|
||||
// In this case it's likely that it's being focused for the first time and we should therefore not submit.
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.target.value !== e.target.dataset.initValue) {
|
||||
// Update the initValue when the event is triggered.
|
||||
// This means that if the click handler fires before the focus handler on a subsequent interaction
|
||||
// with the element, the currently dispalyed value will be the best guess current value.
|
||||
e.target.dataset.initValue = e.target.value;
|
||||
triggerEvent(events.accessibleChange, e);
|
||||
}
|
||||
};
|
||||
var nativeElement = element.get()[0];
|
||||
// The `focus` and `blur` events do not support bubbling. Use Event Capture instead.
|
||||
nativeElement.addEventListener('focus', function(e) {
|
||||
$(e.target).data('initValue', e.target.value);
|
||||
setInitialValue(e.target);
|
||||
}, true);
|
||||
nativeElement.addEventListener('blur', function(e) {
|
||||
var initValue = $(e.target).data('initValue');
|
||||
$(e.target).removeData('initValue');
|
||||
if (e.target.value !== initValue) {
|
||||
triggerEvent(events.accessibleChange, e);
|
||||
}
|
||||
checkAndTriggerAccessibleChange(e);
|
||||
}, true);
|
||||
element.on('keydown', function(e) {
|
||||
if ((e.which === keyCodes.enter) && e.target.value !== $(e.target).data('initValue')) {
|
||||
triggerEvent(events.accessibleChange, e);
|
||||
if ((e.which === keyCodes.enter)) {
|
||||
checkAndTriggerAccessibleChange(e);
|
||||
} else if (e.which === keyCodes.escape) {
|
||||
e.target.value = $(e.target).data('initValue');
|
||||
resetToInitialValue(e.target);
|
||||
e.target.dataset.ignoreChange = true;
|
||||
} else {
|
||||
// Firefox triggers a change event when using the keyboard to scroll through the selection.
|
||||
// Set a data- attribute that the change listener can use to ignore the change event where it was
|
||||
// generated from a keyboard change such as typing to complete a value, or using arrow keys.
|
||||
e.target.dataset.ignoreChange = true;
|
||||
|
||||
}
|
||||
});
|
||||
element.on('click', function(e) {
|
||||
var initValue = $(e.target).data('initValue');
|
||||
// Some browsers trigger onclick before onblur, therefore it is possible that initValue is undefined.
|
||||
if (typeof initValue !== 'undefined' && initValue != e.target.value) {
|
||||
triggerEvent(events.accessibleChange, e);
|
||||
element.on('change', function(e) {
|
||||
if (e.target.dataset.ignoreChange) {
|
||||
// This change event was triggered from a keyboard change which is not yet complete.
|
||||
// Do not trigger the accessibleChange event until the selection is completed using the [return]
|
||||
// key.
|
||||
return;
|
||||
}
|
||||
|
||||
checkAndTriggerAccessibleChange(e);
|
||||
});
|
||||
element.on('keyup', function(e) {
|
||||
// The key has been lifted. Stop ignoring the change event.
|
||||
delete e.target.dataset.ignoreChange;
|
||||
});
|
||||
element.on('click', function(e) {
|
||||
checkAndTriggerAccessibleChange(e);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user