Annotation of zogiLib/js/js_lib.js, revision 1.1
1.1 ! casties 1: /* Copyright (C) 2003,2004 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: ROC 3.5.2004
! 18: first version by Christian Luginbuehl, 01.05.2003
! 19: Changed for digiLib in Zope by DW 24.03.2004
! 20: */
! 21:
! 22: // fixes for javascript < 1.2
! 23: if (! Array.prototype.push) {
! 24: Array.prototype.push = function(val) {
! 25: this[this.length] = val;
! 26: return this.length;
! 27: }
! 28: Array.prototype.pop = function() {
! 29: var val = this[this.length-1];
! 30: this.length -= 1;
! 31: return val;
! 32: }
! 33: }
! 34:
! 35: // auxiliary function to crop senseless precision
! 36: function cropFloat(x) {
! 37: return parseInt(10000*x)/10000;
! 38: }
! 39:
! 40:
! 41: /* **********************************************
! 42: * geometry classes
! 43: * ******************************************** */
! 44:
! 45: /*
! 46: * Size class
! 47: */
! 48: function Size(w, h) {
! 49: this.width = parseFloat(w);
! 50: this.height = parseFloat(h);
! 51: return this;
! 52: }
! 53:
! 54: /*
! 55: * Position class
! 56: */
! 57: function Position(x, y) {
! 58: this.x = parseFloat(x);
! 59: this.y = parseFloat(y);
! 60: return this;
! 61: }
! 62:
! 63: /*
! 64: * Rectangle class
! 65: */
! 66: function Rectangle(x, y, w, h) {
! 67: this.x = parseFloat(x);
! 68: this.y = parseFloat(y);
! 69: this.width = parseFloat(w);
! 70: this.height = parseFloat(h);
! 71: return this;
! 72: }
! 73: Rectangle.prototype.copy = function() {
! 74: // returns a copy of this Rectangle
! 75: return new Rectangle(this.x, this.y, this.width, this.height);
! 76: }
! 77: Rectangle.prototype.containsPosition = function(pos) {
! 78: // returns if the given Position lies in this Rectangle
! 79: return ((pos.x >= this.x)&&(pos.y >= this.y)&&(pos.x <= this.x+this.width)&&(pos.y <= this.y+this.width));
! 80: }
! 81: Rectangle.prototype.intersect = function(rect) {
! 82: // returns the intersection of the given Rectangle and this one
! 83: var sec = rect.copy();
! 84: if (sec.x < this.x) {
! 85: sec.width = sec.width - (this.x - sec.x);
! 86: sec.x = this.x;
! 87: }
! 88: if (sec.y < this.y) {
! 89: sec.height = sec.height - (this.y - sec.y);
! 90: sec.y = this.y;
! 91: }
! 92: if (sec.x + sec.width > this.x + this.width) {
! 93: sec.width = (this.x + this.width) - sec.x;
! 94: }
! 95: if (sec.y + sec.height > this.y + this.height) {
! 96: sec.height = (this.y + this.height) - sec.y;
! 97: }
! 98: return sec;
! 99: }
! 100: Rectangle.prototype.fit = function(rect) {
! 101: // returns a Rectangle that fits into this one (by moving first)
! 102: var sec = rect.copy();
! 103: sec.x = Math.max(sec.x, this.x);
! 104: sec.x = Math.max(sec.x, this.x);
! 105: if (sec.x + sec.width > this.x + this.width) {
! 106: sec.x = this.x + this.width - sec.width;
! 107: }
! 108: if (sec.y + sec.height > this.y + this.height) {
! 109: sec.y = this.y + this.height - sec.height;
! 110: }
! 111: return sec.intersect(this);
! 112: }
! 113:
! 114: /*
! 115: * Transform class
! 116: *
! 117: * defines a class of affine transformations
! 118: */
! 119: function Transform() {
! 120: this.m00 = 1.0;
! 121: this.m01 = 0.0;
! 122: this.m02 = 0.0;
! 123: this.m10 = 0.0;
! 124: this.m11 = 1.0;
! 125: this.m12 = 0.0;
! 126: this.m20 = 0.0;
! 127: this.m21 = 0.0;
! 128: this.m22 = 1.0;
! 129: return this;
! 130: }
! 131: Transform.prototype.concat = function(traf) {
! 132: // add Transform traf to this Transform
! 133: for (var i = 0; i < 3; i++) {
! 134: for (var j = 0; j < 3; j++) {
! 135: var c = 0.0;
! 136: for (var k = 0; k < 3; k++) {
! 137: c += traf["m"+i+k] * this["m"+k+j];
! 138: }
! 139: this["m"+i+j] = c;
! 140: }
! 141: }
! 142: return this;
! 143: }
! 144: Transform.prototype.transform = function(pos) {
! 145: // returns transformed Position pos with this Transform applied
! 146: var x = this.m00 * pos.x + this.m01 * pos.y + this.m02;
! 147: var y = this.m10 * pos.x + this.m11 * pos.y + this.m12;
! 148: return new Position(x, y);
! 149: }
! 150: Transform.prototype.invtransform = function(pos) {
! 151: // returns transformed Position pos with the inverse of this Transform applied
! 152: var det = this.m00 * this.m11 - this.m01 * this.m10;
! 153: var x = (this.m11 * pos.x - this.m01 * pos.y - this.m11 * this.m02 + this.m01 * this.m12) / det;
! 154: var y = (- this.m10 * pos.x + this.m00 * pos.y + this.m10 * this.m02 - this.m00 * this.m12) / det;
! 155: return new Position(x, y);
! 156: }
! 157: function getRotation(angle, pos) {
! 158: // returns a Transform that is a rotation by angle degrees around [pos.x, pos.y]
! 159: var traf = new Transform();
! 160: if (angle != 0) {
! 161: var t = 2.0 * Math.PI * parseFloat(angle) / 360.0;
! 162: traf.m00 = Math.cos(t);
! 163: traf.m01 = - Math.sin(t);
! 164: traf.m10 = Math.sin(t);
! 165: traf.m11 = Math.cos(t);
! 166: traf.m02 = pos.x - pos.x * Math.cos(t) + pos.y * Math.sin(t);
! 167: traf.m12 = pos.y - pos.x * Math.sin(t) - pos.y * Math.cos(t);
! 168: }
! 169: return traf;
! 170: }
! 171: function getTranslation(pos) {
! 172: // returns a Transform that is a translation by [pos.x, pos,y]
! 173: var traf = new Transform();
! 174: traf.m02 = pos.x;
! 175: traf.m12 = pos.y;
! 176: return traf;
! 177: }
! 178: function getScale(size) {
! 179: // returns a Transform that is a scale by [size.width, size.height]
! 180: var traf = new Transform();
! 181: traf.m00 = size.width;
! 182: traf.m11 = size.height;
! 183: return traf;
! 184: }
! 185:
! 186:
! 187: /* **********************************************
! 188: * parameter routines
! 189: * ******************************************** */
! 190:
! 191: var dlParams = new Object();
! 192:
! 193: function newParameter(name, defaultValue, detail) {
! 194: // create a new parameter with a name and a default value
! 195: if (dlParams[name]) {
! 196: alert("Fatal: An object with name '" + name + "' already exists - cannot recreate!");
! 197: return false;
! 198: } else {
! 199: dlParams[name] = new Object();
! 200: dlParams[name].defaultValue = defaultValue;
! 201: dlParams[name].hasValue = false;
! 202: dlParams[name].value = defaultValue;
! 203: dlParams[name].detail = detail;
! 204: return dlParams[name];
! 205: }
! 206: }
! 207:
! 208: function getParameter(name) {
! 209: // returns the named parameter value or its default value
! 210: if (dlParams[name]) {
! 211: if (dlParams[name].hasValue) {
! 212: return dlParams[name].value;
! 213: } else {
! 214: return dlParams[name].defaultValue;
! 215: }
! 216: } else {
! 217: return undefined;
! 218: }
! 219: }
! 220:
! 221: function setParameter(name, value) {
! 222: // sets parameter value
! 223: if (dlParams[name]) {
! 224: dlParams[name].value = value;
! 225: dlParams[name].hasValue = true;
! 226: return true;
! 227: }
! 228: return false;
! 229: }
! 230:
! 231: function getAllParameters(detail) {
! 232: // returns a string of all parameters in query format
! 233: var params = new Array();
! 234: for ( param in dlParams ) {
! 235: if ((dlParams[param].detail <= detail)&&(dlParams[param].hasValue)) {
! 236: var val = getParameter(param);
! 237: if (val != "") {
! 238: params.push(param + "=" + val);
! 239: }
! 240: }
! 241: }
! 242: return params.join("&");
! 243: }
! 244:
! 245: function parseParameters(query) {
! 246: // gets parameter values from query format string
! 247: var params = query.split("&");
! 248: for (var i = 0; i < params.length; i++) {
! 249: var keyval = params[i].split("=");
! 250: if (keyval.length == 2) {
! 251: setParameter(keyval[0], keyval[1]);
! 252: }
! 253: }
! 254: }
! 255:
! 256:
! 257: /* **********************************************
! 258: * HTML/DOM routines
! 259: * ******************************************** */
! 260:
! 261: function getElement(tagid) {
! 262: // returns the element object with the id tagid
! 263: if (document.getElementById) {
! 264: return document.getElementById(tagid);
! 265: } else if (document.all) {
! 266: alert("document.all!");
! 267: return document.all[tagid];
! 268: } else {
! 269: var s = "";
! 270: for (var e in document.layers) {
! 271: s += "'" + e + "', ";
! 272: }
! 273: alert("no document.all! "+tagid+" = "+s);
! 274: return document[tagid];
! 275: }
! 276: }
! 277:
! 278: function getElementSize(tagid) {
! 279: // returns a Rectangle with the size and position of the named element
! 280: var x = 0;
! 281: var y = 0;
! 282: var width = 0;
! 283: var height = 0;
! 284: var elem = getElement(tagid);
! 285: if (elem.left) {
! 286: alert("elem.left!");
! 287: x = elem.left;
! 288: y = elem.top;
! 289: width = elem.width;
! 290: height = elem.height;
! 291: } else {
! 292: if (elem.clientLeft) {
! 293: // spass mit IE
! 294: x = elem.clientLeft;
! 295: y = elem.clientTop;
! 296: } else {
! 297: var e = elem;
! 298: while (e) {
! 299: x += e.offsetLeft;
! 300: y += e.offsetTop;
! 301: e = e.offsetParent;
! 302: }
! 303: }
! 304: width = elem.offsetWidth;
! 305: height = elem.offsetHeight;
! 306: }
! 307: return new Rectangle(x, y, width, height);
! 308: }
! 309:
! 310: function moveElement(tagid, pos) {
! 311: // moves the named element to the indicated position
! 312: var elem = getElement(tagid);
! 313: if (elem.style) {
! 314: elem.style.left = pos.x + "px";
! 315: elem.style.top = pos.y + "px";
! 316: } else {
! 317: alert("moveelement: no style property!");
! 318: elem.left = pos.x;
! 319: elem.top = pos.y;
! 320: }
! 321: return true;
! 322: }
! 323:
! 324: function showElement(tagid, show) {
! 325: // shows or hides the named element
! 326: var elem = getElement(tagid);
! 327: if (elem.style) {
! 328: if (show) {
! 329: elem.style.visibility = "visible";
! 330: } else {
! 331: elem.style.visibility = "hidden";
! 332: }
! 333: } else {
! 334: alert("showelement: no style property!");
! 335: }
! 336: return true;
! 337: }
! 338:
! 339: function evtPosition(evt) {
! 340: // returns the on-screen Position of the Event
! 341: var x;
! 342: var y;
! 343: if (document.all) {
! 344: x = parseInt(document.body.scrollLeft+event.clientX);
! 345: y = parseInt(document.body.scrollLeft+event.clientY);
! 346: } else {
! 347: x = parseInt(evt.pageX);
! 348: y = parseInt(evt.pageY);
! 349: }
! 350: return new Position(x, y);
! 351: }
! 352:
! 353: function registerMouseDown(tagid, handler) {
! 354: // register a mouse down event handler on the indicated element
! 355: if ( document.all ) {
! 356: document.all[tagid].onmousedown = handler;
! 357: } else if (document.getElementById) {
! 358: document.getElementById(tagid).addEventListener("mousedown", handler, true);
! 359: } else {
! 360: document[tagid].captureEvents(Event.MOUSEDOWN);
! 361: document[tagid].onmousedown = handler;
! 362: }
! 363: return true;
! 364: }
! 365:
! 366: function unregisterMouseDown(tagid, handler) {
! 367: // unregister the mouse down event handler
! 368: if ( document.all ) {
! 369: document.all[tagid].onmousedown = null;
! 370: } else if (document.getElementById) {
! 371: document.getElementById(tagid).removeEventListener("mousedown", handler, true);
! 372: } else {
! 373: document[tagid].releaseEvents(Event.MOUSEDOWN);
! 374: }
! 375: return true;
! 376: }
! 377:
! 378: function registerMouseMove(tagid, handler) {
! 379: // register a mouse move event handler on the indicated element
! 380: if ( document.all ) {
! 381: document.all[tagid].onmousemove = handler;
! 382: } else if (document.getElementById) {
! 383: document.getElementById(tagid).addEventListener("mousemove", handler, true);
! 384: } else {
! 385: document[tagid].captureEvents(Event.MOUSEMOVE);
! 386: document[tagid].onmousemove = handler;
! 387: }
! 388: return true;
! 389: }
! 390:
! 391: function unregisterMouseMove(tagid, handler) {
! 392: // unregister the mouse move event handler
! 393: if ( document.all ) {
! 394: document.all[tagid].onmousemove = null;
! 395: } else if (document.getElementById) {
! 396: document.getElementById(tagid).removeEventListener("mousemove", handler, true);
! 397: } else {
! 398: document[tagid].releaseEvents(Event.MOUSEMOVE);
! 399: }
! 400: return true;
! 401: }
! 402:
! 403: function registerKeyDown(handler) {
! 404: // register a key down handler
! 405: if ( document.all ) {
! 406: this.document.onkeypress = handler
! 407: } else if ( typeof(document.addEventListener) == "function" ) {
! 408: this.document.addEventListener('keypress', handler, true);
! 409: } else {
! 410: window.captureEvents(Event.KEYDOWN);
! 411: window.onkeydown = handler;
! 412: }
! 413: return true;
! 414: }
! 415:
! 416: function getWinSize() {
! 417: // returns a Size with the current window size (from www.quirksmode.org)
! 418: var wsize = new Size(100, 100);
! 419: if (self.innerHeight) {
! 420: // all except Explorer
! 421: wsize.width = self.innerWidth;
! 422: wsize.height = self.innerHeight;
! 423: } else if (document.documentElement && document.documentElement.clientHeight) {
! 424: // Explorer 6 Strict Mode
! 425: wsize.width = document.documentElement.clientWidth;
! 426: wsize.height = document.documentElement.clientHeight;
! 427: } else if (document.body) {
! 428: // other Explorers
! 429: wsize.width = document.body.clientWidth;
! 430: wsize.height = document.body.clientHeight;
! 431: }
! 432: return wsize;
! 433: }
! 434:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>