JSLint.
[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
30 (function(){
31
32 function buildMetaFunctions() {
33 addListener = _build_addListener();
34 removeListener = _build_removeListener();
35 raiseMouseEvent = _build_raiseMouseEvent();
36
37 getTargetedObject = _build_getTargetedObject();
38 getEventObject = _build_getEventObject();
39 disableDefault = _build_disableDefault();
40 disablePropagation = _build_disablePropagation();
41 getWindowWidth = _build_getWindowWidth();
42 getWindowHeight = _build_getWindowHeight();
43 clearSelection = _build_clearSelection();
44 }
45
46 __groupListeners = {};
47
48 function _build_addListener() {
49 var _browserSpecific;
50 if (browser.isIE55 || browser.isIE6up) {
51 _browserSpecific = function(ob, eventName, listenerFunction) {
52 eventName = "on" + eventName;
53 ob.attachEvent(eventName, listenerFunction);
54 };
55 }
56 else if (browser.isDOM2Event) {
57 _browserSpecific = function(ob, eventName, listenerFunction) {
58 ob.addEventListener(eventName, listenerFunction, false); // only bubbling events :-(
59 };
60 }
61 var common = function(ob, eventName, listenerFunction, group) {
62 _browserSpecific(ob, eventName, listenerFunction);
63 if (group) {
64 if(!__groupListeners[group]) {
65 __groupListeners[group] = [];}
66 __groupListeners[group].push([ob, eventName, listenerFunction]);
67 }
68 };
69 return common;
70 }
71
72 function _build_removeListener() {
73 if (browser.isIE55 || browser.isIE6up) {
74 var _ie_removeListener = function(ob, eventName, listenerFunction) {
75 eventName = "on" + eventName;
76 ob.detachEvent(eventName, listenerFunction);
77 };
78 return _ie_removeListener;
79 }
80 else if (browser.isDOM2Event) {
81 var _dom2_removeListener = function(ob, eventName, listenerFunction) {
82 ob.removeEventListener(eventName, listenerFunction, false); // only bubbling events :-(
83 };
84 return _dom2_removeListener;
85 }
86 }
87
88 removeGroupListeners = function(group) {
89 var listeners = __groupListeners[group];
90 var l, i;
91 for (i=0 ; i<listeners.length ; i++){
92 l = listeners[i];
93 removeListener(l[0], l[1], l[2]);
94 }
95 __groupListeners[group] = null;
96
97 };
98
99 function _build_raiseMouseEvent() {
100 if (browser.isIE55 || browser.isIE6up) {
101 var _ie_raiseMouseEvent = function(ob, eventName) {
102 ob.fireEvent("on" + eventName);
103 };
104 return _ie_raiseMouseEvent;
105 }
106 else if (browser.isDOM2Event) {
107 var _dom2_raiseMouseEvent = function(ob, eventName) {
108 var event = document.createEvent("MouseEvents");
109 event.initEvent(eventName, true, true);
110 ob.dispatchEvent(event);
111 };
112 return _dom2_raiseMouseEvent;
113 }
114 }
115
116 function _build_getTargetedObject(){
117 if (browser.isIE55 || browser.isIE6up) {
118 var _ie_getTargetedObject = function() {
119 return window.event.srcElement;
120 };
121 return _ie_getTargetedObject;
122 }
123 else if (browser.isDOM2Event) {
124 var _appleWebKit_getTargetedeObject = function(evt) {
125 var target = evt.target;
126 // is it really safe ?...
127 return (target.nodeType === 3) ? target.parentNode : target;
128 };
129 var _dom2_getTargetedObject = function(evt) {
130 return evt.target;
131 };
132 return (browser.isAppleWebKit) ? _appleWebKit_getTargetedeObject : _dom2_getTargetedObject;
133 }
134 }
135
136 function _build_getEventObject(){
137 if (browser.isIE) {
138 var _ie_getEventObject = function() {
139 return window.event;
140 };
141 return _ie_getEventObject;
142 }
143 else if (browser.isDOM2Event) {
144 var _dom2_getEventObject = function(evt) {
145 return evt;
146 };
147 return _dom2_getEventObject;
148 }
149 }
150
151
152 function _build_disableDefault(){
153 if (browser.isIE55 || browser.isIE6up) {
154 var _ie_disableDefault = function() {
155 window.event.returnValue = false;
156 };
157 return _ie_disableDefault;
158 }
159 else if (browser.isDOM2Event) {
160 var _dom2_disableDefault = function(evt) {
161 evt.preventDefault();
162 };
163 return _dom2_disableDefault;
164 }
165 }
166
167 function _build_disablePropagation() {
168 if (browser.isIE55 || browser.isIE6up) {
169 var _ie_disablePropagation = function() {
170 window.event.cancelBubble = true;
171 };
172 return _ie_disablePropagation;
173 }
174 else if (browser.isDOM2Event) {
175 var _dom2_disablePropagation = function(evt) {
176 evt.stopPropagation();
177 };
178 return _dom2_disablePropagation;
179 }
180 }
181
182 function _build_getWindowWidth() {
183 if (window.innerWidth !== undefined){
184 return function(){
185 return window.innerWidth;
186 };
187 }
188 else {
189 return function(){
190 return document.documentElement.clientWidth;
191 };
192 }
193 }
194
195 function _build_getWindowHeight() {
196 if (window.innerHeight !== undefined) {
197 return function(){
198 return window.innerHeight;
199 };
200 }
201 else {
202 return function(){
203 return document.documentElement.clientHeight;
204 };
205 }
206 }
207
208 function _build_clearSelection() {
209 if (document.selection) {
210 return function() {
211 document.selection.clear();
212 };
213 }
214 else {
215 return function() {
216 window.getSelection().removeAllRanges();
217 };
218 }
219 }
220
221
222 buildMetaFunctions();
223
224 var ELEMENT_NODE = 1;
225 var TEXT_NODE = 3;
226 var _setAttribute;
227 getCopyOfNode = function(node) {
228
229 switch(node.nodeType) {
230 case ELEMENT_NODE:
231 var attributes = node.attributes;
232 var childs = node.childNodes;
233
234 var e = document.createElement(node.nodeName);
235
236 var attribute, i;
237 for(i=0 ; i<attributes.length ; i++) {
238 attribute = attributes[i];
239 _setAttribute(e, attribute.name, attribute.value);
240 }
241
242 for(i=0 ; i<childs.length ; i++) {
243 e.appendChild(getCopyOfNode(childs[i]));}
244
245 return e;
246
247 case TEXT_NODE:
248 return document.createTextNode(node.nodeValue);
249 }
250 };
251
252 if (browser.isIE) {
253 _setAttribute = function(e, name, value) {
254 // workarround IE lack of dom implementation.
255 switch(name.toLowerCase()) {
256 case 'colspan' :
257 e.colSpan = value;
258 break;
259 case 'class' :
260 e.className = value;
261 break;
262 case 'style' :
263 loadCssText(e, value);
264 break;
265 default:
266 if (name.slice(0,2) === 'on') { // event handler
267 // A browser normaly eval text code attached to a onXyz attribute. Not IE.
268 /*jslint evil: true */
269 e[name] = function(){eval(value);};}
270 else {
271 e.setAttribute(name, value);}
272 }
273 };
274 var reCompoundPropName = /^\s*([^\-]+)\-([a-z])([a-z]+)\s*$/;
275 var _capitalizeCssPropName = function (s, g1, g2, g3) { // gN args match above regexp groups
276 if(g2) {
277 return g1 + g2.toUpperCase() + g3;}
278 else {
279 return s;}
280 };
281
282 var loadCssText = function (e, cssText) {
283 var pairs = cssText.split(';');
284 var pair, name, value, i;
285 var style = e.style;
286 for (i= 0; i < pairs.length; i++) {
287 pair = pairs[i].split(':');
288 if (pair.length === 2) {
289 name = _capitalizeCssPropName(pair[0]);
290 value = pair[1];
291 style[name] = value;
292 }
293 }
294 };
295 }
296 else {
297 _setAttribute = function(e, name, value) {e.setAttribute(name, value);};
298 }
299
300 }());