Annotation of ECHO_content/js/baselib.js, revision 1.1
1.1 ! casties 1: /* Copyright (C) 2003,2004 IT-Group MPIWG, WTWG Uni Bern and others
! 2:
! 3: This program is free software; you can redistribute it and/or
! 4: modify it under the terms of the GNU General Public License
! 5: as published by the Free Software Foundation; either version 2
! 6: of the License, or (at your option) any later version.
! 7:
! 8: This program is distributed in the hope that it will be useful,
! 9: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 10: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 11: GNU General Public License for more details.
! 12:
! 13: You should have received a copy of the GNU General Public License
! 14: along with this program; if not, write to the Free Software
! 15: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
! 16:
! 17: Authors:
! 18: Christian Luginbuehl, 01.05.2003 (first version)
! 19: DW 24.03.2004 (Changed for digiLib in Zope)
! 20: Robert Casties, 23.11.2004
! 21:
! 22: */
! 23:
! 24: var baseScriptVersion = "1.1b";
! 25: var dlParams = new Object();
! 26: var browserType = getBrowserType();
! 27:
! 28: function base_init() {
! 29: // init function -- must be called first!
! 30: }
! 31:
! 32:
! 33: function getInt(n) {
! 34: // returns always an integer
! 35: n = parseInt(n);
! 36: if (isNaN(n)) return 0;
! 37: return n;
! 38: }
! 39:
! 40: function defined(x) {
! 41: // returns if x is defined
! 42: return (typeof arguments[0] != "undefined");
! 43: }
! 44:
! 45: function cropFloat(x) {
! 46: // auxiliary function to crop senseless precision
! 47: return parseInt(10000*x)/10000;
! 48: }
! 49:
! 50: function getBrowserType() {
! 51: // browser sniffer
! 52: var bt = Object();
! 53: bt.doDHTML = false;
! 54: bt.versIE = 0;
! 55:
! 56: if ((! document.cssonly && document.layers) || document.all || document.getElementById) {
! 57: var vers = navigator.appVersion.split('MSIE ');
! 58: vers = vers[vers.length - 1];
! 59: bt.versIE = getInt(vers);
! 60: bt.isIE = navigator.userAgent.indexOf('MSIE') >= 0;
! 61: bt.isMac = navigator.platform.indexOf('Mac') >= 0;
! 62: bt.isWin = navigator.platform.indexOf('Win') >= 0;
! 63: bt.isN4 = (navigator.userAgent.indexOf('Mozilla/4.') >= 0) && ! bt.isIE;
! 64: bt.isIEWin = bt.versIE > 0 && bt.isWin;
! 65: if (navigator.appVersion.indexOf('MSIE') < 0 || ! bt.isMac || bt.versIE >= 5) {
! 66: bt.doDHTML = true;
! 67: bt.isOpera = navigator.userAgent.indexOf(' Opera ') >= 0;
! 68: bt.isKonq = navigator.userAgent.indexOf(' Konqueror') >= 0;
! 69: }
! 70: }
! 71: return bt;
! 72: }
! 73:
! 74: // fixes for javascript < 1.2
! 75: if (! Array.prototype.push) {
! 76: Array.prototype.push = function(val) {
! 77: this[this.length] = val;
! 78: return this.length;
! 79: }
! 80: Array.prototype.pop = function() {
! 81: var val = this[this.length-1];
! 82: this.length -= 1;
! 83: return val;
! 84: }
! 85: }
! 86:
! 87:
! 88: /* **********************************************
! 89: * geometry classes
! 90: * ******************************************** */
! 91:
! 92: /*
! 93: * Size class
! 94: */
! 95: function Size(w, h) {
! 96: this.width = parseFloat(w);
! 97: this.height = parseFloat(h);
! 98: return this;
! 99: }
! 100: Size.prototype.toString = function() {
! 101: return this.width + "x" + this.height;
! 102: }
! 103:
! 104:
! 105: /*
! 106: * Position class
! 107: */
! 108: function Position(x, y) {
! 109: this.x = parseFloat(x);
! 110: this.y = parseFloat(y);
! 111: return this;
! 112: }
! 113: Position.prototype.toString = function() {
! 114: return this.x + "," + this.y;
! 115: }
! 116:
! 117: /*
! 118: * Rectangle class
! 119: */
! 120: function Rectangle(x, y, w, h) {
! 121: this.x = parseFloat(x);
! 122: this.y = parseFloat(y);
! 123: this.width = parseFloat(w);
! 124: this.height = parseFloat(h);
! 125: return this;
! 126: }
! 127: Rectangle.prototype.toString = function() {
! 128: return this.width+"x"+this.height+"@"+this.x+","+this.y;
! 129: }
! 130: Rectangle.prototype.copy = function() {
! 131: // returns a copy of this Rectangle
! 132: return new Rectangle(this.x, this.y, this.width, this.height);
! 133: }
! 134: Rectangle.prototype.getPosition = function() {
! 135: // returns the position of this Rectangle
! 136: return new Position(this.x, this.y);
! 137: }
! 138: Rectangle.prototype.getSize = function() {
! 139: // returns the size of this Rectangle
! 140: return new Size(this.width, this.height);
! 141: }
! 142: Rectangle.prototype.getArea = function() {
! 143: // returns the area of this Rectangle
! 144: return (this.width * this.height);
! 145: }
! 146: Rectangle.prototype.containsPosition = function(pos) {
! 147: // returns if the given Position lies in this Rectangle
! 148: return ((pos.x >= this.x)&&(pos.y >= this.y)&&(pos.x <= this.x+this.width)&&(pos.y <= this.y+this.width));
! 149: }
! 150: Rectangle.prototype.intersect = function(rect) {
! 151: // returns the intersection of the given Rectangle and this one
! 152: var sec = rect.copy();
! 153: if (sec.x < this.x) {
! 154: sec.width = sec.width - (this.x - sec.x);
! 155: sec.x = this.x;
! 156: }
! 157: if (sec.y < this.y) {
! 158: sec.height = sec.height - (this.y - sec.y);
! 159: sec.y = this.y;
! 160: }
! 161: if (sec.x + sec.width > this.x + this.width) {
! 162: sec.width = (this.x + this.width) - sec.x;
! 163: }
! 164: if (sec.y + sec.height > this.y + this.height) {
! 165: sec.height = (this.y + this.height) - sec.y;
! 166: }
! 167: return sec;
! 168: }
! 169: Rectangle.prototype.fit = function(rect) {
! 170: // returns a Rectangle that fits into this one (by moving first)
! 171: var sec = rect.copy();
! 172: sec.x = Math.max(sec.x, this.x);
! 173: sec.x = Math.max(sec.x, this.x);
! 174: if (sec.x + sec.width > this.x + this.width) {
! 175: sec.x = this.x + this.width - sec.width;
! 176: }
! 177: if (sec.y + sec.height > this.y + this.height) {
! 178: sec.y = this.y + this.height - sec.height;
! 179: }
! 180: return sec.intersect(this);
! 181: }
! 182:
! 183: /*
! 184: * Transform class
! 185: *
! 186: * defines a class of affine transformations
! 187: */
! 188: function Transform() {
! 189: this.m00 = 1.0;
! 190: this.m01 = 0.0;
! 191: this.m02 = 0.0;
! 192: this.m10 = 0.0;
! 193: this.m11 = 1.0;
! 194: this.m12 = 0.0;
! 195: this.m20 = 0.0;
! 196: this.m21 = 0.0;
! 197: this.m22 = 1.0;
! 198: return this;
! 199: }
! 200: Transform.prototype.concat = function(traf) {
! 201: // add Transform traf to this Transform
! 202: for (var i = 0; i < 3; i++) {
! 203: for (var j = 0; j < 3; j++) {
! 204: var c = 0.0;
! 205: for (var k = 0; k < 3; k++) {
! 206: c += traf["m"+i+k] * this["m"+k+j];
! 207: }
! 208: this["m"+i+j] = c;
! 209: }
! 210: }
! 211: return this;
! 212: }
! 213: Transform.prototype.transform = function(rect) {
! 214: // returns transformed Rectangle or Position with this Transform applied
! 215: var x = this.m00 * rect.x + this.m01 * rect.y + this.m02;
! 216: var y = this.m10 * rect.x + this.m11 * rect.y + this.m12;
! 217: if (rect.width) {
! 218: var width = this.m00 * rect.width + this.m01 * rect.height;
! 219: var height = this.m10 * rect.width + this.m11 * rect.height;
! 220: return new Rectangle(x, y, width, height);
! 221: }
! 222: return new Position(x, y);
! 223: }
! 224: Transform.prototype.invtransform = function(pos) {
! 225: // returns transformed Position pos with the inverse of this Transform applied
! 226: var det = this.m00 * this.m11 - this.m01 * this.m10;
! 227: var x = (this.m11 * pos.x - this.m01 * pos.y - this.m11 * this.m02 + this.m01 * this.m12) / det;
! 228: var y = (- this.m10 * pos.x + this.m00 * pos.y + this.m10 * this.m02 - this.m00 * this.m12) / det;
! 229: return new Position(x, y);
! 230: }
! 231: function getRotation(angle, pos) {
! 232: // returns a Transform that is a rotation by angle degrees around [pos.x, pos.y]
! 233: var traf = new Transform();
! 234: if (angle != 0) {
! 235: var t = 2.0 * Math.PI * parseFloat(angle) / 360.0;
! 236: traf.m00 = Math.cos(t);
! 237: traf.m01 = - Math.sin(t);
! 238: traf.m10 = Math.sin(t);
! 239: traf.m11 = Math.cos(t);
! 240: traf.m02 = pos.x - pos.x * Math.cos(t) + pos.y * Math.sin(t);
! 241: traf.m12 = pos.y - pos.x * Math.sin(t) - pos.y * Math.cos(t);
! 242: }
! 243: return traf;
! 244: }
! 245: function getTranslation(pos) {
! 246: // returns a Transform that is a translation by [pos.x, pos,y]
! 247: var traf = new Transform();
! 248: traf.m02 = pos.x;
! 249: traf.m12 = pos.y;
! 250: return traf;
! 251: }
! 252: function getScale(size) {
! 253: // returns a Transform that is a scale by [size.width, size.height]
! 254: var traf = new Transform();
! 255: traf.m00 = size.width;
! 256: traf.m11 = size.height;
! 257: return traf;
! 258: }
! 259:
! 260:
! 261: /* **********************************************
! 262: * parameter routines
! 263: * ******************************************** */
! 264:
! 265: function newParameter(name, defaultValue, detail) {
! 266: // create a new parameter with a name and a default value
! 267: if (defined(dlParams[name])) {
! 268: alert("Fatal: An object with name '" + name + "' already exists - cannot recreate!");
! 269: return false;
! 270: } else {
! 271: dlParams[name] = new Object();
! 272: dlParams[name].defaultValue = defaultValue;
! 273: dlParams[name].hasValue = false;
! 274: dlParams[name].value = defaultValue;
! 275: dlParams[name].detail = detail;
! 276: return dlParams[name];
! 277: }
! 278: }
! 279:
! 280: function getParameter(name) {
! 281: // returns the named parameter value or its default value
! 282: if (defined(dlParams[name])) {
! 283: if (dlParams[name].hasValue) {
! 284: return dlParams[name].value;
! 285: } else {
! 286: return dlParams[name].defaultValue;
! 287: }
! 288: } else {
! 289: return null;
! 290: }
! 291: }
! 292:
! 293: function setParameter(name, value) {
! 294: // sets parameter value
! 295: if (defined(dlParams[name])) {
! 296: dlParams[name].value = value;
! 297: dlParams[name].hasValue = true;
! 298: return true;
! 299: }
! 300: return false;
! 301: }
! 302:
! 303: function hasParameter(name) {
! 304: // returns if the parameter's value has been set
! 305: if (defined(dlParams[name])) {
! 306: return dlParams[name].hasValue;
! 307: }
! 308: return false;
! 309: }
! 310:
! 311: function getAllParameters(detail) {
! 312: // returns a string of all parameters in query format
! 313: if (! detail) {
! 314: detail = 10;
! 315: }
! 316: var params = new Array();
! 317: for ( param in dlParams ) {
! 318: if ((dlParams[param].detail <= detail)&&(dlParams[param].hasValue)) {
! 319: var val = getParameter(param);
! 320: if (val != "") {
! 321: params.push(param + "=" + val);
! 322: }
! 323: }
! 324: }
! 325: return params.join("&");
! 326: }
! 327:
! 328: function parseParameters(query) {
! 329: // gets parameter values from query format string
! 330: var params = query.split("&");
! 331: for (var i = 0; i < params.length; i++) {
! 332: var keyval = params[i].split("=");
! 333: if (keyval.length == 2) {
! 334: setParameter(keyval[0], keyval[1]);
! 335: }
! 336: }
! 337: }
! 338:
! 339:
! 340: /* **********************************************
! 341: * HTML/DOM routines
! 342: * ******************************************** */
! 343:
! 344: function getElement(tagid, quiet) {
! 345: // returns the element object with the id tagid
! 346: var e;
! 347: if (document.getElementById) {
! 348: e = document.getElementById(tagid);
! 349: } else if (document.all) {
! 350: alert("document.all!");
! 351: e = document.all[tagid];
! 352: } else if (document.layers) {
! 353: e = document.layers[tagid];
! 354: }
! 355: if (e) {
! 356: return e;
! 357: } else {
! 358: if (! quiet) {
! 359: alert("unable to find element: "+tagid);
! 360: }
! 361: return null;
! 362: }
! 363: }
! 364:
! 365: function getElementPosition(elem) {
! 366: // returns a Position with the position of the element
! 367: var x = 0;
! 368: var y = 0;
! 369: if (defined(elem.offsetLeft)) {
! 370: var e = elem;
! 371: while (e) {
! 372: if (defined(e.clientLeft)) {
! 373: // special for IE
! 374: if (browserType.isMac) {
! 375: if (e.offsetParent.tagName == "BODY") {
! 376: // IE for Mac extraspecial
! 377: x += e.clientLeft;
! 378: y += e.clientTop;
! 379: break;
! 380: }
! 381: } else {
! 382: if ((e.tagName != "TABLE") && (e.tagName != "BODY")) {
! 383: x += e.clientLeft;
! 384: y += e.clientTop;
! 385: }
! 386: }
! 387: }
! 388: x += e.offsetLeft;
! 389: y += e.offsetTop;
! 390: e = e.offsetParent;
! 391: }
! 392: } else if (defined(elem.pageX)) {
! 393: // for N4 elem.pageX is more correct than elem.x
! 394: x = elem.pageX;
! 395: y = elem.pageY;
! 396: } else if (defined(elem.x)) {
! 397: x = elem.x;
! 398: y = elem.y;
! 399: } else {
! 400: alert("unable to get position of "+elem+" (id:"+elem.id+")");
! 401: }
! 402: return new Position(getInt(x), getInt(y));
! 403: }
! 404:
! 405: function getElementSize(elem) {
! 406: // returns a Rectangle with the size of the element
! 407: var width = 0;
! 408: var height = 0;
! 409: if (defined(elem.offsetWidth)) {
! 410: width = elem.offsetWidth;
! 411: height = elem.offsetHeight;
! 412: } else if (defined(elem.width)) {
! 413: width = elem.width;
! 414: height = elem.height;
! 415: } else if (defined(elem.clip.width)) {
! 416: width = elem.clip.width;
! 417: height = elem.clip.height;
! 418: } else {
! 419: alert("unable to get size of "+elem+" (id:"+elem.id+")");
! 420: }
! 421: return new Size(getInt(width), getInt(height));
! 422: }
! 423:
! 424: function getElementRect(elem) {
! 425: // returns a Rectangle with the size and position of the element
! 426: var pos = getElementPosition(elem);
! 427: var size = getElementSize(elem);
! 428: return new Rectangle(pos.x, pos.y, size.width, size.height);
! 429: }
! 430:
! 431:
! 432:
! 433: function moveElement(elem, rect) {
! 434: // moves and sizes the element
! 435: if (elem.style) {
! 436: if (defined(rect.x)) {
! 437: elem.style.left = Math.round(rect.x) + "px";
! 438: elem.style.top = Math.round(rect.y) + "px";
! 439: }
! 440: if (defined(rect.width)) {
! 441: elem.style.width = Math.round(rect.width) + "px";
! 442: elem.style.height = Math.round(rect.height) + "px";
! 443: }
! 444: } else if (document.layers) {
! 445: if (defined(rect.x)) {
! 446: elem.pageX = getInt(rect.x);
! 447: elem.pageY = getInt(rect.y);
! 448: }
! 449: if (defined(rect.width)) {
! 450: elem.clip.width = getInt(rect.width);
! 451: elem.clip.height = getInt(rect.height);
! 452: }
! 453: } else {
! 454: alert("moveelement: no style nor layer property!");
! 455: return false;
! 456: }
! 457: return true;
! 458: }
! 459:
! 460: function showElement(elem, show) {
! 461: // shows or hides the element
! 462: if (elem.style) {
! 463: if (show) {
! 464: elem.style.visibility = "visible";
! 465: } else {
! 466: elem.style.visibility = "hidden";
! 467: }
! 468: } else if (defined(elem.visibility)) {
! 469: if (show) {
! 470: elem.visibility = "show";
! 471: } else {
! 472: elem.visibility = "hide";
! 473: }
! 474: } else {
! 475: alert("showelement: no style nor layer property!");
! 476: }
! 477: return true;
! 478: }
! 479:
! 480: function evtPosition(evt) {
! 481: // returns the on-screen Position of the Event
! 482: var x;
! 483: var y;
! 484: evt = (evt) ? evt : window.event;
! 485: if (!evt) {
! 486: alert("no event found! "+evt);
! 487: return;
! 488: }
! 489: if (defined(evt.pageX)) {
! 490: x = parseInt(evt.pageX);
! 491: y = parseInt(evt.pageY);
! 492: } else if (defined(evt.clientX)) {
! 493: x = parseInt(document.body.scrollLeft+evt.clientX);
! 494: y = parseInt(document.body.scrollTop+evt.clientY);
! 495: } else {
! 496: alert("evtPosition: don't know how to deal with "+evt);
! 497: }
! 498: return new Position(x, y);
! 499: }
! 500:
! 501: function registerEvent(type, elem, handler) {
! 502: // register the given event handler on the indicated element
! 503: if (elem.addEventListener) {
! 504: elem.addEventListener(type, handler, false);
! 505: } else {
! 506: if (type == "mousedown") {
! 507: if (elem.captureEvents) {
! 508: elem.captureEvents(Event.MOUSEDOWN);
! 509: }
! 510: elem.onmousedown = handler;
! 511: } else if (type == "mouseup") {
! 512: if (elem.captureEvents) {
! 513: elem.captureEvents(Event.MOUSEUP);
! 514: }
! 515: elem.onmouseup = handler;
! 516: } else if (type == "mousemove") {
! 517: if (elem.captureEvents) {
! 518: elem.captureEvents(Event.MOUSEMOVE);
! 519: }
! 520: elem.onmousemove = handler;
! 521: } else if (type == "keypress") {
! 522: if (elem.captureEvents) {
! 523: elem.captureEvents(Event.KEYPRESS);
! 524: }
! 525: elem.onkeypress = handler;
! 526: } else {
! 527: alert("registerEvent: unknown event type "+type);
! 528: return false;
! 529: }
! 530: }
! 531: return true;
! 532: }
! 533:
! 534: function unregisterEvent(type, elem, handler) {
! 535: // unregister the given event handler from the indicated element
! 536: if (elem.removeEventListener) {
! 537: elem.removeEventListener(type, handler, false);
! 538: } else {
! 539: if (type == "mousedown") {
! 540: if (elem.releaseEvents) {
! 541: elem.releaseEvents(Event.MOUSEDOWN);
! 542: }
! 543: elem.onmousedown = null;
! 544: } else if (type == "mouseup") {
! 545: if (elem.releaseEvents) {
! 546: elem.releaseEvents(Event.MOUSEUP);
! 547: }
! 548: elem.onmouseup = null;
! 549: } else if (type == "mousemove") {
! 550: if (elem.releaseEvents) {
! 551: elem.releaseEvents(Event.MOUSEMOVE);
! 552: }
! 553: elem.onmousemove = null;
! 554: } else if (type == "keypress") {
! 555: if (elem.releaseEvents) {
! 556: elem.releaseEvents(Event.KEYPRESS);
! 557: }
! 558: elem.onkeypress = null;
! 559: } else {
! 560: alert("unregisterEvent: unknown event type "+type);
! 561: return false;
! 562: }
! 563: }
! 564: return true;
! 565: }
! 566:
! 567:
! 568: // old registerXXYY API for compatibility
! 569: function registerMouseDown(elem, handler) {
! 570: return registerEvent("mousedown", elem, handler);
! 571: }
! 572: function unregisterMouseDown(elem, handler) {
! 573: return unregisterEvent("mousedown", elem, handler);
! 574: }
! 575: function registerMouseMove(elem, handler) {
! 576: return registerEvent("mousemove", elem, handler);
! 577: }
! 578: function unregisterMouseMove(elem, handler) {
! 579: return unregisterEvent("mousemove", elem, handler);
! 580: }
! 581: function registerKeyDown(handler) {
! 582: return registerEvent("keypress", elem, handler);
! 583: }
! 584:
! 585:
! 586: function getWinSize() {
! 587: // returns a Size with the current window size (mostly from www.quirksmode.org)
! 588: var wsize = new Size(100, 100);
! 589: if (defined(self.innerHeight)) {
! 590: // all except Explorer
! 591: if ((self.innerWidth == 0)||(self.innerHeight == 0)) {
! 592: // Safari 1.2 bug
! 593: if (parent) {
! 594: parent.innerHeight;
! 595: parent.innerWidth;
! 596: }
! 597: }
! 598: wsize.width = self.innerWidth;
! 599: wsize.height = self.innerHeight;
! 600: } else if (document.documentElement && document.documentElement.clientHeight) {
! 601: // Explorer 6 Strict Mode
! 602: wsize.width = document.documentElement.clientWidth;
! 603: wsize.height = document.documentElement.clientHeight;
! 604: } else if (document.body) {
! 605: // other Explorers
! 606: wsize.width = document.body.clientWidth;
! 607: wsize.height = document.body.clientHeight;
! 608: }
! 609: return wsize;
! 610: }
! 611:
! 612: function openWin(url, name, params) {
! 613: // open browser window
! 614: var ow = window.open(url, name, params);
! 615: ow.focus();
! 616: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>