/**
 * CurrencyEditControl.v.0.9.4
 *
 * Transform edit controls into currency edit controls
 *
 * By Hugo Ortega_Hernandez - hugorteg{no_spam}@gmail.com
 *
 * Last version of this code: http://dali.mty.itesm.mx/~hugo/js/currencyeditcontrol/
 *
 * Features:
 *   + Automatic input control conversion with a single attribute
 *     in the 'input' tag or a special 'id' attribute format.
 *   + Format the input as currency automatically.
 *   + User input restricted to valid characters (well, almost).
 *
 * License: GPL (that's, use this code as you wish, just keep it free)
 * Provided as is, without any warranty.
 * Feel free to use this code, but don't remove this disclaimer please.
 *
 * If you're going to use this library, please send me an email, and
 * would be great if you include a photo of your city :)
 * (se habla espa&ntilde;ol)
 *
 * Thanks to Raul Romero for all good sugestions
 *
 *
 *                                        Veracruz & Monterrey, Mexico, 2005.
 */


//-----------------------------------------------------------------------------
// Some parameters for style and behaviour...

CurrencyEditControl.decimalSeparator    = ",";
CurrencyEditControl.decimalQuantity     = 2;
CurrencyEditControl.thousandsSeparator  = ".";
CurrencyEditControl.currencySymbol      = "€"; //"&euro;"//"&pound;"//"&yen;"
CurrencyEditControl.currencySymbolPos   = "l"; //r; //left or rigth
CurrencyEditControl.currSymbolOffsetX   = 0;
CurrencyEditControl.currSymbolOffsetY   = 0;
CurrencyEditControl.autoZeroes          = true; // Set 0.00 if user keeps the field blank

// OK, I hate IE, but many people ask for patches
if (navigator.userAgent.indexOf("MSIE") > 1){
	CurrencyEditControl.currSymbolOffsetX = -1;
	CurrencyEditControl.currSymbolOffsetY = 0;
	// but if document have xhtml dtd, things are differents... :S
	if (document.getElementsByTagName("html")[0].getAttribute("xmlns") != null){
		CurrencyEditControl.currSymbolOffsetX = 9;
		CurrencyEditControl.currSymbolOffsetY = 14;
	}
}


//-----------------------------------------------------------------------------
// Some constants and internal stuff

CurrencyEditControl.currSymWidth    = 20; //px
CurrencyEditControl.paddingTB       = 2;  //px
CurrencyEditControl.paddingLR       = 4;  //px
CurrencyEditControl.editIdPrefix    = "CEC_";
CurrencyEditControl.onSubmitAsigned = false;
CurrencyEditControl.currSymIdPrefix = "CEC_symbol_";
CurrencyEditControl.originalSubmit  = null;

//-----------------------------------------------------------------------------
// The fun

/**
 * Constructor
 */
function CurrencyEditControl()
{
}

/**
 * Search for input controls that will be transformed into CurrencyEditControls
 */
CurrencyEditControl.init = function()
{
	// looking for global parameters:
	
	var objDecimalSep = document.getElementById("CEC_DECIMAL_SEPARATOR");
	if (objDecimalSep) this.decimalSeparator = objDecimalSep.value;
	
	var objDecimalQnty = document.getElementById("CEC_DECIMAL_QUANTITY");
	if (objDecimalQnty) this.decimalQuantity = objDecimalQnty.value;

	var objThousandsSep = document.getElementById("CEC_THOUSANDS_SEPARATOR");
	if (objThousandsSep) this.thousandsSeparator = objThousandsSep.value;

	var objCurrencySymbol = document.getElementById("CEC_CURRENCY_SYMBOL");
	if (objCurrencySymbol) this.currencySymbol = objCurrencySymbol.value;

	var objCurrencySymbolPos = document.getElementById("CEC_CURRENCY_SYMBOL_POS");
	if (objCurrencySymbolPos) this.currencySymbolPos = objCurrencySymbolPos.value;

	var objAutoZeroes = document.getElementById("CEC_AUTO_ZEROES");
	if (objAutoZeroes) this.autoZeroes = (objAutoZeroes.value.toString().toLowerCase() == "true");

	// search for input controls that will be transformed into CurrencyEditControl.
	var inputsLength = document.getElementsByTagName("input").length;
	for (i=0; i<inputsLength; i++){
		if (document.getElementsByTagName("input")[i].type.toLowerCase() == "text"){
			var editctrl  = document.getElementsByTagName("input")[i];
			var cecattr   = editctrl.getAttribute("currencyedit");
			var setEvents = false;
			// if currencyedit pseudo-attribute:
			if (cecattr != null && cecattr == "true"){
				if (editctrl.id){
					if (!this.createCurrencySymbol(editctrl)) continue;
					setEvents = true;
				}
				else{
					alert("Attribute 'id' is mandatory for CurrencyEditControl.");
				}
			}
			// if fomatted id attr:
			else if (editctrl.id && editctrl.id.indexOf(this.editIdPrefix) == 0){
				if (!this.createCurrencySymbol(editctrl)) continue;
				setEvents = true;
			}
			// add the events:
			if (setEvents){
				editctrl.setCurrencyValue = CEC_setCurrencyValue;
				editctrl.getCurrencyValue = CEC_getCurrencyValue;
				editctrl.style.textAlign = "right";
				if (editctrl.value != ""){
					var val = this.reverseFormat(editctrl.value);
					if (val != "" && !isNaN(parseFloat(this.toPointValue(val)))){
						editctrl.value = this.format(val);
						editctrl.setAttribute("currencyvalue", val);
					}
				}
				else{
					editctrl.setAttribute("currencyvalue", "");
				}
				if(editctrl.addEventListener){
					editctrl.addEventListener("blur", CEC_onEditControlBlur, false);
					editctrl.addEventListener("focus", CEC_onEditControlFocus, false);
					editctrl.addEventListener("change", CEC_onEditControlChange, false);
					editctrl.addEventListener("keydown", CEC_onEditControlKeyDown, false);
					editctrl.addEventListener("keyup", CEC_onEditControlKeyUp, false);
				}
				else if (editctrl.attachEvent){
					editctrl.attachEvent("onblur", CEC_onEditControlBlur);
					editctrl.attachEvent("onfocus", CEC_onEditControlFocus);
					editctrl.attachEvent("onchange", CEC_onEditControlChange);
					editctrl.attachEvent("onkeydown", CEC_onEditControlKeyDown);
					editctrl.attachEvent("onkeyup", CEC_onEditControlKeyUp);
				}
				var theForm = editctrl.form;
				if (!this.onSubmitAsigned && theForm){
					this.onSubmitAsigned = true;
					theForm.submitOrig = theForm.submit;
					theForm.submit = CEC_formSubmit;
					if (theForm.addEventListener){
						theForm.addEventListener('submit', CEC_onFormSubmit, false);
					}
					else if (theForm.attachEvent){
						theForm.attachEvent('onsubmit', CEC_onFormSubmit);
					}
				}
			}
		}
	}
}


function CEC_autoInit()
{
	CurrencyEditControl.init();
}

if (window.addEventListener){
	window.addEventListener("load", CEC_autoInit, false);
	window.addEventListener("resize", CEC_onWindowResize, false);
}
else if (window.attachEvent){
	window.attachEvent("onload", CEC_autoInit);
	window.attachEvent("onresize", CEC_onWindowResize);
}


/**
 * Creates the currency simbol layer
 */
CurrencyEditControl.createCurrencySymbol = function(input)
{
	var newid = this.currSymIdPrefix + input.id;
	if (document.getElementById(newid)) return false; // if exists previously....
	var nTop      = getObject.getSize("offsetTop", input);
	var nLeft     = getObject.getSize("offsetLeft", input);
	var currLayer = document.createElement("div");
	currLayer.id  = newid;
	currLayer.setAttribute("inputid", input.id);
	var code = this.currencySymbol;
	document.body.appendChild(currLayer);
	writeLayer(currLayer.id, null, code);
	currLayer.style.zIndex     = 10000;
	currLayer.style.position   = "absolute";
	currLayer.style.textAlign  = "center";
	currLayer.style.width      = this.currSymWidth + "px";
	currLayer.style.top        = nTop + this.currSymbolOffsetY + "px";
	currLayer.className        = "CurrencySymbol";
	
	if (this.currencySymbolPos == "l"){
		currLayer.style.left = (nLeft + this.currSymbolOffsetX) + "px";
		input.style.padding  = this.paddingTB + "px " + this.paddingLR + "px " + this.paddingTB + "px " + this.currSymWidth + "px";
	}
	else{ // "r"
		input.style.padding  = this.paddingTB + "px " + this.currSymWidth + "px " + this.paddingTB + "px " + this.paddingLR + "px";
		currLayer.style.left = (nLeft + input.offsetWidth - this.currSymWidth + this.currSymbolOffsetX) + "px";
	}
	if (input.offsetHeight) currLayer.style.height = (input.offsetHeight-1) + "px";
	currLayer.style.paddingTop = Math.ceil(this.paddingTB/2) + "px";
	return true;
}


/**
 * Key-down event for edit controls
 */
function CEC_onEditControlKeyDown(event){CurrencyEditControl.onEditControlKeyDown(event);}
CurrencyEditControl.onEditControlKeyDown = function(event)
{
	if (event == null) event = window.event;
	var edit = (event.srcElement) ? event.srcElement : event.originalTarget;
	//alert(event.keyCode);
	var kc = event.keyCode;
	if ( kc >= 65 && kc <= 90 ){ // letters
		if (event.stopPropagation) event.stopPropagation();
		if (event.preventDefault) event.preventDefault();
		event.returnValue = false;
		this.cancelKey = true;
		return false;
	}
	 // other symbols (the event is not canceled to verify if it is a separator)
	 // there are some keys with same code, v.gr. "9" and "("... strange...
	else if (!((kc > 48 && kc < 57) || (kc >= 96 && kc <= 105))){
		this.cancelKey = true;
	}
}

/**
 * Key-up event for edit controls
 */
function CEC_onEditControlKeyUp(event){CurrencyEditControl.onEditControlKeyUp(event);}
CurrencyEditControl.onEditControlKeyUp = function(event)
{
	if (event == null) event = window.event;
	var edit = (event.srcElement) ? event.srcElement : event.originalTarget;
	if (this.cancelKey){
		this.cancelKey = false;
		var cv = "";
		var replace = false;
		var val = edit.value.toString();
		var decimalyet = false;
		for(i=0; i<edit.value.length; i++){
			if (!decimalyet && this.decimalSeparator != "." && val.charAt(i) == "."){
				cv += this.decimalSeparator;
			}
			if (!isNaN(parseInt(val.charAt(i))) || val.charAt(i) == this.decimalSeparator && !decimalyet){
				cv += val.charAt(i);
				if (val.charAt(i) == this.decimalSeparator){
					decimalyet = true;
					if (i==0){
						cv = "0" + val.charAt(i);
						replace = true;
					}
				}
			}
			else{
				replace = true;
			}
		}
		if (replace) edit.value = cv;
	}
}


/**
 * Blur event for edit controls
 */
function CEC_onEditControlBlur(event){CurrencyEditControl.onEditControlBlur(event);}
CurrencyEditControl.onEditControlBlur = function(event)
{
	if (event == null) event = window.event;
	var edit = (event.srcElement) ? event.srcElement : event.originalTarget;
	var val = edit.value;
	var nan = isNaN(parseFloat(this.toPointValue(val)));
	if (val != "" && !nan){ // value is ok
		edit.value = this.format(val);
		if (val.indexOf(this.decimalSeparator) < 0) val = val + this.decimalSeparator + this.getZeroesString();
		edit.setAttribute("currencyvalue", val);
		// invoke the onchange event explicity...
		var onchangestr = edit.getAttribute("currencyedit_onchange");
		if (onchangestr){
			onchangestr = onchangestr.replace("this", "document.getElementById('" + edit.id + "')");
			eval(onchangestr);
		}
	}
	else if (val != "" && nan){
		edit.value = "0" + this.decimalSeparator + this.getZeroesString();
		edit.setAttribute("currencyvalue", edit.value);
	}
	else if (val == "" && this.autoZeroes){
		edit.value = "0" + this.decimalSeparator + this.getZeroesString();
		edit.setAttribute("currencyvalue", edit.value);
	}
	else if (val == ""){
		edit.setAttribute("currencyvalue", "");
	}
}


/**
 * On change event
 */
function CEC_onEditControlChange(event){CurrencyEditControl.onEditControlChange(event);}
CurrencyEditControl.onEditControlChange = function(event)
{
	if (event == null) event = window.event;
	var edit = (event.srcElement) ? event.srcElement : event.originalTarget;
	var onchangestr = edit.getAttribute("currencyedit_onchange");
	if (onchangestr){
		onchangestr = onchangestr.replace("this", "document.getElementById('"+edit.id+"')");
		eval(onchangestr);
	}
}


/**
 * Focus event for edit controls
 */
function CEC_onEditControlFocus(event){CurrencyEditControl.onEditControlFocus(event);}
CurrencyEditControl.onEditControlFocus = function(event)
{
	if (event == null) event = window.event;
	var edit = (event.srcElement) ? event.srcElement : event.originalTarget;
	edit.value = edit.getAttribute("currencyvalue");
	edit.select();
}

/**
 * Form's submit event
 */
function CEC_onFormSubmit(event){CurrencyEditControl.onFormSubmit(event);}
CurrencyEditControl.onFormSubmit = function(event)
{
	this.reverseAllInputs();
}

/**
 * Convert all currency edit controls' values to normal float value
 */
CurrencyEditControl.reverseAllInputs = function()
{
	var inputsLength = document.getElementsByTagName("input").length;
	for (i=0; i<inputsLength; i++){
		if (document.getElementsByTagName("input")[i].type.toLowerCase() == "text"){
			var editctrl = document.getElementsByTagName("input")[i];
			var cecattr  = editctrl.getAttribute("currencyedit");
			var reassign = false;
			if (cecattr != null && cecattr == "true"){
				reassign = true;
			}
			else if (editctrl.id && editctrl.id.indexOf(this.editIdPrefix) == 0){
				reassign = true;
			}
			if (reassign && editctrl.value != ""){
				var newval = editctrl.getAttribute("currencyvalue");
				editctrl.value = this.toPointValue(newval);
			}
		}
	}
}

/**
 * Replacement for submit method of the form.
 */
function CEC_formSubmit()
{
	CurrencyEditControl.reverseAllInputs();
	this.submitOrig();
}


/**
 * Window resize event.
 */
function CEC_onWindowResize(event){CurrencyEditControl.onWindowResize(event);}
CurrencyEditControl.onWindowResize = function(event)
{
	this.relocateSymbols();
}


/**
 * Format a value as currency
 */
CurrencyEditControl.format = function(val)
{
	if (val == "") return "";
	var floatVal = parseFloat(this.toPointValue(val));
	if (isNaN(floatVal)) return "0" + this.decimalSeparator + this.getZeroesString();
	var valMoney = floatVal.toFixed(this.decimalQuantity);
	var valSep   = valMoney.toString().split(".");
	var theNum   = valSep[0].toString();
	var theCents = valSep[1].toString();
	var fmt      = new Array();
	var l        = theNum.length;
	var i        = 1;

	for(i=1; i<l+1; i++){
		fmt[i] = theNum.charAt(i-1);
	}
	fmt = fmt.reverse();
	for(i=1; i<l; i++){
		if (i%3 == 0){
			fmt[i] += this.thousandsSeparator;
		}
	}
	var rval = fmt.reverse().join("") + this.decimalSeparator + (theCents == null ? this.getZeroesString() : theCents);
	return rval;
}


/**
 * Reverse a ,000.00 format (i.e. without thousands separator).
 */
CurrencyEditControl.reverseFormat = function(fmt)
{
	if (fmt == "") return "";
	var noFormat = "";
	var format   = fmt.toString();
	var l        = fmt.length;
	var i        = 0;
	for (i=0; i<l; i++){
		if (format.charAt(i) != this.thousandsSeparator) noFormat += format.charAt(i);
	}
	return noFormat;
}

/**
 * Transform the decimal separator into a decimal point.
 */
CurrencyEditControl.toPointValue = function(val)
{
	if (this.decimalSeparator != "."){
		return val.replace(this.decimalSeparator, ".");
	}
	return val;
}

/**
 * Relocate curr-symbols
 */
CurrencyEditControl.relocateSymbols = function()
{
	var divElements = document.getElementsByTagName("div");
	for (key in divElements){
		if (divElements[key].id && divElements[key].id.indexOf(this.currSymIdPrefix) == 0){
			var currSymbol = divElements[key];
			var input = document.getElementById(currSymbol.getAttribute("inputid"));
			if (!input) return;
			var nTop  = getObject.getSize("offsetTop", input);
			var nLeft = getObject.getSize("offsetLeft", input);
			currSymbol.style.top = nTop - 1 + "px";
			if (this.currencySymbolPos == "l"){
				currSymbol.style.left = (nLeft + this.currSymbolOffsetX) + "px";
			}
			else{ // "r"
				currSymbol.style.left = (nLeft + input.offsetWidth - this.currSymWidth + this.currSymbolOffsetX) + "px";
			}
		}
	}
}


/**
 * Get a string fill with zerores acording the value of this.decimalQuantity
 * (yes, there are countries with more tha 2 decimal positions for currency :P )
 */
CurrencyEditControl.getZeroesString = function()
{
	var zeroes = "";
	for (i=0; i<this.decimalQuantity; i++){
		zeroes += "0";
	}
	return zeroes;
}


/**
 * Set the value to the control.
 */
function CEC_setCurrencyValue(newvalue)
{
	var edit = this;
	var val = newvalue.toString();
	if (val != "" && !isNaN(parseFloat(CurrencyEditControl.toPointValue(val)))){
		edit.value = CurrencyEditControl.format(val);
		if (val.indexOf(CurrencyEditControl.decimalSeparator) < 0) val = val + CurrencyEditControl.decimalSeparator + CurrencyEditControl.getZeroesString();
		edit.setAttribute("currencyvalue", val);
	}
	else{
		edit.setAttribute("currencyvalue", "0" + CurrencyEditControl.decimalSeparator + CurrencyEditControl.getZeroesString());
	}
}

/**
 * Get the value from the control.
 */
function CEC_getCurrencyValue()
{
	var edit = this;
	var floatVal = parseFloat(CurrencyEditControl.toPointValue(edit.getAttribute("currencyvalue")));
	if (isNaN(floatVal)) return "0" + CurrencyEditControl.decimalSeparator + CurrencyEditControl.getZeroesString();
	return floatVal;
}


//-----------------------------------------------------------------------------
// Following 2 functions by: Mircho Mirev

function getObject(sId)
{
	if (bw.dom){
		this.hElement = document.getElementById(sId);
		this.hStyle = this.hElement.style;
	}
	else if (bw.ns4){
		this.hElement = document.layers[sId];
		this.hStyle = this.hElement;
	}
	else if (bw.ie){
		this.hElement = document.all[sId];
		this.hStyle = this.hElement.style;
	}
}

getObject.getSize = function(sParam, hLayer)
{
	nPos = 0;
	while ((hLayer.tagName) && !( /(body|html)/i.test(hLayer.tagName))){
		nPos += eval('hLayer.' + sParam);
		if (sParam == 'offsetTop'){
			if (hLayer.clientTop){
				nPos += hLayer.clientTop;
			}
		}
		if (sParam == 'offsetLeft'){
			if (hLayer.clientLeft){
				nPos += hLayer.clientLeft;
			}
		}
		hLayer = hLayer.offsetParent;
	}
	return nPos;
}


/**
 * Based on code by: Peter Todorov
 */
function writeLayer(ID, parentID, sText)
{
	if (document.layers){
		var oLayer;
		if(parentID){
			oLayer = eval('document.' + parentID + '.document.' + ID + '.document');
		}
		else{
			oLayer = document.layers[ID].document;
		}
		oLayer.open();
		oLayer.write(sText);
		oLayer.close();
	}
	else if(document.all){
		document.all[ID].innerHTML = sText;
	}
	else{
		document.getElementById(ID).innerHTML = sText;
	}
}

// EOF

