Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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
}