2150 |
mathias |
1 |
if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dojo._base.event"] = true;
|
|
|
3 |
dojo.provide("dojo._base.event");
|
|
|
4 |
dojo.require("dojo._base.connect");
|
|
|
5 |
|
|
|
6 |
// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
|
|
|
7 |
|
|
|
8 |
(function(){
|
|
|
9 |
// DOM event listener machinery
|
|
|
10 |
var del = dojo._event_listener = {
|
|
|
11 |
add: function(/*DOMNode*/node, /*String*/name, /*Function*/fp){
|
|
|
12 |
if(!node){return;}
|
|
|
13 |
name = del._normalizeEventName(name);
|
|
|
14 |
|
|
|
15 |
fp = del._fixCallback(name, fp);
|
|
|
16 |
|
|
|
17 |
var oname = name;
|
|
|
18 |
if((!dojo.isIE)&&((name == "mouseenter")||(name == "mouseleave"))){
|
|
|
19 |
var oname = name;
|
|
|
20 |
var ofp = fp;
|
|
|
21 |
name = (name == "mouseenter") ? "mouseover" : "mouseout";
|
|
|
22 |
fp = function(e){
|
|
|
23 |
// thanks ben!
|
|
|
24 |
var id = dojo.isDescendant(e.relatedTarget, node);
|
|
|
25 |
if(id == false){
|
|
|
26 |
// e.type = oname; // FIXME: doesn't take?
|
|
|
27 |
return ofp.call(this, e);
|
|
|
28 |
}
|
|
|
29 |
}
|
|
|
30 |
}
|
|
|
31 |
|
|
|
32 |
node.addEventListener(name, fp, false);
|
|
|
33 |
return fp; /*Handle*/
|
|
|
34 |
},
|
|
|
35 |
remove: function(/*DOMNode*/node, /*String*/event, /*Handle*/handle){
|
|
|
36 |
// summary:
|
|
|
37 |
// clobbers the listener from the node
|
|
|
38 |
// node:
|
|
|
39 |
// DOM node to attach the event to
|
|
|
40 |
// event:
|
|
|
41 |
// the name of the handler to remove the function from
|
|
|
42 |
// handle:
|
|
|
43 |
// the handle returned from add
|
|
|
44 |
(node)&&(node.removeEventListener(del._normalizeEventName(event), handle, false));
|
|
|
45 |
},
|
|
|
46 |
_normalizeEventName: function(/*String*/name){
|
|
|
47 |
// Generally, name should be lower case, unless it is special
|
|
|
48 |
// somehow (e.g. a Mozilla DOM event).
|
|
|
49 |
// Remove 'on'.
|
|
|
50 |
return (name.slice(0,2)=="on" ? name.slice(2) : name);
|
|
|
51 |
},
|
|
|
52 |
_fixCallback: function(/*String*/name, fp){
|
|
|
53 |
// By default, we only invoke _fixEvent for 'keypress'
|
|
|
54 |
// If code is added to _fixEvent for other events, we have
|
|
|
55 |
// to revisit this optimization.
|
|
|
56 |
// This also applies to _fixEvent overrides for Safari and Opera
|
|
|
57 |
// below.
|
|
|
58 |
return (name!="keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); });
|
|
|
59 |
},
|
|
|
60 |
_fixEvent: function(evt, sender){
|
|
|
61 |
// _fixCallback only attaches us to keypress.
|
|
|
62 |
// Switch on evt.type anyway because we might
|
|
|
63 |
// be called directly from dojo.fixEvent.
|
|
|
64 |
switch(evt.type){
|
|
|
65 |
case "keypress":
|
|
|
66 |
del._setKeyChar(evt);
|
|
|
67 |
break;
|
|
|
68 |
}
|
|
|
69 |
return evt;
|
|
|
70 |
},
|
|
|
71 |
_setKeyChar: function(evt){
|
|
|
72 |
evt.keyChar = (evt.charCode ? String.fromCharCode(evt.charCode) : '');
|
|
|
73 |
}
|
|
|
74 |
};
|
|
|
75 |
|
|
|
76 |
// DOM events
|
|
|
77 |
|
|
|
78 |
dojo.fixEvent = function(/*Event*/evt, /*DOMNode*/sender){
|
|
|
79 |
// summary:
|
|
|
80 |
// normalizes properties on the event object including event
|
|
|
81 |
// bubbling methods, keystroke normalization, and x/y positions
|
|
|
82 |
// evt: Event
|
|
|
83 |
// native event object
|
|
|
84 |
// sender: DOMNode
|
|
|
85 |
// node to treat as "currentTarget"
|
|
|
86 |
return del._fixEvent(evt, sender);
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
dojo.stopEvent = function(/*Event*/evt){
|
|
|
90 |
// summary:
|
|
|
91 |
// prevents propagation and clobbers the default action of the
|
|
|
92 |
// passed event
|
|
|
93 |
// evt: Event
|
|
|
94 |
// The event object. If omitted, window.event is used on IE.
|
|
|
95 |
evt.preventDefault();
|
|
|
96 |
evt.stopPropagation();
|
|
|
97 |
// NOTE: below, this method is overridden for IE
|
|
|
98 |
}
|
|
|
99 |
|
|
|
100 |
// the default listener to use on dontFix nodes, overriden for IE
|
|
|
101 |
var node_listener = dojo._listener;
|
|
|
102 |
|
|
|
103 |
// Unify connect and event listeners
|
|
|
104 |
dojo._connect = function(obj, event, context, method, dontFix){
|
|
|
105 |
// FIXME: need a more strict test
|
|
|
106 |
var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
|
|
|
107 |
// choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
|
|
|
108 |
// we need the third option to provide leak prevention on broken browsers (IE)
|
|
|
109 |
var lid = !isNode ? 0 : (!dontFix ? 1 : 2), l = [dojo._listener, del, node_listener][lid];
|
|
|
110 |
// create a listener
|
|
|
111 |
var h = l.add(obj, event, dojo.hitch(context, method));
|
|
|
112 |
// formerly, the disconnect package contained "l" directly, but if client code
|
|
|
113 |
// leaks the disconnect package (by connecting it to a node), referencing "l"
|
|
|
114 |
// compounds the problem.
|
|
|
115 |
// instead we return a listener id, which requires custom _disconnect below.
|
|
|
116 |
// return disconnect package
|
|
|
117 |
return [ obj, event, h, lid ];
|
|
|
118 |
}
|
|
|
119 |
|
|
|
120 |
dojo._disconnect = function(obj, event, handle, listener){
|
|
|
121 |
([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
|
|
|
122 |
}
|
|
|
123 |
|
|
|
124 |
// Constants
|
|
|
125 |
|
|
|
126 |
// Public: client code should test
|
|
|
127 |
// keyCode against these named constants, as the
|
|
|
128 |
// actual codes can vary by browser.
|
|
|
129 |
dojo.keys = {
|
|
|
130 |
BACKSPACE: 8,
|
|
|
131 |
TAB: 9,
|
|
|
132 |
CLEAR: 12,
|
|
|
133 |
ENTER: 13,
|
|
|
134 |
SHIFT: 16,
|
|
|
135 |
CTRL: 17,
|
|
|
136 |
ALT: 18,
|
|
|
137 |
PAUSE: 19,
|
|
|
138 |
CAPS_LOCK: 20,
|
|
|
139 |
ESCAPE: 27,
|
|
|
140 |
SPACE: 32,
|
|
|
141 |
PAGE_UP: 33,
|
|
|
142 |
PAGE_DOWN: 34,
|
|
|
143 |
END: 35,
|
|
|
144 |
HOME: 36,
|
|
|
145 |
LEFT_ARROW: 37,
|
|
|
146 |
UP_ARROW: 38,
|
|
|
147 |
RIGHT_ARROW: 39,
|
|
|
148 |
DOWN_ARROW: 40,
|
|
|
149 |
INSERT: 45,
|
|
|
150 |
DELETE: 46,
|
|
|
151 |
HELP: 47,
|
|
|
152 |
LEFT_WINDOW: 91,
|
|
|
153 |
RIGHT_WINDOW: 92,
|
|
|
154 |
SELECT: 93,
|
|
|
155 |
NUMPAD_0: 96,
|
|
|
156 |
NUMPAD_1: 97,
|
|
|
157 |
NUMPAD_2: 98,
|
|
|
158 |
NUMPAD_3: 99,
|
|
|
159 |
NUMPAD_4: 100,
|
|
|
160 |
NUMPAD_5: 101,
|
|
|
161 |
NUMPAD_6: 102,
|
|
|
162 |
NUMPAD_7: 103,
|
|
|
163 |
NUMPAD_8: 104,
|
|
|
164 |
NUMPAD_9: 105,
|
|
|
165 |
NUMPAD_MULTIPLY: 106,
|
|
|
166 |
NUMPAD_PLUS: 107,
|
|
|
167 |
NUMPAD_ENTER: 108,
|
|
|
168 |
NUMPAD_MINUS: 109,
|
|
|
169 |
NUMPAD_PERIOD: 110,
|
|
|
170 |
NUMPAD_DIVIDE: 111,
|
|
|
171 |
F1: 112,
|
|
|
172 |
F2: 113,
|
|
|
173 |
F3: 114,
|
|
|
174 |
F4: 115,
|
|
|
175 |
F5: 116,
|
|
|
176 |
F6: 117,
|
|
|
177 |
F7: 118,
|
|
|
178 |
F8: 119,
|
|
|
179 |
F9: 120,
|
|
|
180 |
F10: 121,
|
|
|
181 |
F11: 122,
|
|
|
182 |
F12: 123,
|
|
|
183 |
F13: 124,
|
|
|
184 |
F14: 125,
|
|
|
185 |
F15: 126,
|
|
|
186 |
NUM_LOCK: 144,
|
|
|
187 |
SCROLL_LOCK: 145
|
|
|
188 |
};
|
|
|
189 |
|
|
|
190 |
// IE event normalization
|
|
|
191 |
if(dojo.isIE){
|
|
|
192 |
var _trySetKeyCode = function(e, code){
|
|
|
193 |
try{
|
|
|
194 |
// squelch errors when keyCode is read-only
|
|
|
195 |
// (e.g. if keyCode is ctrl or shift)
|
|
|
196 |
return (e.keyCode = code);
|
|
|
197 |
}catch(e){
|
|
|
198 |
return 0;
|
|
|
199 |
}
|
|
|
200 |
}
|
|
|
201 |
|
|
|
202 |
// by default, use the standard listener
|
|
|
203 |
var iel = dojo._listener;
|
|
|
204 |
// dispatcher tracking property
|
|
|
205 |
if(!djConfig._allow_leaks){
|
|
|
206 |
// custom listener that handles leak protection for DOM events
|
|
|
207 |
node_listener = iel = dojo._ie_listener = {
|
|
|
208 |
// support handler indirection: event handler functions are
|
|
|
209 |
// referenced here. Event dispatchers hold only indices.
|
|
|
210 |
handlers: [],
|
|
|
211 |
// add a listener to an object
|
|
|
212 |
add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
|
|
|
213 |
source = source || dojo.global;
|
|
|
214 |
var f = source[method];
|
|
|
215 |
if(!f||!f._listeners){
|
|
|
216 |
var d = dojo._getIeDispatcher();
|
|
|
217 |
// original target function is special
|
|
|
218 |
d.target = f && (ieh.push(f) - 1);
|
|
|
219 |
// dispatcher holds a list of indices into handlers table
|
|
|
220 |
d._listeners = [];
|
|
|
221 |
// redirect source to dispatcher
|
|
|
222 |
f = source[method] = d;
|
|
|
223 |
}
|
|
|
224 |
return f._listeners.push(ieh.push(listener) - 1) ; /*Handle*/
|
|
|
225 |
},
|
|
|
226 |
// remove a listener from an object
|
|
|
227 |
remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
|
|
|
228 |
var f = (source||dojo.global)[method], l = f&&f._listeners;
|
|
|
229 |
if(f && l && handle--){
|
|
|
230 |
delete ieh[l[handle]];
|
|
|
231 |
delete l[handle];
|
|
|
232 |
}
|
|
|
233 |
}
|
|
|
234 |
};
|
|
|
235 |
// alias used above
|
|
|
236 |
var ieh = iel.handlers;
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
dojo.mixin(del, {
|
|
|
240 |
add: function(/*DOMNode*/node, /*String*/event, /*Function*/fp){
|
|
|
241 |
if(!node){return;} // undefined
|
|
|
242 |
event = del._normalizeEventName(event);
|
|
|
243 |
if(event=="onkeypress"){
|
|
|
244 |
// we need to listen to onkeydown to synthesize
|
|
|
245 |
// keypress events that otherwise won't fire
|
|
|
246 |
// on IE
|
|
|
247 |
var kd = node.onkeydown;
|
|
|
248 |
if(!kd||!kd._listeners||!kd._stealthKeydown){
|
|
|
249 |
// we simply ignore this connection when disconnecting
|
|
|
250 |
// because it's side-effects are harmless
|
|
|
251 |
del.add(node, "onkeydown", del._stealthKeyDown);
|
|
|
252 |
// we only want one stealth listener per node
|
|
|
253 |
node.onkeydown._stealthKeydown = true;
|
|
|
254 |
}
|
|
|
255 |
}
|
|
|
256 |
return iel.add(node, event, del._fixCallback(fp));
|
|
|
257 |
},
|
|
|
258 |
remove: function(/*DOMNode*/node, /*String*/event, /*Handle*/handle){
|
|
|
259 |
iel.remove(node, del._normalizeEventName(event), handle);
|
|
|
260 |
},
|
|
|
261 |
_normalizeEventName: function(/*String*/eventName){
|
|
|
262 |
// Generally, eventName should be lower case, unless it is
|
|
|
263 |
// special somehow (e.g. a Mozilla event)
|
|
|
264 |
// ensure 'on'
|
|
|
265 |
return (eventName.slice(0,2)!="on" ? "on"+eventName : eventName);
|
|
|
266 |
},
|
|
|
267 |
_nop: function(){},
|
|
|
268 |
_fixEvent: function(/*Event*/evt, /*DOMNode*/sender){
|
|
|
269 |
// summary:
|
|
|
270 |
// normalizes properties on the event object including event
|
|
|
271 |
// bubbling methods, keystroke normalization, and x/y positions
|
|
|
272 |
// evt: native event object
|
|
|
273 |
// sender: node to treat as "currentTarget"
|
|
|
274 |
if(!evt){
|
|
|
275 |
var w = (sender)&&((sender.ownerDocument || sender.document || sender).parentWindow)||window;
|
|
|
276 |
evt = w.event;
|
|
|
277 |
}
|
|
|
278 |
if(!evt){return(evt);}
|
|
|
279 |
evt.target = evt.srcElement;
|
|
|
280 |
evt.currentTarget = (sender || evt.srcElement);
|
|
|
281 |
evt.layerX = evt.offsetX;
|
|
|
282 |
evt.layerY = evt.offsetY;
|
|
|
283 |
// FIXME: scroll position query is duped from dojo.html to
|
|
|
284 |
// avoid dependency on that entire module. Now that HTML is in
|
|
|
285 |
// Base, we should convert back to something similar there.
|
|
|
286 |
var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
|
|
|
287 |
// DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
|
|
|
288 |
// here rather than document.body
|
|
|
289 |
var docBody = ((dojo.isIE<6)||(doc["compatMode"]=="BackCompat")) ? doc.body : doc.documentElement;
|
|
|
290 |
var offset = dojo._getIeDocumentElementOffset();
|
|
|
291 |
evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
|
|
|
292 |
evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
|
|
|
293 |
if(evt.type == "mouseover"){
|
|
|
294 |
evt.relatedTarget = evt.fromElement;
|
|
|
295 |
}
|
|
|
296 |
if(evt.type == "mouseout"){
|
|
|
297 |
evt.relatedTarget = evt.toElement;
|
|
|
298 |
}
|
|
|
299 |
evt.stopPropagation = del._stopPropagation;
|
|
|
300 |
evt.preventDefault = del._preventDefault;
|
|
|
301 |
return del._fixKeys(evt);
|
|
|
302 |
},
|
|
|
303 |
_fixKeys: function(evt){
|
|
|
304 |
switch(evt.type){
|
|
|
305 |
case "keypress":
|
|
|
306 |
var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
|
|
|
307 |
if (c==10){
|
|
|
308 |
// CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
|
|
|
309 |
c=0;
|
|
|
310 |
evt.keyCode = 13;
|
|
|
311 |
}else if(c==13||c==27){
|
|
|
312 |
c=0; // Mozilla considers ENTER and ESC non-printable
|
|
|
313 |
}else if(c==3){
|
|
|
314 |
c=99; // Mozilla maps CTRL-BREAK to CTRL-c
|
|
|
315 |
}
|
|
|
316 |
// Mozilla sets keyCode to 0 when there is a charCode
|
|
|
317 |
// but that stops the event on IE.
|
|
|
318 |
evt.charCode = c;
|
|
|
319 |
del._setKeyChar(evt);
|
|
|
320 |
break;
|
|
|
321 |
}
|
|
|
322 |
return evt;
|
|
|
323 |
},
|
|
|
324 |
// some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
|
|
|
325 |
// we map those virtual key codes to ascii here
|
|
|
326 |
// not valid for all (non-US) keyboards, so maybe we shouldn't bother
|
|
|
327 |
_punctMap: {
|
|
|
328 |
106:42,
|
|
|
329 |
111:47,
|
|
|
330 |
186:59,
|
|
|
331 |
187:43,
|
|
|
332 |
188:44,
|
|
|
333 |
189:45,
|
|
|
334 |
190:46,
|
|
|
335 |
191:47,
|
|
|
336 |
192:96,
|
|
|
337 |
219:91,
|
|
|
338 |
220:92,
|
|
|
339 |
221:93,
|
|
|
340 |
222:39
|
|
|
341 |
},
|
|
|
342 |
_stealthKeyDown: function(evt){
|
|
|
343 |
// IE doesn't fire keypress for most non-printable characters.
|
|
|
344 |
// other browsers do, we simulate it here.
|
|
|
345 |
var kp=evt.currentTarget.onkeypress;
|
|
|
346 |
// only works if kp exists and is a dispatcher
|
|
|
347 |
if(!kp||!kp._listeners)return;
|
|
|
348 |
// munge key/charCode
|
|
|
349 |
var k=evt.keyCode;
|
|
|
350 |
// These are Windows Virtual Key Codes
|
|
|
351 |
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
|
|
|
352 |
var unprintable = (k!=13)&&(k!=32)&&(k!=27)&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222);
|
|
|
353 |
// synthesize keypress for most unprintables and CTRL-keys
|
|
|
354 |
if(unprintable||evt.ctrlKey){
|
|
|
355 |
var c = (unprintable ? 0 : k);
|
|
|
356 |
if(evt.ctrlKey){
|
|
|
357 |
if(k==3 || k==13){
|
|
|
358 |
return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
|
|
|
359 |
}else if(c>95 && c<106){
|
|
|
360 |
c -= 48; // map CTRL-[numpad 0-9] to ASCII
|
|
|
361 |
}else if((!evt.shiftKey)&&(c>=65&&c<=90)){
|
|
|
362 |
c += 32; // map CTRL-[A-Z] to lowercase
|
|
|
363 |
}else{
|
|
|
364 |
c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
|
|
|
365 |
}
|
|
|
366 |
}
|
|
|
367 |
// simulate a keypress event
|
|
|
368 |
var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
|
|
|
369 |
kp.call(evt.currentTarget, faux);
|
|
|
370 |
evt.cancelBubble = faux.cancelBubble;
|
|
|
371 |
evt.returnValue = faux.returnValue;
|
|
|
372 |
_trySetKeyCode(evt, faux.keyCode);
|
|
|
373 |
}
|
|
|
374 |
},
|
|
|
375 |
// Called in Event scope
|
|
|
376 |
_stopPropagation: function(){
|
|
|
377 |
this.cancelBubble = true;
|
|
|
378 |
},
|
|
|
379 |
_preventDefault: function(){
|
|
|
380 |
// Setting keyCode to 0 is the only way to prevent certain keypresses (namely
|
|
|
381 |
// ctrl-combinations that correspond to menu accelerator keys).
|
|
|
382 |
// Otoh, it prevents upstream listeners from getting this information
|
|
|
383 |
// Try to split the difference here by clobbering keyCode only for ctrl
|
|
|
384 |
// combinations. If you still need to access the key upstream, bubbledKeyCode is
|
|
|
385 |
// provided as a workaround.
|
|
|
386 |
this.bubbledKeyCode = this.keyCode;
|
|
|
387 |
if(this.ctrlKey){_trySetKeyCode(this, 0);}
|
|
|
388 |
this.returnValue = false;
|
|
|
389 |
}
|
|
|
390 |
});
|
|
|
391 |
|
|
|
392 |
// override stopEvent for IE
|
|
|
393 |
dojo.stopEvent = function(evt){
|
|
|
394 |
evt = evt || window.event;
|
|
|
395 |
del._stopPropagation.call(evt);
|
|
|
396 |
del._preventDefault.call(evt);
|
|
|
397 |
}
|
|
|
398 |
}
|
|
|
399 |
|
|
|
400 |
del._synthesizeEvent = function(evt, props){
|
|
|
401 |
var faux = dojo.mixin({}, evt, props);
|
|
|
402 |
del._setKeyChar(faux);
|
|
|
403 |
// FIXME: would prefer to use dojo.hitch: dojo.hitch(evt, evt.preventDefault);
|
|
|
404 |
// but it throws an error when preventDefault is invoked on Safari
|
|
|
405 |
// does Event.preventDefault not support "apply" on Safari?
|
|
|
406 |
faux.preventDefault = function(){ evt.preventDefault(); };
|
|
|
407 |
faux.stopPropagation = function(){ evt.stopPropagation(); };
|
|
|
408 |
return faux;
|
|
|
409 |
}
|
|
|
410 |
|
|
|
411 |
// Opera event normalization
|
|
|
412 |
if(dojo.isOpera){
|
|
|
413 |
dojo.mixin(del, {
|
|
|
414 |
_fixEvent: function(evt, sender){
|
|
|
415 |
switch(evt.type){
|
|
|
416 |
case "keypress":
|
|
|
417 |
var c = evt.which;
|
|
|
418 |
if(c==3){
|
|
|
419 |
c=99; // Mozilla maps CTRL-BREAK to CTRL-c
|
|
|
420 |
}
|
|
|
421 |
// can't trap some keys at all, like INSERT and DELETE
|
|
|
422 |
// there is no differentiating info between DELETE and ".", or INSERT and "-"
|
|
|
423 |
c = ((c<41)&&(!evt.shiftKey) ? 0 : c);
|
|
|
424 |
if((evt.ctrlKey)&&(!evt.shiftKey)&&(c>=65)&&(c<=90)){
|
|
|
425 |
// lowercase CTRL-[A-Z] keys
|
|
|
426 |
c += 32;
|
|
|
427 |
}
|
|
|
428 |
return del._synthesizeEvent(evt, { charCode: c });
|
|
|
429 |
}
|
|
|
430 |
return evt;
|
|
|
431 |
}
|
|
|
432 |
});
|
|
|
433 |
}
|
|
|
434 |
|
|
|
435 |
// Safari event normalization
|
|
|
436 |
if(dojo.isSafari){
|
|
|
437 |
dojo.mixin(del, {
|
|
|
438 |
_fixEvent: function(evt, sender){
|
|
|
439 |
switch(evt.type){
|
|
|
440 |
case "keypress":
|
|
|
441 |
var c = evt.charCode, s = evt.shiftKey, k = evt.keyCode;
|
|
|
442 |
// FIXME: This is a hack, suggest we rethink keyboard strategy.
|
|
|
443 |
// Arrow and page keys have 0 "keyCode" in keypress events.on Safari for Windows
|
|
|
444 |
k = k || identifierMap[evt.keyIdentifier] || 0;
|
|
|
445 |
if(evt.keyIdentifier=="Enter"){
|
|
|
446 |
c = 0; // differentiate Enter from CTRL-m (both code 13)
|
|
|
447 |
}else if((evt.ctrlKey)&&(c>0)&&(c<27)){
|
|
|
448 |
c += 96; // map CTRL-[A-Z] codes to ASCII
|
|
|
449 |
} else if (c==dojo.keys.SHIFT_TAB) {
|
|
|
450 |
c = dojo.keys.TAB; // morph SHIFT_TAB into TAB + shiftKey: true
|
|
|
451 |
s = true;
|
|
|
452 |
} else {
|
|
|
453 |
c = (c>=32 && c<63232 ? c : 0); // avoid generating keyChar for non-printables
|
|
|
454 |
}
|
|
|
455 |
return del._synthesizeEvent(evt, {charCode: c, shiftKey: s, keyCode: k});
|
|
|
456 |
}
|
|
|
457 |
return evt;
|
|
|
458 |
}
|
|
|
459 |
});
|
|
|
460 |
|
|
|
461 |
dojo.mixin(dojo.keys, {
|
|
|
462 |
SHIFT_TAB: 25,
|
|
|
463 |
UP_ARROW: 63232,
|
|
|
464 |
DOWN_ARROW: 63233,
|
|
|
465 |
LEFT_ARROW: 63234,
|
|
|
466 |
RIGHT_ARROW: 63235,
|
|
|
467 |
F1: 63236,
|
|
|
468 |
F2: 63237,
|
|
|
469 |
F3: 63238,
|
|
|
470 |
F4: 63239,
|
|
|
471 |
F5: 63240,
|
|
|
472 |
F6: 63241,
|
|
|
473 |
F7: 63242,
|
|
|
474 |
F8: 63243,
|
|
|
475 |
F9: 63244,
|
|
|
476 |
F10: 63245,
|
|
|
477 |
F11: 63246,
|
|
|
478 |
F12: 63247,
|
|
|
479 |
PAUSE: 63250,
|
|
|
480 |
DELETE: 63272,
|
|
|
481 |
HOME: 63273,
|
|
|
482 |
END: 63275,
|
|
|
483 |
PAGE_UP: 63276,
|
|
|
484 |
PAGE_DOWN: 63277,
|
|
|
485 |
INSERT: 63302,
|
|
|
486 |
PRINT_SCREEN: 63248,
|
|
|
487 |
SCROLL_LOCK: 63249,
|
|
|
488 |
NUM_LOCK: 63289
|
|
|
489 |
});
|
|
|
490 |
var dk = dojo.keys, identifierMap = { "Up": dk.UP_ARROW, "Down": dk.DOWN_ARROW, "Left": dk.LEFT_ARROW, "Right": dk.RIGHT_ARROW, "PageUp": dk.PAGE_UP, "PageDown": dk.PAGE_DOWN };
|
|
|
491 |
}
|
|
|
492 |
})();
|
|
|
493 |
|
|
|
494 |
if(dojo.isIE){
|
|
|
495 |
// keep this out of the closure
|
|
|
496 |
// closing over 'iel' or 'ieh' b0rks leak prevention
|
|
|
497 |
// ls[i] is an index into the master handler array
|
|
|
498 |
dojo._getIeDispatcher = function(){
|
|
|
499 |
return function(){
|
|
|
500 |
var ap=Array.prototype, h=dojo._ie_listener.handlers, c=arguments.callee, ls=c._listeners, t=h[c.target];
|
|
|
501 |
// return value comes from original target function
|
|
|
502 |
var r = t && t.apply(this, arguments);
|
|
|
503 |
// invoke listeners after target function
|
|
|
504 |
for(var i in ls){
|
|
|
505 |
if(!(i in ap)){
|
|
|
506 |
h[ls[i]].apply(this, arguments);
|
|
|
507 |
}
|
|
|
508 |
}
|
|
|
509 |
return r;
|
|
|
510 |
}
|
|
|
511 |
}
|
|
|
512 |
// keep this out of the closure to reduce RAM allocation
|
|
|
513 |
dojo._event_listener._fixCallback = function(fp){
|
|
|
514 |
var f = dojo._event_listener._fixEvent;
|
|
|
515 |
return function(e){ return fp.call(this, f(e, this)); };
|
|
|
516 |
}
|
|
|
517 |
}
|
|
|
518 |
|
|
|
519 |
}
|