/* Copyright (C) 2003,2004 WTWG, Uni Bern and others
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Authors: ROC 3.5.2004
first version by Christian Luginbuehl, 01.05.2003
Changed for digiLib in Zope by DW 24.03.2004
*/
// fixes for javascript < 1.2
if (! Array.prototype.push) {
Array.prototype.push = function(val) {
this[this.length] = val;
return this.length;
}
Array.prototype.pop = function() {
var val = this[this.length-1];
this.length -= 1;
return val;
}
}
// auxiliary function to crop senseless precision
function cropFloat(x) {
return parseInt(10000*x)/10000;
}
/* **********************************************
* geometry classes
* ******************************************** */
/*
* Size class
*/
function Size(w, h) {
this.width = parseFloat(w);
this.height = parseFloat(h);
return this;
}
/*
* Position class
*/
function Position(x, y) {
this.x = parseFloat(x);
this.y = parseFloat(y);
return this;
}
/*
* Rectangle class
*/
function Rectangle(x, y, w, h) {
this.x = parseFloat(x);
this.y = parseFloat(y);
this.width = parseFloat(w);
this.height = parseFloat(h);
return this;
}
Rectangle.prototype.copy = function() {
// returns a copy of this Rectangle
return new Rectangle(this.x, this.y, this.width, this.height);
}
Rectangle.prototype.containsPosition = function(pos) {
// returns if the given Position lies in this Rectangle
return ((pos.x >= this.x)&&(pos.y >= this.y)&&(pos.x <= this.x+this.width)&&(pos.y <= this.y+this.width));
}
Rectangle.prototype.intersect = function(rect) {
// returns the intersection of the given Rectangle and this one
var sec = rect.copy();
if (sec.x < this.x) {
sec.width = sec.width - (this.x - sec.x);
sec.x = this.x;
}
if (sec.y < this.y) {
sec.height = sec.height - (this.y - sec.y);
sec.y = this.y;
}
if (sec.x + sec.width > this.x + this.width) {
sec.width = (this.x + this.width) - sec.x;
}
if (sec.y + sec.height > this.y + this.height) {
sec.height = (this.y + this.height) - sec.y;
}
return sec;
}
Rectangle.prototype.fit = function(rect) {
// returns a Rectangle that fits into this one (by moving first)
var sec = rect.copy();
sec.x = Math.max(sec.x, this.x);
sec.x = Math.max(sec.x, this.x);
if (sec.x + sec.width > this.x + this.width) {
sec.x = this.x + this.width - sec.width;
}
if (sec.y + sec.height > this.y + this.height) {
sec.y = this.y + this.height - sec.height;
}
return sec.intersect(this);
}
/*
* Transform class
*
* defines a class of affine transformations
*/
function Transform() {
this.m00 = 1.0;
this.m01 = 0.0;
this.m02 = 0.0;
this.m10 = 0.0;
this.m11 = 1.0;
this.m12 = 0.0;
this.m20 = 0.0;
this.m21 = 0.0;
this.m22 = 1.0;
return this;
}
Transform.prototype.concat = function(traf) {
// add Transform traf to this Transform
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var c = 0.0;
for (var k = 0; k < 3; k++) {
c += traf["m"+i+k] * this["m"+k+j];
}
this["m"+i+j] = c;
}
}
return this;
}
Transform.prototype.transform = function(pos) {
// returns transformed Position pos with this Transform applied
var x = this.m00 * pos.x + this.m01 * pos.y + this.m02;
var y = this.m10 * pos.x + this.m11 * pos.y + this.m12;
return new Position(x, y);
}
Transform.prototype.invtransform = function(pos) {
// returns transformed Position pos with the inverse of this Transform applied
var det = this.m00 * this.m11 - this.m01 * this.m10;
var x = (this.m11 * pos.x - this.m01 * pos.y - this.m11 * this.m02 + this.m01 * this.m12) / det;
var y = (- this.m10 * pos.x + this.m00 * pos.y + this.m10 * this.m02 - this.m00 * this.m12) / det;
return new Position(x, y);
}
function getRotation(angle, pos) {
// returns a Transform that is a rotation by angle degrees around [pos.x, pos.y]
var traf = new Transform();
if (angle != 0) {
var t = 2.0 * Math.PI * parseFloat(angle) / 360.0;
traf.m00 = Math.cos(t);
traf.m01 = - Math.sin(t);
traf.m10 = Math.sin(t);
traf.m11 = Math.cos(t);
traf.m02 = pos.x - pos.x * Math.cos(t) + pos.y * Math.sin(t);
traf.m12 = pos.y - pos.x * Math.sin(t) - pos.y * Math.cos(t);
}
return traf;
}
function getTranslation(pos) {
// returns a Transform that is a translation by [pos.x, pos,y]
var traf = new Transform();
traf.m02 = pos.x;
traf.m12 = pos.y;
return traf;
}
function getScale(size) {
// returns a Transform that is a scale by [size.width, size.height]
var traf = new Transform();
traf.m00 = size.width;
traf.m11 = size.height;
return traf;
}
/* **********************************************
* parameter routines
* ******************************************** */
var dlParams = new Object();
function newParameter(name, defaultValue, detail) {
// create a new parameter with a name and a default value
if (dlParams[name]) {
alert("Fatal: An object with name '" + name + "' already exists - cannot recreate!");
return false;
} else {
dlParams[name] = new Object();
dlParams[name].defaultValue = defaultValue;
dlParams[name].hasValue = false;
dlParams[name].value = defaultValue;
dlParams[name].detail = detail;
return dlParams[name];
}
}
function getParameter(name) {
// returns the named parameter value or its default value
if (dlParams[name]) {
if (dlParams[name].hasValue) {
return dlParams[name].value;
} else {
return dlParams[name].defaultValue;
}
} else {
return undefined;
}
}
function setParameter(name, value) {
// sets parameter value
if (dlParams[name]) {
dlParams[name].value = value;
dlParams[name].hasValue = true;
return true;
}
return false;
}
function getAllParameters(detail) {
// returns a string of all parameters in query format
var params = new Array();
for ( param in dlParams ) {
if ((dlParams[param].detail <= detail)&&(dlParams[param].hasValue)) {
var val = getParameter(param);
if (val != "") {
params.push(param + "=" + val);
}
}
}
return params.join("&");
}
function parseParameters(query) {
// gets parameter values from query format string
var params = query.split("&");
for (var i = 0; i < params.length; i++) {
var keyval = params[i].split("=");
if (keyval.length == 2) {
setParameter(keyval[0], keyval[1]);
}
}
}
/* **********************************************
* HTML/DOM routines
* ******************************************** */
function getElement(tagid) {
// returns the element object with the id tagid
if (document.getElementById) {
return document.getElementById(tagid);
} else if (document.all) {
alert("document.all!");
return document.all[tagid];
} else {
var s = "";
for (var e in document.layers) {
s += "'" + e + "', ";
}
alert("no document.all! "+tagid+" = "+s);
return document[tagid];
}
}
function getElementSize(tagid) {
// returns a Rectangle with the size and position of the named element
var x = 0;
var y = 0;
var width = 0;
var height = 0;
var elem = getElement(tagid);
if (elem.left) {
alert("elem.left!");
x = elem.left;
y = elem.top;
width = elem.width;
height = elem.height;
} else {
if (elem.clientLeft) {
// spass mit IE
x = elem.clientLeft;
y = elem.clientTop;
} else {
var e = elem;
while (e) {
x += e.offsetLeft;
y += e.offsetTop;
e = e.offsetParent;
}
}
width = elem.offsetWidth;
height = elem.offsetHeight;
}
return new Rectangle(x, y, width, height);
}
function moveElement(tagid, pos) {
// moves the named element to the indicated position
var elem = getElement(tagid);
if (elem.style) {
elem.style.left = pos.x + "px";
elem.style.top = pos.y + "px";
} else {
alert("moveelement: no style property!");
elem.left = pos.x;
elem.top = pos.y;
}
return true;
}
function showElement(tagid, show) {
// shows or hides the named element
var elem = getElement(tagid);
if (elem.style) {
if (show) {
elem.style.visibility = "visible";
} else {
elem.style.visibility = "hidden";
}
} else {
alert("showelement: no style property!");
}
return true;
}
function evtPosition(evt) {
// returns the on-screen Position of the Event
var x;
var y;
if (document.all) {
x = parseInt(document.body.scrollLeft+event.clientX);
y = parseInt(document.body.scrollLeft+event.clientY);
} else {
x = parseInt(evt.pageX);
y = parseInt(evt.pageY);
}
return new Position(x, y);
}
function registerMouseDown(tagid, handler) {
// register a mouse down event handler on the indicated element
if ( document.all ) {
document.all[tagid].onmousedown = handler;
} else if (document.getElementById) {
document.getElementById(tagid).addEventListener("mousedown", handler, true);
} else {
document[tagid].captureEvents(Event.MOUSEDOWN);
document[tagid].onmousedown = handler;
}
return true;
}
function unregisterMouseDown(tagid, handler) {
// unregister the mouse down event handler
if ( document.all ) {
document.all[tagid].onmousedown = null;
} else if (document.getElementById) {
document.getElementById(tagid).removeEventListener("mousedown", handler, true);
} else {
document[tagid].releaseEvents(Event.MOUSEDOWN);
}
return true;
}
function registerMouseMove(tagid, handler) {
// register a mouse move event handler on the indicated element
if ( document.all ) {
document.all[tagid].onmousemove = handler;
} else if (document.getElementById) {
document.getElementById(tagid).addEventListener("mousemove", handler, true);
} else {
document[tagid].captureEvents(Event.MOUSEMOVE);
document[tagid].onmousemove = handler;
}
return true;
}
function unregisterMouseMove(tagid, handler) {
// unregister the mouse move event handler
if ( document.all ) {
document.all[tagid].onmousemove = null;
} else if (document.getElementById) {
document.getElementById(tagid).removeEventListener("mousemove", handler, true);
} else {
document[tagid].releaseEvents(Event.MOUSEMOVE);
}
return true;
}
function registerKeyDown(handler) {
// register a key down handler
if ( document.all ) {
this.document.onkeypress = handler
} else if ( typeof(document.addEventListener) == "function" ) {
this.document.addEventListener('keypress', handler, true);
} else {
window.captureEvents(Event.KEYDOWN);
window.onkeydown = handler;
}
return true;
}
function getWinSize() {
// returns a Size with the current window size (from www.quirksmode.org)
var wsize = new Size(100, 100);
if (self.innerHeight) {
// all except Explorer
wsize.width = self.innerWidth;
wsize.height = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) {
// Explorer 6 Strict Mode
wsize.width = document.documentElement.clientWidth;
wsize.height = document.documentElement.clientHeight;
} else if (document.body) {
// other Explorers
wsize.width = document.body.clientWidth;
wsize.height = document.body.clientHeight;
}
return wsize;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>