You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.2 KiB
JavaScript

define([
"dojo/keys", // keys.ENTER keys.SPACE
"dojo/mouse",
"dojo/on",
"dojo/touch" // touch support for click is now there
], function(keys, mouse, on, touch){
// module:
// dijit/a11yclick
/*=====
return {
// summary:
// Custom press, release, and click synthetic events
// which trigger on a left mouse click, touch, or space/enter keyup.
click: function(node, listener){
// summary:
// Logical click operation for mouse, touch, or keyboard (space/enter key)
},
press: function(node, listener){
// summary:
// Mousedown (left button), touchstart, or keydown (space or enter) corresponding to logical click operation.
},
release: function(node, listener){
// summary:
// Mouseup (left button), touchend, or keyup (space or enter) corresponding to logical click operation.
},
move: function(node, listener){
// summary:
// Mouse cursor or a finger is dragged over the given node.
}
};
=====*/
function clickKey(/*Event*/ e){
// Test if this keyboard event should be tracked as the start (if keydown) or end (if keyup) of a click event.
// Only track for nodes marked to be tracked, and not for buttons or inputs,
// since buttons handle keyboard click natively, and text inputs should not
// prevent typing spaces or newlines.
if((e.keyCode === keys.ENTER || e.keyCode === keys.SPACE) && !/input|button|textarea/i.test(e.target.nodeName)){
// Test if a node or its ancestor has been marked with the dojoClick property to indicate special processing
for(var node = e.target; node; node = node.parentNode){
if(node.dojoClick){ return true; }
}
}
}
var lastKeyDownNode;
on(document, "keydown", function(e){
//console.log("a11yclick: onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
if(clickKey(e)){
// needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
lastKeyDownNode = e.target;
// Prevent viewport scrolling on space key in IE<9.
// (Reproducible on test_Button.html on any of the first dijit/form/Button examples)
e.preventDefault();
}else{
lastKeyDownNode = null;
}
});
on(document, "keyup", function(e){
//console.log("a11yclick: onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey
//need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
lastKeyDownNode = null;
on.emit(e.target, "click", {
cancelable: true,
bubbles: true,
ctrlKey: e.ctrlKey,
shiftKey: e.shiftKey,
metaKey: e.metaKey,
altKey: e.altKey,
_origType: e.type
});
}
});
// I want to return a hash of the synthetic events, but for backwards compatibility the main return value
// needs to be the click event. Change for 2.0.
var click = function(node, listener){
// Set flag on node so that keydown/keyup above emits click event.
// Also enables fast click processing from dojo/touch.
node.dojoClick = true;
return on(node, "click", listener);
};
click.click = click; // forward compatibility with 2.0
click.press = function(node, listener){
var touchListener = on(node, touch.press, function(evt){
if(evt.type == "mousedown" && !mouse.isLeft(evt)){
// Ignore right click
return;
}
listener(evt);
}), keyListener = on(node, "keydown", function(evt){
if(evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE){
listener(evt);
}
});
return {
remove: function(){
touchListener.remove();
keyListener.remove();
}
};
};
click.release = function(node, listener){
var touchListener = on(node, touch.release, function(evt){
if(evt.type == "mouseup" && !mouse.isLeft(evt)){
// Ignore right click
return;
}
listener(evt);
}), keyListener = on(node, "keyup", function(evt){
if(evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE){
listener(evt);
}
});
return {
remove: function(){
touchListener.remove();
keyListener.remove();
}
};
};
click.move = touch.move; // just for convenience
return click;
});