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