
/* START shared functions */

slash = null;

function hide(id)
{
	getlayer(id).style.display = 'none';
}

function isIE(){  return /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent);}

function show(id)
{
	getlayer(id).style.display = '';
}

function loadContentAsync(script, action, params, layer, runOnComplete){
	var slash = getSlash();
	var file = appdir + slash + script + '.aspx' + action;
	if(!runOnComplete)
	{
		runOnComplete = function(response){
			if(response.responseText!="")
			{
				writetolayer(layer, response.responseText);
			}
		}
	}
	new Ajax.Request(file, {
		method: 'post',
		parameters: params,
		onComplete: runOnComplete
	});
}

function getSlash(){
	if(slash==null){
		if(appdir && appdir.length > 0 && appdir.charAt(appdir.length-1) != '/'){
			slash = '/';
		}
		else{
			slash = '';
		}
	}
	return slash;
}

function getUrlParam(name)
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );  
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
  {
	var value = results[1];
	value = value.replace(/\+/g, " ");
	value = unescape(value);
	return value;
  }
}

function getError()
{
	return getUrlParam("error");
}

function getMessage()
{
	return getUrlParam("message");
}

function errorAlert()
{
	var error = getError();
	if(error != "")
	{
		var errorOut = "We're sorry!  There was a problem.\n\n" 
			+ error
			+ "\n\nPlease try again.";
		alert(errorOut);
	}
}

function messageAlert()
{
	var message = getMessage();
	if(message != "")
	{
		alert(message);
	}
}

function runAlerts()
{
	errorAlert();
	messageAlert();
}

// Original:  Gregor (legreg@legreg.de) -->
function writetolayer(lay,txt,win) {
	if(!win) win = window;
	if (win.document.all) {
		win.document.all[lay].innerHTML = txt;
	}
	else if (win.document.layers) {
		win.document[lay].document.write(txt);
		win.document[lay].document.close();
	}
	else if (win.document.getElementById) {
		over = win.document.getElementById(lay);
		range = win.document.createRange();
		range.setStartBefore(over);
		domfrag = range.createContextualFragment(txt);
		while (over.hasChildNodes()) {
			over.removeChild(over.lastChild);
		}
		over.appendChild(domfrag);
	}
}

function getlayer(lay,win) {
	if(!win) win = window;
	if (win.document.all) {
		return win.document.all[lay];
	}
	else if (win.document.layers && win.document[lay]) {
		return win.document[lay];
	}
	else if (win.document.getElementById) {
		return win.document.getElementById(lay);
	}
}


function selectOptionValue(selectBox, value)
{
	for(var i = 0; i < selectBox.length; i++)
	{
		if(selectBox.options[i].value == value)
		{
			selectBox.selectedIndex = i;
			return;
		}
	}
}

function containsOption(select, value) 
{
	var i;
	for (i=0; i < select.options.length; i++) {
		if (select.options[i].value === value) 
		{
			return true;
		}
	}
	return false;
};

function indexOfOption(select, value) 
{
	var i;
	for (i=0; i < select.options.length; i++) {
		if (select.options[i].value === value) 
		{
			return i;
		}
	}
	return -1;
};

function resetOptions(select) 
{
	for (var i=0; i < select.options.length; i++) {
		select.options[i].selected = false;
	}
};

function getOptionValue(formField)
{
	if(formField.selectedIndex)
	{
		return formField.options[formField.selectedIndex].value;
	}
	else
	{
		return "";
	}
}

if(!Array.indexOf){
    Array.prototype.indexOf = function(obj){
        for(var i in this){
            if(this[i]==obj){
                return i;
            }
        }
        return -1;
    }
}

function removeAt(array, index)
{
	if(!array[index]) return;
	if(array.length == 1)
	{
		alert('empty array');
		return new Array();
	}
	var newArr = new Array(array.length - 1);
    for(var i in array){
		if(typeof(array[i]) != 'function' && i != index)
		{
			newArr.push(array[i]);
		}
    }
    return newArr;
}

function isset(param)
{ 
	return (typeof(param)!='undefined' && param!==null);
}


function printArray(array)
{
	var first = true;
	var str = '';
	for(var key in array)
	{
		if(typeof(array[key]) != 'function')
		{
			if(first) first = false;
			else
			{
				str += "\n";
			}
			str += "["+key+"] "+array[key];
		}
	}
}
    
/* END shared functions */



/* START STRING FUNCTIONS */

// String.trim()
// Remove whitespace from the beginning and end of a string.
//  returns: void
String.prototype.trim = function(){
  var  str = this.replace(/^\s\s*/, ''),
    ws = /\s/,
    i = str.length;
    while (ws.test(str.charAt(--i)));
  return str.slice(0, i + 1);
}

// String.isEmail()
// Check whether a string represents a plausible email address.
//  returns: TRUE if the string is a plausible email address; otherwise FALSE.
String.prototype.isEmail = function (){
   var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
   return reg.test(this);
}

STR_PAD_LEFT = 1;
STR_PAD_RIGHT = 2;
STR_PAD_BOTH = 3;

// String.pad()
// Pad a string to a given length with a particular character.
//  returns: the padded string.
String.prototype.pad = function(len, pad, dir) {
				 
	if (typeof(len) == "undefined") { var len = 0; }
	if (typeof(pad) == "undefined") { var pad = ' '; }
	if (typeof(dir) == "undefined") { var dir = STR_PAD_RIGHT; }
 
	var str = this;
	if (len + 1 >= str.length) {
 
		switch (dir){
 
			case STR_PAD_LEFT:
				str = Array(len + 1 - str.length).join(pad) + str;
			break;
 
			case STR_PAD_BOTH:
				var right = Math.ceil((padlen = len - str.length) / 2);
				var left = padlen - right;
				str = Array(left+1).join(pad) + str + Array(right+1).join(pad);
			break;
 
			default:
				str = str + Array(len + 1 - str.length).join(pad);
			break;
 
		} // switch
 
	}
 
	return str;
 
}

// String.lpad()
// Left pad a string to a given length with a particular character.
//  returns: the left-padded string.
String.prototype.lpad = function(len, pad) {
	return this.pad(len, pad, STR_PAD_LEFT);
}

// String.rpad()
// Right pad a string to a given length with a particular character.
//  returns: the right-padded string.
String.prototype.rpad = function(len, pad) {
	return this.pad(len, pad, STR_PAD_RIGHT);
}

/* END STRING FUNCTIONS */



/* START authentication functions */


function loginAsync(siteId, login, password) 
{
	new Ajax.Request(appdir + getSlash() + 'Login.aspx', {
		method: 'post',
		parameters: "site="+siteId+"&login="+login+"&password="+password,
		onComplete: function(response)
		{
			if(response.responseText=="OK")
			{
				top.location.reload();
			}
			else
			{
				alert(response.responseText);
			}
		}
	});
	return;
}

function logoutAsync(siteId, login, password) 
{
	new Ajax.Request(appdir + getSlash() + 'Logout.aspx', {
		method: 'post',
		parameters: "site="+siteId,
		onComplete: function(response){
			
			if(response.responseText=="OK")
			{
				top.location.reload();
			}
			else
			{
				alert(response.responseText);
			}
		}
	});
	return;
}

/* END authentication functions */


/* START price functions */

function loadProductPrice(sku, siteId, layer, action){
	var slash = getSlash();
	script = 'Price'
	if(!action)
	{
		action = "/Full";
	}
	var file = appdir + slash + 'Price.aspx' + action;
	new Ajax.Request(file, {
		method: 'post',
		parameters: {'site':siteId,'sku':sku},
		onComplete: function(response){
			if(response.responseText!="")
			{
				var parts = getResponseParts(response.responseText);
				var price = parts["values"];
				writetolayer(layer, parts["html"]);
				if(price>0)
				{
					var productAddForm = document.forms["product_form_" + sku];
					productAddForm.elements["price"].value=price;
					enableProductAdd();
				}
			}
		}
	});
}

function loadProductShortPrice(sku, siteId, layer){
	loadProductPrice(sku, siteId, layer, "/Short");
}

/* END price functions */


/* START cart functions */
cartLoaded = false;
function loadMiniCart(siteId, siteRoot, layer){
	cartLoaded = false;
	loadContentAsync(
		'Cart', '/Mini', 
		'site='+siteId+'&siteRoot='+encodeURIComponent(siteRoot), layer, 
		function(response){
			if(response.responseText!="")
			{
				var parts = getResponseParts(response.responseText);
				var values = parts["values"].split(',');
				itemRowCount=parseInt(values[0],10);
				subtotal=parseFloat(values[1]);
				dynamicLayers['cart_insert'] = new Array(1);
				dynamicLayers['cart_insert'][0] = 'cart_insert';
				if(values[2]!="")
				{
					for(var i=2; i < values.length; i++)
					{
						dynamicLayers['cart_insert'][i-1] = values[i];
					}
				}
				writetolayer(layer, parts["html"]);
				cartLoaded = true;
				enableProductAdd();
			}
		}
	);
}

function enableProductAdd()
{
	var productAddForm = getlayer('prod_add_form');
	if(productAddForm.elements["price"].value > 0 && cartLoaded)
	{
		productAddForm.elements["qty"].disabled = '';
		productAddForm.elements["cart_button"].style.color = '#646161';
	}
}

function insertAdjacentElement(layer, where, parsedNode)
{
	switch (where){
	case 'beforeBegin':
		layer.parentNode.insertBefore(parsedNode,layer);
		break;
	case 'afterBegin':
		layer.insertBefore(parsedNode,layer.firstChild);
		break;
	case 'beforeEnd':
		layer.appendChild(parsedNode);
		break;
	case 'afterEnd':
		if (layer.nextSibling) 
			layer.parentNode.insertBefore(parsedNode,layer.nextSibling);
		else layer.parentNode.appendChild(parsedNode);
		break;
	}
}

function insertAdjacentHTML(layer, where, htmlStr)
{
	var r = layer.ownerDocument.createRange();
	r.setStartBefore(layer);
	var parsedHTML = r.createContextualFragment(htmlStr);
	insertAdjacentElement(layer, where, parsedHTML);
}


function insertAdjacentText(layer, where, txtStr)
{
	var parsedText = document.createTextNode(txtStr);
	insertAdjacentElement(layer, where, parsedText);
}

dynamicLayers = new Array(0);

function insertNewLayer(layerName, content, insertPoint, where, ignoreDynamicLayers)
{
	if(!where)
		where = 'afterEnd';

	if(!insertPoint)
		insertPoint = 'new_layer_insert';
	
	var adjacentLayer;
	if(!ignoreDynamicLayers)
	{
		if(!dynamicLayers[insertPoint] || dynamicLayers[insertPoint].length==0)
			dynamicLayers[insertPoint] = Array(insertPoint);
		
		var dynamicLayerList = dynamicLayers[insertPoint];
		adjacentLayer = dynamicLayerList[dynamicLayerList.length - 1];
	}
	else
	{
		adjacentLayer = insertPoint;
	}
	
	if(document.layers)
	{
		document.layers[adjacentLayer].document.layers[layerName] = 
			new Layer('100%', document.layers[adjacentLayer]);
		with(document.layers[layerName])
		{
			visibility = "show";
			document.open();
			document.write(content);
			document.close();
		}
	}
	else
	{
		var parentLayer = getlayer(adjacentLayer);
		var html = 
			"<div id='" + layerName + "'>\n"
			+ content + "\n</div>";
		if(document.all)
		{
			parentLayer.insertAdjacentHTML(where, html);
		}
		else
		{
			insertAdjacentHTML(parentLayer, where, content);
		}
	}
	
	if(!ignoreDynamicLayers)
	{
		dynamicLayers[insertPoint].push(layerName);
	}
}

function getLayerContents(layerName)
{
	var layer = getlayer(layerName);
	if(!layer){
		return '';
	}
	if(document.layers)
	{
		return layer.document.body;
	}
	else if(layer.innerHTML)
	{
		return layer.innerHTML;
	}
	else{
		return '';
	}
}

function arrIndexOf(array, search)
{
	for(var i = 0; i < array.length; i++){
		if(array[i] == search)
			return i;
	}
	return -1;
}

function getSortedAssoc(data)
{
  var result = {};
  for ( var r = 0; r < data.length; r++ ) {
    var info = data[ r ];
    var key  = info[ 0 ];
    if ( !( key in result ) ) {
      result[ key ] = [];
    }
    var ele = result[ key ];
    ele.push( info[ 1 ] );
  }
  var keys = [];
  for ( key in result ) {
    keys.push( key );
  }
  keys.sort();
  return [result, keys];
}

function strReplace(str, search, replace)
{
	var i = 0;
	var newStr = "";
	while(true)
	{
		var j = str.indexOf(search, i);
		if(j == -1)
		{
			newStr += str.substr(i);
			break;
		}
		else
		{
			newStr += str.substring(i, j) + replace;
			i = j + search.length;
		}
	}
	return newStr;
}

function createContentFromTemplate(templateLayerName, parameters)
{
	var template = getLayerContents(templateLayerName);
	return injectParametersIntoHtml(template, parameters);
}

function injectParametersIntoHtml(html, parameters)
{
	var a = getSortedAssoc(parameters);
	var paramData = a[0];
	var paramNames = a[1];
	// processing parameters in reverse alpha order allows us to avoid
	// conflicts with params that have the name that is a substring of another
	// param name
	paramNames.reverse();
	var paramName;
	for(var i = 0; i < paramNames.length; i++)
	{
		paramName = paramNames[i];		
		html = strReplace(html, "$" + paramName, paramData[paramName]);
	}
	return html;
}


function deleteLayer(layerName, insertPoint)
{
	if(!insertPoint)
		insertPoint = 'new_layer_insert';
		
	if(document.layers)
	{
		document.layers[layerName].visibility = "hide";
		delete document.layers[layerName];
	}
	else if(document.all)
	{
		document.all[layerName].style.visibility = "hidden";
		document.all[layerName].innerHTML = "";
		document.all[layerName].outerHTML = "";
	}
	else if(document.getElementById)
	{
		var layer = document.getElementById(layerName);
		layer.parentNode.removeChild(layer);
	}
	
	if(dynamicLayers[insertPoint])
	{
		var idx = arrIndexOf(dynamicLayers[insertPoint], layerName);
		dynamicLayers[insertPoint].splice(idx, 1);
		
		if(dynamicLayers[insertPoint].length == 0)
		{
			delete dynamicLayers[insertPoint];
		}
	}
}

function insertProductRow(name, sku, qty, price)
{
	if (name.length >= 27) 
	{
        	name = name.substring(0, 27);
        	name = name + "...";
    	}
	var content = 
		"<div id='cart_item_" + sku + "'>\n"
		+ createContentFromTemplate(
			'cart_item_template', 
			[
				["item_total", currency(parseFloat(price)*parseInt(qty,10))],
				["name", name],
				["price_c", currency(price)],
				["price", price],
				["qty", qty],
				["sku", sku]
			])
		+ "\n</div>";
	insertNewLayer('cart_item_'+sku, content, 'cart_insert', 'afterEnd', false);
}

function registerCourse(form)
{
	if(form.price.value == ''){
		return;
	}
	writetolayer('cart_view_progress_message', 'adding course to Course Registration form...');
	getlayer('cart_view_progress').style.visibility = 'visible';
	params = formToHash(form);
	new Ajax.Request(appdir + getSlash() + 'Default.aspx/Add', {
		method: 'post',
		parameters: params,
		onComplete: function(response)
		{
			getlayer('cart_view_progress').style.visibility = 'hidden';
			if(!response || response.responseText!="OK")
			{
				alert(response.responseText);
			}
			else
			{
				window.location=appdir + getSlash() + 'Checkout.aspx?site='
					+ form.elements['site'].value + '&siteRoot='
					+ form.elements['siteRoot'].value;
			}
		}
	});
}

function addProduct(form) 
{
	if(form.price.value == '' || !cartLoaded) return;
	writetolayer('cart_view_progress_message', 'adding items to cart...');
	getlayer('cart_view_progress').style.visibility = 'visible';
	params = formToHash(form);
	new Ajax.Request(appdir + getSlash() + 'Default.aspx/Add', {
		method: 'post',
		parameters: params,
		onComplete: function(response)
		{
			getlayer('cart_view_progress').style.visibility = 'hidden';
			if(!response || response.responseText!="OK")
			{
				alert(response.responseText);
			}
			else
			{
				var sku = params.get('sku');
				var qty = params.get('qty');
				var name = params.get('product');
				var price = params.get('price');
				var existingQtyBox = getlayer('qty_'+sku);
				var existingQtyLayer = getlayer('qty_layer_'+sku);
				var existingQty = 0;
				if(existingQtyBox)
				{
					existingQty = parseInt(existingQtyBox.value,10)
					qty = parseInt(qty,10) + existingQty;
					existingQtyBox.value = qty;
					if(existingQtyLayer)
					{
						writetolayer("qty_layer_"+sku, qty, window);
					}
				}
				else
				{
					if(itemRowCount==0)
					{
						getlayer('cart_view_noitems').style.display = 'none';
					}
					itemRowCount = itemRowCount + 1;
					insertProductRow(name, sku, qty, price);
				}
				var floatPrice = parseFloat(price);
				
				subtotal = parseFloat(subtotal) 
					+ ((parseInt(qty,10)-parseInt(existingQty,10))*floatPrice);
				writeSubtotal();
				if(existingQtyBox)
				{
					var rowTotal = parseInt(qty,10)*parseFloat(price);
					writeItemTotal(sku, rowTotal);
				}
			}
		}
	});
}

function formToHash(form){
	var parameters = new Hash();
	var formField;
	for(var i = 0; i < form.length; i++)
	{
		formField = form.elements[i];
		
		switch(formField.type)
		{
			case "radio":
			case "checkbox":
				if(formField.checked)
				{
					parameters.set(formField.name, formField.value);
				}
				break;
			case "text":
			case "textarea":
			case "hidden":
			case "password":
				parameters.set(formField.name, formField.value);
				break;
			case "select-one":
				if(formField.selectedIndex>=0 && formField.selectedIndex<formField.options.length)
				{
					var option = formField.options[formField.selectedIndex];
					parameters.set(formField.name, option.value);
				}
				break;
			case "select-multiple":
				var values = new Array();
				for(var j = 0; j < formField.options.length; j++)
				{
					var option = formField.options[j];
					if(option.selected)
					{
						values[values.length-1] = option.value;
					}
				}
				parameters.set(formField.name, values);
				break;
		}
		
	}
	return parameters;
}

function getChildNodeById(node, id){
	var nodeList = node.childNodes;
	for(var i = 0; i < nodeList.length; i++)
	{
		if(nodeList[i].id == id){
			return nodeList[i];
		}
	}
	return false;
}

function submitValidated(form, callback)
{

	var params = formToHash(form);
	var submitVal;
	var statusLayer = getlayer('cart_view_progress');
	var successLayer = getlayer('success_message_layer');
	
	if(successLayer)
	{
		successLayer.style.display='none';
	}
	if(statusLayer.style.visibility=='hidden')
	{
		writetolayer('cart_view_progress_message', 'Please wait while we process your form...');
		statusLayer.style.visibility = 'visible';
	}
	
	var lastElement = form.elements[form.elements.length-1];
	if(lastElement.type && lastElement.type=='submit')
	{
		lastElement.disabled = true;
	}
	
	new Ajax.Request(form.action, {
		method: 'post',
		parameters: params,
		onComplete: function(response){
			statusLayer.style.visibility = 'hidden';
			var errorLayer = getlayer('error_message_layer');
			var firstline = '';
			var firstNL;
			if(response)
			{
				firstNL = response.responseText.indexOf('\n');
				if(firstNL>-1)
				{
					firstline = response.responseText.substr(0,firstNL);
				}
				else firstline = response.responseText;
			}
			else firstline = "The form processing website is down. Please try back later.";
			var valid = true;
			switch(firstline)
			{
				case "GOTO":
					var newUrl;
					var secondNL = response.responseText.indexOf('\n', firstNL+1);
					if(secondNL>-1)
					{
						newUrl = response.responseText.substr(firstNL+1, secondNL-firstNL-1);
					}
					else{
						newUrl = response.responseText.substr(firstNL+1);
					}
					window.location = newUrl;
					break;
				case "OK": 
					if(successLayer)
					{
						successLayer.style.display='';
					}
					if(callback)
					{
						callback.call(null, form, response);
					}
					break;
				default:
					valid = false;
					writetolayer("error_message", "<li>"+response.responseText.replace(/\n/g,"</li><li>")+"</li>");
					break;
			}
			if(lastElement.type && lastElement.type=='submit')
			{
				lastElement.disabled = false;
			}
			errorLayer.style.display = valid ? 'none' : '';
			if(!valid)
			{
				window.scrollTo(0,errorLayer.offsetTop);
			}
		}
	});
}

function updateQuantities()
{
	var form = document.forms['cart_form'];
	var params = formToHash(form);
	writetolayer('cart_view_progress_message', 'updating item quantities...');
	getlayer('cart_view_progress').style.visibility = 'visible';
	new Ajax.Request(appdir + getSlash() + 'Default.aspx/Update', {
		method: 'post',
		parameters: params,
		onComplete: function(response){
			getlayer('cart_view_progress').style.visibility = 'hidden';
			if(!response || response.responseText != "OK")
			{
				alert(response.responseText);
			}
			else
			{
				updateCartTotalsFromQuantities();
			}
		}
	});
}

function updateCartTotalsFromQuantities()
{
	var form = document.forms['cart_form'];
	var newSubtotal = 0.0;
	var itemCount = 0;
	for(var i = itemRowCount - 1; i > -1; i--)
	{
		var itemLayerName = dynamicLayers['cart_insert'][i];
		var sku = itemLayerName.substr(10);
		var qty = parseInt(form['qty_'+sku].value,10);
		if(qty==0)
		{
			deleteLayer(itemLayerName, 'cart_insert')
			// if deleting the last item from the cart, show the no
			// items in cart message
			if(i==0 && itemCount==0)
			{
				getlayer('cart_view_noitems').style.display = '';
			}
		}
		else
		{
			itemCount++;
			var price = form['price_'+sku].value;
			var newItemTotal = parseFloat(parseInt(qty,10)*parseFloat(price));
			writeItemTotal(sku, newItemTotal);
			newSubtotal = parseFloat(newSubtotal) + parseFloat(newItemTotal);
		}
	}
	subtotal = newSubtotal;
	writeSubtotal();
}

function writeItemTotal(sku, newItemTotal)
{
	writetolayer('cart_item_total_'+sku, currency(newItemTotal));
}

function writeSubtotal()
{
	writetolayer('cart_subtotal', currency(subtotal));
}

function removeProduct(sku)
{
	writetolayer('cart_view_progress_message', 'removing items from cart...');
	removeItem(sku);
}

function removeCourse(sku)
{
	writetolayer('cart_view_progress_message', 'removing course from registration form...');
	removeItem(sku);
}

function removeItem(sku)
{
	var form = document.forms['cart_form'];
	getlayer('cart_view_progress').style.visibility = 'visible';
	new Ajax.Request(appdir + getSlash() + 'Default.aspx/Remove', 
	{
		method: 'post',
		parameters: { 
			'site':form.site.value,
			'sku':sku 
		},
		onComplete: function(response){
			getlayer('cart_view_progress').style.visibility = 'hidden';
			
			if(response.responseText!="OK")
			{
				alert(response.responseText);
			}
			else
			{
				var qty = form.elements['qty_'+sku].value;
				var price = form.elements['price_'+sku].value;
				var rowTotal = parseInt(qty,10)*parseFloat(price);
				deleteLayer('cart_item_'+sku, 'cart_insert');
				itemRowCount = itemRowCount - 1;
				if(itemRowCount==0)
				{
					getlayer('cart_view_noitems').style.display = '';
				}
				subtotal = parseFloat(subtotal) - parseFloat(rowTotal);
				writeSubtotal();
			}
		}
	});
	return;
}

function getResponseParts(responseText)
{
	var results = new Array(2);
	var eol = responseText.indexOf("\n");
	results["values"] = responseText.substr(0, eol);
	results["html"] = responseText.substr(eol + 1);
	return results;
}

/* END cart functions */


/* BEGIN numeric functions */

function currency(amount)
{
	var i = parseFloat(amount);
	if(isNaN(i)) { i = 0.00; }
	var minus = '';
	if(i < 0) { minus = '-'; }
	i = Math.abs(i);
	i = parseInt((i + .005) * 100,10);
	i = i / 100;
	s = new String(i);
	if(s.indexOf('.') < 0) { s += '.00'; }
	if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
	s = minus + s;
	return '$'+s;
}

/* END numeric functions */

runAlerts();
