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