/**********************************************************************************************************

	Purpose:
		This file contains javascript functions that are not Squirrelcart specific
		
	History:
		File modified on 09/19/2005 for v2.0.1 - general improvements to data grid load appearance
		File modified on 10/26/2005 - added "addRow" function
		File modified on 11/04/2005 - IE 5 and 5.5 treat a comment tag as nodeType 1, which caused problems
		File modified on 03/08/2006 - added formatDecimal and formatCommas functions
	
**********************************************************************************************************/

// way to grab a reference to an element via ID that
// works in all browsers	
function getRefToDivMod( divID, oDoc ) {
	if( !oDoc ) { oDoc = document; }
	if( document.layers ) {
		if( oDoc.layers[divID] ) { return oDoc.layers[divID]; } else {
			for( var x = 0, y; !y && x < oDoc.layers.length; x++ ) {
				y = getRefToDivNest(divID,oDoc.layers[x].document); }
			return y; } }
	if( document.getElementById ) { return oDoc.getElementById(divID); }
	if( document.all ) { return oDoc.all[divID]; }
	return document[divID];
}









/***********************************************************************************************************
	
	Function adds JS to an eventhandler on any element, maintaining existing JS in eventhandler
		
	Parameters:
		elem	id OR ref. to element to add event JS to
		evtName	name event, including the "on" part at the begininning
		func	func reference (not a string! also can't pass params, or parenthesis)
		
***********************************************************************************************************/
function addEventJS(elem,evtName,func) {
	// if elem is an id, grab ref.
	if (typeof(elem) == 'string') elem = document.getElementById(elem);
	// for IE
	if (document.all) {
		elem.attachEvent(evtName,func);
	} else {
		// for DOM compliant browsers
		elem.addEventListener(evtName.replace('on',''),func,false);
	}
}





// purpose of function is to return the inside dimensions of the window
// returns an object with height and width properties set
function getWindowDims() {
	var x = window; 
	var myW = 0, myH = 0, d = x.document.documentElement, b = x.document.body;
	var dims = new Object();
	// for NS
	if( x.innerWidth ) {
		myW = x.innerWidth; myH = x.innerHeight;
	} else if ( d && d.clientWidth ) {
		myW = d.clientWidth; myH = d.clientHeight; 
	} else if( b && b.clientWidth ) {
		// for IE
		myW = b.clientWidth; myH = b.clientHeight; 
	}
	
	if( window.opera && !document.childNodes ) { myW += 16; }
	dims.height = myH;
	dims.width = myW;
	return dims;
}




/******************************************************************************************
	Purpose of function is to return the position of any element on screen...looping
	thru all offsetParents until it hits the top, or hits one that is positioned relative
	
	This returns an object that has a x and y property
	
	Based on this: http://www.quirksmode.org/js/findpos.html
	
	Parameters:
	obj					can be a ref. to OR id of an element
	stopAtRelative		when set to 1, the coordinates will be returned based on the first
						parent element that has a relative position
******************************************************************************************/
function getCoordinates(obj,stopAtRelative) {
	var coordinates = new Object();
	
	// if element id is passed, grab ref. to it
	if (typeof(obj)=='string') obj = document.getElementById(obj);

	var parentStyle;
	var curleft = 0;
	var curtop = 0;
	var checkObj = obj;
	if (checkObj.offsetParent) {
		while (checkObj.offsetParent) {
			curleft += checkObj.offsetLeft;
			curtop += checkObj.offsetTop;

			if (checkObj.offsetParent) {
				
				if (stopAtRelative) {
					// grab current style for this objects parent
					parentStyle = getCurrentStyle(checkObj.offsetParent);
	
					// bail if the parent is relative, because we can't move the object outside of it
					if (parentStyle.position=='relative') {
						break;
					}
				}
				
				// obj is now its parent
				checkObj = checkObj.offsetParent;
			} else {
				break;
			}
			
		}
	} else if (checkObj.x) {
		curleft += checkObj.x;
		curtop += checkObj.y;
	}
	
	coordinates.xLeft 		= curleft;
	coordinates.xRight 		= coordinates.xLeft + obj.offsetWidth;
	coordinates.yTop 		= curtop;
	coordinates.yBottom 	= coordinates.yTop + obj.offsetHeight;
	return coordinates;
}








/**********************************************************************************************************
	Function getCurrentStyle()
	
	Purpose is to return a CSSStyleDeclaration object representing the current applied style, plus CSS
	stylesheets. The style property of an element strictly returns the inline style. This returns the CSS
	actually being used at the time this is called.
	
	The only reason for this function is because IE does not support the DOM2 window.getComputedStyle()
	function, so we have to use the currentStyle property instead.
	
	Params: ref. to OR id of an element
**********************************************************************************************************/
function getCurrentStyle(elem) {
	if (typeof(elem)=='string') elem=document.getElementById(elem);
	
	// if IE and getComputedStyle() is not available (in case IE 7+ adds it)
	if (elem.currentStyle) {
		return elem.currentStyle;
	} else {
		return document.defaultView.getComputedStyle(elem,'');
	}
}




// function takes an object as a parameter, and returns
// a copy of the object
// called like this:
// myNewObj = new cloneObject(origObj);
function cloneObject(what) {

	if (what.valueOf) {
		// this does not work in IE
		return what.valueOf();
	} else {
		// this does work in IE
		for (i in what) {
			this[i] = what[i];
		}
	}
}
				



// Purpose of function is to return a reference to the element that triggered an event
function getEventTarget(evt) {
	evt = (evt) ? evt : ((window.event) ? event : null);
	if (!evt) return false;
	
	var elem = (evt.target) ? evt.target :
		((evt.srcElement) ? evt.srcElement : null);
	if (elem.nodeType == 3) {
		elem = elem.parentNode;
	}
	
	return elem;
}




		
		
// purpose of function is to move an element in an array up or down
function moveArrayPos(arr,old_i,jump) {
	// arr 		the array
	// old_i 	the index of the element u want to move
	// jump 	a pos or neg integer representing how may moves to make in which direction
	//
	// function will return the new array
	
	// calculate new index
	new_i = old_i + jump;

	// account for fact that new index can't be above or below the top or bottom options	
	new_i = new_i < 0 ? 0 : 						// if new position is above the top option, set it to 0 (top)
			new_i > arr.length - 1 ? arr.length - 1: // if new position is below the last option, set it to the last index
			new_i;
	
	if (new_i >= 0) {
		// cut the option from the list
		cut_opt = arr.splice(old_i,1);
		// put back, in the new position
		arr.splice(new_i,0,cut_opt);
	}
	
	//alert("moving index: " + old_i + "(" + jump + "), new i: " + new_i);
	return arr;		
}

		

// purpose of function is to take an element and swap it's class on different event
// this is here, because IE doesn't support CSS pseudo classes "hover, active, etc..."
// on none <a> tags!
// elemRef is optional...if left out, the element that was moused over will get it's className swapped
// if specified, then that element will have its class swapped
// elemId is the ID of the elemnt you want to swap.
function swapClass(evtRef, elemRef, elemId) {
	
	if (!evtRef) return;	
	
	// try to grab by ID first, if elemRef is not passed
	if (!elemRef && elemId) elemRef = document.getElementById(elemId);
	
	// else, grab it from the evt. itself
	if (!elemRef) var elemRef = evtRef.target ? evtRef.target : evtRef.srcElement;

	if (!elemRef.oldClassName) elemRef.oldClassName = elemRef.className;
	
	if (evtRef.type == "mouseover" || evtRef.type == "mousedown") {
		elemRef.className = elemRef.oldClassName + "-" + evtRef.type;
	} else {
		elemRef.className = elemRef.oldClassName;
	}
	
}



// purpose is to toggle visibility of an element
function swapVis(elemRef) {
	elemRef = typeof(elemRef) == 'object' ? elemRef : document.getElementById(elemRef);

	if (elemRef.style) {
		elemRef.style.visibility = elemRef.style.visibility == 'hidden' ? 'visible' : 'hidden';
	}
}

// purpose is to toggle display of an element
function swapDisplay(elemRef) {
	elemRef = typeof(elemRef) == 'object' ? elemRef : document.getElementById(elemRef);
	
	if (elemRef.style) {
		elemRef.style.display = elemRef.style.display == 'none' ? '' : 'none';
	}
}



// submit form on enter
function submitEnter(myfield,e) {
	var keycode;
	if (window.event) {
		keycode = window.event.keyCode;
	} else if (e) {
		keycode = e.which;
	} else {
		return true;
	}
	if (keycode == 13)	{
		myfield.form.submit();
		return false;
	} else {
		return true;
	}
}



/*
Purpose:
	Swap the src of all images that are specified by the imgName var. 

Parameters:
	imgName			name of image(s) to swap src
	excludeRef		ref. to an image to exclude
	forceNewSrc		URL to use for new src, if you don't want to use the one set in the swapsrc attribute
*/
function swapAllSrc(imgName,excludeRef,forceNewSrc) {

	// grab all images with imgName
	imgs = document.getElementsByName(imgName);

	for(i=0; i < imgs.length; i++) {
		img = imgs[i];

		if(excludeRef != img) {
			newSrc = forceNewSrc ? forceNewSrc : img.getAttribute('swapsrc');
			// store current src as swapsrc
			img.setAttribute('swapsrc',img.src);
			img.src = newSrc;
		}
	}
}




function getNextElement(elemRef) {
	/*************************************************************************
		Purpose:
			Grab the next sibling node of elemRef, excluding any text, comments,
			or other non tag nodes
		
		Parameters:
			elemRef	= a element reference, OR id
	*************************************************************************/
	if (typeof(elemRef) == 'string') elemRef = document.getElementById(elemRef);
	
	if (elemRef) {
		// node Type 1 is for an element...tag only. (not a comment, text, etc...)
		nextSib = elemRef.nextSibling;
		if (nextSib) {
			if (nextSib.nodeType != 1 || nextSib.nodeName == '!') {
				nextSib = nextSib.nextSibling;
			} 
			if (nextSib) {
				if (nextSib.nodeType != 1 || nextSib.nodeName == '!') {
					nextSib = nextSib.nextSibling;
				} 
			}
			if (nextSib) {
				if (nextSib.nodeType != 1 || nextSib.nodeName == '!') {
					nextSib = nextSib.nextSibling;
				}
			}
		}
		
		if (nextSib) return nextSib;
	}
	
}


function getPreviousElement(elemRef) {
	/*************************************************************************
		Purpose:
			Grab the previous sibling node of elemRef, excluding any text, 
			comments, or other non tag nodes
		
		Parameters:
			elemRef	= a element reference, OR id
	*************************************************************************/
	if (typeof(elemRef) == 'string') elemRef = document.getElementById(elemRef);
	
	if (elemRef) {
		// node Type 1 is for an element...tag only. (not a comment, text, etc...)
		previousSib = elemRef.previousSibling;
		if (previousSib) {
			if (previousSib.nodeType != 1 || previousSib.nodeName == '!') {
				previousSib = previousSib.previousSibling;
			} 
			if (previousSib) {
				if (previousSib.nodeType != 1 || previousSib.nodeName == '!') {
					previousSib = previousSib.previousSibling;
				} 
			}
			if (previousSib) {
				if (previousSib.nodeType != 1 || previousSib.nodeName == '!') {
					previousSib = previousSib.previousSibling;
				}
			}
		}
		
		if (previousSib) return previousSib;
	}
	
}





function getLastChildElement(parentRef) {
	/*************************************************************************
		Purpose:
			Grab the last child element of parent node parentRef, excluding any text, 
			comments, or other non tag nodes
		
		Parameters:
			parentRef	= an element reference, OR id
	*************************************************************************/
	if (typeof(parentRef) == 'string') parentRef = document.getElementById(parentRef);
	
	if (parentRef) {
		// node Type 1 is for an element...tag only. (not a comment, text, etc...)
		lastChildRef = parentRef.lastChild;
		if (lastChildRef) {
			if (lastChildRef.nodeType != 1 || lastChildRef.nodeName == '!') {
				lastChildRef = getPreviousElement(lastChildRef);
			}
		
			if (lastChildRef.nodeType == 1 && lastChildRef.nodeName != '!') return lastChildRef;
		}	
	}
}





/***************************************************************************
	Purpose:
		To return a reference to the first child node that is an actual
		element (tag).
	
	Parameters:
		elemRef		- reference to element OR id
***************************************************************************/
function getFirstChildElement(elemRef) {
	
	if (typeof(elemRef) == 'string') elemRef = document.getElementById(elemRef);
	
	if (elemRef) {
		// node Type 1 is for an element...tag only. (not a comment, text, etc...)
		// IE prior to 6.0 still treats a comment as node type 1, so we add something to throw that out by nodeName
		firstChildRef = elemRef.firstChild;
		if (firstChildRef) {
			if (firstChildRef.nodeType != 1 || firstChildRef.nodeName == '!') {
				firstChildRef = firstChildRef.nextSibling;
			} 
			if (firstChildRef) {
				if (firstChildRef.nodeType != 1 || firstChildRef.nodeName == '!') {
					firstChildRef = firstChildRef.nextSibling;
				} 
			}
			if (firstChildRef) {
				if (firstChildRef.nodeType != 1 || firstChildRef.nodeName == '!') {
					firstChildRef = firstChildRef.nextSibling;
				}
			}
		}
		
		if (firstChildRef) return firstChildRef;
	}

}





/*********************************************************************************************************
	
	Function returns all elements that have a name that contains the string passed as 'match'.
	Example:
		HTML:
		<div id="parentDiv">
			<input name="test_1" /><br />
			<input name="test_2" /><br />
			<input name="test_3" /><br />
		</div>
		
		JS:
		var testFlds = getElementsByPartialName('parentDiv','input','test_');
		
		The above JS will return an array containing all 3 inputs that start with 'test_'
		
	Parameters:
		parent	- a reference to OR an id of an element to search inside
		tag		- type of tag to look for
		match	- string to match
		
*********************************************************************************************************/
function getElementsByPartialName(parent,tag,match) {
	var i;
	var matches = new Array();

	if (typeof (parent) == 'string') {
		parent = document.getElementById(parent);
	}
	
	var allTags = parent.getElementsByTagName(tag);
	
	if (!allTags) return matches;
	
	// loop thru all tags looking for match
	for(i=0;allTags[i];i++) {
		if (allTags[i].name.indexOf(match) != -1) {
			matches[matches.length] = allTags[i];
		}
	}
	return matches;
}





/*********************************************************************************************************
	
	Function returns all elements that have an id that contains the string passed as 'match'.
	Example:
		HTML:
		<div id="parentDiv">
			<input id="test_1" /><br />
			<input id="test_2" /><br />
			<input id="test_3" /><br />
		</div>
		
		JS:
		var testFlds = getElementsByPartialId('parentDiv','input','test_');
		
		The above JS will return an array containing all 3 inputs that start with 'test_'
		
	Parameters:
		parent	- a reference to OR an id of an element to search inside
		tag		- type of tag to look for
		match	- string to match
		
*********************************************************************************************************/
function getElementsByPartialId(parent,tag,match) {
	var i;
	var matches = new Array();
	if (typeof (parent) == 'string') {
		parent = document.getElementById(parent);
	}
	var allTags = parent.getElementsByTagName(tag);
	if (!allTags) return matches;

	// loop thru all tags looking for match
	for(i=0;allTags[i];i++) {
		if (allTags[i].id.indexOf(match) != -1) {
			matches[matches.length] = allTags[i];
		}
	}
	return matches;
}




/*********************************************************************************************************

	Function toggleCheckboxes()

	Purpose: 
		Toggle check box state for all fields with the given name
		
	Parameters:
		fieldName		- string - name of field, or string that occurs in the field
		state			- state - true for checked, false for unchecked
		partial			- optional. set to true to make this work for all fields that contain the string
						specified as fieldName
		insideEleme		- optional - either the id of or a reference to an element that is the parent of
						 all the fields we want to toggle. This should improve performance a bit for pages
						 with large numbers of inputs

*********************************************************************************************************/
function toggleCheckboxes (fieldName, state, partial, parent) {
	// grab reference to parent if needed
	if (parent) {
		if (typeof(parent) == 'string') parent = document.getElementById(parent);
	} else {
		parent = document;
	}
	
	// grab fields...either ALL input fields, or the ones with the given name
	fields = partial ? parent.getElementsByTagName('INPUT') : parent.getElementsByName(fieldName);
	
	// store the count so we don't have to keep accessing it
	var count = fields.length;
	
	// loop through them
	//for(i=0;i<fields.length;i++){
	for(i=0;i<count;i++){
		if (
				(
					(partial && fields[i].name.indexOf(fieldName) != -1) 
					|| !partial
				)
				&& fields[i].type == "checkbox"
		) 
		{
			fields[i].checked = state;
			
			// this is for IE...without it, if you try to move this field via the DOM, it loses it's value :(
			fields[i].defaultChecked = state;
		}	
	}
}





function dumpElement(elemRef) {
	// purpose of function is to dump the element passed
	// into a table showing each prop and its value
	// this does not recurse through objects
	
	var t; // for text output from this function
	var dumpArr = new Array();
	var propArr = new Array();
	var prop;
	
	for(prop in elemRef) {
		dumpArr[prop] = elemRef[prop];
		propArr[propArr.length] = prop;
	}
	propArr.sort();
	
	t += '<html><head><style>td {font-size: 10px; font-family: tahoma}</style></head><body><table border="1">';
	
	for(i=0; i < propArr.length; i++) {
		prop = propArr[i];
		t += '<tr><td>' + prop + '</td><td>';
		if (prop == 'innerHTML' || prop == 'outerHTML') {
			t += 'HTML ...';
		} else {
			t += dumpArr[prop];
		}
		t += '&nbsp;</td></tr>';
	}
	t += '</table></body></html>';
	var newWin = window.open();
	newWin.document.write(t);		
}






/***********************************************************************
	Purpose:
		To loop through all rows in a table, and alternate the className
		
	Parameters:
		tableRef	- element reference OR id of table
		class1		- string - name of 1st class to use
		class2		- string - name of 2nd clas to use
***********************************************************************/
function altRowClass(tableRef, class1, class2) {
	var currentClass;
	
	// check if tableRef is an ID
	if (typeof(tableRef) == 'string') tableRef = document.getElementById(tableRef);
	
	// grab TBODY tag (inside <table>)
	tBodyRef = getFirstChildElement(tableRef);
	if (tBodyRef) {
		// table rows AND text nodes
		rows = tBodyRef.childNodes;
				
		if (rows) {
			// loop through children, and alternate className on the TR tags only
			// we are skipping the first row, assuming it is a header
			for(i=1; i < rows.length; i++) {
				if (rows[i].tagName == "TR") {
					currentClass = currentClass == class1 ? class2 : class1;
					rows[i].className = currentClass;
				}
			}
		}
	}
}





/********************************************************************************************************

	Function addRow
	
	Purpose: to add 1 or more rows to a table before another row
	
	Parameters:
		beforeRow		ref. OR id of the row to insert the new row before
		rowTag			(string) row tag(s) to add. Example: <tr><td>stuff</td></tr>
		
********************************************************************************************************/
function addRow(beforeRow,rowTag) {
	// if beforeRow was passed as an id, grab a ref. to that row
	if (typeof(beforeRow) == 'string') beforeRow = document.getElementById(beforeRow);
	
	//var tb 		= document.getElementById('tbl');
	//var beforeRow = document.getElementById('prod_opts_last_row');
	var tbody 	= beforeRow.parentNode;

	// create new div to receive the dummy table
	var dummy_div = document.createElement('div');
	
	// add dummy table to dummy div
	dummy_div.innerHTML = '<table>'+ rowTag + '</table>';
	
	// grab reference to the content div
	var contentDiv = document.getElementById('content');

	// store the scrollHeight before the row is added
	contentDiv.oldScrollHeight = contentDiv.scrollHeight;

	// grab reference to the row inside the dummy table
	var newRow, newRowCloned, newRowRef, i, scriptTags,scriptToEval;
	var dummyTbody = getFirstChildElement(getFirstChildElement(dummy_div));
	var numRows = dummyTbody.rows.length;
	for(i=0; i < numRows; i++) {
		newRow = dummyTbody.rows[0];
		
		// insert row in table, right before row specified
		// this in effect moves the row from dummyTbody to the target table,
		// which is why the index for dummyTbody.rows above doesn't increment
		newRowRef = tbody.insertBefore(newRow,beforeRow);
		
		/*********************************************************************
			When replacing the innerHTML in mozilla based browsers,
			any JS inside the new HTML is executed automatically. In IE and 
			Safari, it is not. This fixes that by grabbing the JS and 
			evaluating it.
		*********************************************************************/
		if (!isMoz) {
			// grab any script tags that are inside the new row
			scriptTags = newRowRef.getElementsByTagName('script');

			// loop thru them, and store the JS inside in a variable
			for(var s=0; s < scriptTags.length; s++) {
				scriptToEval += scriptTags[s].innerHTML;
			}
		}
	}

	// evaluate any JS found in new rows
	if (scriptToEval) eval(scriptToEval);
	
	// scroll up as needed, so the new row doesn't affect the scroll position
	var newScrollTop = contentDiv.scrollTop + contentDiv.scrollHeight - contentDiv.oldScrollHeight;
	if (newScrollTop > 0) contentDiv.scrollTop = newScrollTop;

	// return reference to new row
	return newRowRef;
}









/***************************************************************************************************************
	
	Purpose: to remove an element from the DOM
	
	Parameters:
		elem		- a reference to node to remove OR it's ID
		fixScroll	- adjust content area scroll to account for change in content height. Set to 0 to disable
		
***************************************************************************************************************/
function removeElement(elem,fixScroll){
	// bail if nothing passed
	if (!elem) return;
	
	// if id is passed, grab that element's reference
	if (typeof(elem) == 'string') elem = document.getElementById(elem);
	
	// bail if element not found
	if (!elem) return;
	
	// grab reference to the content div
	var contentDiv = document.getElementById('content');

	// store the scrollHeight before the row is added
	contentDiv.oldScrollHeight = contentDiv.scrollHeight;
	
	// remove element via a call to removeChild
	elem.parentNode.removeChild(elem);

	// scroll up as needed, so the new row doesn't affect the scroll position
	var newScrollTop = contentDiv.scrollTop + contentDiv.scrollHeight - contentDiv.oldScrollHeight;
	if (newScrollTop > 0 && fixScroll != 0) contentDiv.scrollTop = newScrollTop;
		
	// For some reason, Safari goes crazy under certain circumstances, and causes the main content area to drop off screen
	// ONLY when DHTML menu builder code is in place. It has something to do with the scrolling for the main content div....
	// If enough vertical scrolling is present, the problem doesn't happen.
	// This makes a hack div appear below the copright notice only for Safari :(
	if (isSafari) {
		document.getElementById('safari_remove_element_hack').style.display = '';
	}
}









/***************************************************************************************************************
	
	Purpose: 
		To loop through a collection of input fields, and return true IF value passed as needle matches (exactly)
		one of the field values
		
	Parameters:
		needle		(string)	string to look for
		haystack	(object)	array of input fields
	
***************************************************************************************************************/
function inFieldValues(needle,haystack) {
	// bail if parameters are ng
	if (typeof(needle) != 'string') return false;
	if (typeof(haystack) != 'object') return false;

	// loop thru each form field
	for(x=0;haystack[x];x++) {
		// if we found a match, return true
		if (haystack[x].value == needle) return true;
	}
	
	// if here, no matches where found
	return false;
}







/**************************************************************
 setfocus
 Delayed focus setting to get around IE bug
**************************************************************/
function setFocusDelayed()
{
  glb_vfld.focus()
}

function setFocus(vfld)
{
  // save vfld in global variable so value retained when routine exits
  glb_vfld = vfld;
  setTimeout( 'setFocusDelayed()', 100 );
}





/*************************************************************************************************

	Function formatDecimal
	
	Purpose: to take a number and format it to specified number of decimal places.
	
	From:
    	Example File From "JavaScript and DHTML Cookbook"
     	Published by O'Reilly & Associates
     	Copyright 2003 Danny Goodman
     	
	Parameters:
		num			(mixed) 	number in string or numeric format
		decplace	(integer)	number of decimal places for output

	Returns a string representation of the number
		
*************************************************************************************************/
function formatDecimal (num, decplaces) {
    // convert in case it arrives as a string value
    num = parseFloat(num);
    // make sure it passes conversion
    if (!isNaN(num)) {
        // multiply value by 10 to the decplaces power;
        // round the result to the nearest integer;
        // convert the result to a string
        var str = "" + Math.round (eval(num) * Math.pow(10,decplaces));
        // exponent means value is too big or small for this routine
        if (str.indexOf("e") != -1) {          return "Out of Range";
        }
        // if needed for small values, pad zeros
        // to the left of the number
        while (str.length <= decplaces) {
            str = "0" + str;
        }
        // calculate decimal point position
        var decpoint = str.length - decplaces;
        // assemble final result from: (a) the string up to the position of
        // the decimal point; (b) the decimal point; and (c) the balance
        // of the string. Return finished product.
        return str.substring(0,decpoint) + "." + str.substring(decpoint,str.length);
    } else {
        return "NaN";
    }
}



/********************************************************************************************************

	Function formatCommas
	
	Purpose:
		To return a string with commas inserted in appropriate places
		
	Parameters:
		numString	(string)	string representing integer portion of number.
		
	From:
    	Example File From "JavaScript and DHTML Cookbook"
     	Published by O'Reilly & Associates
     	Copyright 2003 Danny Goodman

********************************************************************************************************/
function formatCommas(numString) {
    // strip out anything after a decimal, if present
    var re = /(\.\d*)/;
	var dec = numString.match(re)[0];

	// replace decimal in numString so it won't receive commas
	numString = numString.replace(dec,'');

	// add commas
	re = /(-?\d+)(\d{3})/;
    while (re.test(numString)) {
        numString = numString.replace(re, "$1,$2");
    }
    
    // add decimal back
    numString += dec;
    
    return numString;
}





/**********************************************************************************************************

	Function formatCurrency
	
	Purpose: to add commas and 2 decimal places to a number
	
	Parameters:
		num		(mixed)	string OR number

**********************************************************************************************************/
function formatCurrency(num) {
	if (typeof(num) != 'string') num = num.toString();
	return formatCommas(formatDecimal(num,2));
}