// ----------------------------------------------------------------------------------------------------
// UTILITY FUNCTIONS
// ----------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------
// GET OBJECTS, TAGS, CHILD OR PARENT ELEMENTS 

function formatPrice(price) {

	if ( price == 0 ) {
		var formattedPrice = "0.00";
	} else {
		var pricestr = price.toString();
		var length = pricestr.length;
		var dollarLength = length - 2;
		var dollars = pricestr.substr(0,dollarLength);
		var cents = pricestr.substr(dollarLength,2);
		var formattedPrice = dollars + "." + cents;
	}
	
	return formattedPrice;
}	

// get the object with the specified id
function getObject(id){
	if (document.getElementById){
		return document.getElementById(id);
	}
	else if (document.all){
		return  document.all[id];
	}
	else if (document.layers){
		return getObjectNN4(document, id);
	}
	else{
		return null;
	}
}

// helper function for getObject
// get object in Netscape 4
function getObjectNN4(obj,name){
	var x = obj.layers;
	var foundLayer;
	for (var i=0;i<x.length;i++){
		if (x[i].id == name)
			foundLayer = x[i];
		else if (x[i].layers.length)
			var tmp = getObjectNN4(x[i],name);
		if (tmp) foundLayer = tmp;
	}
	return foundLayer;
}

// this replaces getElementsWithTagName
// works in IE4+, NS6+
function getTags(obj, tagName){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (obj.getElementsByTagName){
		return obj.getElementsByTagName(tagName);
	}
	else if (document.all){
		if (tagName == "*"){
			return obj.all;
		}
		else{
			// IE4 (and maybe some other browsers) support this method
			// but tagname must be in uppercase
			tagName = tagName.toUpperCase();
			return obj.all.tags(tagName);
		}
	}
	else{
	// we can't get the tags, so we'll return nothing
	return null;
	}
}

// return the object's parent
// this does not work in NS 4.x
function getParent(obj){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (obj.parentNode){
		return obj.parentNode;
	}
	else if (obj.parentElement){
		return obj.parentElement;
	}
	else if (obj.parentLayer){
		return obj.parentLayer;
	}
	else{
		// we can't get the parent, so return null
		return null;
	}
}

// get parent of a specific tag type
function getSpecParent(obj,parentTag) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	var p = getParent(obj);
	var pTag = parentTag.toUpperCase();
	
	do {
		p = getParent(p);
	}
	while (p.nodeName != pTag);			
	
	return p;
}

// this is a more compatible version of element.childNodes
// works in IE4+, NS6+
// moz/opera count whitespace nodes, but IE does not
function getChildren(obj){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (obj.childNodes){
		// for non IE browsers, we need to clean out the whitespace nodes
		// for consistency
		var nonWhitespace = new Array();
	
		for (var i = 0; i < obj.childNodes.length; i++){
			if (obj.childNodes[i].tagName != null && obj.childNodes[i].tagName != "!"){
				nonWhitespace[nonWhitespace.length] = obj.childNodes[i];
			}
		}
		return nonWhitespace;
	}
	else if (obj.children){	
		var nonWhitespace = new Array();
	
		// don't include comment tags (tags that have a tagName of !)
		for (var i = 0; i < obj.children.length; i++){
			if (obj.children[i].tagName != "!"){
				nonWhitespace[nonWhitespace.length] = obj.children[i];
			}
		}
		return nonWhitespace;
	}
	else if (obj.layers){
		return obj.layers;
	}
	else{
	// we can't get the tags, so we'll return nothing
	return null;
	}
}

// ----------------------------------------------------------------------------------------------------
// MANIPULATE STYLES, CLASSES

// set the style for an object
function setStyle(obj, styleTag, value){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	// get the style object
	var style;
	if (document.getElementById){
		style = obj.style;
	}
	else if (document.all){
		style = obj.style;
	}
	else if (document.layers){
		style = obj;
	} 
	else{
		// we can't get the style, so return
		return false;
	}	
	// now, set the style
	style[styleTag] = value;
}

function setOpacity(obj,opVal){	
	if (typeof(obj) == 'string') obj = getObject(obj);		
	if (document.all) { // IE
		obj.style.filter = "alpha(opacity=" + opVal + ")"; 
	}	
	else if (document.doctype != null) {
		obj.style.MozOpacity = opVal / 100;  
	}
	else {		
		obj.style.opacity = opVal / 100;
	}	
}

// check to see if an element has a particular attribute value
function hasAttr(obj,attribute){
	if (typeof(obj) == 'string') obj = getObject(obj);
	var attr = false;
	if (obj.getAttribute(attribute) != null){
		attr = obj.getAttribute(attribute);
		return attr;
	}
}

// returns true if the object has the specified class
function hasClass(obj, className){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (obj.className){
		var classes = obj.className.split(" ");
		for (var i = 0; i < classes.length; i++){
			if (classes[i]	== className){
				return true;
			}
		}
		return false;
	}
	else{
		return false;
	}
}

// add the CSS class to the object
function addClass(obj, className){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (!hasClass(obj, className)){
		if (obj.className == null || obj.className == ""){
			obj.className = className;
		}
		else{
			// append this to the list of existing classes
			obj.className = obj.className + " " + className;
		}
	}
}

// remove the CSS class (if it exists)
function removeClass(obj, className){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	var classes = obj.className.split(" ");
	var newClasses = new Array();
	
	for (var i = 0; i < classes.length; i++){
		if (classes[i]	!= className){
			newClasses[newClasses.length] = classes[i];
		}
	}
	
	var newClassString = newClasses.join(" ");
	obj.className = newClassString; 
}

// toggle the CSS class
// if its there, remove it
// if it isn't, add it
function toggleClass(obj, className){
	if (hasClass(obj, className)){
		removeClass(obj, className);
	}
	else{
		addClass(obj, className);
	}
}

// highlight a specific object in a group
function hiLite(obj,par,tag,className){
	if (typeof(obj) == 'string') obj = getObject(obj);
	if (typeof(par) == 'string') par = getObject(par);
	
	var c = getTags(par,tag);
	
	for(var i=0; i < c.length; i++){
		if(hasClass(c[i],className)){
			removeClass(c[i],className);
		}
		addClass(obj,className);
	}
}

// ----------------------------------------------------------------------------------------------------
// SHOW / HIDE OBJECTS

// show an element
// unless you specify a display type, the default of "block" is used
function show(obj, displayType){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (document.layers){
		obj.visibility  = "show";
		if (displayType != null){
			obj.display = displayType;
		}
		else{
			obj.display = "block";
		}
	}
	else if (obj.style){
		obj.style.visibility  = "visible";
		if (displayType != null){
			obj.style.display = displayType;
		}
		else{
			obj.style.display = "block";
		}
	}
	else{
		return false;
	}
}

// hide all objects in a container
// then show the other one
function showOnly(obj){
	if (typeof(obj) == "string") obj = getObject(obj);
	show(obj);
	
	var container = getParent(obj);	
	var children = getChildren(container);
	
	for (var i = 0; i < children.length; i++){
		if (children[i] != obj){
			hide(children[i]);
		}
	}
}

// hide an object
// note that objects set display: none are inaccessible
// in the NN4.x DOM. If this matters, use hide instead
function hide(obj){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (document.layers){
		obj.visibility  = "hidden";
		obj.display = "none";
	}
	else if (obj.style){
		obj.style.visibility  = "hidden";
		obj.style.display = "none";
	}
	else{
		return false;
	}
}

// hide the object by setting visibility: hidden
// objects hidden with this function will remain in
// the document flow
function hideVisibility(obj){
	// we can take in an id string or an object pointer
	// if it's a string, just use getObject on the id
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (document.layers){
		obj.visibility  = "hidden";
	}
	else if (obj.style){
		obj.style.visibility  = "hidden";
	}
	else{
		return false;
	}
}

// ----------------------------------------------------------------------------------------------------
// GET DIMENSIONS AND POSITION

// get the document / body width
function getBodyWidth(){
	var x,y;
	
	if (document.getElementsByTagName){
		var bd = document.getElementsByTagName("body").item(0);
		x = getWidth(bd);
	}	
	return x;
}

function getBodyHeight(){
	var x,y;
	
	if (document.getElementsByTagName){
		var bd = document.getElementsByTagName("body").item(0);
		y = getHeight(bd);
	}	
	return y;
}

// get the browser width
function getScreenWidth(){
	var x,y;
	
	// all except Explorer
	if (self.innerHeight){
		x = self.innerWidth;
	}
	// Explorer 6 Strict Mode
	else if (document.documentElement && document.documentElement.clientHeight){
		x = document.documentElement.clientWidth;
	}
	// other Explorers
	else if (document.body){
		x = document.body.clientWidth;
	}
	return x;
}

// get the browser height
function getScreenHeight(){
	var x,y;
	
	// all except Explorer
	if (self.innerHeight){
		y = self.innerHeight;
	}
	// Explorer 6 Strict Mode
	else if (document.documentElement && document.documentElement.clientHeight){
		y = document.documentElement.clientHeight;
	}
	// other Explorers
	else if (document.body){
		y = document.body.clientHeight;
	}
	return y;
}

// get the vertical scroll
function getScrollTop(){
   var scrollTop = 0;
   if (self.pageYOffset){
      scrollTop = self.pageYOffset;
   }
   else if (document.documentElement && document.documentElement.scrollTop){
      scrollTop = document.documentElement.scrollTop;
   }
   else if (document.body){
      scrollTop = document.body.scrollTop;
   }
   return scrollTop;
}

// get the horizontal scroll
function getScrollLeft(){
   var scrollLeft = 0;
   if (self.pageXOffset){
      scrollLeft = self.pageXOffset;
   }
   else if (document.documentElement && document.documentElement.scrollLeft){
      scrollLeft = document.documentElement.scrollLeft;
   }
   else if (document.body){
      scrollLeft = document.body.scrollLeft;
   }
   return scrollLeft;
}

// get the height of an element
function getHeight(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);		
	return obj.offsetHeight;
}

// get the width
function getWidth(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);		
	return obj.offsetWidth;
}

// Returns the horizontal center coordinate. This is just the left scroll offset + browser width/2.
function getCenterX(){
	return ((getScrollLeft() + getScreenWidth())/2);
}

//  Returns the vertical center coordinate. This is just the top scroll offset + browser height/2.
function getCenterY(){
	return ((getScrollTop() + getScreenHeight())/2);
}

// will this object fit in the document horizontally?
function fitHorizontal(obj, xpos){
	return (xpos + getWidth(obj) <= getScreenWidth() + getScrollLeft() && xpos - getScrollLeft() >= 0);
}

function fitVertical(obj, ypos){
	return (ypos + getHeight(obj) <= getScreenHeight() + getScrollTop() && ypos - getScrollTop() >= 0);
}

// find the horizontal offset
function findPosX(obj){
	var left = 0;
	if (obj.offsetParent){
		while (obj.offsetParent){
			left += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		left += obj.x;
	return left;
}

// find the vertical offset
function findPosY(obj){
	var top = 0;
	if (obj.offsetParent){
		while (obj.offsetParent){
			top += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		top += obj.y;
	return top;
}

// resize object (stretch) functions
function stretchWidth(obj, offset){
	if (typeof(obj) == 'string') obj = getObject(obj);
	var w = getScreenWidth();
	obj.style.width = (w - offset) + "px";
}

function stretchHeight(obj, offset){
	if (typeof(obj) == 'string') obj = getObject(obj);
	var h = getScreenHeight();
	obj.style.height = (h - offset) + "px";
}


// ----------------------------------------------------------------------------------------------------
// WIDGETS -- SMALL, COMPOSITE FUNCTIONS
// ----------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------
// FORM ELEMENT FUNCTIONS

// check a specific checkbox
function setCheck(obj) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	obj.checked = true;
}

// uncheck a specific checkbox
function undoCheck(obj) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	obj.checked = false;
}

// check all in a group
function checkAll(obj) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	//get checkboxes
	var checks = getTags(obj, 'input');
	
	for(var i=0; i<checks.length; i++) {
	checks[i].checked = true;
	}									
}

// uncheck all in a group
function checkNone(obj) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	//get checkboxes
	var checks = getTags(obj, 'input');
	
	for(var i=0; i<checks.length; i++) {
	checks[i].checked = false;
	}								
}

// uncheck checked, check unchecked
function toggleChecked(obj) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	//get checkboxes
	var checks = getTags(obj, 'input');
	
	for(var i=0; i<checks.length; i++) {
	if (checks[i].checked) {
		checks[i].checked = false;
		}
	else {
		checks[i].checked = true;
		}
	}									
}

// check a 'master' checkbox to enable / disable other checkboxes
function disableCheck(obj,chk){
	if (typeof(obj) == 'string') obj = getObject(obj);
	if (typeof(chk) == 'string') chk = getObject(chk);
	
	//get checkboxes
	var c = getTags(obj, 'input');	
	
	for(var i=0; i<c.length; i++){
		
		if (c[i] != chk){
			
			if (chk.checked){
				c[i].disabled = false;
			}
			else{
				c[i].disabled = true;
				c[i].checked = false;					
			}
		}	
	}				
}

// do a function onchange
// can be called from the value attribute assigned to <option> tags, but
// we should find a different way to call this in case it needs to be used for a real application
function doFunction(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	var c = obj.options[obj.selectedIndex].value;
	if (c) setTimeout(c,0);
}

// faux select box
// this will update link text in a button-styled dropdown
function updateLink(obj,value){
	if (typeof(obj) == 'string') obj = getObject(obj);
	obj.innerHTML = '<span>' + value + '</span>';
}

// simple text replacement
function replaceText(obj,text) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	obj.innerHTML = text;
}

// ----------------------------------------------------------------------------------------------------
// SPINDOWNS

function spindown(e, caller) {
	if (!caller) caller = this;
	
	// get the bottom element
	var bd = caller.id + "_body";
	var b = getObject(bd);
	var slct = getTags(b,'select');
	
	// if we have both the top and bottom
	// set the appropriate styles
	if (b != null) {
		if (hasClass(caller, "spdn_open")) {
			// close it
			hide(bd);
			removeClass(caller, "spdn_open");
			addClass(caller, "spdn_closed");
			if (slct != null){
				for(var z=0; z < slct.length; z++){
					hide(slct[z]);
				}
			}		
		}
		else {
			// open it
			if (b.nodeName == "TR"){
				showRow(bd);
			}
			else{
				show(bd);
			}					
			removeClass(caller, "spdn_closed");
			addClass(caller, "spdn_open");		
			if (slct != null){
				for(var z=0; z < slct.length; z++){
					show(slct[z]);
				}
			}			
		}
	}	
}

// control all spindowns within a specified container
// used for the accordion menu
function spindownOnly(e, caller) {
	if (!caller) caller = this;
	
	var p = getParent(caller);
	var c = getChildren(p);
	var b = getObject(caller.id + '_body');
	
	if (b != null){
		if (hasClass(caller,'spdn_closed')){	
			for (i = 0; i < c.length; i++){				
				if (hasClass(c[i],'spdn_open')){
					hide(c[i].id + '_body');
					removeClass(c[i],'spdn_open');
					addClass(c[i],'spdn_closed');
				}				
			}
			show(b);
			removeClass(caller,'spdn_closed');
			addClass(caller,'spdn_open');
		}
		else{
			hide(b)
			removeClass(caller,'spdn_open');
			addClass(caller,'spdn_closed');
		}
	}			
}

// to initialize spindowns onload
function setSpindown(obj) {
	if (typeof(obj) == "string") obj = getObject(obj);

	if (obj.captureEvents)
		obj.captureEvents(Event.CLICK);
	
	obj.onclick = spindown;
}

// ----------------------------------------------------------------------------------------------------
// TABS

// show the tab you've clicked
function showTab(e, caller){
	if (!caller) caller = this;	
	
	var par = getParent(caller);
	var tabs = getParent(par);
	var dv = getChildren(tabs);
	
	//tabLinks
	//tabContent
			
	for (var i = 0; i < dv.length; i++) {
	
		if (hasClass(dv[i],'tabLinks')){		
			var lnk = getTags(dv[i],'a');	
			var div = getTags(dv[i],'div');
			
			// horizontal tab strip
			if (lnk != null){
				for (var j = 0; j < lnk.length; j++){
							
					// turn off the anchor linking so that it doesn't interfere
					lnk[j].href = 'javascript://';
					
					if (lnk[j].id != caller.id) { 
						removeClass(lnk[j],'on');
					}
					else { 
						addClass(lnk[j],'on'); 
					}
				}
			}
			
			// vertical tab strip w/ radios
			if (div != null){
				for (var k = 0; k < div.length; k++){
							
					// turn off the anchor linking so that it doesn't interfere
					div[k].href = 'javascript://';
					
					if (div[k].id != caller.id) { 
						removeClass(div[k],'on');
					}
					else { 
						addClass(div[k],'on'); 
					}
				}
			}
				
		}
		
		if (hasClass(dv[i],'tabContent')){			
			var tb = getChildren(dv[i]);
			for (var k = 0; k < tb.length; k++){				
				// make sure the divs not selected are hidden
				if (tb[k].id != caller.id + '_body') { hide(tb[k]); }				
				// show the div you selected
				else { 
					show(tb[k]);
					// custom check for screen height in PPC edit screens:
					if (getObject('editBody') != null){
						setStyle('editBody','height','auto');
					}		
				}					
			}	
		}
	}
}

// initialize tabs onload 
function setTabs(obj){
	if (typeof(obj) == "string") obj = getObject(obj);

	if (obj.captureEvents)
		obj.captureEvents(Event.CLICK);
	
	obj.onclick = showTab;
}

// ----------------------------------------------------------------------------------------------------
// XMLHttpRequest FUNCTIONS

var xmlhttp=false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@end @*/

if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { xmlhttp = new XMLHttpRequest(); }

function getText(serverPage, objID) {
	var obj = document.getElementById(objID); 
	
	xmlhttp.open("GET", serverPage); 
	xmlhttp.onreadystatechange = function(){ 
		if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { 
			obj.innerHTML = xmlhttp.responseText; 
			} 
	} 
	xmlhttp.send(null); 
} 

// swap content onchange using getText
// used briefly for AdoramaPix prototype -- not fully tested
function switchContent(obj){
	var d = document.forms[0].displaytype;
	var c = d.options[d.selectedIndex].value;
	if (c) getText(c,obj);
}

// ----------------------------------------------------------------------------------------------------
// POPUPS

// custom popup function - parameters passed in with link
function popup(alink, popup_width, popup_height, scrollbars, toolbars, resize){
	var url = alink.href;
	var name = alink.target;
	
	var popup_window = window.open(url,name,"toolbar="+toolbars+",directories="+toolbars+",status="+toolbars+",menubar="+toolbars+",location="+toolbars+",scrollbars="+scrollbars+",resizable="+resize+",width="+popup_width+",height="+popup_height);
	popup_window.focus();
}

// fixed popup function - parameters set in script which references popup()
function popupFixed(alink){
	var popup_window = popup(alink, 300, 220, 0, 0, 0); return false;
	popup_window.focus();			
}

function popupSimple(url){
	var popup_window = window.open(url,'newWindow','width=400,height=300');
	// popup_window.focus();
}

// ----------------------------------------------------------------------------------------------------
// IFRAME FUNCTIONS

// get to the iframes
function updateFrame(obj,url){
	if (typeof(obj) == 'string') obj = getObject(obj);
	//if (obj) obj.location.href = url;	
	if (obj) obj.src = url;
}

// ----------------------------------------------------------------------------------------------------
// TABLE FUNCTIONS - STRIPE, SHOW / HIDE COLUMNS
// see the SPINDOWN functions for showing / hiding rows

// Alternating table row colors
// modified by Shaun to change classes rather than colors
// modified by Maggie to use our core scripts
function stripe(){
	
	// the flag we'll use to keep track of whether the current row is odd or even
	var even = false;
	var evenStyle = 'even';
	var oddStyle = 'odd';
	
	var tb = getTags(document, 'tbody');
	
	for (var h = 0; h < tb.length; h++){
		// reset the even attribute
		even = false;
		
		if (hasClass(tb[h],'stripe')){
			// find all the tr elements... 
			var tr = getTags(tb[h], 'tr');
		
			// ... and iterate through them
			for (var i = 0; i < tr.length; i++){
				// avoid rows that have a class attribute
				// or backgroundColor style
				tr[i].className = even ? evenStyle : oddStyle;
		
				// flip from odd to even, or vice-versa
				even =  ! even;
			}		
		}			
	}
}

// hide column 
// not fully tested !!
function hideCol(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (obj.nodeName == "TH"){
		var k = obj.id;
		var tr = getParent(obj);
		var hd = getParent(tr);
		var tb = getParent(hd);			
		var r = getTags(tb,'tr');
		
		hide(obj);
		
		for (var i = 0; i < r.length; i++){
			var d = getChildren(r[i]);				
			
			for (var x = 0; x < d.length; x++){
				if (d[x].getAttribute('headers') == k){
					hide(d[x]);
				}
			}
		}			
	}		
}

// show column
// not fully tested !!
function showCol(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	if (obj.nodeName == "TH"){
		var k = obj.id;
		var tr = getParent(obj);
		var hd = getParent(tr);
		var tb = getParent(hd);			
		var r = getTags(tb,'tr');
		
		showCell(obj);
		
		for (var i = 0; i < r.length; i++){
			var d = getChildren(r[i]);				
			
			for (var x = 0; x < d.length; x++){
				if (d[x].getAttribute('headers') == k){
					showCell(d[x]);
				}
			}
		}			
	}		
}	

// show row
function showRow(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	// only supported by IE 5-6
	if (typeof(document.all)=='object'){			
		show(obj);
	}
	else{
		setStyle(obj,'display','table-row');
		setStyle(obj,'visibility','visible');
	} 
}

// show a single cell
function showCell(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	// only supported by IE 5-6
	if (typeof(document.all)=='object'){			
		show(obj);
	}
	else{
		setStyle(obj,'display','table-cell');
		setStyle(obj,'visibility','visible');
	} 
}

// get the column placement in the table (first column returns 0);
function getIndex(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	return obj.cellIndex;
}


// ----------------------------------------------------------------------------------------------------
// ANIMATION OJBECTS AND TRANSITIONS

function isNegative(num) {
	if (typeof(num) == 'number') {
		var ns = num.toString();
		if (ns.indexOf('-') != -1) { return true; }
		else { return false; }
	}
}

var effectCounter = 0;

function Effect(id,optParams) {
	if (id) {
		// get characteristics
		this.id = getObject(id);
		this.height = getHeight(id);
		this.width = getWidth(id);
		this.currXpos = findPosX(id);
		this.currYpos = findPosY(id);
		
		// set default values for optional parameters
		this.inc = 1;
		this.minht = 1;
		this.maxht = null;	
		this.distX = 0;		
		this.distY = 0;	
		
		// specify values parameters if they exist
		if (optParams) {
			this.params = optParams;
			
			if (this.params.increment) { 
				this.inc = this.params.increment; 
			}
			if (this.params.minHeight) { 
				this.minht = this.params.minHeight; 
			}
			if (this.params.maxHeight) { 
				this.maxht = this.params.maxHeight; 
			}			
			if (this.params.minWidth) { 
				this.minwd = this.params.minWidth; 
			}
			if (this.params.maxWidth) { 
				this.maxwd = this.params.maxWidth; 
			}			
			if (this.params.distanceX) {
				this.distX = this.params.distanceX;
			}
			if (this.params.distanceY) {
				this.distY = this.params.distanceY;
			}			
			if (this.params.nextMove) {
				this.next = this.params.nextMove;
			}
			if (this.params.nextDelay) {
				this.delay = this.params.nextDelay;
			}
		}
				
		// set methods
		this.show = function(){
			effectShow(this.id);
		}
		
		this.hide = function(){
			effectHide(this.id);
		}
		
		this.fadeIn = function() {		
			effectFadeIn(this.id,this.inc);
		}	
		
		this.fadeOut = function() {		
			effectFadeOut(this.id,this.inc);
		}			
		
		this.incHeight = function() {
			this.height = getHeight(id);
			effectIncHeight(this.id,this.inc,this.height,this.maxht,this.next,this.delay);
		}
		
		this.decHeight = function() {
			this.height = getHeight(id);
			effectDecHeight(this.id,this.inc,this.height,this.minht);
		}
		
		this.incWidth = function() {	
			this.width = getWidth(id);	
			effectIncWidth(this.id,this.inc,this.width,this.maxwd,this.next,this.delay);
		}
		
		this.decWidth = function() {
			this.width = getWidth(id);	
			effectDecWidth(this.id,this.inc,this.width,this.minwd);
		}		
		
		this.moveByX = function() {
			effectMoveByX(this.id,this.inc,this.distX);
		}
		
		this.moveByY = function() {
			effectMoveByY(this.id,this.inc,this.distY);
		}
		
		this.closeWidth = function() {
			effectCloseWidth(this.id,this.inc,this.width,this.minwd);
		}
	}
}

function effectShow(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	show(obj);
}

function effectHide(obj){
	if (typeof(obj) == 'string') obj = getObject(obj);
	hide(obj);
}

function effectIncHeight(obj,increment,currht,maxht,next,delay){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	var inc = increment;
	
	// get the object's content 
	var c = getChildren(obj);
	
	// if no max height specified, use the height of the object's content
	if (!maxht || maxht == 'blank'){ 
		var maxht = getHeight(c[0]); 
	}
	
	// after the animation begins, check to see if the remainder is smaller than the increment
	// if so, set the increment to 1px so that we match the max height exactly
	if ((maxht - currht) < inc){ inc = 1; }	

	if (currht < maxht){  // set the new height, and keep running the function
		var newht = currht += inc;
		setStyle(obj,'height',newht + 'px');
		setTimeout(function(){effectIncHeight(obj,inc,currht,maxht,next,delay);},0);
	}
	else {
		if (next) {
			var d = 1000;
			if (delay) {
				var d = delay * 1000;
			}
			setTimeout(next,d);
		}
	}
}

function effectDecHeight(obj,increment,currht,minht){
	if (typeof(obj) == 'string') obj = getObject(obj);	
	
	var inc = increment;
	var minht = minht;
	
	// after the animation begins, check to see if the remainder is smaller than the increment
	// if so, set the increment to 1px so that we match the min height exactly
	if ((currht - minht) < inc){ inc = 1; }
	
	if (currht > minht){  // set the new height, and keep running the function
		var newht = currht -= inc;
		setStyle(obj,'height',newht + 'px');
		setTimeout(function(){effectDecHeight(obj,inc,currht,minht);},0);
	}
	else {
		//doNextEffect(++effectCounter);
	}
}

function effectIncWidth(obj,increment,currwd,maxwd,next,delay){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	var inc = increment;
	
	// get the object's content 
	var c = getChildren(obj);	
	
	// if no max height specified, use the height of the object's content
	if (!maxwd){ 
		var maxwd = getWidth(c[0]); 
	}
	else {
		var maxwd = maxwd;
	}
	
	// after the animation begins, check to see if the remainder is smaller than the increment
	// if so, set the increment to 1px so that we match the max height exactly
	if ((maxwd - currwd) < inc){ inc = 1; }	
	
	//alert(currwd+', '+maxwd);

	if (currwd < maxwd){  // set the new width, and keep running the function		
		var newwd = currwd += inc;
		setStyle(obj,'width',newwd + 'px');
		setTimeout(function(){effectIncWidth(obj,inc,currwd,maxwd,next,delay);},0);
	}
	else {
		if (c.length > 0) {
			for (var i = 0; i < c.length; i++) {
				show(c[i]);	
			}
		}
		if (next) {
			var d = 1000;
			if (delay) {
				var d = delay * 1000;
			}
			setTimeout(next,d);
		}
	}
}

function effectDecWidth(obj,increment,currwd,minwd){
	if (typeof(obj) == 'string') obj = getObject(obj);

	var inc = increment;
	var minwd = minwd;
	
	if (!obj.kids) {		
		var c = getChildren(obj);
		if (c != null && c.length > 0) {
			for (var i = 0; i < c.length; i++) {
				hide(c[i]);
			}
		}
		obj.kids = true;
	}	
	
	// after the animation begins, check to see if the remainder is smaller than the increment
	// if so, set the increment to 1px so that we match the min height exactly
	if ((currwd - minwd) < inc){ inc = 1; }
	
	if (currwd > minwd){  // set the new width, and keep running the function
		var newwd = currwd -= inc;
		setStyle(obj,'width',newwd + 'px');
		setTimeout(function(){effectDecWidth(obj,inc,currwd,minwd);},0);
	}
	else {
		obj.kids = null;
		//doNextEffect(++effectCounter);
	}
}

function effectFadeIn(obj,increment,newOp){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	// make sure you're not using Opera, which doesn't support opacity
	if (!window.opera) {
	
		var maxOpacity = 99;
		
		if (!newOp) { var currOp = 1; }		
		else { currOp = newOp; }
		
		var inc = increment;
		if ((maxOpacity - currOp) < inc){ inc = 1; }
		
		if (currOp < maxOpacity) {
			var opVal = currOp += inc;
			setOpacity(obj,opVal);
			setTimeout(function(){effectFadeIn(obj,inc,currOp);},0);
		}
	}
}

function effectFadeOut(obj,increment,newOp){
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	// make sure you're not using Opera, which doesn't support opacity
	if (!window.opera) {
	
		var minOpacity = 1;
		
		if (!newOp) { var currOp = 99; }		
		else { currOp = newOp; }
		
		var inc = increment;
		if ((currOp - minOpacity) < inc){ inc = 1; }
		
		if (currOp > minOpacity) {
			var opVal = currOp -= inc;
			setOpacity(obj,opVal);
			setTimeout(function(){effectFadeOut(obj,inc,currOp);},0);
		}
	}
}

function effectMoveByX(obj,increment,distanceX,currX,loop) {
	if (typeof(obj) == 'string') obj = getObject(obj);	
	
	var inc = increment;
	var dX = distanceX;
	var currX;
	var newX;
	
	if (!loop) {
		currX = 0;		
	}
	else {
		currX = currX;
	}
	
	if (isNegative(dX)) {
		if (currX > dX) {
			newX = currX - inc;
			obj.style.left = newX + 'px';
			setTimeout(function(){effectMoveByX(obj,inc,dX,newX,true);},0);
		}		
	}
	else {		
		if (currX < dX) {
			newX = currX + inc;
			obj.style.left = newX + 'px';
			setTimeout(function(){effectMoveByX(obj,inc,dX,newX,true);},0);
		}
	}
}

function effectMoveByY(obj,increment,distanceY,currY,loop) {
	if (typeof(obj) == 'string') obj = getObject(obj);	
	
	var inc = increment;
	var dY = distanceY;
	var currY;
	var newY;
	
	if (!loop) {
		currY = 0;
	}
	else {
		currY = currY;
	}	
	
	if (isNegative(dY)) {
		if (currY > dY) {
			newY = currY - inc;
			obj.style.top = newY + 'px';
			setTimeout(function(){effectMoveByY(obj,inc,dY,newY,true);},0);
		}
	}
	else {		
		if (currY < dY) {
			newY = currY + inc;
			obj.style.top = newY + 'px';
			setTimeout(function(){effectMoveByY(obj,inc,dY,newY,true);},0);
		}	
	}
}

function effectCloseWidth(obj,increment,width,minwd) {
	if (typeof(obj) == 'string') obj = getObject(obj);
	
	var inc = increment;
	var halfInc = inc/2;
	var width = width;
	var center = width/2;
	var minwd = minwd;
	
	var c = getChildren(obj);
	if (c.length > 0) {
		for (var i = 0; i < c.length; i++) {
			hide(c[i]);
		}
	}
	
	effectMoveByX(obj,halfInc,center);	
	effectDecWidth(obj,inc,width,minwd);
}

// ----------------------------------------------------------------------------------------------------
// MORE COMBO EFFECT WIDGETS...

// ---------- slide height

function toggleSlideOpen(e, caller) {
	if (!caller) caller = this;
	
	var p = getParent(caller);
	var ht = getHeight(caller);
	var c = getChildren(caller);
	var fullHt = getHeight(c[0]);
	
	if (!caller.startHt) {
		caller.startHt = getHeight(caller);
	}
	
	var s = getChildren(p);	
	for (var i = 0; i < s.length; i++) {	
		if (hasClass(s[i],'highlightRow')) {
			removeClass(s[i],'highlightRow');
		}	
	}	
	
	if (fullHt > ht){	
		addClass(caller,'highlightRow');	
		slideClosedAll(p);	
		effectIncHeight(caller,15,ht,fullHt);		
	}
	else {
		effectDecHeight(caller,15,ht,caller.startHt);		
	}		
}

function slideOpenAll(container) {
	if (container) {
		var c = getChildren(container);
		for (var i = 0; i < c.length; i++) {	
					
			var ht = getHeight(c[i]);
			var cc = getChildren(c[i]);
			var fullHt = getHeight(cc[0]);
			
			if (!c[i].startHt) {
				c[i].startHt = getHeight(c[i]);
			}
			removeClass(c[i],'highlightRow');
			addClass(c[i],'highlightWordOnly');
			setStyle(c[i],'cursor','default');
			effectIncHeight(c[i],10,ht,fullHt);			
			
			if (c[i].removeEventListener) {
				c[i].removeEventListener('click',toggleSlideOpen,false);	
			}
			else {
				c[i].onclick = null;
			}
		}
	}
}

function slideClosedAll(container) {
	if (container) {
		var c = getChildren(container);
		for (var i = 0; i < c.length; i++) {	
					
			var ht = getHeight(c[i]);
			
			if (!c[i].startHt) {
				c[i].startHt = getHeight(c[i]);
			}
			effectDecHeight(c[i],10,ht,c[i].startHt);
			setStyle(c[i],'backgroundImage','');
			removeClass(c[i],'highlightWordOnly');
			
			if (c[i].addEventListener) {
				c[i].addEventListener('click',toggleSlideOpen,false);	
			}
			else {
				c[i].onclick = toggleSlideOpen;
			}
		}
	}
}

function setToggleSlideOpen(container) {
	if (container) {
		var c = getChildren(container);		
		
		for (var i = 0; i < c.length; i++) {	
			if (c[i].addEventListener) {
				c[i].addEventListener('click',toggleSlideOpen,false);	
			}
			else {
				c[i].onclick = toggleSlideOpen;
			}
		}	
	}		
}

function setWordDetailLinks(container) {
	if (container) {	
		
		var lnks = getTags(container,'a');
		
		var linkMouseOver = function () {
			disableToggleSlideOpen(container);
		}
		var linkMouseOut = function () {
			setToggleSlideOpen(container);
		}
		
		for (var k = 0; k < lnks.length; k++) {	
			if (hasClass(lnks[k],'detailsLink')) {	
			
				if (lnks[k].addEventListener) {
					lnks[k].addEventListener('mouseover',linkMouseOver,false);
					lnks[k].addEventListener('mouseout',linkMouseOut,false);
				}
				else {
					lnks[k].onmouseover = linkMouseOver;
					lnks[k].onmouseout = linkMouseOut;
				}
			}				
		}		
	}
}

function setProgressDetails(container) {
	if (container) {	
		
		var divs = getTags(container,'div');
		
		var linkMouseOver = function () {
			disableToggleSlideOpen(container);
		}
		var linkMouseOut = function () {
			setToggleSlideOpen(container);
		}
		
		for (var k = 0; k < divs.length; k++) {	
			if (hasClass(divs[k],'progressDetails')) {	
			
				if (divs[k].addEventListener) {
					divs[k].addEventListener('mouseover',linkMouseOver,false);
					divs[k].addEventListener('mouseout',linkMouseOut,false);
				}
				else {
					divs[k].onmouseover = linkMouseOver;
					divs[k].onmouseout = linkMouseOut;
				}
			}				
		}		
	}
}

function disableToggleSlideOpen(container) {
	if (container) {
		var c = getChildren(container);
		for (var i = 0; i < c.length; i++) {			
			if (c[i].removeEventListener) {
				c[i].removeEventListener('click',toggleSlideOpen,false);	
			}
			else {
				c[i].onclick = null;
			}
		}
	}		
}

function setFlashcards(container) {
	if (container) {
		var c = getChildren(container);
		
		for (var i = 0; i < c.length; i++) {
			var t = getTags(c[i],'div');
						
			for (var k = 0; k < t.length; k++) {
				if (hasClass(t[k],'cardBack')) {
					if (t[k].addEventListener) {
						t[k].addEventListener('click',hideFlashCard,false);	
					}
					else{
						t[k].onclick = hideFlashCard;
					}
				}					
			}
			
			var lnks = getTags(c[i],'a');
			
			for (var m = 0; m < lnks.length; m++) {
				if (hasClass(lnks[m],'cardFront')) {
					if (lnks[m].addEventListener) {
						lnks[m].addEventListener('click',showFlashCard,false);	
					}
					else{
						lnks[m].onclick = showFlashCard;
					}
				}	
			}								
		}
	}
}

function showFlashCard(e, caller) {
	if (!caller) caller = this;	
	var wd = getWidth(caller);		
	if (wd == 176){		
		effectDecWidth(caller,15,176,1);
	}
}

function hideFlashCard(e, caller) {
	if (!caller) caller = this;	
	var p = getParent(caller);
	var c = getChildren(p);		
	for (var i = 0; i < c.length; i++) {
		if (hasClass(c[i],'cardFront')) {
			var cf = c[i].id;
			effectIncWidth(cf,15,1,176);
		}
	}
}

function disableHideFlashCard(container) {
	if (container) {
		var c = getTags(container,'div');
		for (var i = 0; i < c.length; i++) {		
			if (hasClass(c[i],'cardBack')) {
				if (c[i].removeEventListener) {
					c[i].removeEventListener('click',hideFlashCard,false);	
				}
				else {
					c[i].onclick = null;
				}
			}								
		}
	}		
}

function setFlashDetailLinks(container) {
	if (container) {	
		
		var linkClick = function () {
			if (getObject('wordPopup') != null) {
				showInfo('wordPopup', this, 'popup', 'persist');
			}			
		}
		
		var linkMouseOver = function () {
			disableHideFlashCard(container);
		}
		var linkMouseOut = function () {
			setFlashcards(container);
		}
		
		var lnks = getTags(container,'a');
		
		for (var k = 0; k < lnks.length; k++) {		
			if (hasClass(lnks[k],'detailsLink')) {
				if (lnks[k].addEventListener) {
					lnks[k].addEventListener('click',linkClick,false);	
					lnks[k].addEventListener('mouseover',linkMouseOver,false);
					lnks[k].addEventListener('mouseout',linkMouseOut,false);
				}
				else {
					lnks[k].onclick = linkClick;
					lnks[k].onmouseover = linkMouseOver;
					lnks[k].onmouseout = linkMouseOut;
				}
			}				
		}		
	}
}

function showScoreHistory(e,caller){
	if (!caller) caller = this;	
	var table = getSpecParent(caller,'table');	
	var rows = getTags(table,'tr');
	var td = getParent(caller);
	var lnks = getTags(td,'a');
		
	for (var i = 0; i < rows.length; i++) {
		if (hasClass(rows[i],'hiddenRow')) {
			removeClass(rows[i],'hiddenRow');
			addClass(rows[i],'tempShow');			
		}
		else if (hasClass(rows[i],'tempShow')) {
			removeClass(rows[i],'tempShow');
			addClass(rows[i],'hiddenRow');
		}
	}	
	
	for (var k = 0; k < lnks.length; k++) {
		show(lnks[k]);
	}			
	hide(caller);	
}

function stretchExScreen() {
	if (getObject('exScreen') != null) {
		var scHt = getScreenHeight();
		var pgHt = 0; 
		
		var divs = getTags(document,'div');
		for (var i = 0; i < divs.length; i++) {
			if (hasClass(divs[i],'popupExercise')){
				pgHt = getHeight(divs[i]) + 50;
			}
		}
		
		show('exScreen');
		
		if (document.all){ stretchWidth('exScreen',0); }
		else { stretchWidth('exScreen',20); }		
		
		if (pgHt > scHt) {		
			setStyle('exScreen','height',pgHt + 50 + 'px');			
		}	
		else {
			stretchHeight('exScreen',0);
		}		
	}
}

function spinRow(e,caller) {
	if (!caller) caller = this;
	
	var tbody = getSpecParent(caller,'tbody');
	var trs = getTags(tbody,'tr');
	var par = getSpecParent(caller,'tr');
	
	for (var i = 0; i < trs.length; i++) {
		if (trs[i] == par) {
			if (hasClass(trs[++i],'subRow')) {
				do {
					if (hasClass(trs[i],'hiddenRow')) {
						removeClass(trs[i],'hiddenRow');
						addClass(trs[i],'tempShow');
						removeClass(caller,'spinClosed');
						addClass(caller,'spinOpen');
					}
					else if (hasClass(trs[i],'tempShow')) {
						removeClass(trs[i],'tempShow');
						addClass(trs[i],'hiddenRow');
						removeClass(caller,'spinOpen');
						addClass(caller,'spinClosed');
					}				
					++i;		
				}
				while (hasClass(trs[i],'subRow'));				
			}					
		}	
	}
}


function spinRowsClosed(container) {
	if (typeof(container) == 'string') obj = getObject(container);
	
	var trs = getTags(obj,'tr');
	for (var i = 0; i < trs.length; i++) {
		if (hasClass(trs[i],'tempShow')) {
			removeClass(trs[i],'tempShow');
			addClass(trs[i],'hiddenRow');
		}
	}
	
	var lnks = getTags(obj,'a');
	for (var k = 0; k < lnks.length; k++) {
		if (hasClass(lnks[k],'spinOpen')) {
			removeClass(lnks[k],'spinOpen');
			addClass(lnks[k],'spinClosed');
		}
	}
}

function spinRowsOpen(container) {
	if (typeof(container) == 'string') obj = getObject(container);
	
	var trs = getTags(obj,'tr');
	for (var i = 0; i < trs.length; i++) {
		if (hasClass(trs[i],'hiddenRow')) {
			removeClass(trs[i],'hiddenRow');
			addClass(trs[i],'tempShow');
		}
	}
	
	var lnks = getTags(obj,'a');
	for (var k = 0; k < lnks.length; k++) {
		if (hasClass(lnks[k],'spinClosed')) {
			removeClass(lnks[k],'spinClosed');
			addClass(lnks[k],'spinOpen');
		}
	}
}