]> git.wh0rd.org - tt-rss.git/blame - lib/dijit/a11yclick.js.uncompressed.js
add prototype simple remover of baaaad tags based on domdocument
[tt-rss.git] / lib / dijit / a11yclick.js.uncompressed.js
CommitLineData
f0cfe83e
AD
1define("dijit/a11yclick", [
2 "dojo/on",
3 "dojo/_base/array", // array.forEach
4 "dojo/keys", // keys.ENTER keys.SPACE
5 "dojo/_base/declare", // declare
6 "dojo/has", // has("dom-addeventlistener")
7 "dojo/_base/unload", // unload.addOnWindowUnload
8 "dojo/_base/window" // win.doc.addEventListener win.doc.attachEvent win.doc.detachEvent
9], function(on, array, keys, declare, has, unload, win){
10
11 // module:
12 // dijit/a11yclick
13
14 // Keep track of where the last keydown event was, to help avoid generating
15 // spurious ondijitclick events when:
16 // 1. focus is on a <button> or <a>
17 // 2. user presses then releases the ENTER key
18 // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
19 // 4. onkeyup event fires, causing the ondijitclick handler to fire
20 var lastKeyDownNode = null;
21 if(has("dom-addeventlistener")){
22 win.doc.addEventListener('keydown', function(evt){
23 lastKeyDownNode = evt.target;
24 }, true);
25 }else{
26 // Fallback path for IE6-8
27 (function(){
28 var keydownCallback = function(evt){
29 lastKeyDownNode = evt.srcElement;
30 };
31 win.doc.attachEvent('onkeydown', keydownCallback);
32 unload.addOnWindowUnload(function(){
33 win.doc.detachEvent('onkeydown', keydownCallback);
34 });
35 })();
36 }
37
38 function clickKey(/*Event*/ e){
39 return (e.keyCode === keys.ENTER || e.keyCode === keys.SPACE) &&
40 !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey;
41 }
42
43 return function(node, listener){
44 // summary:
45 // Custom a11yclick (a.k.a. ondijitclick) event
46 // which triggers on a mouse click, touch, or space/enter keyup.
47
48 if(/input|button/i.test(node.nodeName)){
49 // pass through, the browser already generates click event on SPACE/ENTER key
50 return on(node, "click", listener);
51 }else{
52 // Don't fire the click event unless both the keydown and keyup occur on this node.
53 // Avoids problems where focus shifted to this node or away from the node on keydown,
54 // either causing this node to process a stray keyup event, or causing another node
55 // to get a stray keyup event.
56
57 var handles = [
58 on(node, "keydown", function(e){
59 //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
60 if(clickKey(e)){
61 // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
62 lastKeyDownNode = e.target;
63
64 // Prevent viewport scrolling on space key in IE<9.
65 // (Reproducible on test_Button.html on any of the first dijit/form/Button examples)
66 e.preventDefault();
67 }
68 }),
69
70 on(node, "keyup", function(e){
71 //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
72 if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey
73 //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
74 lastKeyDownNode = null;
75 on.emit(e.target, "click", {
76 cancelable: true,
77 bubbles: true
78 });
79 }
80 }),
81
82 on(node, "click", function(e){
83 // catch mouse clicks, plus the on.emit() calls from above and below
84 listener.call(this, e);
85 })
86 ];
87
88 if(has("touch")){
89 // touchstart-->touchend will automatically generate a click event, but there are problems
90 // on iOS after focus has been programatically shifted (#14604, #14918), so setup a failsafe
91 // if click doesn't fire naturally.
92
93 var clickTimer;
94 handles.push(
95 on(node, "touchend", function(e){
96 var target = e.target;
97 clickTimer = setTimeout(function(){
98 clickTimer = null;
99 on.emit(target, "click", {
100 cancelable: true,
101 bubbles: true
102 });
103 }, 600);
104 }),
105 on(node, "click", function(e){
106 // If browser generates a click naturally, clear the timer to fire a synthetic click event
107 if(clickTimer){
108 clearTimeout(clickTimer);
109 }
110 })
111 // TODO: if the touchstart and touchend were <100ms apart, and then there's another touchstart
112 // event <300ms after the touchend event, then clear the synthetic click timer, because user
113 // is doing a zoom. Alternately monitor screen.deviceXDPI (or something similar) to see if
114 // zoom level has changed.
115 );
116 }
117
118 return {
119 remove: function(){
120 array.forEach(handles, function(h){ h.remove(); });
121 if(clickTimer){
122 clearTimeout(clickTimer);
123 clickTimer = null;
124 }
125 }
126 };
127 }
128 };
129
130 return ret;
131});