]> git.wh0rd.org - tt-rss.git/blame - lib/dojo/_base/event.js
upgrade Dojo to 1.6.1
[tt-rss.git] / lib / dojo / _base / event.js
CommitLineData
2f01fe57 1/*
81bea17a 2 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
2f01fe57
AD
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
5*/
6
7
a089699c
AD
8if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9dojo._hasResource["dojo._base.event"] = true;
2f01fe57
AD
10dojo.provide("dojo._base.event");
11dojo.require("dojo._base.connect");
a089699c 12
81bea17a 13
a089699c
AD
14// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
15
2f01fe57 16(function(){
a089699c
AD
17 // DOM event listener machinery
18 var del = (dojo._event_listener = {
19 add: function(/*DOMNode*/ node, /*String*/ name, /*Function*/ fp){
81bea17a 20 if(!node){return;}
a089699c
AD
21 name = del._normalizeEventName(name);
22 fp = del._fixCallback(name, fp);
a089699c 23 if(
81bea17a 24 !dojo.isIE &&
a089699c
AD
25 (name == "mouseenter" || name == "mouseleave")
26 ){
27 var ofp = fp;
a089699c
AD
28 name = (name == "mouseenter") ? "mouseover" : "mouseout";
29 fp = function(e){
30 if(!dojo.isDescendant(e.relatedTarget, node)){
31 // e.type = oname; // FIXME: doesn't take? SJM: event.type is generally immutable.
81bea17a 32 return ofp.call(this, e);
a089699c
AD
33 }
34 }
35 }
36 node.addEventListener(name, fp, false);
37 return fp; /*Handle*/
38 },
39 remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
40 // summary:
41 // clobbers the listener from the node
42 // node:
43 // DOM node to attach the event to
44 // event:
45 // the name of the handler to remove the function from
46 // handle:
47 // the handle returned from add
48 if(node){
49 event = del._normalizeEventName(event);
50 if(!dojo.isIE && (event == "mouseenter" || event == "mouseleave")){
51 event = (event == "mouseenter") ? "mouseover" : "mouseout";
52 }
53
54 node.removeEventListener(event, handle, false);
55 }
56 },
57 _normalizeEventName: function(/*String*/ name){
58 // Generally, name should be lower case, unless it is special
59 // somehow (e.g. a Mozilla DOM event).
60 // Remove 'on'.
61 return name.slice(0,2) =="on" ? name.slice(2) : name;
62 },
63 _fixCallback: function(/*String*/ name, fp){
64 // By default, we only invoke _fixEvent for 'keypress'
65 // If code is added to _fixEvent for other events, we have
66 // to revisit this optimization.
67 // This also applies to _fixEvent overrides for Safari and Opera
68 // below.
69 return name != "keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); };
70 },
71 _fixEvent: function(evt, sender){
72 // _fixCallback only attaches us to keypress.
81bea17a 73 // Switch on evt.type anyway because we might
a089699c
AD
74 // be called directly from dojo.fixEvent.
75 switch(evt.type){
76 case "keypress":
77 del._setKeyChar(evt);
78 break;
79 }
80 return evt;
81 },
82 _setKeyChar: function(evt){
81bea17a 83 evt.keyChar = evt.charCode >= 32 ? String.fromCharCode(evt.charCode) : '';
a089699c
AD
84 evt.charOrCode = evt.keyChar || evt.keyCode;
85 },
86 // For IE and Safari: some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
87 // we map those virtual key codes to ascii here
88 // not valid for all (non-US) keyboards, so maybe we shouldn't bother
81bea17a
AD
89 _punctMap: {
90 106:42,
91 111:47,
92 186:59,
93 187:43,
94 188:44,
95 189:45,
96 190:46,
97 191:47,
98 192:96,
99 219:91,
100 220:92,
101 221:93,
102 222:39
a089699c
AD
103 }
104 });
105
106 // DOM events
107
108 dojo.fixEvent = function(/*Event*/ evt, /*DOMNode*/ sender){
109 // summary:
110 // normalizes properties on the event object including event
111 // bubbling methods, keystroke normalization, and x/y positions
112 // evt: Event
113 // native event object
114 // sender: DOMNode
115 // node to treat as "currentTarget"
116 return del._fixEvent(evt, sender);
81bea17a 117 };
a089699c
AD
118
119 dojo.stopEvent = function(/*Event*/ evt){
120 // summary:
121 // prevents propagation and clobbers the default action of the
122 // passed event
123 // evt: Event
124 // The event object. If omitted, window.event is used on IE.
125 evt.preventDefault();
126 evt.stopPropagation();
127 // NOTE: below, this method is overridden for IE
81bea17a 128 };
a089699c
AD
129
130 // the default listener to use on dontFix nodes, overriden for IE
131 var node_listener = dojo._listener;
132
133 // Unify connect and event listeners
134 dojo._connect = function(obj, event, context, method, dontFix){
135 // FIXME: need a more strict test
136 var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
137 // choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
138 // we need the third option to provide leak prevention on broken browsers (IE)
139 var lid = isNode ? (dontFix ? 2 : 1) : 0, l = [dojo._listener, del, node_listener][lid];
140 // create a listener
141 var h = l.add(obj, event, dojo.hitch(context, method));
142 // formerly, the disconnect package contained "l" directly, but if client code
81bea17a 143 // leaks the disconnect package (by connecting it to a node), referencing "l"
a089699c
AD
144 // compounds the problem.
145 // instead we return a listener id, which requires custom _disconnect below.
146 // return disconnect package
147 return [ obj, event, h, lid ];
81bea17a 148 };
a089699c
AD
149
150 dojo._disconnect = function(obj, event, handle, listener){
151 ([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
81bea17a 152 };
a089699c
AD
153
154 // Constants
155
156 // Public: client code should test
157 // keyCode against these named constants, as the
158 // actual codes can vary by browser.
159 dojo.keys = {
160 // summary:
161 // Definitions for common key values
162 BACKSPACE: 8,
163 TAB: 9,
164 CLEAR: 12,
165 ENTER: 13,
166 SHIFT: 16,
167 CTRL: 17,
168 ALT: 18,
169 META: dojo.isSafari ? 91 : 224, // the apple key on macs
170 PAUSE: 19,
171 CAPS_LOCK: 20,
172 ESCAPE: 27,
173 SPACE: 32,
174 PAGE_UP: 33,
175 PAGE_DOWN: 34,
176 END: 35,
177 HOME: 36,
178 LEFT_ARROW: 37,
179 UP_ARROW: 38,
180 RIGHT_ARROW: 39,
181 DOWN_ARROW: 40,
182 INSERT: 45,
183 DELETE: 46,
184 HELP: 47,
185 LEFT_WINDOW: 91,
186 RIGHT_WINDOW: 92,
187 SELECT: 93,
188 NUMPAD_0: 96,
189 NUMPAD_1: 97,
190 NUMPAD_2: 98,
191 NUMPAD_3: 99,
192 NUMPAD_4: 100,
193 NUMPAD_5: 101,
194 NUMPAD_6: 102,
195 NUMPAD_7: 103,
196 NUMPAD_8: 104,
197 NUMPAD_9: 105,
198 NUMPAD_MULTIPLY: 106,
199 NUMPAD_PLUS: 107,
200 NUMPAD_ENTER: 108,
201 NUMPAD_MINUS: 109,
202 NUMPAD_PERIOD: 110,
203 NUMPAD_DIVIDE: 111,
204 F1: 112,
205 F2: 113,
206 F3: 114,
207 F4: 115,
208 F5: 116,
209 F6: 117,
210 F7: 118,
211 F8: 119,
212 F9: 120,
213 F10: 121,
214 F11: 122,
215 F12: 123,
216 F13: 124,
217 F14: 125,
218 F15: 126,
219 NUM_LOCK: 144,
220 SCROLL_LOCK: 145,
221 // virtual key mapping
222 copyKey: dojo.isMac && !dojo.isAIR ? (dojo.isSafari ? 91 : 224 ) : 17
223 };
224
225 var evtCopyKey = dojo.isMac ? "metaKey" : "ctrlKey";
226
227 dojo.isCopyKey = function(e){
228 // summary:
229 // Checks an event for the copy key (meta on Mac, and ctrl anywhere else)
230 // e: Event
231 // Event object to examine
232 return e[evtCopyKey]; // Boolean
233 };
234
235 // Public: decoding mouse buttons from events
236
237/*=====
238 dojo.mouseButtons = {
239 // LEFT: Number
240 // Numeric value of the left mouse button for the platform.
241 LEFT: 0,
242 // MIDDLE: Number
243 // Numeric value of the middle mouse button for the platform.
244 MIDDLE: 1,
245 // RIGHT: Number
246 // Numeric value of the right mouse button for the platform.
247 RIGHT: 2,
248
249 isButton: function(e, button){
250 // summary:
251 // Checks an event object for a pressed button
252 // e: Event
253 // Event object to examine
254 // button: Number
255 // The button value (example: dojo.mouseButton.LEFT)
256 return e.button == button; // Boolean
257 },
258 isLeft: function(e){
259 // summary:
260 // Checks an event object for the pressed left button
261 // e: Event
262 // Event object to examine
263 return e.button == 0; // Boolean
264 },
265 isMiddle: function(e){
266 // summary:
267 // Checks an event object for the pressed middle button
268 // e: Event
269 // Event object to examine
270 return e.button == 1; // Boolean
271 },
272 isRight: function(e){
273 // summary:
274 // Checks an event object for the pressed right button
275 // e: Event
276 // Event object to examine
277 return e.button == 2; // Boolean
278 }
279 };
280=====*/
281
81bea17a 282 if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
a089699c
AD
283 dojo.mouseButtons = {
284 LEFT: 1,
285 MIDDLE: 4,
286 RIGHT: 2,
287 // helper functions
288 isButton: function(e, button){ return e.button & button; },
289 isLeft: function(e){ return e.button & 1; },
290 isMiddle: function(e){ return e.button & 4; },
291 isRight: function(e){ return e.button & 2; }
292 };
293 }else{
294 dojo.mouseButtons = {
295 LEFT: 0,
296 MIDDLE: 1,
297 RIGHT: 2,
298 // helper functions
299 isButton: function(e, button){ return e.button == button; },
300 isLeft: function(e){ return e.button == 0; },
301 isMiddle: function(e){ return e.button == 1; },
302 isRight: function(e){ return e.button == 2; }
303 };
304 }
305
306 // IE event normalization
81bea17a 307 if(dojo.isIE){
a089699c
AD
308 var _trySetKeyCode = function(e, code){
309 try{
310 // squelch errors when keyCode is read-only
311 // (e.g. if keyCode is ctrl or shift)
312 return (e.keyCode = code);
313 }catch(e){
314 return 0;
315 }
81bea17a 316 };
a089699c
AD
317
318 // by default, use the standard listener
319 var iel = dojo._listener;
320 var listenersName = (dojo._ieListenersName = "_" + dojo._scopeName + "_listeners");
321 // dispatcher tracking property
322 if(!dojo.config._allow_leaks){
323 // custom listener that handles leak protection for DOM events
324 node_listener = iel = dojo._ie_listener = {
81bea17a 325 // support handler indirection: event handler functions are
a089699c
AD
326 // referenced here. Event dispatchers hold only indices.
327 handlers: [],
328 // add a listener to an object
329 add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
330 source = source || dojo.global;
331 var f = source[method];
332 if(!f||!f[listenersName]){
333 var d = dojo._getIeDispatcher();
334 // original target function is special
335 d.target = f && (ieh.push(f) - 1);
336 // dispatcher holds a list of indices into handlers table
337 d[listenersName] = [];
338 // redirect source to dispatcher
339 f = source[method] = d;
340 }
341 return f[listenersName].push(ieh.push(listener) - 1) ; /*Handle*/
342 },
343 // remove a listener from an object
344 remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
345 var f = (source||dojo.global)[method], l = f && f[listenersName];
346 if(f && l && handle--){
347 delete ieh[l[handle]];
348 delete l[handle];
349 }
350 }
351 };
352 // alias used above
353 var ieh = iel.handlers;
354 }
355
356 dojo.mixin(del, {
357 add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
358 if(!node){return;} // undefined
359 event = del._normalizeEventName(event);
360 if(event=="onkeypress"){
361 // we need to listen to onkeydown to synthesize
362 // keypress events that otherwise won't fire
363 // on IE
364 var kd = node.onkeydown;
365 if(!kd || !kd[listenersName] || !kd._stealthKeydownHandle){
366 var h = del.add(node, "onkeydown", del._stealthKeyDown);
367 kd = node.onkeydown;
368 kd._stealthKeydownHandle = h;
369 kd._stealthKeydownRefs = 1;
370 }else{
371 kd._stealthKeydownRefs++;
372 }
373 }
374 return iel.add(node, event, del._fixCallback(fp));
375 },
376 remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
377 event = del._normalizeEventName(event);
81bea17a 378 iel.remove(node, event, handle);
a089699c
AD
379 if(event=="onkeypress"){
380 var kd = node.onkeydown;
381 if(--kd._stealthKeydownRefs <= 0){
382 iel.remove(node, "onkeydown", kd._stealthKeydownHandle);
383 delete kd._stealthKeydownHandle;
384 }
385 }
386 },
387 _normalizeEventName: function(/*String*/ eventName){
388 // Generally, eventName should be lower case, unless it is
389 // special somehow (e.g. a Mozilla event)
390 // ensure 'on'
391 return eventName.slice(0,2) != "on" ? "on" + eventName : eventName;
392 },
393 _nop: function(){},
394 _fixEvent: function(/*Event*/ evt, /*DOMNode*/ sender){
395 // summary:
396 // normalizes properties on the event object including event
397 // bubbling methods, keystroke normalization, and x/y positions
398 // evt:
399 // native event object
400 // sender:
401 // node to treat as "currentTarget"
402 if(!evt){
403 var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window;
81bea17a 404 evt = w.event;
a089699c
AD
405 }
406 if(!evt){return(evt);}
81bea17a
AD
407 evt.target = evt.srcElement;
408 evt.currentTarget = (sender || evt.srcElement);
a089699c
AD
409 evt.layerX = evt.offsetX;
410 evt.layerY = evt.offsetY;
411 // FIXME: scroll position query is duped from dojo.html to
412 // avoid dependency on that entire module. Now that HTML is in
413 // Base, we should convert back to something similar there.
414 var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
415 // DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
416 // here rather than document.body
417 var docBody = ((dojo.isIE < 6) || (doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
418 var offset = dojo._getIeDocumentElementOffset();
419 evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
420 evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
81bea17a 421 if(evt.type == "mouseover"){
a089699c
AD
422 evt.relatedTarget = evt.fromElement;
423 }
81bea17a 424 if(evt.type == "mouseout"){
a089699c
AD
425 evt.relatedTarget = evt.toElement;
426 }
81bea17a
AD
427 if (dojo.isIE < 9 || dojo.isQuirks) {
428 evt.stopPropagation = del._stopPropagation;
429 evt.preventDefault = del._preventDefault;
430 }
a089699c
AD
431 return del._fixKeys(evt);
432 },
433 _fixKeys: function(evt){
434 switch(evt.type){
435 case "keypress":
436 var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
437 if (c==10){
438 // CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
439 c=0;
440 evt.keyCode = 13;
441 }else if(c==13||c==27){
442 c=0; // Mozilla considers ENTER and ESC non-printable
443 }else if(c==3){
444 c=99; // Mozilla maps CTRL-BREAK to CTRL-c
445 }
446 // Mozilla sets keyCode to 0 when there is a charCode
447 // but that stops the event on IE.
448 evt.charCode = c;
449 del._setKeyChar(evt);
450 break;
451 }
452 return evt;
453 },
454 _stealthKeyDown: function(evt){
455 // IE doesn't fire keypress for most non-printable characters.
456 // other browsers do, we simulate it here.
457 var kp = evt.currentTarget.onkeypress;
458 // only works if kp exists and is a dispatcher
459 if(!kp || !kp[listenersName]){ return; }
460 // munge key/charCode
461 var k=evt.keyCode;
462 // These are Windows Virtual Key Codes
463 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
81bea17a
AD
464 var unprintable = (k!=13 || (dojo.isIE >= 9 && !dojo.isQuirks)) && k!=32 && k!=27 && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222);
465
a089699c
AD
466 // synthesize keypress for most unprintables and CTRL-keys
467 if(unprintable||evt.ctrlKey){
468 var c = unprintable ? 0 : k;
469 if(evt.ctrlKey){
470 if(k==3 || k==13){
81bea17a
AD
471 return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
472 }else if(c>95 && c<106){
a089699c 473 c -= 48; // map CTRL-[numpad 0-9] to ASCII
81bea17a 474 }else if((!evt.shiftKey)&&(c>=65&&c<=90)){
a089699c 475 c += 32; // map CTRL-[A-Z] to lowercase
81bea17a 476 }else{
a089699c
AD
477 c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
478 }
479 }
480 // simulate a keypress event
481 var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
482 kp.call(evt.currentTarget, faux);
81bea17a
AD
483 if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
484 evt.cancelBubble = faux.cancelBubble;
485 }
a089699c
AD
486 evt.returnValue = faux.returnValue;
487 _trySetKeyCode(evt, faux.keyCode);
488 }
489 },
490 // Called in Event scope
491 _stopPropagation: function(){
81bea17a 492 this.cancelBubble = true;
a089699c
AD
493 },
494 _preventDefault: function(){
495 // Setting keyCode to 0 is the only way to prevent certain keypresses (namely
496 // ctrl-combinations that correspond to menu accelerator keys).
497 // Otoh, it prevents upstream listeners from getting this information
81bea17a 498 // Try to split the difference here by clobbering keyCode only for ctrl
a089699c
AD
499 // combinations. If you still need to access the key upstream, bubbledKeyCode is
500 // provided as a workaround.
501 this.bubbledKeyCode = this.keyCode;
502 if(this.ctrlKey){_trySetKeyCode(this, 0);}
503 this.returnValue = false;
504 }
505 });
506
507 // override stopEvent for IE
81bea17a 508 dojo.stopEvent = (dojo.isIE < 9 || dojo.isQuirks) ? function(evt){
a089699c
AD
509 evt = evt || window.event;
510 del._stopPropagation.call(evt);
511 del._preventDefault.call(evt);
81bea17a 512 } : dojo.stopEvent;
a089699c
AD
513 }
514
515 del._synthesizeEvent = function(evt, props){
516 var faux = dojo.mixin({}, evt, props);
517 del._setKeyChar(faux);
81bea17a 518 // FIXME: would prefer to use dojo.hitch: dojo.hitch(evt, evt.preventDefault);
a089699c
AD
519 // but it throws an error when preventDefault is invoked on Safari
520 // does Event.preventDefault not support "apply" on Safari?
81bea17a
AD
521 faux.preventDefault = function(){ evt.preventDefault(); };
522 faux.stopPropagation = function(){ evt.stopPropagation(); };
a089699c 523 return faux;
81bea17a 524 };
a089699c
AD
525
526 // Opera event normalization
527 if(dojo.isOpera){
528 dojo.mixin(del, {
529 _fixEvent: function(evt, sender){
530 switch(evt.type){
531 case "keypress":
532 var c = evt.which;
533 if(c==3){
534 c=99; // Mozilla maps CTRL-BREAK to CTRL-c
535 }
536 // can't trap some keys at all, like INSERT and DELETE
537 // there is no differentiating info between DELETE and ".", or INSERT and "-"
538 c = c<41 && !evt.shiftKey ? 0 : c;
539 if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
540 // lowercase CTRL-[A-Z] keys
541 c += 32;
542 }
543 return del._synthesizeEvent(evt, { charCode: c });
544 }
545 return evt;
546 }
547 });
548 }
549
550 // Webkit event normalization
551 if(dojo.isWebKit){
552 del._add = del.add;
553 del._remove = del.remove;
554
555 dojo.mixin(del, {
556 add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
557 if(!node){return;} // undefined
558 var handle = del._add(node, event, fp);
559 if(del._normalizeEventName(event) == "keypress"){
560 // we need to listen to onkeydown to synthesize
561 // keypress events that otherwise won't fire
562 // in Safari 3.1+: https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html
563 handle._stealthKeyDownHandle = del._add(node, "keydown", function(evt){
564 //A variation on the IE _stealthKeydown function
565 //Synthesize an onkeypress event, but only for unprintable characters.
566 var k=evt.keyCode;
567 // These are Windows Virtual Key Codes
568 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
569 var unprintable = k!=13 && k!=32 && (k<48 || k>90) && (k<96 || k>111) && (k<186 || k>192) && (k<219 || k>222);
570 // synthesize keypress for most unprintables and CTRL-keys
571 if(unprintable || evt.ctrlKey){
572 var c = unprintable ? 0 : k;
573 if(evt.ctrlKey){
574 if(k==3 || k==13){
81bea17a
AD
575 return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
576 }else if(c>95 && c<106){
a089699c 577 c -= 48; // map CTRL-[numpad 0-9] to ASCII
81bea17a 578 }else if(!evt.shiftKey && c>=65 && c<=90){
a089699c 579 c += 32; // map CTRL-[A-Z] to lowercase
81bea17a 580 }else{
a089699c
AD
581 c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
582 }
583 }
584 // simulate a keypress event
585 var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
586 fp.call(evt.currentTarget, faux);
587 }
588 });
589 }
590 return handle; /*Handle*/
591 },
592
593 remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
594 if(node){
595 if(handle._stealthKeyDownHandle){
596 del._remove(node, "keydown", handle._stealthKeyDownHandle);
597 }
598 del._remove(node, event, handle);
599 }
600 },
601 _fixEvent: function(evt, sender){
602 switch(evt.type){
603 case "keypress":
604 if(evt.faux){ return evt; }
605 var c = evt.charCode;
606 c = c>=32 ? c : 0;
607 return del._synthesizeEvent(evt, {charCode: c, faux: true});
608 }
609 return evt;
610 }
611 });
612 }
613 })();
614
2f01fe57 615if(dojo.isIE){
a089699c
AD
616 // keep this out of the closure
617 // closing over 'iel' or 'ieh' b0rks leak prevention
618 // ls[i] is an index into the master handler array
619 dojo._ieDispatcher = function(args, sender){
620 var ap = Array.prototype,
621 h = dojo._ie_listener.handlers,
622 c = args.callee,
623 ls = c[dojo._ieListenersName],
624 t = h[c.target];
625 // return value comes from original target function
626 var r = t && t.apply(sender, args);
627 // make local copy of listener array so it's immutable during processing
628 var lls = [].concat(ls);
629 // invoke listeners after target function
630 for(var i in lls){
631 var f = h[lls[i]];
632 if(!(i in ap) && f){
633 f.apply(sender, args);
634 }
635 }
636 return r;
81bea17a 637 };
a089699c
AD
638 dojo._getIeDispatcher = function(){
639 // ensure the returned function closes over nothing ("new Function" apparently doesn't close)
640 return new Function(dojo._scopeName + "._ieDispatcher(arguments, this)"); // function
81bea17a 641 };
a089699c
AD
642 // keep this out of the closure to reduce RAM allocation
643 dojo._event_listener._fixCallback = function(fp){
644 var f = dojo._event_listener._fixEvent;
645 return function(e){ return fp.call(this, f(e, this)); };
81bea17a 646 };
2f01fe57 647}
a089699c 648
2f01fe57 649}