Refactoring en cours.
[Plinn.git] / skins / ajax_scripts / javascript_events_api.js
1 // (c) BenoƮt PIN 2006-2009
2 // http://plinn.org
3 // Licence GPL
4 //
5 //
6 // Meta functions for events management.
7
8 var addListener; /* (ob, eventName, listenerFunction, group) add event listener eventName without "on" prefix.
9 * optionally, listeners can be grouped to make removing convenient.
10 */
11 var removeListener; // (ob, eventName, listenerFunction, group) remove event listener.
12 var removeGroupListeners; // (group) remove all listeners in group.
13 var raiseMouseEvent; // (ob, eventName) raise mouse event (without "on" prefix) on object.
14
15 var getTargetedObject; // (event) retrieves the object that fired the event. Event parameter is optional.
16 var getEventObject; // (event) return the event object. Event parameter is optional.
17 var disableDefault; // (event) disable default event's action. Event parameter is optional.
18 var disablePropagation; // (event) disable event propagation or bubbling.
19
20 // etc utils
21 var getWindowWidth; // returns browser's window width
22 var getWindowHeight; // returns browser's window height
23 var clearSelection; // clear current selection (useful on drag and drop)
24 var getCopyOfNode; /* (node) returns a clone of the given node.
25 * Useful when :
26 * the node came from a foreign document (eg. XmlHttpRequest xml reponse)
27 * to inject HMTL code inside tags where innerHtml is read only (IE)
28 */
29 var copyPrototype; // (descendant, parent) lightwheight javascript inheritance
30
31 (function(){
32
33 function buildMetaFunctions() {
34 addListener = _build_addListener();
35 removeListener = _build_removeListener();
36 raiseMouseEvent = _build_raiseMouseEvent();
37
38 getTargetedObject = _build_getTargetedObject();
39 getEventObject = _build_getEventObject();
40 disableDefault = _build_disableDefault();
41 disablePropagation = _build_disablePropagation();
42 getWindowWidth = _build_getWindowWidth();
43 getWindowHeight = _build_getWindowHeight();
44 clearSelection = _build_clearSelection();
45 }
46
47 __groupListeners = {};
48
49 function _build_addListener() {
50 var _browserSpecific;
51 if (browser.isIE55 || browser.isIE6up) {
52 _browserSpecific = function(ob, eventName, listenerFunction) {
53 eventName = "on" + eventName;
54 ob.attachEvent(eventName, listenerFunction);
55 };
56 }
57 else if (browser.isDOM2Event) {
58 _browserSpecific = function(ob, eventName, listenerFunction) {
59 ob.addEventListener(eventName, listenerFunction, false); // only bubbling events :-(
60 };
61 }
62 var common = function(ob, eventName, listenerFunction, group) {
63 _browserSpecific(ob, eventName, listenerFunction);
64 if (group) {
65 if(!__groupListeners[group]) {
66 __groupListeners[group] = [];}
67 __groupListeners[group].push([ob, eventName, listenerFunction]);
68 }
69 };
70 return common;
71 }
72
73 function _build_removeListener() {
74 if (browser.isIE55 || browser.isIE6up) {
75 var _ie_removeListener = function(ob, eventName, listenerFunction) {
76 eventName = "on" + eventName;
77 ob.detachEvent(eventName, listenerFunction);
78 };
79 return _ie_removeListener;
80 }
81 else if (browser.isDOM2Event) {
82 var _dom2_removeListener = function(ob, eventName, listenerFunction) {
83 ob.removeEventListener(eventName, listenerFunction, false); // only bubbling events :-(
84 };
85 return _dom2_removeListener;
86 }
87 }
88
89 removeGroupListeners = function(group) {
90 var listeners = __groupListeners[group];
91 var l, i;
92 for (i=0 ; i<listeners.length ; i++){
93 l = listeners[i];
94 removeListener(l[0], l[1], l[2]);
95 }
96 __groupListeners[group] = null;
97
98 };
99
100 function _build_raiseMouseEvent() {
101 if (browser.isIE55 || browser.isIE6up) {
102 var _ie_raiseMouseEvent = function(ob, eventName) {
103 ob.fireEvent("on" + eventName);
104 };
105 return _ie_raiseMouseEvent;
106 }
107 else if (browser.isDOM2Event) {
108 var _dom2_raiseMouseEvent = function(ob, eventName) {
109 var event = document.createEvent("MouseEvents");
110 event.initEvent(eventName, true, true);
111 ob.dispatchEvent(event);
112 };
113 return _dom2_raiseMouseEvent;
114 }
115 }
116
117 function _build_getTargetedObject(){
118 if (browser.isIE55 || browser.isIE6up) {
119 var _ie_getTargetedObject = function() {
120 return window.event.srcElement;
121 };
122 return _ie_getTargetedObject;
123 }
124 else if (browser.isDOM2Event) {
125 var _appleWebKit_getTargetedeObject = function(evt) {
126 var target = evt.target;
127 // is it really safe ?...
128 return (target.nodeType === 3) ? target.parentNode : target;
129 };
130 var _dom2_getTargetedObject = function(evt) {
131 return evt.target;
132 };
133 return (browser.isAppleWebKit) ? _appleWebKit_getTargetedeObject : _dom2_getTargetedObject;
134 }
135 }
136
137 function _build_getEventObject(){
138 if (browser.isIE) {
139 var _ie_getEventObject = function() {
140 return window.event;
141 };
142 return _ie_getEventObject;
143 }
144 else if (browser.isDOM2Event) {
145 var _dom2_getEventObject = function(evt) {
146 return evt;
147 };
148 return _dom2_getEventObject;
149 }
150 }
151
152
153 function _build_disableDefault(){
154 if (browser.isIE55 || browser.isIE6up) {
155 var _ie_disableDefault = function() {
156 window.event.returnValue = false;
157 };
158 return _ie_disableDefault;
159 }
160 else if (browser.isDOM2Event) {
161 var _dom2_disableDefault = function(evt) {
162 evt.preventDefault();
163 };
164 return _dom2_disableDefault;
165 }
166 }
167
168 function _build_disablePropagation() {
169 if (browser.isIE55 || browser.isIE6up) {
170 var _ie_disablePropagation = function() {
171 window.event.cancelBubble = true;
172 };
173 return _ie_disablePropagation;
174 }
175 else if (browser.isDOM2Event) {
176 var _dom2_disablePropagation = function(evt) {
177 evt.stopPropagation();
178 };
179 return _dom2_disablePropagation;
180 }
181 }
182
183 function _build_getWindowWidth() {
184 if (window.innerWidth !== undefined){
185 return function(){
186 return window.innerWidth;
187 };
188 }
189 else {
190 return function(){
191 return document.documentElement.clientWidth;
192 };
193 }
194 }
195
196 function _build_getWindowHeight() {
197 if (window.innerHeight !== undefined) {
198 return function(){
199 return window.innerHeight;
200 };
201 }
202 else {
203 return function(){
204 return document.documentElement.clientHeight;
205 };
206 }
207 }
208
209 function _build_clearSelection() {
210 if (document.selection) {
211 return function() {
212 document.selection.clear();
213 };
214 }
215 else {
216 return function() {
217 window.getSelection().removeAllRanges();
218 };
219 }
220 }
221
222
223 buildMetaFunctions();
224
225 var ELEMENT_NODE = 1;
226 var TEXT_NODE = 3;
227 var _setAttribute;
228 getCopyOfNode = function(node) {
229
230 switch(node.nodeType) {
231 case ELEMENT_NODE:
232 var attributes = node.attributes;
233 var childs = node.childNodes;
234
235 var e = document.createElement(node.nodeName);
236
237 var attribute, i;
238 for(i=0 ; i<attributes.length ; i++) {
239 attribute = attributes[i];
240 _setAttribute(e, attribute.name, attribute.value);
241 }
242
243 for(i=0 ; i<childs.length ; i++) {
244 e.appendChild(getCopyOfNode(childs[i]));}
245
246 return e;
247
248 case TEXT_NODE:
249 return document.createTextNode(node.nodeValue);
250 }
251 };
252
253 if (browser.isIE) {
254 _setAttribute = function(e, name, value) {
255 // workarround IE lack of dom implementation.
256 switch(name.toLowerCase()) {
257 case 'colspan' :
258 e.colSpan = value;
259 break;
260 case 'class' :
261 e.className = value;
262 break;
263 case 'style' :
264 loadCssText(e, value);
265 break;
266 default:
267 if (name.slice(0,2) === 'on') { // event handler
268 // A browser normaly eval text code attached to a onXyz attribute. Not IE.
269 /*jslint evil: true */
270 e[name] = function(){eval(value);};}
271 else {
272 e.setAttribute(name, value);}
273 }
274 };
275 var reCompoundPropName = /^\s*([^\-]+)\-([a-z])([a-z]+)\s*$/;
276 var _capitalizeCssPropName = function (s, g1, g2, g3) { // gN args match above regexp groups
277 if(g2) {
278 return g1 + g2.toUpperCase() + g3;}
279 else {
280 return s;}
281 };
282
283 var loadCssText = function (e, cssText) {
284 var pairs = cssText.split(';');
285 var pair, name, value, i;
286 var style = e.style;
287 for (i= 0; i < pairs.length; i++) {
288 pair = pairs[i].split(':');
289 if (pair.length === 2) {
290 name = _capitalizeCssPropName(pair[0]);
291 value = pair[1];
292 style[name] = value;
293 }
294 }
295 };
296 }
297 else {
298 _setAttribute = function(e, name, value) {e.setAttribute(name, value);};
299 }
300
301 /*
302 * http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/
303 */
304
305 copyPrototype = function (descendant, parent) {
306 var sConstructor = parent.toString();
307 var aMatch = sConstructor.match( /\s*function (.*)\(/ );
308 if ( aMatch !== null ) { descendant.prototype[aMatch[1]] = parent; }
309 var m;
310 for (m in parent.prototype) {
311 if (parent.prototype.hasOwnProperty(m)) {
312 descendant.prototype[m] = parent.prototype[m]; }
313 }
314 };
315
316 }());