File:  [Repository] / ECHO_content / js / baselib.js
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Tue Sep 11 15:42:26 2007 UTC (16 years, 10 months ago) by casties
Branches: MAIN
CVS tags: cleanup, Root_cleanup, HEAD
new js code with fix to getposition for ff3 and safari3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>