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