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