
/* ******************************
Cross-Browser DHTML library
Works with IE 5+, Mozilla/Firefox, and Safari
Untested in Opera, Konquerer, etc.

Created by Alan Bellows
alan@alanbellows.com
version 2005-06-24

If you wish to use this code, this information header
must be left intact. If you want the most up-to-date,
commented, non-compressed version, contact me at
alan@alanbellows.com
****************************** */

var IE = "Internet Explorer"; var MOZILLA = "Mozilla Compatible"; var SAFARI = "Safari"; var OPERA = "Opera"; var Browser = new BrowserAccess(); window.onload = function () { Browser.callOnLoadActions();}; window.onresize = function () { Browser.callOnResizeActions();}; if (typeof XMLHttpRequest != "object") { function XMLHttpRequest() { return new ActiveXObject("Microsoft.XMLHTTP");}}function BrowserAccess () { this.name = ""; this.onLoadActions = new Array(); this.onResizeActions = new Array(); this.preloadedImages = new Array(); this.debugMode = false; this.debugOutput = ""; this.trackingCursor = false; this.cursorX = 0; this.cursorY = 0; this.params = new Array(); if (window.opera) { this.name = OPERA;}else if (navigator.appVersion.indexOf("MSIE") > -1 && document.all) { this.name = IE;}else if (navigator.appVersion.indexOf("Safari") > -1) { this.name = SAFARI;}else { this.name = MOZILLA;}var loc = document.location.href; if (loc.indexOf("?") > -1) { var paramString = loc.substring(loc.indexOf("?")+1); var paramStrings = paramString.split("&"); for (var i=0; i < paramStrings.length; i++) { var keyValue = paramStrings[i].split("=", 2); if (keyValue.length < 2) keyValue[1] = ""; this.params[keyValue[0]] = keyValue[1];}}}BrowserAccess.prototype.preloadImage = function (url) { this.preloadedImages[this.preloadedImages.length] = new Image(); this.preloadedImages[this.preloadedImages.length-1].src = url;}; BrowserAccess.prototype.trackCursor = function (e) { if (this.trackingCursor == false) { this.debug("[Browser] Now tracking cursor"); document.onmousemove = Browser.trackCursor;}else { if (e != null) { Browser.cursorX = e.pageX; Browser.cursorY = e.pageY;}else { Browser.cursorX = event.clientX; Browser.cursorY = event.clientY;}}this.trackingCursor = true;}; BrowserAccess.prototype.getScrollX = function () { var scrollX = (window.pageXOffset) ? window.pageXOffset : (DOM.getBodyElement().scrollLeft); return scrollX;}; BrowserAccess.prototype.getScrollY = function () { var scrollY = (window.pageYOffset) ? window.pageYOffset : (DOM.getBodyElement().scrollTop); return scrollY;}; BrowserAccess.prototype.fixPngImages = function () { if (this.name == IE) { this.debug("[Browser] Fixing PNG images..."); var allImages = document.getElementsByTagName('img'); for (var i=0; i < allImages.length; i++) { if (allImages[i].src.indexOf(".png") > -1 && allImages[i].src.indexOf("transparency=no") < 0) { var parent = allImages[i].parentNode; var image = allImages[i]; var rects = parent.getClientRects(); var sizingMethod = image.getAttribute("sizing"); if (sizingMethod == null) { if (parent.style.position == "absolute" || image.style.width.indexOf("%") > -1 || parent.style.width.indexOf("%") > -1 || image.style.height.indexOf("%") > -1 || parent.style.height.indexOf("%") > -1) { sizingMethod = "scale";}else { sizingMethod = "image";}}if (rects[0]) rects = rects[0]; this.debug("[Browser] Fixing PNG image (" + image.src + ") in '" + sizingMethod + "' sizing mode"); parent.removeChild(image); parent.style.backgroundImage = 'none'; parent.style.width = rects.right - rects.left; parent.style.height = rects.bottom - rects.top; parent.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + image.src + "',sizingMethod='" + sizingMethod + "')"; i-= 1;}}}}; BrowserAccess.prototype.getInnerHeight = function () { var height = 0; if (window.innerHeight) { height = window.innerHeight;}else if (document.body && document.body.clientHeight) { height = document.body.clientHeight;}else if (document.documentElement && document.documentElement.clientHeight) { height = document.documentElement.clientHeight;}else { height = 0;}this.debug("[Browser] getInnerHeight() = " + height); return height;}; BrowserAccess.prototype.getInnerWidth = function () { var width = 0; if (window.innerWidth) { width = window.innerWidth;}else if (document.body && document.body.clientWidth) { width = document.body.clientWidth;}else if (document.documentElement && document.documentElement.clientWidth) { width = document.documentElement.clientWidth;}else { width = 0;}this.debug("[Browser] getInnerWidth() = " + width); return width;}; BrowserAccess.prototype.openWindow = function (url, name, width, height, resizable) { var leftPos = (screen.availWidth/2) - (width/2); var topPos = (screen.availHeight/2) - (height/2); var properties = ""; if (resizable == null)resizable = true; if (screen.availHeight < height) { height = screen.availHeight - 50; topPos = 0;}if (screen.availWidth < width) { width = screen.availWidth; leftPos = 0;}properties+= "width=" + width + ","; properties+= "height=" + height + ","; properties+= "screenX=" + leftPos + ","; properties+= "screenY=" + topPos + ","; properties+= "directories=no,"; properties+= "location=no,"; properties+= "menubar=yes,"; properties+= "personalbar=no,"; if (resizable) { properties+= "resizable=yes,";}else { properties+= "resizable=no,";}properties+= "status=no,"; properties+= "toolbar=yes,"; properties+= "scrollbars=yes,"; properties+= "dependent=yes"; var popup = window.open(url, name, properties);}; BrowserAccess.prototype.debugOn = function (debugOutput) { this.debugMode = true; this.debugOutput = debugOutput; this.addOnLoadAction(this.debugOutput + ".value = ''"); alert("Debug on (" + debugOutput + ")"); return true;}; BrowserAccess.prototype.debug = function () { var string = ""; for (var i=0; i < arguments.length; i++) { string+= arguments[i]; if (i+1 < arguments.length) string += " / ";}string+= "\\n"; if (this.debugMode == true) { if (! eval(this.debugOutput.substring(0, this.debugOutput.lastIndexOf(".")))) { this.addOnLoadAction(this.debugOutput + ".value = \"" + string + "\" + " + this.debugOutput + ".value", true);}else { eval(this.debugOutput + ".value+= \"" + string + "\"");}}return string;}; BrowserAccess.prototype.addOnLoadAction = function (string, addToTop) { if (addToTop) this.onLoadActions.unshift(string); else this.onLoadActions.push(string);}; BrowserAccess.prototype.callOnLoadActions = function () { this.evalAll(this.onLoadActions);}; BrowserAccess.prototype.addOnResizeAction = function (string) { this.onResizeActions.push(string);}; BrowserAccess.prototype.callOnResizeActions = function () { this.evalAll(this.onResizeActions);}; BrowserAccess.prototype.evalAll = function (commandArray) { for (var i=0; i < commandArray.length; i++) { if (commandArray[i] != null) { if (typeof(commandArray[i]) == "string") { eval(commandArray[i]);}else if (typeof(commandArray[i]) == "object") { commandArray[i];}}}}; var TOP = "top"; var RIGHT = "right"; var BOTTOM = "bottom"; var LEFT = "left"; var DOM = new DOMAccess(); function DOMAccess () { this.allExtendedElements = new Array(); this.elementIDs = new Array(); this.bodyElement = null; this.counter = 0; Browser.addOnResizeAction("DOM.clearRects();");}DOMAccess.prototype.getBodyElement = function () { if (this.bodyElement == null)this.bodyElement = this.extend((document.compatMode && document.compatMode.toLowerCase() != "backcompat") ? document.documentElement : (document.body || null)); return this.bodyElement;}; DOMAccess.prototype.getElement = function (eID) { var e; if (typeof(eID) == "string") { if (this.allExtendedElements[eID]) { e = this.allExtendedElements[eID];}else { if (document.getElementById) e = document.getElementById(eID); else if(document.all) e = document.all[eID];}return this.extend(e);}else { if (eID) { return this.extend(eID);}}}; DOMAccess.prototype.get = DOMAccess.prototype.getElement; DOMAccess.prototype.createElement = function (tagName, id) { var newElement = document.createElement(tagName); newElement.setAttribute("id", id); return this.extend(newElement);}; DOMAccess.prototype.createTextNode = function (string) { return document.createTextNode(string);}; DOMAccess.prototype.remove = function (e) { e = this.getElement(e); if (e.parentNode) { return e.parentNode.removeChild(e); this.allExtendedElements[e.id] = null; e = null;}return null;}; DOMAccess.prototype.extend = function (e) { if (e && ! e.isExtended) { e.isExtended = true; e.storedRect = null; e.addClass = E_addClass; e.removeClass = E_removeClass; e.hide = E_hide; e.show = E_show; e.toggleVisibility = E_toggleVisibility; e.getRect = E_getRect; e.setRect = E_setRect; e.getSide = E_getSide; e.getCorner = E_getCorner; e.getWidth = E_getWidth; e.setWidth = E_setWidth; e.adjustWidth = E_adjustWidth; e.getHeight = E_getHeight; e.setHeight = E_setHeight; e.adjustHeight = E_adjustHeight; e.getCSSValue = E_getCSSValue; e.moveTo = E_moveTo; e.moveBy = E_moveBy; e.center = E_center; e.overlay = E_overlay; e.getParent = E_getParent; e.getChildren = E_getChildren; if (! e.id) e.id = e.nodeName + (this.counter++); this.allExtendedElements[e.id] = e; this.elementIDs.push(e.id);}return e;}; function E_addClass (className) { this.className += " " + className;}function E_removeClass (className) { this.className = this.className.replace(className, '');}function E_hide (noBlock) { this.style.visibility = "hidden"; if (noBlock) { this.style.display = "none";}}function E_show (block) { this.style.visibility = "visible"; if (block) this.style.display = "block";}function E_toggleVisibility (blocking) { if (this.style.visibility == "hidden") { this.show(blocking);}else { this.hide(blocking);}}function E_getRect (sizeAdjustment) { if (sizeAdjustment == null) sizeAdjustment = 0; if (this.storedRect == null) { var rectangle = null; if (Browser.name == IE) { var rects = this.getClientRects(); if (rects[0]) rects = rects[0]; var topDiff = 0, rightDiff = 0, bottomDiff = 0, leftDiff = 0; if (this.nodeName.toUpperCase() != 'BODY') { var body = DOM.getBodyElement(); topDiff = body.getSide(TOP) * -1; leftDiff = body.getSide(LEFT) * -1;}Browser.debug("[" + this.id + "] IE rect is " + rects.top, rects.right, rects.bottom, rects.left); rectangle = new Rect( Math.max(0, rects.top-2) + Browser.getScrollY() + (-1 * sizeAdjustment) + topDiff, Math.max(0, rects.right-2) + Browser.getScrollX() + sizeAdjustment + leftDiff, Math.max(0, rects.bottom-2) + Browser.getScrollY() + sizeAdjustment + topDiff, Math.max(0, rects.left-2) + Browser.getScrollX() + (-1 * sizeAdjustment) + leftDiff );}else { var width, height; if (Browser.name == SAFARI || Browser.name == OPERA) { width = this.offsetWidth; height = this.offsetHeight;}else { width = this.getCSSValue("width"); height = this.getCSSValue("height");}rectangle = new Rect( this.offsetTop + (-1 * sizeAdjustment), this.offsetLeft + width + sizeAdjustment + this.getCSSValue("border-right-width") + this.getCSSValue("border-left-width") + this.getCSSValue("padding-left") + this.getCSSValue("padding-right"), this.offsetTop + height + sizeAdjustment + this.getCSSValue("border-bottom-width") + this.getCSSValue("border-top-width") + this.getCSSValue("padding-bottom") + this.getCSSValue("padding-top"), this.offsetLeft + (-1 * sizeAdjustment) );}this.storedRect = rectangle; Browser.debug("[" + this.id + "] getRect() returned " + rectangle.toString());}return this.storedRect;}function E_setRect (newRect) { this.moveTo(newRect.getSide(LEFT), rect.getSide(TOP)); this.setWidth(newRect.width); this.setHeight(newRect.height); this.storedRect = newRect; Browser.debug("[" + this.id + "] setRect() set to " + newRect.toString()); return newRect;}function E_getSide (side, relativeTo) { if (relativeTo == null) relativeTo = TOP+LEFT; var thisSide = this.getRect().getSide(side, relativeTo); Browser.debug("[" + this.id + "] getSide('" + side + "', '" + relativeTo + "') returned " + thisSide); return thisSide;}function E_getCorner (corner) { var vertices = this.getRect().getVertices(); return vertices[corner];}function E_getWidth (innerOnly) { var width = this.getRect().width; if (innerOnly) width-= this.getCSSValue("border-right-width") + this.getCSSValue("border-left-width"); return width;}function E_setWidth (newWidth) { newWidth-= this.getCSSValue("border-right-width") + this.getCSSValue("border-left-width"); if (this.storedRect) { var difference = newWidth - this.getWidth(true); this.getRect().adjustSize(RIGHT, difference);}if (Browser.name == MOZILLA) newWidth-= this.getCSSValue("padding-left") + this.getCSSValue("padding-right"); this.style.width = Math.max(0, newWidth); return newWidth;}function E_adjustWidth (diff) { var newWidth = Math.max(0, this.getWidth() + diff); this.setWidth(newWidth); Browser.debug("[" + this.id + "] adjustWidth() set to " + newWidth); return newWidth;}function E_getHeight (innerOnly) { var height = this.getRect().height; if (innerOnly) height-= this.getCSSValue("border-bottom-width") + this.getCSSValue("border-top-width"); Browser.debug("[" + this.id + "] getHeight() returned " + height); return height;}function E_setHeight (newHeight) { newHeight-= this.getCSSValue("border-bottom-width") + this.getCSSValue("border-top-width"); if (this.storedRect) { var difference = newHeight - this.getHeight(true); this.getRect().adjustSize(BOTTOM, difference);}if (Browser.name == MOZILLA) newHeight-= this.getCSSValue("padding-top") + this.getCSSValue("padding-bottom"); this.style.height = Math.max(0, newHeight); Browser.debug("[" + this.id + "] setHeight() set to " + newHeight); return newHeight;}function E_adjustHeight (diff) { var newHeight = Math.max(0, this.getHeight() + diff); this.setHeight(newHeight); return newHeight;}function E_getCSSValue (property) { var value; if (Browser.name == MOZILLA) { var computedStyle = document.defaultView.getComputedStyle(this,""); if (computedStyle != null) value = computedStyle.getPropertyValue(property);}else { while (property.indexOf("-") > -1 && property.length >= property.indexOf("-") + 2) { property = property.substring(0, property.indexOf("-")) + property.charAt(property.indexOf("-") + 1).toUpperCase() + property.substr(property.indexOf("-") + 2);}if (Browser.name == SAFARI) { value = eval("this.style." + property);}else if (eval("this.currentStyle && this.currentStyle." + property)){ value = eval("this.currentStyle." + property);}else { value = null;}}if (property != null) { var lcProp = property.toLowerCase(); if ( lcProp == ("top") || lcProp == ("right") || lcProp == ("left") || lcProp == ("bottom") || lcProp.indexOf("width") > -1 || lcProp.indexOf("height") > -1 || lcProp.indexOf("padding") > -1 || lcProp.indexOf("margin") > -1 ) { value = parseInt(value); if (isNaN(value)) value = 0;}}else { return "";}Browser.debug("[" + this.id + "] getCSSValue('" + property + "') returned " + value); return value;}function E_moveTo (x, y, relativeTo, insideBorder) { if (! relativeTo) relativeTo = TOP+LEFT; if (this.storedRect) { this.storedRect.setPosition(x, y, relativeTo);}if (x != null) { if (typeof(x) == "string") x = parseInt(x); if (relativeTo.indexOf(LEFT) > -1) { if (insideBorder && Browser.name == MOZILLA) { x += DOM.getBodyElement().getCSSValue("border-left-width");}else if (! insideBorder && Browser.name == IE) { x -= DOM.getBodyElement().getCSSValue("border-left-width");}this.style.right = null; this.style.left = x;}if (relativeTo.indexOf(RIGHT) > -1) { if (insideBorder && Browser.name == MOZILLA) { x += DOM.getBodyElement().getCSSValue("border-right-width");}else if (! insideBorder && Browser.name == IE) { x -= DOM.getBodyElement().getCSSValue("border-right-width");}this.style.left = null; this.style.right = x;}}if (y != null) { if (typeof(y) == "string") y = parseInt(y); if (relativeTo.indexOf(TOP) > -1) { if (insideBorder && Browser.name == MOZILLA) { y += DOM.getBodyElement().getCSSValue("border-top-width");}else if (! insideBorder && Browser.name == IE) { y -= DOM.getBodyElement().getCSSValue("border-top-width");}this.style.bottom = null; this.style.top = y;}if (relativeTo.indexOf(BOTTOM) > -1) { if (insideBorder && Browser.name == MOZILLA) { y += DOM.getBodyElement().getCSSValue("border-bottom-width");}else if (! insideBorder && Browser.name == IE) { y -= DOM.getBodyElement().getCSSValue("border-bottom-width");}this.style.top = null; this.style.bottom = y;}}Browser.debug("[" + this.id + "] moveTo() moved to (" + x + "," + y + ") relative to " + relativeTo);}function E_moveBy (x, y) { var xDiff = x; var yDiff = y; if (x != 0) { if (this.style.right) { this.style.right = this.getSide(RIGHT, RIGHT) + x; xDiff *= -1;}else { this.style.left = this.getSide(LEFT) + x;}}if (y != 0) { if (this.style.bottom) { this.style.bottom = this.getSide(BOTTOM, BOTTOM) + y; yDiff *= -1;}else { this.style.top = this.getSide(TOP) + y;}}this.storedRect.adjustPosition(xDiff, yDiff); Browser.debug("[" + this.id + "] moveBy() moved by (" + xDiff + "," + yDiff + ") to (" + this.getSide(LEFT) + "," + this.getSide(TOP) + ")"); return new Point(this.getSide(LEFT), this.getSide(TOP));}function E_center (centerX, centerY) { var left = null, top = null; if (centerX) left = this.getParent().getWidth()/2 - this.getWidth()/2; if (centerY) top = this.getParent().getHeight()/2 - this.getHeight()/2; this.moveTo(left, top, TOP+LEFT);}function E_overlay (other) { other = DOM.getElement(other); this.setRect(other.getRect()); return other.getRect();}function E_getParent () { return DOM.getElement(this.parentNode);}function E_getChildren (tagName) { var children; if (tagName) { children = this.getElementsByTagName(tagName);}else { children = this.childNodes;}for (var i=0; i < children.length; i++) { children[i] = DOM.extend(children[i]);}return children;}DOMAccess.prototype.clearRects = function () { for (var i=0; i < this.elementIDs.length; i++) { this.allExtendedElements[this.elementIDs[i]].storedRect = null;}}; function Rect (top, right, bottom, left, sizeAdjustment) { if (sizeAdjustment == null) sizeAdjustment = 0; this.sides = new Array(); this.sides[TOP] = top + (-1 * sizeAdjustment); this.sides[RIGHT] = right + sizeAdjustment; this.sides[BOTTOM] = bottom + sizeAdjustment; this.sides[LEFT] = left + (-1 * sizeAdjustment); this.init();}Rect.prototype.toString = function () { return this.sides[TOP] + ',' + this.sides[RIGHT] + ',' + this.sides[BOTTOM] + ',' + this.sides[LEFT];}; Rect.prototype.init = function () { this.width = this.sides[RIGHT] - this.sides[LEFT]; this.height = this.sides[BOTTOM] - this.sides[TOP]; this.shortestEdge = Math.min(this.width, this.height); this.lines = null; this.vertices = null;}; Rect.prototype.getDiagonal = function () { return distance(new Point(this.sides[TOP], this.sides[LEFT]), new Point(this.sides[BOTTOM], this.sides[RIGHT]));}; Rect.prototype.adjustSize = function (side, diff) { if (side == TOP || side == LEFT) { this.sides[side]-= diff;}else if (side == RIGHT || side == BOTTOM) { this.sides[side]+= diff;}this.init();}; Rect.prototype.setPosition = function (x, y, relativeTo) { if (relativeTo == null) relativeTo = TOP+LEFT; if (relativeTo.indexOf(RIGHT) > -1)x = Browser.getInnerWidth() - this.width - x; if (relativeTo.indexOf(BOTTOM) > -1)y = Browser.getInnerHeight() - this.height - y; this.sides[TOP] = y; this.sides[RIGHT] = x + this.width; this.sides[BOTTOM]+= y + this.height; this.sides[LEFT] = x; this.lines = null; this.vertices = null;}; Rect.prototype.adjustPosition = function (x, y) { this.sides[TOP]+= y; this.sides[RIGHT]+= x; this.sides[BOTTOM]+= y; this.sides[LEFT]+= x; this.lines = null; this.vertices = null;}; Rect.prototype.getSide = function (side, relativeTo, insideBorder) { var thisSide = this.sides[side]; if ((side == LEFT || side == RIGHT) && relativeTo.indexOf(RIGHT) > -1) { thisSide = Browser.getInnerWidth() - thisSide;}else if ((side == TOP || side == BOTTOM) && relativeTo.indexOf(BOTTOM) > -1) { thisSide = Browser.getInnerHeight() - thisSide;}if (insideBorder && Browser.name == MOZILLA) { thisSide += DOM.getBodyElement().getCSSValue("border-" + side + "-width");}else if (! insideBorder && Browser.name == IE) { thisSide -= DOM.getBodyElement().getCSSValue("border-" + side + "-width");}return thisSide;}; Rect.prototype.getVertices = function () { if (! this.vertices) { var vertices = new Array(); vertices[TOP+LEFT] = new Point(this.sides[LEFT], this.sides[TOP]); vertices[TOP+RIGHT] = new Point(this.sides[RIGHT], this.sides[TOP]); vertices[BOTTOM+RIGHT] = new Point(this.sides[RIGHT], this.sides[BOTTOM]); vertices[BOTTOM+LEFT] = new Point(this.sides[LEFT], this.sides[BOTTOM]); this.vertices = vertices;}return this.vertices;}; function Line (startPoint, endPoint) { this.startPoint = startPoint; this.endPoint = endPoint;}Line.prototype.getLength = function () { return startPoint.distanceFrom(endPoint);}; Line.prototype.intersects = function (other) { var result = null; var ua_t = (other.endPoint.X - other.startPoint.X) * (this.startPoint.Y - other.startPoint.Y) - (other.endPoint.Y - other.startPoint.Y) * (this.startPoint.X - other.startPoint.X); var ub_t = (this.endPoint.X - this.startPoint.X) * (this.startPoint.Y - other.startPoint.Y) - (this.endPoint.Y - this.startPoint.Y) * (this.startPoint.X - other.startPoint.X); var u_b = (other.endPoint.Y - other.startPoint.Y) * (this.endPoint.X - this.startPoint.X) - (other.endPoint.X - other.startPoint.X) * (this.endPoint.Y - this.startPoint.Y); if ( u_b != 0 ) { var ua = ua_t / u_b; var ub = ub_t / u_b; if ( 0 <= ua && ua <= 1 && 0 <= ub && ub <= 1 ) { result = new Point(this.startPoint.X + ua * (this.endPoint.X - this.startPoint.X), this.startPoint.Y + ua * (this.endPoint.Y - this.startPoint.Y));}}return result;}; function Point (x, y) { this.X = (x) ? x : 0; this.Y = (y) ? y : 0;}Point.prototype.distanceFrom = function (other) { var dist = Math.sqrt(Math.pow((this.X - other.X),2) + Math.pow((this.Y - other.Y),2)); return Math.round(dist);}; Point.prototype.getRelativePoint = function (distance, angle) { var thisX = this.X + Math.round(distance * Math.cos(toRadians(validAngle(angle)))); var thisY = this.Y + Math.round(distance * Math.sin(toRadians(validAngle(angle)))); return new Point(thisX, thisY);}; function toRadians (degrees) { return degrees * (Math.PI/180);}function validAngle (angle) { if (angle < 0) { angle = 360 + angle;}if (angle > 359) { angle = angle - 359;}return angle;}
