dijit
Version:
Dijit provides a complete collection of user interface controls based on Dojo, giving you the power to create web applications that are highly optimized for usability, performance, internationalization, accessibility, but above all deliver an incredible u
140 lines (122 loc) • 4.3 kB
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;
});