


/*---------------------------------------------------------------------*/
/* Misc functions */

// add leading zeros
function alz(v, len) {
	if (v.length < len)
		return "0" + alz(v, len-1);
	else
		return v;
}

function empty(v) {
	if (v == undefined || v == null || v == false || v == 0 || v == "" || v.length == 0)
		return true;
	return false;
}

function rand(min, max) {
	return Math.round(Math.random() * (max - min) + min);
}

function debug(txt) {
	var debug_mode = false;
	
	if (debug_mode)
		alert(txt);
}
 
function openPopup(url, name, width, height) {
	mywidth = width;
	myheight = height;
	myleft = (screen.width - mywidth) / 2;
	mytop = (screen.height - myheight) / 2;
	new_win = window.open(url, name, "width="+mywidth+",height="+myheight+",scrollbars=0,resizable=1,menubar=0,toolbar=0,status=0,location=0,directories=0,left="+myleft+",top="+mytop);
	new_win.opener.top.name = "opener";
	new_win.focus();
	return new_win;
}

function bindEvent(elm, evType, fn, useCapture) {
	elm = elem(elm);
	if (elm.addEventListener){
		elm.addEventListener(evType, fn, useCapture);
		return true;
	} else if (elm.attachEvent){
		var r = elm.attachEvent("on"+evType, fn);
		return r;
	} else {
    	elm["on"+evType] = fn;
	}
}

document.getElementsByClassName = function(className) {
	var children = document.getElementsByTagName("*") || document.all;
	var elements = new Array();

	for (var i = 0; i < children.length; i++) {
		var child = children[i];
		var classNames = child.className.split(" ");
		for (var j = 0; j < classNames.length; j++) {
			if (classNames[j] == className) {
				elements.push(child);
				break;
			}
		}
	}
	return elements;
}

if (!Array.prototype.push) {
	Array.prototype.push = function() {
		var startLength = this.length;
		for (var i = 0; i < arguments.length; i++)
			this[startLength + i] = arguments[i];
		return this.length;
	}
}

function get_repr(obj) {
	var repr = "";
	
	repr += "(" + typeof obj + ") ";
	if (typeof obj == "object" || typeof obj == "array") {
		repr += "{ ";
		for (var i in obj)
			repr += i + ": " + get_repr(obj[i]) + ", ";
		repr = repr.substr(0, repr.length-2) + " }";
	} else if (typeof obj == "string") {
		repr += '"' + obj + '"';
	} else {
		repr += obj;
	}
	return repr;
}

function elem() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var name = arguments[i];
		var val = name;
		if (typeof name == "string") {
			val = document.getElementById(name);
			if (! val) {
				debug("Could not find element " + name);
				return false;
			}
		}
		if (arguments.length == 1) 
			return val;
		elements.push(val);
	}
	return elements;
}

/*	Apply default values to an object or array. Use like this:
	
		var opts = { name: "Tom", age: 26 };
		var fullOpts = applyDefaults(opts, { id: -1 });

		fullOpts will now == { name: "Tom", age: 26, id: -1 }
	
 */ 
function applyDefaults(obj, defaults) {
	for (property in defaults) {
		if (typeof obj[property] == "undefined") {
			obj[property] = defaults[property];
		}
	}
	return obj;
}



/*---------------------------------------------------------------------*/
/*	Calendar popup */

var Calendar = { 
	is_open: false,
	
	cur_window: false,
	
	draw: function(id1, id2, id3, id4) {
		if (Calendar.is_open && Calendar.cur_window && !Calendar.cur_window.closed) {
			Calendar.cur_window.close();
			Calendar.cur_window = false;
			Calendar.is_open = false;
		} else {
			var url = "calendar.phtml?w=250&h=250&method=mY-d&id1=" + id1 + "&id2=" + id2 + "&id3=" + id3 + "&id4=" + id4;
			Calendar.cur_window = openPopup(url, "calendar", 250, 250);
			Calendar.is_open = true;
		}
	}
}



/*---------------------------------------------------------------------*/
/*	Hover-over rows 

		To use, include hovertable.css, assign a class of "hover" to the
		table(s) you want, and then do
		
		HoverTable.init();
		
 */	
 
var HoverTable = { 
	init: function() {
		var tables;
		var this_table;
		var i;
	
		if (!document.getElementsByTagName) return;
		tables = document.getElementsByTagName("table");
		for (i = 0; i < tables.length; i++) {
			this_table = tables[i];
			if (this_table.className == "hover" ||
					this_table.className.search(/\bhover\b/) != -1) {
				HoverTable.prepTable(this_table);
			}
		}
	},
	
	prepTable: function(table) {
		var i;
		var this_row;
	
		if (! table ||
				! table.rows ||
				! table.rows.length > 1) {
			return;
		}
		
		for (i = 1; i < table.rows.length; i++) {
			this_row = table.rows[i];
			if (! this_row) return;
			bindEvent(this_row, "mouseover", HoverTable.mouseOver);
			bindEvent(this_row, "mousedown", HoverTable.mouseDown);
			bindEvent(this_row, "mouseout", HoverTable.mouseOut);
		}
	},

	mouseOver: function(e) {	
		var t = null;
		if (e && e.target) t = e.target;
		if (window.event && window.event.srcElement) t = window.event.srcElement;
	
		if (t.tagName == "TD") {
			var children = t.parentNode.childNodes;
			var i;
			
			for (i = 0; i < children.length; i++)
				children[i].className = children[i].className + " hoverover ";
				
		} else {
			t.className = t.className + " hoverover ";
		}
		debug(t.tagName + " - " + t.className);
	},
	
	mouseDown: function(e)
	{
		var t = null;
		if (e && e.target) t = e.target;
		if (window.event && window.event.srcElement) t = window.event.srcElement;
		
		if (t.tagName == "TD") {
			var children = t.parentNode.childNodes;
			var i;
			
			for (i = 0; i < children.length; i++) {
				t = children[i];
		    	if (t.className.search(/\bhoverdown\b/) != -1) 
		    		t.className = t.className.replace(/\bhoverdown\b/, "");
		    	else 
 	   			t.className = t.className + " hoverdown ";
			}		
		} else {
 	   	if (t.className.search(/\bhoverdown\b/) != -1) 
 	   		t.className = t.className.replace(/\bhoverdown\b/, "");
 	   	else 
 	   		t.className = t.className + " hoverdown ";
		}
		debug(t.tagName + " - " + t.className);
	},
	
	mouseOut: function(e)
	{
		var t = null;
		if (e && e.target) t = e.target;
		if (window.event && window.event.srcElement) t = window.event.srcElement;

		if (t.tagName == "TD") {
			var children = t.parentNode.childNodes;
			var i;
			
			for (i = 0; i < children.length; i++) {
				t = children[i];
				t.className = t.className.replace(/\bhoverover\b/, "");
			}
		}
		else {
			t.className = t.className.replace(/\bhoverover\b/, "");
		}
	}	
}



/*---------------------------------------------------------------------*/
/*	Cookies */

var Cookies = {

	get: function(name, or_value) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++)
		{
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return or_value;
	},

	set: function(name, value, days) {
		if (days)
		{
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		} else
			var expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
	}	
}



/*---------------------------------------------------------------------*/
/*	HTML elements */

var Element = {

	getLeft: function(element) {
		element = elem(element);
		var left = 0;
		
		while (element.tagName != "BODY") {
			left = left + element.offsetLeft;
			element = element.offsetParent;
		}
		
		return left;
	},

	getTop: function(element) {
		element = elem(element);
		var top = 0;
		
		while (element.tagName != "BODY") {
			top = top + element.offsetTop;
			element = element.offsetParent;
		}
	},

	getHeight: function(element) {
		return elem(element).clientHeight;
	},
	
	getWidth: function(element) {
		return elem(element).clientWidth;
	},
	
	toggle: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = elem(arguments[i]);
			element.style.display = 
				(element.style.display == "none" ? "" : "none");
		}
	},

	hide: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = elem(arguments[i]);
			element.style.display = "none";
		}
	},

	show: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = elem(arguments[i]);
			element.style.display = "";
		}
	},

	showBlock: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = elem(arguments[i]);
			element.style.display = "block";
		}
	},

	remove: function(element) {
		element = elem(element);
		element.parentNode.removeChild(element);
	},
		
	getValue: function(element) {
		var element = elem(element);
	
		var tag = element.tagName.toLowerCase();
		if (Element.Values[tag]) 
			return Element.Values[tag](element);
		else
			return Element.Values.other(element);
	},
	
	setValue: function(element, val) {
		var element = elem(element);
		
		var tag = element.tagName.toLowerCase();
		if (Element.SetValues[tag]) 
			Element.SetValues[tag](element, val);
		else
			Element.SetValues.other(element, val);
	},
	
	/* 
	 * A series of functions to obtain the value of an HTML element
	 * be it a regular element, an INPUT, etc..
	 *
	 */
	Values: {
		checkbox: function(element) {
			if (element.checked) 
				return element.value;
			else
				return false;	// should this be ""?
		},
		input: function(element) {
			switch (element.type.toLowerCase()) {
				case "checkbox":
					return Element.Values.checkbox(element);
				// all the text fields use the same function:
				case "hidden":
				case "password":
				case "text":
					return Element.Values.textarea(element);
				case "radio":
					return Element.Values.radio(element);
				default:
					return Element.Values.other(element);
			}
		},
		other: function(element) {
			return element.innerHTML;
		},
		radio: function(element) {
			var form = element.form;
			var name = element.name;
			for (var i = 0; i < form[name].length; i++) {
				if (form[name][i].checked) {
					return form[name][i].value;
				} 
			}
			return false;
		},
		select: function(element) {
			var idx = element.selectedIndex;
			if (idx >= 0) 
				return element.options[idx].value || element.options[idx].text;
			else
				return "";
		},
		textarea: function(element) {
			return element.value;
		}
	},
	
	SetValues: {
		input: function(element, val) {
			switch (element.type.toLowerCase()) {
				case "hidden":
				case "password":
				case "text":
					Element.SetValues.textarea(element, val);
					break;
				default:
					debug("Cannot set value for " + element.name + " of type: " + element.tagName);
					break;
			}
		},
		other: function(element, val) {
			element.innerHTML = val;
		},
		select: function(element, val) {
			Select.set(element, val);
		},
		textarea: function(element, val) {
			element.value = val;
		}
	}
}



/*---------------------------------------------------------------------*/
/*	CSS class manipulation */
Element.Class = {

	// add a class (className) to an element
	add: function(element, className) {
		element = elem(element);
		if (! element) return;
		Element.Class.remove(element, className);
		element.className += (element.className.length > 0 ? " " : "") + className;
	},
	
	// return an array of the classes an element belongs to
	get: function(element) {
		element = elem(element);
		if (! element) return;
		return element.className.split(' ');
	},
	
	// returns true or false depending on whether or not an element belongs to className
	has: function(element, className) {
		element = elem(element);
		if (! element) return;
		if (!element || !element.className) return false;
		var re = new RegExp("\\b" + className + "\\b");
		if (!re.test(element.className)) return false;
	},
	
	// remove a class (className) from an element
	remove: function(element, className) {
		element = elem(element);
		if (! element) return;
		var re = new RegExp("^" + className + "\\b\\s*|\\s*\\b" + className + "\\b", 'g');
		element.className = element.className.replace(re, '')
	},
	
	// toggle a class on or off
	toggle: function(element, className) {
		if (Element.Class.has(element, className))
			Element.Class.remove(element, className);
		else
			Element.Class.add(element, className);
	}	
}



/*---------------------------------------------------------------------*/
/*	Select manipulation */

var Select = {
	get: function(element) {
		return Element.getValue(element);
	},
	
	getIdx: function(element, val) {
		var e = elem(element);
		debug("Checking " + e + " -- " + e.options.length);
		for (var i = 0; i < e.options.length; i++) {
			debug("Checking " + e.options[i].value);
			if (e.options[i].value == val || e.options[i].text == val) {
				return i;
			}
		}
		return -1;
	},
	
	set: function(element, val) {
		var i = Select.getIdx(element, val);
		if (i != -1) {
			elem(element).selectedIndex = i;
			return true;
		}
		return false;
	},
	
	add: function(element, val, text) {
		var e = elem(element);
		if (! text)
			text = val;
		e.options[e.options.length] = new Option(text, val);
	},
	
	remove: function(element, val) {
		var e = elem(element);
		var i = Select.getIdx(e, val);
		if (i) {
			e.options[i] = null;
			return true;
		}
		return false;
	},
	
	clear: function(element) {
		elem(element).options.length = 0;
	},
	
	clone: function(element, new_element) {
		var e = elem(element);
		var new_e = elem(new_element);
		Select.clear(new_e);
		for (var i in e.options) 
			Select.add(new_e, e.options[i].value, e.options[i].text);
		new_e.selectedIndex = e.selectedIndex;
	}
}



/*---------------------------------------------------------------------*/
/*	Effects to use on a DIV */

var Effect = {
	appear: function(element) {
		var x = new Object();
		x.element = elem(element);
		
		x.init = function() {
			x.start = 0;
			x.finish = 100;
			x.delay = 65;
			x.current = x.start;
			x.fade();
		}
		
		x.fade = function() {
			if (x.current > x.finish) return;
			if (x.timer) clearTimeout(x.timer);
			x.setOpacity(x.element, x.current);
			x.current += 10;
			x.timer = setTimeout(x.fade, x.delay);
		}
		
		x.setOpacity = function(element, opacity) {
			opacity = (opacity == 100) ? 99.999 : opacity;
			element.style.filter = "alpha(opacity:"+opacity+")";
			element.style.opacity = opacity/100 /*//*/;
			element.style.display = "";			
		}
		
		x.init();
	},

	disappear: function(element) {
		var x = new Object();
		x.element = elem(element);
		
		x.init = function() {
			x.start = 100;
			x.finish = 0;
			x.delay = 85;
			x.current = x.start;
			x.fade();
		}
		
		x.done = function() {
			Element.remove(x.element)
		}
		
		x.fade = function() {
			if (x.current < x.finish) {
				setTimeout(x.done, x.delay*2);
				return;
			}
			if (x.timer) clearTimeout(x.timer);
			x.setOpacity(x.element, x.current);
			x.current -= 10;
			x.timer = setTimeout(x.fade, x.delay);
		}
		
		x.setOpacity = function(element, opacity) {
			opacity = (opacity == 100) ? 99.999 : opacity;
			element.style.filter = "alpha(opacity:"+opacity+")";
			element.style.opacity = opacity/100 /*//*/;
			element.style.display = "";			
		}
		
		x.init();
	},
	
	flash: function(element) {
		var x = new Object();
		x.element = elem(element);
		
		x.init = function() {
			x.curPops = 0;
			x.nPops = 3;
			x.delay = 75;
			x.popColor = "#ff0000";
			x.background = x.element.style.backgroundColor == "" ? "#ffffff" : x.element.style.backgroundColor;
			x.setPop();
		}
		
		x.setPop = function() {
			if (x.curPops >= x.nPops) 
				return;
				
			x.element.style.background = x.popColor;
			x.curPops = x.curPops + 1;
			setTimeout(x.unPop, x.delay);
		}
		
		x.unPop = function() {
			x.element.style.background = x.background;
			setTimeout(x.setPop, x.delay);
		}
		
		x.init();
	},
	
	pulsate: function(element, options) {
		var x = new Object();
		x.element = elem(element);
		x.options = options || {};
		
		x.init = function() {
			x.options = x.options.applyDefaults({
				autoStop: true,
				autoStopSecs: 5,
				scalePercent: 50,
				frameRate: 25 });
			x.start();
		}
		
		x.start = function() {
			x.n = 0;
			x.going = 1;
			x.growing = 1;
			x.skipThisCycle = 0;
			x.delay = 1000 / x.options.frameRate;
			
			if (x.options.autoStop) {
				x.maxCycles = x.delay * x.options.autoStopSecs;
			} else {
				x.maxCycles = 99999;
			}
				
			if (x.element.style.fontSize == "") {
				x.sizeIsEm = false;
				x.startSize = 12;
			} else {
				x.sizeIsEm = x.element.style.fontSize.indexOf("em") > 0;
				x.startSize = x.getSize();
			}
			x.endSize = x.startSize + (x.startSize * (x.options.scalePercent/100));
			// alert("Going from " + x.startSize + " to " + x.endSize);
			x.setSize(x.startSize);	// just to be safe..
			x.doPulsate();
		}
		
		x.setSize = function(n) {
			if (x.sizeIsEm)
				x.element.style.fontSize = n + "em";
			else
				x.element.style.fontSize = n + "pt";
		}
		
		x.getSize = function() {
			return parseFloat(x.element.style.fontSize);
		}
		
		x.doPulsate = function() {
			if (x.going) {
				
				// if we've run more cycles than necessary, exit..
				if (x.n > x.maxCycles) {
					x.going = 0;
					x.stop();
					return;
				}
				
				if (x.skipThisCycle) {
					if (x.skipThisCycle < 2)	
						x.skipThisCycle = x.skipThisCycle + 1;
					else
						x.skipThisCycle = 0;
				} else {
					// if we're expanding, we'll increase the size by one increment
					// and make sure we should keep growing; otherwise shrink until
					// we're back at startSize
					if (x.growing) {
						newSz = x.getSize() + (x.startSize / x.options.frameRate);
						x.setSize(newSz);
						if (x.getSize() >= x.endSize) {
							x.growing = false;
							x.skipThisCycle = 1;
						}
					} else {
						newSz = x.getSize() - (x.startSize / x.options.frameRate);
						x.setSize(newSz);
						if (x.getSize() <= x.startSize) {
							x.growing = true;
						}
					}				
				}
				
				// alert("Setting to " + newSz);
				x.n = x.n + 1;
				setTimeout(x.doPulsate, x.delay);
			}
		}
		
		x.stop = function() {	
			var sz;
			var newSz;
			var i;
			
			sz = x.getSize();
			// scale back for the last time.
			while (i < 20 && sz >= x.startSize) {
				newSz = sz - (sz / 10);
				x.setSize(newSz);
				sz = x.getSize();
				i = i + 1;
			}
		}
		
		x.init();
	}
}
