/**
 * ------------------------------------------------------
 * various functions used by financeit
 * ------------------------------------------------------
 * @version			$Revision: $
 * @modifiedby		$LastChangedBy: $
 * @lastmodified	$LastChangedDate: $
 */

var FINANCE_OPTION_GET_PAID_NOW = 1;
var FINANCE_OPTION_BE_THE_BANK = 2;
var FINANCE_OPTION_BEAT_THE_BANK = 3;
var COST_OF_CAPITAL = 5.000;

var ie = (document.all) ? true : false;
var ns = (document.layers) ? true : false;
var dom = (!document.all && document.getElementById) ? true : false;

/**
 * ------------------------------------------------------
 * preload images
 * ------------------------------------------------------
 */
function preload(imgObj,imgSrc) {
	if (document.images) {
		eval(imgObj+' = new Image()')
		eval(imgObj+'.src = "'+imgSrc+'"')
	}
}

/**
 * ------------------------------------------------------
 * switch an image, multi-browser
 * ------------------------------------------------------
 * todo1 - make other references to img.src use this function
 */
function chgImg(imgField,newImg) {
	if (ns) {eval('document.images[imgField].src = '+newImg+'.src')}
	if (ie) {document[imgField].src = eval(newImg+'.src')}
	if (dom) {document.images[imgField].src = eval(newImg+'.src');}
}

/**
 * ------------------------------------------------------
 * help ie support the drop down menus
 * ------------------------------------------------------
 */
sfHover = function() {
	var sfEls = document.getElementById("navManage").getElementsByTagName("LI");
	for (var i=0; i<sfEls.length; i++) {
		sfEls[i].onmouseover=function() {
			this.className+=" sfhover";
		}
		sfEls[i].onmouseout=function() {
			this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
		}
	}
}

if (document.getElementById("navManage") && window.attachEvent) window.attachEvent("onload", sfHover);

// ====================================================================
//       URLEncode and URLDecode functions
//
// Copyright Albion Research Ltd. 2002
// http://www.albionresearch.com/
//
// You may copy these functions providing that 
// (a) you leave this copyright notice intact, and 
// (b) if you use these functions on a publicly accessible
//     web site you include a credit somewhere on the web site 
//     with a link back to http://www.albionresarch.com/
//
// If you find or fix any bugs, please let us know at albionresearch.com
//
// SpecialThanks to Neelesh Thakur for being the first to
// report a bug in URLDecode() - now fixed 2003-02-19.
// ====================================================================

function URLEncode(plaintext) {
	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz"/* +
					"-_.!~*'()"*/;					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var encoded = "";
	for (var i = 0; i < plaintext.length; i++ ) {
		var ch = plaintext.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for

	return encoded;
};


function URLDecode(encoded)
{
   // Replace + with ' '
   // Replace %xx with equivalent character
   // Put [ERROR] in output if %xx is invalid.
   var HEXCHARS = "0123456789ABCDEFabcdef"; 
   var plaintext = "";
   var i = 0;
   while (i < encoded.length) {
       var ch = encoded.charAt(i);
	   if (ch == "+") {
	       plaintext += " ";
		   i++;
	   } else if (ch == "%") {
			if (i < (encoded.length-2) 
					&& HEXCHARS.indexOf(encoded.charAt(i+1)) != -1 
					&& HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 ) {
				plaintext += unescape( encoded.substr(i,3) );
				i += 3;
			} else {
				alert( 'Bad escape combination near ...' + encoded.substr(i) );
				plaintext += "%[ERROR]";
				i++;
			}
		} else {
		   plaintext += ch;
		   i++;
		}
	} // while
   return plaintext;
};

// This code was written by Tyler Akins and has been placed in the
// public domain.  It would be nice if you left this header intact.
// Base64 code from Tyler Akins -- http://rumkin.com

//JMB NOTE - I've changed the standard / character to a ~ to make this url safe

String.prototype.base64_encode=function(){
   var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+~=";
   var output = "";
   var chr1, chr2, chr3;
   var enc1, enc2, enc3, enc4;
   var i = 0;

   do {
      chr1 = this.charCodeAt(i++);
      chr2 = this.charCodeAt(i++);
      chr3 = this.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
         enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
         enc4 = 64;
      }

      output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + 
         keyStr.charAt(enc3) + keyStr.charAt(enc4);
   } while (i < this.length);
   
   return output;
}

String.prototype.base64_decode=function(){
   var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+~=";
   var output = "";
   var chr1, chr2, chr3;
   var enc1, enc2, enc3, enc4;
   var i = 0;

   // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
   var input = this.replace(/[^A-Za-z0-9\+\/\=]/g, "");
   if (input.length<4)
      return ''; //jmb - added to prevent wacky null characters

   do {
      enc1 = keyStr.indexOf(input.charAt(i++));
      enc2 = keyStr.indexOf(input.charAt(i++));
      enc3 = keyStr.indexOf(input.charAt(i++));
      enc4 = keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
         output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
         output = output + String.fromCharCode(chr3);
      }
   } while (i < input.length);

   return output;
}

// number formatting function
// copyright Stephen Chapman 24th March 2006, 10th February 2007
// permission to use this function is granted provided
// that this copyright notice is retained intact

function formatNumber(num,dec,thou,pnt,curr1,curr2,n1,n2) {var x = Math.round(num * Math.pow(10,dec));if (x >= 0) n1=n2='';var y = (''+Math.abs(x)).split('');var z = y.length - dec; if (z<0) z--; for(var i = z; i < 0; i++) y.unshift('0');y.splice(z, 0, pnt); while (z > 3) {z-=3; y.splice(z,0,thou);}var r = curr1+n1+y.join('')+n2+curr2;return r;}

/**
 * ------------------------------------------------------
 * format currency
 * ------------------------------------------------------
 */
function formatCurrency(num,raw) {
	if (raw == undefined)
		raw = false;
	num = num.toString().replace(/\$|\,/g,'');
	if(isNaN(num))
		num = "0";
	sign = (num == (num = Math.abs(num)));
	num = Math.floor(num*100+0.50000000001);
	cents = num%100;
	num = Math.floor(num/100).toString();
	if(cents<10)
		cents = "0" + cents;
	if (!raw) {
		for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
			num = num.substring(0,num.length-(4*i+3))+','+
		num.substring(num.length-(4*i+3));
	}
	if (raw) {
		rtnval = (num + '.' + cents);
	} else {
		rtnval = (((sign)?'':'-') + '$' + num + '.' + cents);
	}
	return rtnval;
}

/**
 * ------------------------------------------------------
 * format percentage
 * ------------------------------------------------------
 */
function formatPercent(num) {
	if (num == undefined)
		num = "0";
	if(isNaN(num))
		num = "0";
	num *= 100;
	num = Math.round(num*100,3)/100 + .001;
	num = num.toString();
	num = num.substr(0,num.length-1);
	return num;
}

/**
 * ------------------------------------------------------
 * extract a field from a querystring
 * ------------------------------------------------------
 */
function getURLParam(name,qs) {
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( qs );
  if( results == null )
    return '';
  else
    return results[1];
}

/**
 * ------------------------------------------------------
 * trim whitespace from the ends of a string
 * ------------------------------------------------------
 */
function trimString (str) {
	return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
}

/**
 * ------------------------------------------------------
 * remove comma and dollar sign , $ from numeric values
 * ------------------------------------------------------
 * other characters will be caught by isNumeric
 */
function stripNum(v) {
	return(v.replace(/[\,\$]/g, ''));
}

/**
 * ------------------------------------------------------
 * strip a string of all but the specified characters
 * ------------------------------------------------------
 */
function stripField(id,okchars) {
	var regex = new RegExp( '[^'+okchars+']','g' );
	$(id).value = $(id).value.replace(regex, '');
	flag = false;
	validating = false;
	$(id).focus();
}

/**
 * ------------------------------------------------------
 * check if a string is numeric
 * ------------------------------------------------------
 */
function isNumeric(v) {
	myRegExp = /^[0-9\.]*$/;
    return(myRegExp.test(v));
}

/**
 * ------------------------------------------------------
 * make a field autotab to the next field in line when 
 * it contains as many characters as field.length
 * ------------------------------------------------------
 */
function makeAutoTab(field) {
	Event.observe(field,'keypress', function() {tabNext($(field),'down');});
	Event.observe(field,'keyup', function() {tabNext($(field),'up');});
}

var data_length=0;
/**
 * ------------------------------------------------------
 * keypress event for autotab
 * ------------------------------------------------------
 */
function tabNext(obj,event) {
	if (event == "down") {
		data_length=obj.value.length;
	} else if (event == "up") {
		if (obj.value.length != data_length) {
			data_length=obj.value.length;
			if (data_length == obj.maxLength) {
				obj.next().focus();
			}
		}
	}
}
 
/**
 * ------------------------------------------------------
 * add a load event, without overwriting the current one
 * ------------------------------------------------------
 */
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

/**
 * ------------------------------------------------------
 * check if an object is an array
 * ------------------------------------------------------
 */
function isArray(obj) {
   if (obj.constructor.toString().indexOf("Array") == -1)
      return false;
   else
      return true;
}

/**
 * ------------------------------------------------------
 * copy text to the clipboard
 * ------------------------------------------------------
 */
function copyToClipboard(text2copy) {
  if (window.clipboardData) {
    window.clipboardData.setData("Text",text2copy);
  } else {
    var flashcopier = 'flashcopier';
    if(!document.getElementById(flashcopier)) {
      var divholder = document.createElement('div');
      divholder.id = flashcopier;
      document.body.appendChild(divholder);
    }
    document.getElementById(flashcopier).innerHTML = '';
    var divinfo = '<embed src="/css/_clipboard.swf" FlashVars="clipboard='+escape(text2copy)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
    document.getElementById(flashcopier).innerHTML = divinfo;
  }
}

/**
 * ------------------------------------------------------
 * call the server to get the payment for the given loan terms
 * ------------------------------------------------------
 * callback is the function that will be called with the result as a parameter
 * todo3 - this shouldn't have to use an eval statement
 */
var a_bak = 0;
var n_bak = 0;
var p_bak = 0;
function getPaymentAJAX(loan_amount,term,item_actual_price,callback) {
	if ((loan_amount != a_bak) || (term != n_bak) || (item_actual_price != p_bak)) {
		a_bak = loan_amount;
		n_bak = term;
		p_bak = item_actual_price;
		if (typeof(extra)=='undefined')
			extra = '';
		else
			extra = '/' + extra
		eval("new Ajax.Request(secure_url('offer/get_payment/'+loan_amount+'/'+term+'/'+item_actual_price), {method:'post', asynchronous:false, onSuccess:function(t,json){"+callback+"(t.responseText,json);}});");
	}
}

/**
 * ------------------------------------------------------
 * call the server to get the loan value for the given loan terms
 * ------------------------------------------------------
 * callback is the function that will be called with the result as a parameter
 * todo3 - this shouldn't have to use an eval statement
 */
function getLoanValueAJAX(a,n,p,callback) {
	eval("new Ajax.Request(secure_url('offer/get_value/'+a+'/'+n+'/'+p), {method:'post', asynchronous:false, onSuccess:function(t,json){"+callback+"(t.responseText,json);}});");
}

/**
 * ------------------------------------------------------
 * calculate loan payment with javascript
 * ------------------------------------------------------
 * the AJAX version above is preferable since it keeps all the calculations on our servers
 */
function getPayment(a,n,p) {
	//getPayment(principal,term,apr)
	/* Calculates the monthly payment from annual percentage
	   rate, term of loan in months and loan amount. **/
	var acc=0;
	var base = 1 + p/1200;
	for (i=1;i<=n;i++) 
		{ acc += Math.pow(base,-i); }
	//alert(a + ' - ' + n + ' - ' + p + ' - ' + acc + ' - ' + base);
	return a/acc;
}

/**
 * ------------------------------------------------------
 * calculate loan value with javascript
 * ------------------------------------------------------
 * the AJAX version above is preferable since it keeps all the calculations on our servers
 */
function getLoanValue(a,n,p) {
	ret = amortCalc(a,p,n);
//	return(ret['total_pmts']);
	return(ret);
}

/**
 * ------------------------------------------------------
 * amortization calculator
 * ------------------------------------------------------
 * only used by getLoanValue which shouldn't be being used anymore
 */
function amortCalc(P,I,N) {
	J = I/(12*100);    // Monthly interest in decimal form
	
    not_zero = (1 - Math.pow((1 + J), -N));
    if(not_zero>0) {
    	M = P * (J/not_zero );    // Monthly Payment
    }else {
    	M = P * (1/N);    // Monthly Payment for zero interest
    }
	
	M = Math.round(M+.005,2);
	
	Q = P;              // Set balance to principal
	H = 0;               // Set cumulative Interest to 0;
	i = 0;               // Month counter
	HT = 0;
	MT = 0;
	tpmt = 0;
	
//	ret['payment'] = M;
//	ret['schedule'] = array();
	while(Q > 0){
	    H = Math.round((P * J)+.005,2);    // Current Monthly Interest
	    if (M > P+H) M = P+H; // correct for final month's inexact payment due to rounding errors
	    C = M - H;     // Monthly principal
	    Q = P - C;     // New balance
	    HT += H;        // Cumulative Interest Payments
	    MT += M;        // Cumulative Monthly Payments
	    //not using this stuff currently but we might as well keep it here for reference
//	    ret['schedule'][i] =array('month_number'=>++i,
//	    							PHP->'payment_date'=>date('Y-m-d', mktime(0, 0, 0, date('m',$startDate)+$i , 15, date('Y',$startDate))),
//	    							'payment'=>C + H,
//	    							'principal'=>C,
//									'interest'=>H,
//									'cum_interest'=>HT,
//									'cum_payments'=>MT,
//									'balance'=>Q);
	    if(P == Q){
//			throw new Exception("Balance didn't decrease.");
//			break;
			return(0);
	    }
	    P = Q;          // Reset Principal to new balance
	}
//	ret['total_pmts'] = MT;

//	return(ret);
	return(MT);
}

/**
 * ------------------------------------------------------
 * get the checked value from a radio list
 * ------------------------------------------------------
 */
function getCheckedValue(radioObj) {
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(radioLength == undefined)
		if(radioObj.checked)
			return radioObj.value;
		else
			return "";
	for(var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return "";
}

var alertAnchor;
/**
 * ------------------------------------------------------
 * modal / lightbox alert
 * ------------------------------------------------------
 */
function modal_alert(txt, callback) {
	// create an anchor object if there isn't one already
	if (!alertAnchor) {
		alertAnchor = document.createElement('A');
	}
	
	if (!callback) callback = '';
	
	txt = '<p class="head" style="text-align:right;"><a href="javascript:;" onclick="Control.Modal.close();'+callback+'"><img src="' + secure_url('img/icon_x_sm.gif') + '" border="0"> CLOSE</a></p><p style="padding-top:12px;"><b>' + txt + '</b></p><br />';
	x = new Control.Modal(alertAnchor,{
						contents: txt
						});
	closeOverlay();
	x.open();
}

/**
 * ------------------------------------------------------
 * modal / lightbox confirm
 * ------------------------------------------------------
 */
function modal_confirm(txt, callbackYes, callbackNo) {
	
	if (!callbackYes) callbackYes = "parent.Control.Modal.close()";
	if (!callbackNo) callbackNo = "parent.Control.Modal.close()";
	
	// create an anchor object if there isn't one already
	if (!alertAnchor) {
		alertAnchor = document.createElement('A');
	}
	txt = '<p class="head" style="text-align:right;"><a href="javascript:;" onclick="parent.Control.Modal.close();"><img src="/img/icon_x_sm.gif" border="0"> CLOSE</a></p><p style="padding-top:12px;"><b>' + txt + '</b></p><p style="padding: 0px 0px 10px 255px;"><b><input onclick="parent.Control.Modal.close();' + callbackYes + ';" type="button" value="Yes" /><input onclick="' + callbackNo + '" type="button" value="No" style="margin: 0px 0px 0px 10px;"/></b></p>';
	x = new Control.Modal(alertAnchor,{
						contents: txt
						});
	closeOverlay();
	x.open();
}

/**
 * ------------------------------------------------------
 * set overlay
 * ------------------------------------------------------
 * used to ghost the screen while waiting for AJAX feedback, etc
 */
function setOverlay(){
	if (!$('pageOverlay')) {
		pageOverlay = document.createElement('DIV');
		pageOverlay.id = 'pageOverlay';
		pageOverlay.style.display = 'none';
		document.body.appendChild(pageOverlay);
	}
	$('pageOverlay').style.position = 'absolute';
	$('pageOverlay').style.align = 'center';
	$('pageOverlay').style.top = '0px';
	$('pageOverlay').style.left = '0px';
	$('pageOverlay').style.height = Math.max(document.body.scrollHeight,(self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0)) + 'px';
	$('pageOverlay').style.width = Math.max(document.body.scrollWidth,(self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0)) + 'px';
	$('pageOverlay').style.backgroundColor = '#000000';
	$('pageOverlay').style.zIndex = '123456';
	$('pageOverlay').style.opacity = .40;
	$('pageOverlay').style.filter = 'alpha(opacity=40)';
	//$('pageOverlay').innerHTML = '<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><img src="/img/indicator.gif" width="200" height="200" style="display: block;margin-top: auto;margin-bottom: auto;margin-left: auto;margin-right: auto" />';
	$('pageOverlay').style.display = 'inline';
}

/**
 * ------------------------------------------------------
 * close overlay
 * ------------------------------------------------------
 */
function closeOverlay(){
	if ($('pageOverlay'))
		$('pageOverlay').style.display = 'none';
}

/**
 * ------------------------------------------------------
 * remove an image from the image upload form
 * ------------------------------------------------------
 */
function removeImage(div,ext) {
	var par = document.getElementById('upl_images');
	var removeme = document.getElementById(div);
	par.removeChild(removeme);
	new Ajax.Request(secure_url('upload/delimg/' + ext), {asynchronous:true});
}

/**
 * ------------------------------------------------------
 * remove an image from the modified image upload form
 * ------------------------------------------------------
 * the _one versions are optimized for a single image
 */
function removeImage_one(div,ext) {
	removeImage(div,ext)
	$('upl_iframe').style.display = 'block';
	$('upl_noimages').style.display = '';
	$('upl_images').style.display = 'none';
	// from offsiteoffer and offsiteofferterms
	//$('upl_iframe').style.display = 'inline';
	//$('upl_noimages').style.display = 'inline';
	if ($('itemimage')) {
		$('itemimage').src = '';
		$('itemimage').style.width = '95px';
		$('itemimage').style.height = '71px';
		$('itemimage').src = '/img/no_image_available.jpg';
	}
	
}

/**
 * ------------------------------------------------------
 * display the image just scraped from another site
 * ------------------------------------------------------
 */
function process_img(img) {
	// this may only work on firefox - maybe just needs more tweaking and playing with contentdoc / contentwindow for other browsers
	
	// if there's already an image, remove it then try again
	if ($('linkRemoveOne')) {
		$('linkRemoveOne').onclick();
		setTimeout(function () {process_img(img)},1);
		return;
	}
	
	var num = $('upl_iframe').getElementsByTagName('iframe').length - 1;
	var iframe = $('upl_iframe').getElementsByTagName('iframe')[num];

	iframe.contentDocument.iform.scraped.value = img;
	iframe.contentWindow.upload();
//	if ($('itemimage')) {
//		myImage = new Image()
//		myImage.src = img
//		$('itemimage').src = img;
//		$('itemimage').width = myImage.width + 'px';
//		$('itemimage').height = myImage.height + 'px';
//	}
}

/**
 * ------------------------------------------------------
 * AJAX-safe javascript include
 * ------------------------------------------------------
 */
function include_js(file,exec) {
    var html_doc = document.getElementsByTagName('head')[0];
    var attached = html_doc.getElementsByTagName('script');
    // if there are already other scripts attached,
    // check and see if the new one is among them
    // and if so, delete it
    if (attached)
	    for (i in attached)
    		if (attached[i])
	    		if (attached[i].src)
		    		if (attached[i].src.indexOf(file)>0)
		    			html_doc.removeChild(attached[i]);
		    			
	// attach script file
    var js = document.createElement('script');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', file);
    if (exec) {
		js.onreadystatechange = function () {
			if (this.readyState == 'complete') {
				setTimeout(exec,100);
			}
		}
		js.onload = function() {setTimeout(exec,100);};
    }
	html_doc.appendChild(js);
	
	return false;
}

/**
 * ------------------------------------------------------
 * sets tabNumber as the currently visible tab
 * ------------------------------------------------------
 * expects tabs to be called Page_1tabSet through Page_#tabSet with no gaps
 * as it sets each tab, it checks for a function called Page_#tabSet_callback(tab) and calls it if it exists
 * also checks for elements with id="tabBG_#tabSet" and switches its class from *_on to *_off as appropriate
 */
function selectTab(tabNumber,tabSet) {
	var i = 1;
	if (!tabSet) tabSet = '';
	while ($('Page_' + i + tabSet)) {
		// set page visible / invisible
		$('Page_' + i + tabSet).style.display = (i==tabNumber)?'block':'none';
		
		// set tab background if it exists
		// and ends with the prevStr [_on|_off]
		if ($('tabBG_' + i + tabSet)) {
			if (i==tabNumber) {
				var regex = new RegExp( '\_off$','g' );
				var newStr = '_on';
			} else {
				var regex = new RegExp( '\_on$','g' );
				var newStr = '_off';
			}
			if ($('tabBG_' + i + tabSet).className.match(regex)) {
				$('tabBG_' + i + tabSet).className = 
					$('tabBG_' + i + tabSet).className.replace(regex, newStr);
			}
		}
		
		// attempt to run the callback for the current tab
		eval('func = window.Page_' + i + tabSet + '_callback;');
		if (func) {
			func(tabNumber);
		}
		i ++;
	}
}

var lightbox_login = '';
/**
 * ------------------------------------------------------
 * show the login form in a lightbox
 * ------------------------------------------------------
 */
function ShowLogin(context,callback,callbackfunction) {
	closeOverlay();
	// create an anchor object if there isn't one already
	if (!$('lightbox_login')) {
		var new_elem = document.createElement('A');
		new_elem.id = 'lightbox_login';
		new_elem.style.display = 'none';
		document.body.appendChild(new_elem);
	}
	
	// save the calling context so we can try again after the login is processed
	reCall_context = context;
	reCall_callback = callback;
	reCall_callbackfunction = callbackfunction;
	
	context = context.base64_encode();
	callback = callback.base64_encode();
	serialized_form = Form.serialize($('mainform')).base64_encode();
	saveCallback(context + "/" + callback + "/" + serialized_form);
	
	$('lightbox_login').href = '/login/frame';
	lightbox_login = new Control.Modal($('lightbox_login'),{
                												iframe: true,
																width: 440,
																height: 400,
																afterClose: function() {Submitted = false;}
															});
	lightbox_login.open();
}

/**
 * ------------------------------------------------------
 * callback after login
 * ------------------------------------------------------
 * after a login attempt completes, retry the original form post
 *  using the values stored during the last form post attempt
 */
function LoginCallback() {
	Control.Modal.close();
	//if (reCall_callbackfunction) {
		Submitted = false;
		FormSubmit(reCall_context,reCall_callback,reCall_callbackfunction);
//	} else {
//		$('mainform').submit();
//	}
}

var Submitted = false;
var reCall_context = '';
var reCall_callback = '';
var reCall_callbackfunction = '';
/**
 * ------------------------------------------------------
 * generic form submit
 * ------------------------------------------------------
 * context = buy, sell, buying_power, or none
	 * none does only error checking
	 * the following check for login status as well as:
	 * buy checks for a buying profile
	 * sell checked for a seller profile
	 * buying_power checks for a minimal buying power profile
 * This is documented at http://trac.financeit.com/attachment/wiki/technology/specs/financeit/CallbackSystem
 */
function FormSubmit(context,callback,callbackfunction) {
	// don't bother if we're already submitting
	if (Submitted) 
		return;
		
	if (callbackfunction == undefined) {
		// no callback defined, use the generic one
		callbackfunction = 'FormSubmit_cb';
	}

	// try again in a moment if we're processing ajax still
	if (Ajax.activeRequestCount) {
		setTimeout("FormSubmit('" + context + "','" + callback + "','" + callbackfunction + "');",100);
		return;
	}
	
	// check if the form passes validation
	var canSub = (!window.canSubmit || typeof validationRules == 'undefined');
	if (!canSub) canSub = canSubmit();
	
	// form passes validation and it is not in the middle of a submit
	if (canSub) {
		Submitted = true;
		if (context!='none') {
			// save these for when we try to resubmit
			reCall_context = context;
			reCall_callback = callback;
			reCall_callbackfunction = callbackfunction;
			
			//the following settimeout / evalscript is to deal with a firefox error:
			//http://www.fleegix.org/articles/2006/10/21/xmlhttprequest-and-0x80004005-ns_error_failure-error
			evalJS = "new Ajax.Request(secure_url('login/status/"+context+"'), {asynchronous:true, onFailure:function(e){alert('Error ' + t.status + ' -- ' + t.statusText);}, onSuccess:function(t){"+callbackfunction+"(t,'"+callback+"');}});";
			setTimeout(evalJS,1);
		} else {
			eval(callbackfunction + '();');
		}
	}
}

/**
 * ------------------------------------------------------
 * cancel login, close lightbox
 * ------------------------------------------------------
 */
function CancelLogin() {
	Submitted = false;
	Control.Modal.close();
}

/**
 * ------------------------------------------------------
 * close signup confirmation lightbox
 * ------------------------------------------------------
 */
function CloseSignupConfirm() {
	Submitted = false;
    Control.Modal.close();
}

/**
 * ------------------------------------------------------
 * truncate and add elipses if necessary
 * ------------------------------------------------------
 */
function eltrunc(str, segLength) {
	if (str.length>segLength)
		str = str.substr(0,segLength-3) + '...';
	return (str);
}

/**
 * ------------------------------------------------------
 * nicely split a string to lengths no longer than segLength
 * trying to honor space characters
 * and return segment seg
 * ------------------------------------------------------
 */
function split(s, segLength, seg) {
    if (s == '') {
        return '';
    } else {
    	var i=0;
    	var xit = false;
        for (i = segLength; i>=0 && !xit;i--) {
            if ((" .,;:'\"/?!@#$%^&*()~`-=\_+|{}[]<>\t\n").indexOf(s.substr(i, 1))>=0) {
                xit = true;
            }
        }
        if (i == 0) i = segLength;
        if (seg == 1) {
            return (s.substr(0,i+1));
        } else {
        	i++;
            if ((" \t\n").indexOf(s.substr(i, 1))>=0) {
            	//document.write(seg + '-XX1-' + s.substr(i + 1)+'<BR>');
                return(split(s.substr(i + 1), segLength, seg - 1));
            } else {
            	//document.write(seg + '-XX2-' + s.substr(i)+'<BR>');
                return(split(s.substr(i), segLength, seg - 1));
            }
        }
    }
}

/**
 * ------------------------------------------------------
 * split a long string and then rejoin with <br /> tags
 * ------------------------------------------------------
 */
function sploin(s, segLength, concat) {
	var seg = 1;
	var s_out = '';
	var s_this = '';
	if (!concat) concat = '<br />';
	while (s_this = split(s,segLength,seg++)) s_out += ((s_out != '')?concat:'') + s_this;
	return (s_out);
}

/**
 * ------------------------------------------------------
 * parse a video url to its simplest form
 * ------------------------------------------------------
 * equivalent php function is in listing_model.php
 */
function clean_video_url(url) {
	var myRegExp = /youtube\.com/;
    if (myRegExp.test(url)) {
    	myRegExp = /.*\[\?\/]v[=\/]([^&]*).*/;
    	var results = myRegExp.exec( url );
		if( results )
			url = 'http://www.youtube.com/v/' +  results[1];
	}
	return(url);
}

/**
 * ------------------------------------------------------
 * scroll the browser window to show element with specified id
 * ------------------------------------------------------
 */
function scrollToId(theId) {
	var theElement = $(theId);
	var selectedPosX = 0;
	var selectedPosY = 0;
	
	while(theElement != null) {
		selectedPosX += theElement.offsetLeft;
		selectedPosY += theElement.offsetTop;
		theElement = theElement.offsetParent;
	}
	
	window.scrollTo(selectedPosX,selectedPosY);
}

/**
 * ------------------------------------------------------
 * secure url based on regex
 * ------------------------------------------------------
 */
var httpRegex = new RegExp('^https?\:\/\/');

function secure_url(url) {
	if (url == 'sessioncheck') {
		url = appRoot + url;
		url = url.replace(httpRegex,document.location.protocol + '//');
		//alert(url);
		return(url);
	} else if (USE_SSL) {
		secure = shouldBeSecured('/'+url)
		protocol = secure?'https://':'http://';
		url = appRoot + url;
		url = url.replace(httpRegex,protocol);
		//alert(url);
		return(url);
	} else {
		return(appRoot + url);
	}
}

function shouldBeSecured(url) {
	var res = null;
	if (USE_SSL) {
		// some paths are just never secured
		if ((url.substring(0,5)=='/img/') || (url.substring(0,4)=='/js/') || (url.substring(0,5)=='/css/'))
			return(false);
		
		// check each item for a regex match with the uri
		// return false on a match
		ambivalentPages.each(function(key) {
				r = new RegExp(key);
				if (r.test(url)) {
					res = (document.location.protocol == 'https:');
					throw $break;
				}
			});
		if (res != null) return(res);
		
		// check each item for a regex match with the uri
		// return false on a match
		unsecuredPages.each(function(key) {
				r = new RegExp(key);
				if (r.test(url)) {
					res = false;
					throw $break;
				}
			});
		if (res != null) return(res);
		
		// check each item for a regex match with the uri
		// return true on a match
		securedPages.each(function(key) {
				r = new RegExp(key);
				if (r.test(url)) {
					res = true;
					throw $break;
				}
			});
		if (res != null) return(res);
	}
	// we're still here, just use the current protocol
	return(document.location.protocol == 'https:');
}

/**
  * ------------------------------------------------------
  * resizing the modal box
  * ------------------------------------------------------
  */
function resizeModal(width,height){
	$('modal_container').style.width = width+'px';
	$('modal_container').style.height = height+'px';
}

/**
 * ------------------------------------------------------
 * simulate isset function
 * ------------------------------------------------------
 */
function isset(variable_name) {
	try {
		if (typeof(eval(variable_name)) != 'undefined')
			if (eval(variable_name) != null)
				return true;
	} catch(e) { }
	
	return false;
}

/**
 * ------------------------------------------------------
 * show the prequalify form on the next page then redirect back here
 * ------------------------------------------------------
 */
function ShowPrequalify(context,callback) {
	closeOverlay();
	context = context.base64_encode();
	callback = callback.base64_encode();
	serialized_form = Form.serialize($('mainform')).base64_encode();
	saveCallback(context + '/' + callback + '/' + serialized_form);	
	document.location = secure_url('member/buying_power');
}

/**
 * ------------------------------------------------------
 * if not authenticated, prompt for authentication
 * ------------------------------------------------------
 */
function PromptForAuthentication(context,callback) {
	closeOverlay();
	encoded_context = context.base64_encode();
	callback = callback.base64_encode();
	serialized_form = Form.serialize($('mainform')).base64_encode();
	saveCallback(encoded_context + '/' + callback + '/' + serialized_form);	
	if(context == 'sell')
	  document.location = secure_url('authentication/seller');
	else
	  document.location = secure_url('authentication');
}

function CloseModalAndRedirect(uri) {
  closeOverlay();
  document.location = uri;
}

function disableEnterKey(e)
{
     var key;

     if(window.event)
          key = window.event.keyCode;     //IE
     else
          key = e.which;     //firefox

     if(key == 13)
          return false;
     else
          return true;
}

function removeCallback() {
  new Ajax.Request('/login/remove_callback', {
      method:'post', 
      parameters:'', 
      asynchronous:true
  });
}

function saveCallback(callback) {
  new Ajax.Request(secure_url('login/save_callback'), {
      method:'post', 
      parameters:'callback=' + callback, 
      asynchronous:true
  });
}

/*var JS_CONSOLE = true;  
// When logging messages with console.log()  
// if user doesn't have Firebug, write them to the DOM instead  
if (typeof console == "undefined" && JS_CONSOLE == true) {  
	// Create an unordered list to display log messages  
//	var logsOutput = document.createElement('ul');  
//	document.getElementsByTagName('body')[0].appendChild(logsOutput);  
	
	// Define console.log() function  
//	console = {  
//		log: function(msg) {  
//			logsOutput.innerHTML += '<li>' + msg + '</li>';  
//		}  
//	};  
	console = {  
		log: function() {} // Do nothing  
	};  
} else if (JS_CONSOLE == false) {  
	console = {  
		log: function() {} // Do nothing  
	};  
}*/