]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dijit/typematic", [ |
2 | "dojo/_base/array", // array.forEach | |
3 | "dojo/_base/connect", // connect.connect | |
4 | "dojo/_base/event", // event.stop | |
5 | "dojo/_base/kernel", // kernel.deprecated | |
6 | "dojo/_base/lang", // lang.mixin, lang.hitch | |
7 | "dojo/on", | |
8 | "dojo/sniff", // has("ie") | |
9 | "./main" // setting dijit.typematic global | |
10 | ], function(array, connect, event, kernel, lang, on, has, dijit){ | |
11 | ||
12 | // module: | |
13 | // dijit/typematic | |
14 | ||
15 | var typematic = (dijit.typematic = { | |
16 | // summary: | |
17 | // These functions are used to repetitively call a user specified callback | |
18 | // method when a specific key or mouse click over a specific DOM node is | |
19 | // held down for a specific amount of time. | |
20 | // Only 1 such event is allowed to occur on the browser page at 1 time. | |
21 | ||
22 | _fireEventAndReload: function(){ | |
23 | this._timer = null; | |
24 | this._callback(++this._count, this._node, this._evt); | |
25 | ||
26 | // Schedule next event, timer is at most minDelay (default 10ms) to avoid | |
27 | // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup) | |
28 | this._currentTimeout = Math.max( | |
29 | this._currentTimeout < 0 ? this._initialDelay : | |
30 | (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)), | |
31 | this._minDelay); | |
32 | this._timer = setTimeout(lang.hitch(this, "_fireEventAndReload"), this._currentTimeout); | |
33 | }, | |
34 | ||
35 | trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number?*/ subsequentDelay, /*Number?*/ initialDelay, /*Number?*/ minDelay){ | |
36 | // summary: | |
37 | // Start a timed, repeating callback sequence. | |
38 | // If already started, the function call is ignored. | |
39 | // This method is not normally called by the user but can be | |
40 | // when the normal listener code is insufficient. | |
41 | // evt: | |
42 | // key or mouse event object to pass to the user callback | |
43 | // _this: | |
44 | // pointer to the user's widget space. | |
45 | // node: | |
46 | // the DOM node object to pass the the callback function | |
47 | // callback: | |
48 | // function to call until the sequence is stopped called with 3 parameters: | |
49 | // count: | |
50 | // integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped | |
51 | // node: | |
52 | // the DOM node object passed in | |
53 | // evt: | |
54 | // key or mouse event object | |
55 | // obj: | |
56 | // user space object used to uniquely identify each typematic sequence | |
57 | // subsequentDelay: | |
58 | // if > 1, the number of milliseconds until the 3->n events occur | |
59 | // or else the fractional time multiplier for the next event's delay, default=0.9 | |
60 | // initialDelay: | |
61 | // the number of milliseconds until the 2nd event occurs, default=500ms | |
62 | // minDelay: | |
63 | // the maximum delay in milliseconds for event to fire, default=10ms | |
64 | if(obj != this._obj){ | |
65 | this.stop(); | |
66 | this._initialDelay = initialDelay || 500; | |
67 | this._subsequentDelay = subsequentDelay || 0.90; | |
68 | this._minDelay = minDelay || 10; | |
69 | this._obj = obj; | |
70 | this._node = node; | |
71 | this._currentTimeout = -1; | |
72 | this._count = -1; | |
73 | this._callback = lang.hitch(_this, callback); | |
74 | this._evt = { faux: true }; | |
75 | for(var attr in evt){ | |
76 | if(attr != "layerX" && attr != "layerY"){ // prevent WebKit warnings | |
77 | var v = evt[attr]; | |
78 | if(typeof v != "function" && typeof v != "undefined"){ this._evt[attr] = v } | |
79 | } | |
80 | } | |
81 | this._fireEventAndReload(); | |
82 | } | |
83 | }, | |
84 | ||
85 | stop: function(){ | |
86 | // summary: | |
87 | // Stop an ongoing timed, repeating callback sequence. | |
88 | if(this._timer){ | |
89 | clearTimeout(this._timer); | |
90 | this._timer = null; | |
91 | } | |
92 | if(this._obj){ | |
93 | this._callback(-1, this._node, this._evt); | |
94 | this._obj = null; | |
95 | } | |
96 | }, | |
97 | ||
98 | addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){ | |
99 | // summary: | |
100 | // Start listening for a specific typematic key. | |
101 | // See also the trigger method for other parameters. | |
102 | // keyObject: | |
103 | // an object defining the key to listen for: | |
104 | // | |
105 | // - charOrCode: the printable character (string) or keyCode (number) to listen for. | |
106 | // - keyCode: (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0). | |
107 | // - charCode: (deprecated - use charOrCode) the charCode (number) to listen for. | |
108 | // - ctrlKey: desired ctrl key state to initiate the callback sequence: | |
109 | // - pressed (true) | |
110 | // - released (false) | |
111 | // - either (unspecified) | |
112 | // - altKey: same as ctrlKey but for the alt key | |
113 | // - shiftKey: same as ctrlKey but for the shift key | |
114 | // returns: | |
115 | // a connection handle | |
116 | ||
117 | if(keyObject.keyCode){ | |
118 | keyObject.charOrCode = keyObject.keyCode; | |
119 | kernel.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0"); | |
120 | }else if(keyObject.charCode){ | |
121 | keyObject.charOrCode = String.fromCharCode(keyObject.charCode); | |
122 | kernel.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0"); | |
123 | } | |
124 | var handles = [ | |
125 | on(node, connect._keypress, lang.hitch(this, function(evt){ | |
126 | if(evt.charOrCode == keyObject.charOrCode && | |
127 | (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) && | |
128 | (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) && | |
129 | (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey | |
130 | (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){ | |
131 | event.stop(evt); | |
132 | typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay); | |
133 | }else if(typematic._obj == keyObject){ | |
134 | typematic.stop(); | |
135 | } | |
136 | })), | |
137 | on(node, "keyup", lang.hitch(this, function(){ | |
138 | if(typematic._obj == keyObject){ | |
139 | typematic.stop(); | |
140 | } | |
141 | })) | |
142 | ]; | |
143 | return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } }; | |
144 | }, | |
145 | ||
146 | addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){ | |
147 | // summary: | |
148 | // Start listening for a typematic mouse click. | |
149 | // See the trigger method for other parameters. | |
150 | // returns: | |
151 | // a connection handle | |
152 | var handles = [ | |
153 | on(node, "mousedown", lang.hitch(this, function(evt){ | |
154 | evt.preventDefault(); | |
155 | typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay); | |
156 | })), | |
157 | on(node, "mouseup", lang.hitch(this, function(evt){ | |
158 | if(this._obj){ | |
159 | evt.preventDefault(); | |
160 | } | |
161 | typematic.stop(); | |
162 | })), | |
163 | on(node, "mouseout", lang.hitch(this, function(evt){ | |
164 | if(this._obj){ | |
165 | evt.preventDefault(); | |
166 | } | |
167 | typematic.stop(); | |
168 | })), | |
169 | on(node, "dblclick", lang.hitch(this, function(evt){ | |
170 | evt.preventDefault(); | |
171 | if(has("ie") < 9){ | |
172 | typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay); | |
173 | setTimeout(lang.hitch(this, typematic.stop), 50); | |
174 | } | |
175 | })) | |
176 | ]; | |
177 | return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } }; | |
178 | }, | |
179 | ||
180 | addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){ | |
181 | // summary: | |
182 | // Start listening for a specific typematic key and mouseclick. | |
183 | // This is a thin wrapper to addKeyListener and addMouseListener. | |
184 | // See the addMouseListener and addKeyListener methods for other parameters. | |
185 | // mouseNode: | |
186 | // the DOM node object to listen on for mouse events. | |
187 | // keyNode: | |
188 | // the DOM node object to listen on for key events. | |
189 | // returns: | |
190 | // a connection handle | |
191 | var handles = [ | |
192 | this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay), | |
193 | this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay) | |
194 | ]; | |
195 | return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } }; | |
196 | } | |
197 | }); | |
198 | ||
199 | return typematic; | |
200 | ||
201 | }); |