forked from dojo/dijit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
a11yclick.js
139 lines (122 loc) · 4.2 KB
/
a11yclick.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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;
});