// DHTML SLIDER CONTROL JAVASCRIPT
// (C) Digita. By Craig Buckler.
// Please send any queries, comments, or bug reports to craigb@digita.com


// DHTML global variables
var curDiv = null;
var dragDiv = null;
var dragOn = false;
var dragStart = false;
var osX = 0;
var osY = 0;


// slider global variables
var minZ = -1;
var maxZ = -1;


// _____________________________________________________________________
// SliderControl object
function SliderControl(name, vPos, vMin, vMax, x1, y1, x2, y2) {

	// main properties
	this.name = name;
	this.vPos = vPos;
	this.vMin = vMin;
	this.vMax = vMax;
	this.disabled = false;

	// event properties
	this.onStart = "";
	this.onFinish = "";
	this.onMove = "";

	// z-Index property
	this.zPos= 0;

	// define start and end coordinates
	this.x1 = x1;
	this.y1 = y1;
	this.x2 = x2;
	this.y2 = y2;
	this.xMin = Math.min(x1, x2)
	this.xMax = Math.max(x1, x2)
	this.yMin = Math.min(y1, y2)
	this.yMax = Math.max(y1, y2)

	// define significant axis and relation equation
	var saxis, eq;
	if (this.yMax-this.yMin == 0) { saxis = "x"; eq = y1; }
	else if (this.xMax-this.xMin == 0) { saxis = "y"; eq = x1; }
	else {
		var m, c;
		m = (y2 - y1) / (x2 - x1);
		c = y1 - (m*x1);
		if (Math.abs(m)<1) { saxis = "x"; eq = "("+m+" * x) + "+c; }
		else { saxis = "y"; eq = "(y - "+c+") / "+m; }
	}
	this.saxis = saxis;
	this.eq = eq;

	// pixel location
	this.posX = 0;
	this.posY = 0;

	// define object methods
	this.changeValue = changeValue;
	this.calcValue = calcValue;
	this.index = index;
	this.display = display;
	this.destroy = destroy;

	// display slider
	this.changeValue(this.vPos);
}


// _____________________________________________________________________
// SliderControl method: change the value of a slider
function changeValue(vNew) {

	// ensure new value is valid
	if (vNew < Math.min(this.vMin,this.vMax)) { vNew = Math.min(this.vMin,this.vMax); }
	if (vNew > Math.max(this.vMin,this.vMax)) { vNew = Math.max(this.vMin,this.vMax); }

	this.vPos = vNew;

	// calculate pixel position
	var x, y;
	if (this.saxis == "x") {
		x = (((this.x2 - this.x1) / (this.vMax - this.vMin)) * (this.vPos - this.vMin)) + this.x1;
		y = eval(this.eq);
	}
	else {
		y = (((this.y2 - this.y1) / (this.vMax - this.vMin)) * (this.vPos - this.vMin)) + this.y1;
		x = eval(this.eq);
	}

	// update and display slider
	if (x < this.xMin) { x = this.xMin; }
	if (x > this.xMax) { x = this.xMax; }
	if (y < this.yMin) { y = this.yMin; }
	if (y > this.yMax) { y = this.yMax; }

	this.posX = x;
	this.posY = y;
	this.display();
}


// _____________________________________________________________________
// SliderControl method: returns the translated value of the slider
function calcValue() {

	var val;
	if (this.saxis == "x") {
		val = (((this.posX - this.x1) / (this.x2 - this.x1)) * (this.vMax - this.vMin)) + this.vMin;
	}
	else {
		val = (((this.posY - this.y1) / (this.y2 - this.y1)) * (this.vMax - this.vMin)) + this.vMin;
	}
	this.vPos = val;
}


// _____________________________________________________________________
// SliderControl method: modify the zIndex of a slider
function index(zVal) {

	var z = "NaN";

	if (isNaN(zVal)) {
		// parse zIndex string (front, back)
		zVal = zVal.toString();
		zVal = zVal.toLowerCase();
		if (zVal == "front") {
			if (maxZ < 0) { maxZ = 0; }
			z = parseInt(maxZ) + 1;
		}
		if (zVal == "back") { z = parseInt(minZ) - 1; }
	}
	else {
		z = parseInt(zVal);
	}

	// change zIndex
	if (!isNaN(z)) {

		if (z < 0) { z = 0; }

		this.zPos = z;
		var thisDiv = findDiv(this.name);
		if (thisDiv) { thisDiv.style.zIndex = this.zPos; }

		// modify zIndex minimum and maximums
		if (minZ < 0) { minZ = z; }
		if (maxZ < 0) { maxZ = z; }
		if (z < minZ) { minZ = z; }
		if (z > maxZ) { maxZ = z; }
	}
}


// _____________________________________________________________________
// SliderControl method: display the slider
function display() {
	var showDiv = findDiv(this.name);
	if (showDiv) {
		showDiv.style.left = this.posX;
		showDiv.style.top = this.posY;
		showDiv.style.visibility="visible";
	}
}


// _____________________________________________________________________
// SliderControl method: destroy the slider
function destroy() {
	var removeDiv = findDiv(this.name);
	if (removeDiv) { removeDiv.style.visibility="hidden"; }
}


// _____________________________________________________________________
// create a DIV reference object given DIV name
function findDiv(divname) {
	var divObj = null;
	if (document.getElementById) { divObj = document.getElementById(divname); }
	else if (document.all) { divObj = document.all[divname]; }
	else if (document.layers) { divObj = document.layers[divname]; divObj.style = divObj; }
	return divObj;
}


// _____________________________________________________________________
// start DHTML dragging
function drag(div) {

		if (!dragOn) {
			curDiv = eval(div);
			dragDiv=findDiv(curDiv.name);
			if (dragDiv) { dragDiv.onmouseout = dragHandler; }
		}
		if (!dragStart && dragDiv) { dragInit(); }

}


// _____________________________________________________________________
// initialise DHTML dragging event capture
function dragInit() {

	if (dragDiv) {
		if (document.layers) { document.captureEvents(Event.MOUSEMOVE|Event.MOUSEDOWN|Event.MOUSEUP); }
	
		document.onmousemove = dragHandler;
		document.onmousedown = dragHandler;
		document.onmouseup = dragHandler;

		dragStart = true;
	}
}


// _____________________________________________________________________
// handle DHTML dragging
function dragHandler(arg) {

	var ev = arg?arg:event;

	if (curDiv && ev.type=="mousedown" && !dragOn) {

		// movement started
		dragOn = true;
		osX = (ev.pageX?ev.pageX:ev.clientX) - parseInt(dragDiv.style.left);
		osY = (ev.pageY?ev.pageY:ev.clientY) - parseInt(dragDiv.style.top);

		// run onStart event
		if (curDiv.onStart!="") { eval(curDiv.onStart); }
		return false;
	}

	if (curDiv && ev.type=="mousemove" && dragOn) {

		// handle path movement
		var x, y;
		if (curDiv.saxis=="x") {
			x = (ev.pageX?ev.pageX:ev.clientX) - osX;
			if (x<curDiv.xMin) { x = curDiv.xMin; }
			if (x>curDiv.xMax) { x = curDiv.xMax; }
			y = eval(curDiv.eq);
		}
		else {
			y = (ev.pageY?ev.pageY:ev.clientY) - osY;
			if (y<curDiv.yMin) { y = curDiv.yMin; }
			if (y>curDiv.yMax) { y = curDiv.yMax; }
			x = eval(curDiv.eq);
		}

		if (!curDiv.disabled) {
			// move slider
			curDiv.posX = parseInt(x);
			curDiv.posY = parseInt(y);
			dragDiv.style.left = curDiv.posX;
			dragDiv.style.top = curDiv.posY;
	
			// update calculated value
			curDiv.calcValue();
	
			// run onMove event
			if (curDiv.onMove!="") { eval(curDiv.onMove); }
		}

		return false;
	}

	if (curDiv && ev.type=="mouseup") {
		// run onFinish event
		if (curDiv.onFinish!="") { eval(curDiv.onFinish); }
		dragStart = false;
		dragOn = false;
	}

	if (!dragOn && ev.type=="mouseout") {
	 	curDiv=null;
	 	dragDiv=null;
	}
}


