]> git.wh0rd.org Git - tt-rss.git/blob - lib/dijit/_OnDijitClickMixin.js.uncompressed.js
update dojo to 1.7.3
[tt-rss.git] / lib / dijit / _OnDijitClickMixin.js.uncompressed.js
1 define("dijit/_OnDijitClickMixin", [
2         "dojo/on",
3         "dojo/_base/array", // array.forEach
4         "dojo/keys", // keys.ENTER keys.SPACE
5         "dojo/_base/declare", // declare
6         "dojo/_base/sniff", // has("ie")
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/_OnDijitClickMixin
13         // summary:
14         //              Mixin so you can pass "ondijitclick" to this.connect() method,
15         //              as a way to handle clicks by mouse, or by keyboard (SPACE/ENTER key)
16
17
18         // Keep track of where the last keydown event was, to help avoid generating
19         // spurious ondijitclick events when:
20         // 1. focus is on a <button> or <a>
21         // 2. user presses then releases the ENTER key
22         // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
23         // 4. onkeyup event fires, causing the ondijitclick handler to fire
24         var lastKeyDownNode = null;
25         if(has("ie")){
26                 (function(){
27                         var keydownCallback = function(evt){
28                                 lastKeyDownNode = evt.srcElement;
29                         };
30                         win.doc.attachEvent('onkeydown', keydownCallback);
31                         unload.addOnWindowUnload(function(){
32                                 win.doc.detachEvent('onkeydown', keydownCallback);
33                         });
34                 })();
35         }else{
36                 win.doc.addEventListener('keydown', function(evt){
37                         lastKeyDownNode = evt.target;
38                 }, true);
39         }
40
41         // Custom a11yclick (a.k.a. ondijitclick) event
42         var a11yclick = function(node, listener){
43                 if(/input|button/i.test(node.nodeName)){
44                         // pass through, the browser already generates click event on SPACE/ENTER key
45                         return on(node, "click", listener);
46                 }else{
47                         // Don't fire the click event unless both the keydown and keyup occur on this node.
48                         // Avoids problems where focus shifted to this node or away from the node on keydown,
49                         // either causing this node to process a stray keyup event, or causing another node
50                         // to get a stray keyup event.
51
52                         function clickKey(/*Event*/ e){
53                                 return (e.keyCode == keys.ENTER || e.keyCode == keys.SPACE) &&
54                                                 !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey;
55                         }
56                         var handles = [
57                                 on(node, "keypress", function(e){
58                                         //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
59                                         if(clickKey(e)){
60                                                 // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
61                                                 lastKeyDownNode = e.target;
62
63                                                 // Prevent viewport scrolling on space key in IE<9.
64                                                 // (Reproducible on test_Button.html on any of the first dijit.form.Button examples)
65                                                 // Do this onkeypress rather than onkeydown because onkeydown.preventDefault() will
66                                                 // suppress the onkeypress event, breaking _HasDropDown
67                                                 e.preventDefault();
68                                         }
69                                 }),
70
71                                 on(node, "keyup", function(e){
72                                         //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
73                                         if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey
74                                                 //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
75                                                 lastKeyDownNode = null;
76                                                 listener.call(this, e);
77                                         }
78                                 }),
79
80                                 on(node, "click", function(e){
81                                         // and connect for mouse clicks too (or touch-clicks on mobile)
82                                         listener.call(this, e);
83                                 })
84                         ];
85
86                         return {
87                                 remove: function(){
88                                         array.forEach(handles, function(h){ h.remove(); });
89                                 }
90                         };
91                 }
92         };
93
94         return declare("dijit._OnDijitClickMixin", null, {
95                 connect: function(
96                                 /*Object|null*/ obj,
97                                 /*String|Function*/ event,
98                                 /*String|Function*/ method){
99                         // summary:
100                         //              Connects specified obj/event to specified method of this object
101                         //              and registers for disconnect() on widget destroy.
102                         // description:
103                         //              Provide widget-specific analog to connect.connect, except with the
104                         //              implicit use of this widget as the target object.
105                         //              This version of connect also provides a special "ondijitclick"
106                         //              event which triggers on a click or space or enter keyup.
107                         //              Events connected with `this.connect` are disconnected upon
108                         //              destruction.
109                         // returns:
110                         //              A handle that can be passed to `disconnect` in order to disconnect before
111                         //              the widget is destroyed.
112                         // example:
113                         //      |       var btn = new dijit.form.Button();
114                         //      |       // when foo.bar() is called, call the listener we're going to
115                         //      |       // provide in the scope of btn
116                         //      |       btn.connect(foo, "bar", function(){
117                         //      |               console.debug(this.toString());
118                         //      |       });
119                         // tags:
120                         //              protected
121
122                         return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]);
123                 }
124         });
125 });