source: gs3-extensions/seaweed-debug/trunk/src/events/Events.js@ 25160

Last change on this file since 25160 was 25160, checked in by sjm84, 12 years ago

Initial cut at a version of seaweed for debugging purposes. Check it out live into the web/ext folder

File size: 9.0 KB
Line 
1/*
2 * file: Events.js
3 *
4 * @BEGINLICENSE
5 * Copyright 2010 Brook Novak (email : [email protected])
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 * @ENDLICENSE
18 */
19bootstrap.provides("events.Events");
20
21/**
22 * Adds an event handler to a DOM Event Source.
23 *
24 * If you are planning to listen for keyboard strokes, you can use "keystroke." This uses keydown and/or keypress
25 * and provides an extra argument to your handler containing the normalized key identifier string.
26 *
27 * @param {Object} eventSource The Element or Window to add the event to.
28 *
29 * @param {String} eventName The name of the dom event. Must be lowercase and omit the "on" prefix. For example "load" or "keypress".
30 *
31 * @param {Function} handler A function to handle the event being registered. When called, the dom event will
32 * be passed as the first (and only) argument.
33 */
34function _addHandler(sourceEle, eventName, handlerFunc) {
35
36 debug.assert(sourceEle.nodeType != Node.TEXT_NODE && sourceEle.nodeType != Node.COMMENT_NODE);
37 debug.assert(eventName.indexOf('on') !== 0);
38
39 // IE has trouble passing the window object around - it can be cloned for no reason
40 if (sourceEle.setInterval && sourceEle != window)
41 sourceEle = window;
42
43 switch(eventName) {
44
45 case "keystroke":
46 // Keystroke is a combo of keydown and key press - normalizes
47 // key identifiers and passes them as extra arg to handler
48 addEventHandler(sourceEle, "keydown", function(e) {
49 var keyIndent = de.events.Keyboard.getKeyIdentifier(e, true);
50 if (keyIndent)
51 return handlerFunc(e, keyIndent);
52 });
53 addEventHandler(sourceEle, "keypress", function(e) {
54 var keyIndent = de.events.Keyboard.getKeyIdentifier(e, false);
55 if (keyIndent)
56 return handlerFunc(e, keyIndent);
57 });
58 break;
59
60 case "mousedown": // Keep mouse state updated
61 addEventHandler(sourceEle, eventName, function(e) {
62 return de.events.Mouse.sniffMouseDownEvent(e) ? handlerFunc(e) : true;
63 });
64 break;
65 case "mouseup": // Keep mouse state updated
66 addEventHandler(sourceEle, eventName, function(e) {
67 return de.events.Mouse.sniffMouseUpEvent(e) ? handlerFunc(e) : true;
68 });
69 break;
70 case "mousemove": // Keep mouse state updated
71 addEventHandler(sourceEle, eventName, function(e) {
72 return de.events.Mouse.sniffMouseMoveEvent(e) ? handlerFunc(e) : true;
73 });
74 break;
75
76 default:
77 addEventHandler(sourceEle, eventName, handlerFunc);
78 }
79
80 function addEventHandler(sourceEle, eventName, actualHandler) {
81
82 // Keep track of wrapper handlers for removal
83
84 // Create event wrapper map (Event type -> tuple[event-source, wrapper handler])
85 if (!handlerFunc.evWrappers)
86 handlerFunc.evWrappers = {};
87
88 // Ensure the map contains an entry for this event type
89 if (!handlerFunc.evWrappers[eventName])
90 handlerFunc.evWrappers[eventName] = [];
91
92 // Store this event tuple
93 handlerFunc.evWrappers[eventName].push([sourceEle, forwardEvent]);
94
95 if (sourceEle.addEventListener)
96 sourceEle.addEventListener(eventName, forwardEvent, false); // DOM Compliant
97
98 else if (sourceEle.attachEvent)
99 sourceEle.attachEvent("on" + eventName, forwardEvent); // IE
100
101 // @DEBUG ON
102 else debug.assert(false, "Unsupported browser: does not support addEventListener or attachEvent");
103 // @DEBUG OFF
104
105 /**
106 * Wraps an event handler so that the event handler gets a non null event
107 * and if the handler returns false the event is consumed.
108 * @param {Event} e provided by native event dispatcher
109 */
110 function forwardEvent(e){
111 de.events.current = e = e || window.event;
112 try {
113 if (actualHandler(e) === false)
114 return de.events.consume(e);
115 } finally {
116 de.events.current = 0;
117 }
118 }
119
120 }
121
122}
123
124/**
125 * Removes an event handler from a DOM Event Source.
126 *
127 * @param {Object} eventSource The Element or Window to add the event to.
128 *
129 * @param {String} eventName The name of the dom event. Must be lowercase and omit the "on" prefix. For example "load" or "keypress".
130 *
131 * @param {Function} handler The handler function to remove form the given event source.
132 */
133function _removeHandler(sourceEle, eventName, handlerFunc){
134 debug.assert(eventName.indexOf('on') !== 0);
135
136 // Keystoke is comprized of keydown and key press
137 if (eventName == "keystroke") {
138 _removeHandler(sourceEle, 'keydown', handlerFunc);
139 _removeHandler(sourceEle, 'keypress', handlerFunc);
140 return;
141 }
142
143 // Check if the handler has been wrapped for this event type / source
144 if (handlerFunc.evWrappers && handlerFunc.evWrappers[eventName]) {
145
146 // Look for wrapper handlers for this event type for this handler
147 for (var i in handlerFunc.evWrappers[eventName]) {
148
149 var tuple = handlerFunc.evWrappers[eventName][i];
150
151 // Was there a wrapped handler create for this handler on this event type and source?
152 if (tuple[0] == sourceEle) {
153
154 // Remove tuple
155 if (handlerFunc.evWrappers[eventName].length == 1)
156 delete handlerFunc.evWrappers[eventName];
157 else
158 handlerFunc.evWrappers[eventName].splice(i, 1);
159
160 // Assign handlerFunc to be the wrapped handler
161 handlerFunc = tuple[1];
162
163 break;
164 }
165
166 }
167
168 }
169
170 // Remove the handler from the event source
171 if (sourceEle.removeEventListener)
172 sourceEle.removeEventListener(eventName, handlerFunc, false); // DOM Compliant
173
174 else if (sourceEle.detachEvent)
175 sourceEle.detachEvent("on" + eventName, handlerFunc); // IE
176
177 // @DEBUG ON
178 else debug.assert(false, "Unsupported browser: does not support addEventListener or attachEvent");
179 // @DEBUG OFF
180
181}
182
183
184$extend(de.events, {
185
186 /**
187 * A pointer to the current event
188 */
189 current : 0,
190
191 addHandler : _addHandler,
192
193 removeHandler : _removeHandler,
194
195 /**
196 * @param {Event} e An event
197 *
198 * @return {Object} The x and y coordinates of the event relative to the window.
199 */
200 getXYInWindowFromEvent : function(e){
201
202 var targetX = 0, targetY = 0;
203
204 if (e.clientX || e.clientX === 0) {
205 targetX = e.clientX;
206 targetY = e.clientY;
207 } else if (e.pageX != null) {
208 var scrollPos = _getDocumentScrollPos();
209 targetX = e.pageX - scrollPos.left;
210 targetY = e.pageY - scrollPos.top;
211 }
212
213 return {x : targetX, y : targetY };
214 },
215
216 /**
217 *
218 * @param {Event} e A dom event
219 * @return {Node} An element or text node which the event was targetted at.
220 */
221 getEventTarget: function(e) {
222 return e.target || e.srcElement || document;
223 },
224
225 /**
226 * Consumes an event... stop is from propagating and prevents the default action.
227 *
228 * @example
229 * myhandlers = function(e) {
230 * ...
231 * if (somecondition) return de.events.consume(e);
232 * return true;
233 * }
234 *
235 * @param {Event} e A dom event.
236 *
237 * @return {Boolean} False always.
238 */
239 consume : function(e) {
240 de.events.stopPropogation(e);
241 de.events.preventDefault(e);
242 return false;
243 },
244
245 /**
246 * Stops the event from propogating / bubbling.
247 * @param {Event} e A dom event.
248 */
249 stopPropogation : function(e) {
250 if (_engine == _Platform.TRIDENT)
251 e.cancelBubble = true;
252 else if (e.stopPropagation)
253 e.stopPropagation();
254 },
255
256 /**
257 * Prevents the default behaviour from occuring on a given event.
258 * @param {Event} e An event object
259 */
260 preventDefault : function(e) {
261 if (_engine == _Platform.TRIDENT)
262 e.returnValue = false;
263 else if(e.preventDefault)
264 e.preventDefault();
265 }
266
267});
268
Note: See TracBrowser for help on using the repository browser.