125 lines
4.6 KiB
JavaScript
125 lines
4.6 KiB
JavaScript
define("dijit/_OnDijitClickMixin", [
|
|
"dojo/on",
|
|
"dojo/_base/array", // array.forEach
|
|
"dojo/keys", // keys.ENTER keys.SPACE
|
|
"dojo/_base/declare", // declare
|
|
"dojo/_base/sniff", // has("ie")
|
|
"dojo/_base/unload", // unload.addOnWindowUnload
|
|
"dojo/_base/window" // win.doc.addEventListener win.doc.attachEvent win.doc.detachEvent
|
|
], function(on, array, keys, declare, has, unload, win){
|
|
|
|
// module:
|
|
// dijit/_OnDijitClickMixin
|
|
// summary:
|
|
// Mixin so you can pass "ondijitclick" to this.connect() method,
|
|
// as a way to handle clicks by mouse, or by keyboard (SPACE/ENTER key)
|
|
|
|
|
|
// Keep track of where the last keydown event was, to help avoid generating
|
|
// spurious ondijitclick events when:
|
|
// 1. focus is on a <button> or <a>
|
|
// 2. user presses then releases the ENTER key
|
|
// 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
|
|
// 4. onkeyup event fires, causing the ondijitclick handler to fire
|
|
var lastKeyDownNode = null;
|
|
if(has("ie")){
|
|
(function(){
|
|
var keydownCallback = function(evt){
|
|
lastKeyDownNode = evt.srcElement;
|
|
};
|
|
win.doc.attachEvent('onkeydown', keydownCallback);
|
|
unload.addOnWindowUnload(function(){
|
|
win.doc.detachEvent('onkeydown', keydownCallback);
|
|
});
|
|
})();
|
|
}else{
|
|
win.doc.addEventListener('keydown', function(evt){
|
|
lastKeyDownNode = evt.target;
|
|
}, true);
|
|
}
|
|
|
|
// Custom a11yclick (a.k.a. ondijitclick) event
|
|
var a11yclick = function(node, listener){
|
|
if(/input|button/i.test(node.nodeName)){
|
|
// pass through, the browser already generates click event on SPACE/ENTER key
|
|
return on(node, "click", listener);
|
|
}else{
|
|
// Don't fire the click event unless both the keydown and keyup occur on this node.
|
|
// Avoids problems where focus shifted to this node or away from the node on keydown,
|
|
// either causing this node to process a stray keyup event, or causing another node
|
|
// to get a stray keyup event.
|
|
|
|
function clickKey(/*Event*/ e){
|
|
return (e.keyCode == keys.ENTER || e.keyCode == keys.SPACE) &&
|
|
!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey;
|
|
}
|
|
var handles = [
|
|
on(node, "keypress", function(e){
|
|
//console.log(this.id + ": 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)
|
|
// Do this onkeypress rather than onkeydown because onkeydown.preventDefault() will
|
|
// suppress the onkeypress event, breaking _HasDropDown
|
|
e.preventDefault();
|
|
}
|
|
}),
|
|
|
|
on(node, "keyup", function(e){
|
|
//console.log(this.id + ": 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;
|
|
listener.call(this, e);
|
|
}
|
|
}),
|
|
|
|
on(node, "click", function(e){
|
|
// and connect for mouse clicks too (or touch-clicks on mobile)
|
|
listener.call(this, e);
|
|
})
|
|
];
|
|
|
|
return {
|
|
remove: function(){
|
|
array.forEach(handles, function(h){ h.remove(); });
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
return declare("dijit._OnDijitClickMixin", null, {
|
|
connect: function(
|
|
/*Object|null*/ obj,
|
|
/*String|Function*/ event,
|
|
/*String|Function*/ method){
|
|
// summary:
|
|
// Connects specified obj/event to specified method of this object
|
|
// and registers for disconnect() on widget destroy.
|
|
// description:
|
|
// Provide widget-specific analog to connect.connect, except with the
|
|
// implicit use of this widget as the target object.
|
|
// This version of connect also provides a special "ondijitclick"
|
|
// event which triggers on a click or space or enter keyup.
|
|
// Events connected with `this.connect` are disconnected upon
|
|
// destruction.
|
|
// returns:
|
|
// A handle that can be passed to `disconnect` in order to disconnect before
|
|
// the widget is destroyed.
|
|
// example:
|
|
// | var btn = new dijit.form.Button();
|
|
// | // when foo.bar() is called, call the listener we're going to
|
|
// | // provide in the scope of btn
|
|
// | btn.connect(foo, "bar", function(){
|
|
// | console.debug(this.toString());
|
|
// | });
|
|
// tags:
|
|
// protected
|
|
|
|
return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]);
|
|
}
|
|
});
|
|
});
|