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