// Dynamic HTML library functions

var dhtmelCoreLoaded = false;
if (typeof runExtendCode != 'string') {
	var runExtendCode = "";
}
var extendCodeRun = false;
var ddV;
if (document.defaultView) ddV = document.defaultView;
var agt = navigator.userAgent.toLowerCase();
var geckoBuild;
if (agt.indexOf('gecko')!=-1) { // extract 8 digit gecko build ID
	geckoBuild = agt.substring(agt.indexOf('gecko/')+6,agt.indexOf('gecko/')+14);
}

var dhtmels = new Array();
// function to add new elements, here for legacy purposes only
function addDhtmel(theName) {
	return new dhtmel(theName);
}
// dhtmel object dummy constructor - extends dhtmel methods from external libs before creation of object
function dhtmel(divName,theDiv) {
	if (runExtendCode != "" && !extendCodeRun) eval(runExtendCode);
	return new dhtmel_const(divName,theDiv);
}
// the dhtmel constructor
function dhtmel_const(divName,theDiv) {
	this.name = divName;
	this.el = (theDiv) ? theDiv : findDiv(divName);
	if (this.el) { // if we found a div
		this.css = (document.layers) ? this.el : this.el.style;
		this.document = this.el.document;
		this.txtRef = 'dhtmels.'+divName;
		this.moveTo = dhtmel_moveTo;
		this.moveBy = dhtmel_moveBy;
		this.setBgColor = dhtmel_setBgColor;
		this.setZIndex = dhtmel_setZIndex;
		this.setDefaultPos = dhtmel_setDefaultPos;
		this.fixNN6 = dhtmel_fixNN6;
		this.update = dhtmel_update;
		this.update(true);
		dhtmels[this.name] = this;
	}
	return this;
}

// - methods -
// updates the properties
function dhtmel_update(setDefaultsToCurrent) {
	if (this.doDebug) this.updateDebug();
	if (this.el.currentStyle) { // IE5
		this.zIndex = this.el.currentStyle.zIndex;
		this.left = parseInt(this.el.currentStyle.left);
		this.top = parseInt(this.el.currentStyle.top);
		this.visible = (this.el.currentStyle.visibility.indexOf("visible") != -1);
		this.height = parseInt(this.el.offsetHeight);
		this.width = parseInt(this.el.offsetWidth);
		this.bgColor = this.el.currentStyle.backgroundColor;
	}
	else if (document.getElementById) { // NN6 / DOM
		this.zIndex = this.css.zIndex;
		this.visible = (this.css.visibility != "hidden");
		this.height = parseInt(ddV.getComputedStyle(this.el, "").getPropertyValue("height"));
		this.width = parseInt(ddV.getComputedStyle(this.el, "").getPropertyValue("width"));
		this.left = parseInt(ddV.getComputedStyle(this.el, "").getPropertyValue("left"));
		this.top = parseInt(ddV.getComputedStyle(this.el, "").getPropertyValue("top"));
		this.bgColor = ddV.getComputedStyle(this.el, "").getPropertyValue("background-color");
		// workaround for bug with Gecko builds prior to 20010402 (gives position realtive to <body> rather than container) (assumes only DIVs used for positioning)
		if(geckoBuild && geckoBuild < 20010402) this.fixNN6();
	}
	else { // NN4, IE4
		this.zIndex = this.css.zIndex;
		this.visible = (this.css.visibility.indexOf("show") != -1 || this.css.visibility.indexOf("visible") != -1);
		this.left = (document.layers) ? parseInt(this.css.left) : parseInt(this.el.offsetLeft);
		this.top = (document.layers) ? parseInt(this.css.top) : parseInt(this.el.offsetTop);
		this.bgColor = (document.layers) ? this.el.bgColor : this.css.backgroundColor;
		this.height = (document.layers) ? this.el.document.height : this.el.offsetHeight;
		this.width = (document.layers) ? this.el.document.width : this.el.offsetWidth;
	}
	if (setDefaultsToCurrent) {
		this.defaultX = this.left;
		this.defaultY = this.top;
	}
	if (this.doDebug) this.updateDebug();
}

// corrects NN6 getComputedStyle bug
function dhtmel_fixNN6() {
	var theShifts = dhtmel_fixNN6_loop(this.el);
	this.left += theShifts['left'];
	this.top += theShifts['top'];
}
// recursively corrects positionin given by buggy getComputedStyle
function dhtmel_fixNN6_loop(theEl) {
	var theShifts = new Array();
	theShifts['left'] = 0;
	theShifts['top'] = 0;
	if (theEl.parentNode.tagName.toLowerCase() == "div") {
		theShifts['left'] -= parseInt(ddV.getComputedStyle(theEl.parentNode, "").getPropertyValue("left"));
		theShifts['top'] -= parseInt(ddV.getComputedStyle(theEl.parentNode, "").getPropertyValue("top"));
		if (theEl.parentNode.parentNode.tagName.toLowerCase == "div") {
			var newShifts = dhtmel_fixNN6(theEl.parentNode);
			theShifts['left'] += newShifts['left'];
			theShifts['top'] += newShifts['top'];
		}
	}
	return theShifts;
}
// sets background color
function dhtmel_setBgColor(col) {
	if (document.layers) {
		this.el.bgColor = col;
	}
	else {
		this.css.backgroundColor = col;
	}
	this.update();
}
// moves the element to
function dhtmel_moveTo(newX,newY) {
	if (document.layers) {
		this.el.moveTo(newX,newY);
	}
	else {
		this.css.left = newX + 'px';
		this.css.top = newY + 'px';
	}
	this.update();
}
// moves the element by
function dhtmel_moveBy(shiftX,shiftY) {
	this.update();
	this.moveTo(this.left+shiftX,this.top+shiftY);
}
// sets the z-index
function dhtmel_setZIndex(newvalue) {
	this.css.zIndex = newvalue;
	this.update();
}

// sets default positions
dhtmel_setDefaultPos = function(defX,defY,doMove) {
	this.defaultX = defX;
	this.defaultY = defY;
	if (doMove) this.moveTo(defX,defY);
}
// returns a pointer to a Div (parentObj optional, recursive search)
function findDiv(divName,parentObj) {
	if (divName=='') return document;
	if (!parentObj) parentObj = document;
	var theDiv = false;
	if (document.all && eval('document.all.'+divName)) {
		theDiv = eval(divName);
	}
	else if (document.getElementById) {
		theDiv = document.getElementById(divName);
	}
	else if (parentObj.layers) {
		if (parentObj.layers[divName]) {
			theDiv = parentObj.layers[divName];
		}
		else if (parentObj.layers && parentObj.layers.length > 0) {
			var tempDiv;
			for (var i=0;i<parentObj.layers.length;i++) {
				if (parentObj.layers[i].document.layers) {
					tempDiv = findDiv(divName,parentObj.layers[i].document);
				}
				if (tempDiv) break;
			}
			theDiv = tempDiv;
		}
	}
	return theDiv;
}

// dhtml scroll bar lib
// requires dhtml_core_lib.js


var dsb_scroll_step = 5;
var dsb_scroll_interval = 40;
var dsb_end_gap = 15;

var allScrollBars = new Array();

// DHTML scroll bar constructor
function dhtmelScrollBar(varName,toBeScrolled,scrollWindow,scrollerButton,scrollerBar,dir,outerCont) {
	this.varName = varName;
	this.toBeScrolled = (typeof toBeScrolled == 'string') ? addDhtmel(toBeScrolled) : toBeScrolled;
	this.scrollWindow = (typeof scrollWindow == 'string') ? addDhtmel(scrollWindow) : scrollWindow;
	this.scrollerButton = (typeof scrollerButton == 'string') ? ((scrollerButton=='') ? false : addDhtmel(scrollerButton)) : scrollerButton;
	this.scrollerBar = (typeof scrollerBar == 'string') ? ((scrollerButton=='') ? false : addDhtmel(scrollerBar)) : scrollerBar;
	this.outerCont=outerCont;
	// event capture
	if (this.scrollerButton != false) {
		if (document.layers) {
			document.captureEvents(Event.MOUSEDOWN);
			document.onmousedown = dsb_mouseDown;
		}
		else {
			// can't build an event handler to reference this object directly (it's not built yet), so let's generate a function
			eval('var '+this.varName.makeLegal()+'dragStart = new Function("evt","'+this.varName+'.dragStart(evt);")');
			this.scrollerButton.el.onmousedown = eval(this.varName.makeLegal()+'dragStart');
		}
	}
	this.isVertical = (dir=='vertical');
	this.dragStart = dsb_dragStart;
	this.dragStop = dsb_dragStop;
	this.doDrag = dsb_doDrag;
	this.resetIt = dsb_resetIt;
	this.calcRatio = dsb_calcRatio;
	this.scroll = dsb_scroll;
	this.shiftTo = dsb_shiftTo;
	this.scrollRelease = dsb_scrollRelease;
	this.lastX = 0;
	this.lastY = 0;
	this.firstCoordsIn = false;
//	this.dragRatio;
	this.worthScrolling = false;
	this.timerRef = 0;
	this.calcRatio();
	allScrollBars[allScrollBars.length] = this;
	return this;
}

function dsb_dragStart(evt) {
	// set initial drag start position
	var curMouseX;
	var curMouseY;
	if (!evt) evt = window.event;
	if (document.all || evt.clientX) {
		curMouseX = evt.clientX;
		curMouseY = evt.clientY;
	}
	else {
		curMouseX = evt.pageX;
		curMouseY = evt.pageY;
	}
	this.initTop = this.scrollerButton.top;
	this.initLeft = this.scrollerButton.left;
	this.previousX = curMouseX;
	this.previousY = curMouseY;
	// capture drag events
	if (document.layers) document.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
	dsb_currentScroller = this;
	document.onmousemove = dsb_doDrag;
	eval('var '+this.varName.makeLegal()+'dragStop = new Function("'+this.varName+'.dragStop();")');
	document.onmouseup = eval(this.varName.makeLegal()+'.dragStop');
}

function dsb_dragStop() {
	if (document.layers) document.releaseEvents(Event.MOUSEUP|Event.MOUSEMOVE);
	document.onmousemove = null;
	document.onmouseup = null;
}

function dsb_resetIt() {
	this.calcRatio();
	if (this.scrollerButton) this.scrollerButton.moveTo(0,0);
	this.toBeScrolled.moveTo(0,0);
}

function dsb_calcRatio() {
	// calclates ratio of scrollbar to content and decides if content is bigger than scroll window
	this.dragRatio = (this.isVertical) ? (this.toBeScrolled.height-this.scrollWindow.height)/(this.scrollerBar.height-this.scrollerButton.height) : (this.toBeScrolled.width-this.scrollWindow.height)/(this.scrollerBar-this.scrollerButton.width);
	this.worthScrolling = (this.isVertical && this.toBeScrolled.height > this.scrollWindow.height || !this.isVertical && this.toBeScrolled.width > this.scrollWindow.width);
	// show/hide the button
	if (this.scrollerButton) {
		if (this.worthScrolling) {
			this.scrollerButton.css.visibility='inherit';
		}
		else {
			this.scrollerButton.hideIt();
		}
	}
}

function dsb_shiftTo(position) { // pixels from top/left
	var newX = (this.isVertical) ? this.toBeScrolled.left : -position;
	var newY = (this.isVertical) ? -position : this.toBeScrolled.top;
	this.toBeScrolled.moveTo(newX,newY);
	// synchronise the scrollbar
	if (this.scrollerButton) this.scrollerButton.moveTo(-Math.round(this.toBeScrolled.left/this.dragRatio),-Math.round(this.toBeScrolled.top/this.dragRatio));
}

function dsb_scroll(direction) {
	if (this.worthScrolling) {
		clearTimeout(this.timerRef);
		var moveX;
		var moveY;
		// check we're in bounds
		switch (direction) {
			case 'up':
				moveX = 0;
				moveY = (Math.abs(this.toBeScrolled.top) < dsb_scroll_step) ? -this.toBeScrolled.top : dsb_scroll_step;
				break;
			case 'down':
				moveX = 0;
				moveY = (this.toBeScrolled.height - this.scrollWindow.height - Math.abs(this.toBeScrolled.top) < dsb_scroll_step) ? -(this.toBeScrolled.height - this.scrollWindow.height - Math.abs(this.toBeScrolled.top)) : -dsb_scroll_step ;
				break;
			case 'left':
				moveX = (Math.abs(this.toBeScrolled.left) < dsb_scroll_step) ? -this.toBeScrolled.left : dsb_scroll_step;;
				moveY = 0;
				break;
			case 'right':
				moveX = (this.toBeScrolled.width - this.scrollWindow.width - Math.abs(this.toBeScrolled.left) < dsb_scroll_step) ? -(this.toBeScrolled.width - this.scrollWindow.width - Math.abs(this.toBeScrolled.left)) : -dsb_scroll_step ;
				moveY = 0;
				break;
		}
		this.toBeScrolled.moveBy(moveX,moveY);
		// synchronise the scrollbar
		if (this.scrollerButton) this.scrollerButton.moveTo(-Math.round(this.toBeScrolled.left/this.dragRatio),-Math.round(this.toBeScrolled.top/this.dragRatio));
		this.timerRef= (document.layers && this.outerCont) ? eval('setTimeout("document.layers.'+this.outerCont+'.'+this.varName+'.scroll(\''+direction+'\')",'+dsb_scroll_interval+')') : eval('setTimeout("'+this.varName+'.scroll(\''+direction+'\');",'+dsb_scroll_interval+')');
	}
	return false;
}

function dsb_scrollRelease() {
	clearTimeout(this.timerRef);
}

// variable to store reference to currently active scrollbar
var dsb_currentScroller;

// this *isn't* a method of the dhtmelScrollBar function (NN4 mousedown event handler)
function dsb_mouseDown(evt) {
	var mseX = evt.pageX;
	var mseY = evt.pageY;
	var passEvent = true;
	// loop through all scroll bars on the page & see if we're over a button
	for (var i=0;i<allScrollBars.length;i++) {
		var curSBB = allScrollBars[i].scrollerButton;
		if (curSBB) {
			var pgTop = curSBB.el.pageY;
			var pgLeft = curSBB.el.pageX;
			if (mseX >= pgLeft && mseX <= pgLeft+curSBB.width && mseY >= pgTop && mseY <= pgTop+curSBB.height) {
				allScrollBars[i].dragStart(evt);
				passEvent = false;
				break;
			}
		}
	}
	if (passEvent) {
		document.routeEvent(evt);
	}
	else {
		return false;
	}
}

// this *isn't* a method of the dhtmelScrollBar function (cross-platform drag event handler)
function dsb_doDrag(evt) {
	if (!evt) evt = window.event;
	var curMouseX;
	var curMouseY;
	theDsb = dsb_currentScroller;
	if (document.all || evt.clientX) {
		curMouseX = evt.clientX;
		curMouseY = evt.clientY;
	}
	else {
		curMouseX = evt.pageX;
		curMouseY = evt.pageY;
	}
	// calculate new button position
	var newX = (theDsb.isVertical) ? theDsb.scrollerButton.left : curMouseX - theDsb.previousX;
	var newY = (theDsb.isVertical) ? curMouseY - theDsb.previousY + theDsb.initTop : theDsb.scrollerButton.top;
	// check we're in bounds
	if (newY < 0) newY = 0;
	if (newY > theDsb.scrollerBar.height - theDsb.scrollerButton.height) newY = theDsb.scrollerBar.height - theDsb.scrollerButton.height;
	if (newX < 0) newX = 0;
	if (newX > theDsb.scrollerBar.width - theDsb.scrollerButton.width) newX = theDsb.scrollerBar.width - theDsb.scrollerButton.width;
	// move everything
	theDsb.scrollerButton.moveTo(newX,newY);
	if (theDsb.worthScrolling) theDsb.toBeScrolled.moveTo(-Math.round(newX*theDsb.dragRatio),-Math.round(newY*theDsb.dragRatio));

	return false;
}

// replaces [ and ] with _
String.prototype.makeLegal = function() {
	var outputStr = "";
	for (var i=0;i<this.length;i++) {
		outputStr += (this.charAt(i) == "[" || this.charAt(i) == "]") ? "_" : this.charAt(i);
	}
	return outputStr;
}