1 /* 2 * SIMPLICITE - runtime & framework 3 * http://www.simplicite.fr 4 * Copyright (c)2006-2013 Simplicite Software. All rights reserved. 5 */ 6 7 /** 8 * Tools 9 * @class 10 */ 11 Simplicite.Tools = { 12 13 log : function(text, popup) { 14 try { 15 console.log(text); 16 } catch(e) { 17 if (popup) alert(text); 18 else console.log(text); 19 } 20 }, 21 22 debug : function(text) { this.log("[DEBUG]: " + text); }, 23 24 info : function(text, popup) { this.log("[INFO]: " + text, popup); }, 25 26 warning : function(text, popup) { this.log("[WARNING]: " + text, popup); }, 27 28 error : function(text, e, popup) { 29 var t = "[ERROR]: " + (text ? text : "") + (e ? "\nException: "+ (e.message ? e.message : e.description) : ""); 30 try { 31 console.error(t); 32 } catch(e) { 33 if (popup) alert(t); 34 else console.log(t); 35 } 36 }, 37 38 T : function(code) { 39 var t = Simplicite.TEXT !== undefined ? Simplicite.TEXT[code] : code; 40 return t === undefined ? code : t; 41 }, 42 43 wait : function(ms) { 44 if (ms<0) return; 45 ms += new Date().getTime(); 46 while (new Date() < ms){} 47 }, 48 49 isWinIE : navigator.userAgent.indexOf("MSIE")!=-1 && navigator.userAgent.indexOf("Win")!=-1, 50 winIEVersion : parseInt(navigator.appVersion.split("MSIE")[1]), 51 isFirefox : navigator.userAgent.indexOf("Firefox")!=-1, 52 isSafari : navigator.userAgent.indexOf("Safari")!=-1, 53 isChrome : navigator.userAgent.indexOf("Chrome")!=-1, 54 isIPad : navigator.userAgent.indexOf("iPad")!=-1, 55 isIPhone : navigator.userAgent.indexOf("iPhone")!=-1, 56 57 urlEncodeParam : function(val) { 58 if (Simplicite.ENCODING == "UTF-8") 59 return encodeURIComponent(val); 60 else 61 return escape(val).replace(/\+/g, "%2B"); 62 }, 63 64 isCanvasSupported : function () { 65 var elem = document.createElement('canvas'); 66 return !!(elem.getContext && elem.getContext('2d')); 67 }, 68 69 getEvent : function(e) { 70 return e ? e : window.event; 71 }, 72 getEventElement : function(e) { 73 e = this.getEvent(e); 74 return (e.srcElement ? e.srcElement: (e.target ? e.target : e.currentTarget)); 75 }, 76 stopEvent : function(e) { 77 e = this.getEvent(e); 78 if (e.stopPropagation) { 79 e.stopPropagation(); 80 } else { // IE8- or IE9/HTML4 81 e.cancelBubble = true; 82 } 83 }, 84 freezeEvent : function(e) { 85 e = this.getEvent(e); 86 if (e.stopPropagation) { 87 e.preventDefault(); 88 e.stopPropagation(); 89 } else { // IE8- or IE9/HTML4 90 e.returnValue = false; 91 e.cancelBubble = true; 92 } 93 }, 94 getEventPosX : function(e) { 95 var posx = 0; 96 e = this.getEvent(e); 97 if (e.pageX) { 98 posx = e.pageX; 99 } else if (e.clientX) { 100 posx = e.clientX + document.body.scrollLeft 101 + document.documentElement.scrollLeft; 102 } 103 return posx; 104 }, 105 getEventPosY : function(e) { 106 var posy = 0; 107 e = this.getEvent(e); 108 if (e.pageY) { 109 posy = e.pageY; 110 } else if (e.clientY) { 111 posy = e.clientY + document.body.scrollTop 112 + document.documentElement.scrollTop; 113 } 114 return posy; 115 }, 116 addEvent : function(el, evnt, func) { 117 if (el.addEventListener) { 118 el.addEventListener(evnt, func, false); 119 } else if (el.attachEvent) { 120 el.attachEvent('on'+evnt, func); 121 } 122 }, 123 addClickEvent : function(el, f) { 124 this.addEvent(el, "click", f); 125 }, 126 fireEvent : function(el, evnt) { 127 if (!el) return; 128 if(document.createEvent) { 129 var ev = document.createEvent('HTMLEvents'); 130 ev.initEvent(evnt, true, true); 131 el.dispatchEvent(ev); 132 } else if(document.createEventObject) { 133 var ev = document.createEventObject(); 134 el.fireEvent('on'+evnt, ev); 135 } else if(el['on'+evnt]) { 136 el['on'+evnt](); 137 } 138 }, 139 140 isArray : function(v) { 141 return v.constructor == Array; 142 }, 143 144 toInt : function(v) { 145 if (!v || v=='') return 0; 146 v = v.replace(/[^0-9]+|[\r\n\t\f\s]+/gi,''); 147 return parseInt(v); 148 }, 149 toFloat : function(v) { 150 if (!v || v=='') return 0.0; 151 v = v.replace(/[^0-9.,]+|[\r\n\t\f\s]+/gi,'').replace(/,+/,'.'); 152 return parseFloat(v); 153 }, 154 contains : function(ar, obj) { 155 for (var i = 0; ar && i < ar.length; i++) 156 if (ar[i]==obj) return true; 157 return false; 158 }, 159 160 KEY_BACKSPACE : 8, 161 KEY_TAB : 9, 162 KEY_ENTER : 13, 163 KEY_SHIFT : 16, 164 KEY_CTRL : 17, 165 KEY_ALT : 18, 166 KEY_PAUSE : 19, 167 KEY_CAPS_LOCK : 20, 168 KEY_ESCAPE : 27, 169 KEY_PAGE_UP : 33, 170 KEY_PAGE_DOWN : 34, 171 KEY_END : 35, 172 KEY_HOME : 36, 173 KEY_LEFT_ARROW : 37, 174 KEY_UP_ARROW : 38, 175 KEY_RIGHT_ARROW : 39, 176 KEY_DOWN_ARROW : 40, 177 KEY_INSERT : 45, 178 KEY_DELETE : 46, 179 180 getKeyCode : function(e) { 181 if (!e) return 0; 182 var key = e.keyCode; 183 if (!key || key==0) key = e.charCode; 184 return key; 185 }, 186 187 isWithinNode : function(elem, id, clas, tag, obj) { 188 var answer = false; 189 var te = elem; 190 while(te && !answer) { 191 if ((te.id && te.id==id) 192 || (te.className && te.className==id+"Class") 193 || (!tag && clas && te.className && te.className==clas) 194 || (!tag && clas && te.className && te.className.indexOf(clas)!=-1) 195 || (tag && te.tagName && te.tagName.toLowerCase()==tag.toLowerCase()) 196 || (obj && te==obj)) { 197 answer = te; 198 } else { 199 te = te.parentNode; 200 } 201 } 202 return te; 203 }, 204 205 posX : function(obj) { 206 if (!obj) return 0; 207 var curleft = 0; 208 if (obj.offsetParent) { 209 while(obj.offsetParent) { 210 curleft += obj.offsetLeft; 211 obj = obj.offsetParent; 212 } 213 } else if (obj.x) { 214 curleft += obj.x; 215 } 216 return curleft; 217 }, 218 219 posY : function(obj) { 220 if (!obj) return 0; 221 var curtop = 0; 222 if (obj.offsetParent) { 223 while(obj.offsetParent) { 224 curtop += obj.offsetTop; 225 obj = obj.offsetParent; 226 } 227 } else if (obj.y) { 228 curtop += obj.y; 229 } 230 return curtop; 231 }, 232 width : function(obj) { 233 if (!obj) return 0; 234 if (obj.offsetWidth) return obj.offsetWidth; 235 if (obj.offsetParent) { 236 while(obj.offsetParent) { 237 if (obj.offsetParent.offsetWidth) return obj.offsetParent.offsetWidth; 238 obj = obj.offsetParent; 239 } 240 } 241 return 0; 242 }, 243 height : function(obj) { 244 if (!obj) return 0; 245 if (obj.offsetHeight) return obj.offsetHeight; 246 if (obj.offsetParent) { 247 while(obj.offsetParent) { 248 if (obj.offsetParent.offsetHeight) return obj.offsetParent.offsetHeight; 249 obj = obj.offsetParent; 250 } 251 } 252 return 0; 253 }, 254 getElementPos : function(elt) { 255 return [ this.posX(elt), this.posY(elt) ]; 256 }, 257 getElementSize : function (elt) { 258 return [ this.width(elt), this.height(elt) ]; 259 }, 260 261 windowWidth : function() { 262 var w = 0; 263 if (typeof( window.innerWidth) == 'number') { 264 w = window.innerWidth; 265 } else if( document.documentElement && document.documentElement.clientWidth) { 266 w = document.documentElement.clientWidth; 267 } else if( document.body && document.body.clientWidth) { 268 w = document.body.clientWidth; 269 } 270 return w; 271 }, 272 windowHeight : function() { 273 var h = 0; 274 if (typeof(window.innerHeight) == 'number') { 275 h = window.innerHeight; 276 } else if( document.documentElement && document.documentElement.clientHeight) { 277 h = document.documentElement.clientHeight; 278 } else if( document.body && document.body.clientHeight) { 279 h = document.body.clientHeight; 280 } 281 return h; 282 }, 283 284 getRelMousePos : function(e) { 285 var x = 0, y = 0; 286 if (!e) { e = window.event; } 287 if (typeof e.offsetX === 'number') { 288 x = e.offsetX; 289 y = e.offsetY; 290 } else if (typeof e.layerX === 'number') { 291 x = e.layerX; 292 y = e.layerY; 293 } 294 return { x: x, y: y }; 295 }, 296 297 298 getViewPos : function() { 299 if(typeof window.pageYOffset === 'number') { 300 return [window.pageXOffset, window.pageYOffset]; 301 } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) { 302 return [document.body.scrollLeft, document.body.scrollTop]; 303 } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 304 return [document.documentElement.scrollLeft, document.documentElement.scrollTop]; 305 } else { 306 return [0, 0]; 307 } 308 }, 309 getViewSize : function() { 310 if(typeof window.innerWidth === 'number') { 311 return [window.innerWidth, window.innerHeight]; 312 } else if(document.body && (document.body.clientWidth || document.body.clientHeight)) { 313 return [document.body.clientWidth, document.body.clientHeight]; 314 } else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) { 315 return [document.documentElement.clientWidth, document.documentElement.clientHeight]; 316 } else { 317 return [0, 0]; 318 } 319 }, 320 321 getPickerPos : function(elt, align, ps) { 322 var tp = this.getElementPos(elt); 323 var ts = this.getElementSize(elt); 324 var vp = this.getViewPos(); 325 var vs = this.getViewSize(); 326 var a, b, c; 327 switch(align) { 328 case 'left': a=1; b=0; c=-1; break; 329 case 'right':a=1; b=0; c=1; break; 330 case 'top': a=0; b=1; c=-1; break; 331 default: a=0; b=1; c=1; break; 332 } 333 var pp = new Array(); 334 var l = (ts[b]+ps[b])/2; 335 if (!align) { 336 pp = [tp[a], tp[b]+ts[b]-l+l*c]; 337 } 338 else { 339 pp = [ 340 -vp[a]+tp[a]+ps[a] > vs[a] ? 341 (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) : 342 tp[a], 343 -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ? 344 (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) : 345 (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c) 346 ]; 347 } 348 return [pp[a], pp[b]]; 349 }, 350 351 // TODO : should be in Simplicite.UI ? 352 screenshot : function(type) { 353 try { return getTop().document.theFeedbackApplet.screenshot(type); } catch(e) {} 354 return null; 355 }, 356 357 // HTTP Request tools 358 httpCall : function(obj, type, url, params, onSuccess, onError, async, method, user, password) { 359 try { 360 if (!method) method = (params ? "POST" : "GET"); 361 if (!async) async = false; 362 363 var req; 364 if (window.XMLHttpRequest) { 365 req = new XMLHttpRequest(); 366 } else if (window.ActiveXObject) { 367 try { 368 req = new ActiveXObject("Msxml2.XMLHTTP"); 369 } catch (e) { 370 req = new ActiveXObject("Microsoft.XMLHTTP"); 371 } 372 } 373 if (!req) 374 throw ("Error creating the XMLHttpRequest object"); 375 try { if (async) req.withCredentials = true; } catch(ex) {} 376 req.open(method, url, async, user, password); 377 req.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 378 if (method=="POST") 379 // POST encoding must be explicitly set to UTF-8 with XMLHttpRequest posts 380 req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); 381 if (async) { 382 var self = this; 383 req.onreadystatechange = function() { self.httpCallStateChange(obj, req, type, onSuccess, onError); }; 384 req.send(params); 385 return ""; 386 } else { 387 req.send(params); 388 return this.httpCallStateChange(obj, req, type, onSuccess, onError); 389 } 390 } catch (e) { 391 this.error("httpCall for URL : "+url, e); 392 return null; 393 } 394 }, 395 httpCallStateChange : function(obj, req, type, onSuccess, onError) { 396 if (req && req.readyState==4) { 397 if (req.status==200) { 398 try { 399 if (type=='json') { 400 var res = eval("("+req.responseText+")"); 401 return (onSuccess ? onSuccess(res, obj) : res); 402 } else if (type=='xml') { 403 return (onSuccess ? onSuccess(req.responseXML, obj) : req.responseXML); 404 } else 405 return (onSuccess ? onSuccess(req.responseText, obj) : req.responseText); 406 } catch(e) { 407 var err = "httpCallStateChange: Error reading the response"; 408 this.error(err, e); 409 return (onError ? onError(err, obj) : err); 410 } 411 } else if (req.status>0) { 412 var err = "httpCallStateChange: http status "+req.status+" "+req.statusText; 413 this.error(err); 414 return (onError ? onError(err, obj) : err); 415 } 416 } 417 } 418 }; 419 420 // Base64 functions 421 (function() { 422 /** 423 * Encode to base64 424 * @param input Input string 425 * @return Base64 encoded string 426 * @function 427 */ 428 Simplicite.Tools.base64Encode = function(s) { 429 if (s === undefined || typeof s != "string" || s.length == 0) return ""; 430 //if (typeof btoa !== "undefined") return btoa(s); 431 432 var o = s.replace(/\r\n/g, "\n"); 433 var u = ""; 434 if (Simplicite.ENCODING == "UTF-8") { 435 for ( var n = 0; n < o.length; n++) { 436 var c = o.charCodeAt(n); 437 if (c < 128) { 438 u += String.fromCharCode(c); 439 } else if ((c > 127) && (c < 2048)) { 440 u += String.fromCharCode((c >> 6) | 192); 441 u += String.fromCharCode((c & 63) | 128); 442 } else { 443 u += String.fromCharCode((c >> 12) | 224); 444 u += String.fromCharCode(((c >> 6) & 63) | 128); 445 u += String.fromCharCode((c & 63) | 128); 446 } 447 } 448 } else 449 u = o; 450 451 o = ""; 452 var c1, c2, c3 = ""; 453 var e1, e2, e3, e4 = ""; 454 var i = 0; 455 var k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 456 do { 457 c1 = u.charCodeAt(i++); 458 c2 = u.charCodeAt(i++); 459 c3 = u.charCodeAt(i++); 460 461 e1 = c1 >> 2; 462 e2 = ((c1 & 3) << 4) | (c2 >> 4); 463 e3 = ((c2 & 15) << 2) | (c3 >> 6); 464 e4 = c3 & 63; 465 466 if (isNaN(c2)) { 467 e3 = e4 = 64; 468 } else if (isNaN(c3)) { 469 e4 = 64; 470 } 471 472 o = o + 473 k.charAt(e1) + 474 k.charAt(e2) + 475 k.charAt(e3) + 476 k.charAt(e4); 477 c1 = c2 = c3 = ""; 478 e1 = e2 = e3 = e4 = ""; 479 } while (i < u.length); 480 481 return o; 482 }; 483 484 /** 485 * Decode base64 486 * @param s Base64 encoded input string 487 * @return Decoded string 488 * @function 489 */ 490 Simplicite.Tools.base64Decode = function(s) { 491 if (s === undefined || typeof s != "string" || s.length == 0) return ""; 492 //if (typeof atob !== "undefined") return atob(s); 493 494 var o = ""; 495 var c1, c2, c3 = ""; 496 var e1, e2, e3, e4 = ""; 497 var i = 0; 498 var k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 499 do { 500 e1 = k.indexOf(s.charAt(i++)); 501 e2 = k.indexOf(s.charAt(i++)); 502 e3 = k.indexOf(s.charAt(i++)); 503 e4 = k.indexOf(s.charAt(i++)); 504 505 c1 = (e1 << 2) | (e2 >> 4); 506 c2 = ((e2 & 15) << 4) | (e3 >> 2); 507 c3 = ((e3 & 3) << 6) | e4; 508 509 o = o + String.fromCharCode(c1); 510 511 if (e3 != 64) { 512 o = o + String.fromCharCode(c2); 513 } 514 if (e4 != 64) { 515 o = o + String.fromCharCode(c3); 516 } 517 518 c1 = c2 = c3 = ""; 519 e1 = e2 = e3 = e4 = ""; 520 521 } while (i < s.length); 522 523 if (Simplicite.ENCODING == "UTF-8") { 524 var u = ""; 525 var i = 0; 526 var c = c1 = c2 = 0; 527 while (i < o.length) { 528 c = o.charCodeAt(i); 529 if (c < 128) { 530 u += String.fromCharCode(c); 531 i++; 532 } else if ((c > 191) && (c < 224)) { 533 c2 = o.charCodeAt(i + 1); 534 u += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); 535 i += 2; 536 } else { 537 c2 = o.charCodeAt(i + 1); 538 c3 = o.charCodeAt(i + 2); 539 u += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); 540 i += 3; 541 } 542 } 543 return u; 544 } else 545 return o; 546 }; 547 548 /** 549 * HTTP Basic auth header 550 * @param user User name 551 * @param password User password 552 * @return Authorization header 553 * @function 554 */ 555 Simplicite.Tools.basicAuthString = function(user, password) { 556 return "Basic " + this.base64Encode(user + ":" + password); 557 }; 558 559 })(); 560 561 // Event listener 562 Simplicite.EventListener = { 563 _listeners : {}, 564 565 /** 566 * Get the event listener 567 * @param name event name 568 * @function 569 */ 570 get : function(name) { 571 // Singleton on top window 572 var l = getTop().Simplicite.EventListener._listeners; 573 // Named event handlers or all listeners 574 return name ? l[name] : l; 575 }, 576 577 /** 578 * Add one event listener 579 * @param name event name 580 * @param handler listener function 581 * @param target targetted object 582 * @function 583 */ 584 add : function(name, handler, target) { 585 if (!name) return; 586 var l = Simplicite.EventListener.get(); 587 if (!l[name]) l[name] = []; 588 handler = { fn: handler, target: target || this }; 589 l[name].push(handler); 590 }, 591 592 /** 593 * Remove one event listener 594 * @param name event name 595 * @param handler handler, function or target 596 * @function 597 */ 598 remove : function(name, handler) { 599 if (!name) return; 600 var l = Simplicite.EventListener.get(name); 601 if (!l) return; 602 for (var i=0; i<l.length; i++) { 603 if (l[i]==handler || l[i].fn===handler || l[i].target===handler) { 604 l.splice(i,1); 605 i--; 606 } 607 } 608 }, 609 610 /** 611 * Fire one event 612 * @function 613 */ 614 fire : function(name, emitter, data) { 615 if (!name) return; 616 var l = Simplicite.EventListener.get(name); 617 if (l) { 618 var event = { name: name, emitter: emitter || this, data: data }; 619 for (var i=0; i<l.length; i++) { 620 var h = l[i]; 621 h.fn.call(h.target, event); 622 } 623 } 624 } 625 }; // Simplicite.EventListener 626