/** 
 fvValidation="extension" fvAllowEmpty="true" fvExtensionsAllowed="jpg,jpeg,gif,bmp,png"
 * @fileoverview Este modulo esta pensado para utilizar en todo
 * tipo de validaciones de formularios HTML. La idea es que las reglas
 * de las validaciones se colocan dentro de los tags HTML, sin
 * tener que agregar mas que una linea de codigo para llamar a la validacion.
 *
 * @version 2.0 
 */ 

// Constantes (para parametrizacion)

// Salida de mensajes de error
var sHeader				= '';
var sErrorLineStart		= '-- ';
var sErrorLineEnd		= ' --';

// Atributos
var sAtrValidacion			  = 'fvValidation';
var sAtrEmpty						  = 'fvAllowEmpty';
var sAtrMatcher				  	= 'fvMatchWith';
var sAtrMin						  	= 'fvMin';
var sAtrMax					  		= 'fvMax';
var sAtrEmptyValue	  		= 'fvEmptyValue';
var sAtrEmptyIfCond		  	= 'fvEmptyIfCondition';
var sAtrCCType				  	= 'fvCreditCardType';
var sAtrExtensionsAllowed = 'fvExtensionsAllowed';
var sAtrMinHeight		  		= 'fvMinHeight';
var sAtrMaxHeight		  		= 'fvMaxHeight';
var sAtrMinWidth					= 'fvMinWidth';
var sAtrMaxWidth					= 'fvMaxWidth';
//var sAtrFriend					= 'fvFriend'; *** DEPRECATED ***
//var sAtrEmptyIf					= 'fvEmptyIf'; *** DEPRECATED ***
//var sAtrEmptyIfValue		= 'fvEmptyIfValue'; *** DEPRECATED ***

var sAtrMsgEmpty				= 'fvOnEmpty';
var sAtrMsgError				= 'fvOnError';
var sAtrMsgMismatch			= 'fvOnMismatch';

// Tipos de tarjetas de credito
var sAtrCCTypeVISA			= 'visa';
var sAtrCCTypeMASTER		= 'mastercard';
var sAtrCCTypeAMERICAN	= 'americanexpress';
var sAtrCCTypeDISCOVER	= 'discover';
var sAtrCCTypeJCB				= 'jcb';
var sAtrCCTypeDINERS		= 'diners';
var sAtrCCTypeCB				= 'carteblanche';
var sAtrCCTypeENROUTE		= 'enroute';

// Para las islands de condiciones
var sFVIslandID						= 'fvIsland';
var sTagConditions				= 'fvConditions';
var sTagConditionsFor			= 'fvConditionsFor';
var sAtrConditionsForForm	= 'form';
var sTagCondition					= 'fvCondition';
var sAtrConditionID				= 'id';
var sTagConditionAND			= 'and';
var sTagConditionOR				= 'or';
var sTagConditionNOT			= 'not';
var sTagConditionEMPTY		= 'isEmpty';
var sTagConditionNOTEMPTY	= 'isNotEmpty';
var sTagConditionVALID   	= 'isValid';
var sTagConditionVALUE   	= 'valueEquals';
var sAtrConditionCtrlID		= 'control';
var sAtrConditionCtrlVAL	= 'value';

// Tipos de validaciones para <input type="text">
var sVtAny							= 'any';
var sVtAlphaNumeric			= 'alphanum';
var sVtAlpha						= 'alpha';
var sVtUnsignedInteger	= 'unsigned';
var sVtInteger					= 'integer';
var sVtUnsignedFloat		= 'unsigned_float';
var sVtFloat						= 'float';
var sVtIntegerRange			= 'integer_range';
var sVtEmail						= 'email';
var sVtURL							= 'url';
var sVtDate							= 'date';
var sVtCreditCard				= 'creditcard';
var sVtExtension				= 'extension';
var sVtImageOfSize			= 'imageofsize';

// Tipos de validaciones para <input type="radio">
var sVtAtLeastOne				= "selectone"

// Tipos de validaciones para <input type="checkbox">
var sVtRange						= "range"

// Tipos de validaciones para <select>
var sVtSelect						= "select"

// Sufijos
var sVSufAuxImage				= "_fvAuxImage"

// Variables para los errores
var sControlError;

/**
	* Valida un formulario en particular y, en caso de error, muestra el mensaje correspondiente
	* con un "alert" comun y corriente.
	* @param {Form} theForm El formulario a validar
	* @type boolean
	* @returns TRUE sii los controles del formulario son validos
	*/
function fvValidateForm(theForm)
{
	var sError = sHeader;
	if (sError != '') sError += '\n';
	var bValid = true;
	
	// Limpio el cache de condiciones de este formulario
	clearConditionCache(theForm);
	
	// Recorro los controles del formulario enviado para validar cada uno
	for (i=0;i<theForm.elements.length;i++)
	{
		// Valido este control
		if (!isControlValid(theForm,theForm.elements.item(i)))
		{
			sError += sErrorLineStart + sControlError + sErrorLineEnd + '\n';
			bValid = false;
		}
	}
	
	if (!bValid)
		alert(sError);
		
	return bValid;
}

/**
	* Para validar un control individual. En caso de no pasar la validacion,
	* se setea la variable global <i>sControlError</i> con el mensaje de error correpondiente.
	* @param {Form} theForm El formulario al que pertenece el control a validar
	* @param {Control} theControl El control a validar
	* @type boolean
	* @returns TRUE sii el control pasa la validacion
	*/
function isControlValid(theForm, theControl)
{
	// Variables
	var bControlValid;
	var sValidacion;
	var sType;
	var bEmptyAllowing;
	var bAllowEmpty;
	var sCondition;
	var iPosEq;
	var sTruthValue;
	var bConditionIsTrue;
	var iCantidadSeleccionados;
	var iMin;
	var iMax;
	
	// Levanto la validacion
	sValidacion = theControl.getAttribute(sAtrValidacion);
	
	// Por el momento, todo bien
	bControlValid = true;
	
	// Si el elemento actual tiene validacion y el elemento esta habilitado, la efectuo
	if (sValidacion != null && !theControl.disabled)
	{
		// Dependiendo del tipo de control me fijo que validaciones pueden ser...
		if (theControl.tagName == 'INPUT')
		{
			// Tipo de control
			try{
			    sType = theControl.getAttribute('type').toUpperCase();
			}
			catch(err)
			{
			    sType = theControl.type.toUpperCase();
			}
			if (sType=='TEXT' || sType=='PASSWORD' || sType=='FILE')
			{
				// INPUT type="text" o type="password"
				if (theControl.getAttribute(sAtrEmptyIfCond)!=null)
				{
					// Condicion de vacio?
					bEmptyAllowing = (conditionAllowsEmpty(theForm, theControl.id, theControl.getAttribute(sAtrEmptyIfCond)) && isControlEmpty(theControl));
				}
				else
				{
					// Permitir vacios siempre?
					bEmptyAllowing = (theControl.getAttribute(sAtrEmpty)=='true' && isControlEmpty(theControl));
				}
				/*else if (theControl.getAttribute(sAtrEmptyIf)!=null)
			  {
					// *** DEPRECATED ***
					bAllowEmpty = (!isChecked(theForm, theControl.getAttribute(sAtrEmptyIf), theControl.getAttribute(sAtrEmptyIfValue)) && isWhitespace(theControl.value));
				}*/
				
				if (!bEmptyAllowing)
				{
					// Si no pasa que es vacio permitiendo vacio, valido...
					if (isControlEmpty(theControl))
					{
						// Vacio?
						sControlError = theControl.getAttribute(sAtrMsgEmpty);
						bControlValid = false;
					}
					else if (
									(sValidacion == sVtAlphaNumeric && !isAlphanumeric(theControl.value)) ||	
									(sValidacion == sVtAlpha && !isAlphabetic(theControl.value)) ||	
									(sValidacion == sVtUnsignedInteger && !isInteger(theControl.value)) ||
									(sValidacion == sVtInteger && !isSignedInteger(theControl.value)) ||
									(sValidacion == sVtUnsignedFloat && !isFloat(theControl.value)) ||
									(sValidacion == sVtFloat && !isSignedFloat(theControl.value)) ||
									(sValidacion == sVtEmail && !isEmail(theControl.value)) ||
									(sValidacion == sVtURL && !isURL(theControl.value)) ||
									(sValidacion == sVtDate && !strIsDate(theControl.value)) ||
									(sValidacion == sVtIntegerRange && (!isInteger(theControl.value) || parseInt(theControl.value,10)<parseInt(theControl.getAttribute(sAtrMin),10) || parseInt(theControl.value,10)>parseInt(theControl.getAttribute(sAtrMax),10))) ||
									(sValidacion == sVtExtension && !hasAnyExtension(theControl.value,theControl.getAttribute(sAtrExtensionsAllowed))) || 
									(sValidacion == sVtImageOfSize && !imageIsOfSizeAndExtension(theControl.id,theControl.value,theControl.getAttribute(sAtrExtensionsAllowed),theControl.getAttribute(sAtrMinHeight),theControl.getAttribute(sAtrMaxHeight),theControl.getAttribute(sAtrMinWidth),theControl.getAttribute(sAtrMaxWidth))) || 
									(sValidacion == sVtCreditCard && !isValidCreditCardNumber(theControl.value,theControl.getAttribute(sAtrCCType)))
									)
					{
						// Error
						sControlError = theControl.getAttribute(sAtrMsgError);
						bControlValid = false;
					}
					
					// Si la validacion para este control es valida y tengo que matchear con otro control, me fijo...
					if (bControlValid && theControl.getAttribute(sAtrMatcher) != null)
					{
						// Validacion normalmente para INPUT type="password"
						if (theControl.value != formControl(theForm,theControl.getAttribute(sAtrMatcher)).value)
						{
							// Error
							sControlError = theControl.getAttribute(sAtrMsgMismatch);
							bControlValid = false;
						}
					}
				}
			}
			else if (sType=='RADIO')
			{
				// INPUT type="radio"
				
				if (sValidacion == sVtAtLeastOne)
				{
					// Al menos uno seleccionado (todos deben tener el mismo nombre)
					// Recorro todos y me fijo...
										
					// Condicion de vacio?
					if (theControl.getAttribute(sAtrEmptyIfCond)!=null) 
						bControlValid = conditionAllowsEmpty(theForm, theControl.id, theControl.getAttribute(sAtrEmptyIfCond));
					else 
						bControlValid = false;
					
					// *** DEPRECATED ***
					/*if (theControl.getAttribute(sAtrEmptyIf)!=null)
						bControlValid = !isChecked(theForm, theControl.getAttribute(sAtrEmptyIf), theControl.getAttribute(sAtrEmptyIfValue));*/
										
					for (j=0;j<theForm.elements.length;j++)
					{
						if (isRadio(theForm.elements.item(j)) && theForm.elements.item(j).name == theControl.name)
							bControlValid = bControlValid || theForm.elements.item(j).checked;
					}
					
					if (!bControlValid)
					{
						// Error
						sControlError = theControl.getAttribute(sAtrMsgError);
					}
				}
			}
			else if (sType=='CHECKBOX')
			{
				if (sValidacion == sVtRange)
				{
					// Rango de seleccionados
					iCantidadSeleccionados=0;
					iMin = theControl.getAttribute(sAtrMin);
					iMax = theControl.getAttribute(sAtrMax);
					if (iMax==null)
						iMax=0;
						
					// Condicion de vacio?
					if (theControl.getAttribute(sAtrEmptyIfCond)!=null)
					{
						bAllowEmpty = conditionAllowsEmpty(theForm, theControl.id, theControl.getAttribute(sAtrEmptyIfCond));
					}
					else 
					{
						bAllowEmpty = false;
					}
					
					// *** DEPRECATED ***
					/*if (theControl.getAttribute(sAtrEmptyIf)!=null)
						bAllowEmpty = !isChecked(theForm, theControl.getAttribute(sAtrEmptyIf), theControl.getAttribute(sAtrEmptyIfValue));
					else
						bAllowEmpty = false;*/
					
					for (j=0;j<theForm.elements.length;j++)
					{
						if (isCheckBox(theForm.elements.item(j)) && theForm.elements.item(j).name == theControl.name)
							iCantidadSeleccionados += (theForm.elements.item(j).checked?1:0);
					}

					if ( ((iCantidadSeleccionados < parseInt(iMin)) || ((iCantidadSeleccionados > parseInt(iMax)) && (iMax>0))) && !bAllowEmpty)
					{
						// *** DEPRECATED ***
						/*if (theControl.getAttribute(sAtrFriend) == null)
							bFriendOK = false;
						else
							bFriendOK = !isWhitespace(formControl(theForm,theControl.getAttribute(sAtrFriend)).value);
							
						if (!bFriendOK)
						{
							// Error
							sControlError = theControl.getAttribute(sAtrMsgError);
							bControlValid = false;
						}*/
						
						// Error
						sControlError = theControl.getAttribute(sAtrMsgError);
						bControlValid = false;
					}
				}
			}
		}
		else if (theControl.tagName == 'SELECT')
		{
			// SELECT
			if (sValidacion == sVtSelect)
			{
				// Condicion de vacio??
				if (theControl.getAttribute(sAtrEmptyIfCond)!=null)
				{
					bAllowEmpty = conditionAllowsEmpty(theForm, theControl.id, theControl.getAttribute(sAtrEmptyIfCond));
				}
				else
				{
					bAllowEmpty = false;
				}
				
				// Que haya algun valor seleccionado
				if (isControlEmpty(theControl) && !bAllowEmpty)
				{
					// Error
					sControlError = theControl.getAttribute(sAtrMsgError);
					bControlValid = false;	
				}
			}				
		}
		else if (theControl.tagName == 'TEXTAREA')
		{
			// TEXTAREA
			
			// Me fijo que no sea vacio
			if (isControlEmpty(theControl))
			{
				// Error
				sControlError = theControl.getAttribute(sAtrMsgEmpty);
				bControlValid = false;	
			}
		}
	}
	
	return bControlValid;
}

/**
	* Dice si un control esta vacio o no, de acuerdo al valor de vacio que tenga seteado (o no).
	* Controles a los que aplica:
	* INPUT text
	* SELECT
	* TEXTAREA
	*
	* @ignore
	*/
function isControlEmpty(theControl)
{
	if (theControl.getAttribute(sAtrEmptyValue) == null) return isWhitespace(theControl.value);
	else return (theControl.value == theControl.getAttribute(sAtrEmptyValue));
}

/**
	* Dado un control, nos dice si es un INPUT radio.
	*
	* @ignore
	*/
function isRadio(control)
{
	if (control.tagName == 'INPUT')
	    try{
		    return control.getAttribute('type').toUpperCase()=='RADIO';
		   }
		   catch(err)
		   {
		    return control.type.toUpperCase()=='RADIO';
		   }
	else
		return false;
}

/**
	* Dado un control, nos dice si es un INPUT checkbox.
	*
	* @ignore
	*/
function isCheckBox(control)
{
	if (control.tagName == 'INPUT')
		return control.getAttribute('type').toUpperCase()=='CHECKBOX';
	else
		return false;
}

/**
	* Dado un formulario y un id de control, devuelve el control con 
	* ese id en el formulario (si existe, sino, NULL).
	*
	* @ignore
	*/
function formControl(theForm,sControl)
{
	var control = null;
	for (h=0;h<theForm.elements.length;h++)
	{
		if (theForm.elements.item(h).id == sControl)
		{
			control = theForm.elements.item(h)
			break;
		}
	}
	
	return control;
}

/**
	* Para validar una tarjeta de credito
	*
	* @ignore
	*/
function isValidCreditCardNumber(sNumber,sType)
{
	var bIsValid;
	switch (sType)
	{
		case sAtrCCTypeVISA: 
			bIsValid = isVisa(sNumber); 
			break
		case sAtrCCTypeMASTER: 
			bIsValid = isMasterCard(sNumber); 
			break
		case sAtrCCTypeAMERICAN: 
			bIsValid = isAmericanExpress(sNumber); 
			break
		case sAtrCCTypeDISCOVER: 
			bIsValid = isDiscover(sNumber); 
			break
		case sAtrCCTypeJCB: 
			bIsValid = isJCB(sNumber); 
			break
		case sAtrCCTypeDINERS: 
			bIsValid = isDinersClub(sNumber); 
			break
		case sAtrCCTypeCB: 
			bIsValid = isCarteBlanche(sNumber); 
			break
		default: 
			bIsValid = isCreditCard(sNumber);
	}
	return bIsValid;
}

/**
	* Para limpiar el cache de condiciones de un form particular
	*
	* @ignore
	*/
function clearConditionCache(theForm)
{
	// Traigo las condiciones de este formulario
	var theConditions = getFormConditions(theForm);
	if (!theConditions) return false;
	
	// A cada condicion le marco el cache como no procesado...
	for (var i=0;i<theConditions.length;i++)
	{
		try{
		    theConditions[i].setAttribute("inCache","false");
		}
		catch(err)
		{
		    theConditions[i].inCache = "false";
		}
	}
}

/**
	* Dice si una condicion de vacio permite vacio o no, acorde a su valor
	*
	* @ignore
	*/
function conditionAllowsEmpty(theForm, sControlID, sCondition)
{
	var iPosEq;
	var sTruthValue;
	var bConditionIsTrue;
	
	// Parseo el valor del atributo (debe ser de la forma condicion=true o condicion=false)
	iPosEq = sCondition.indexOf("=");
	if (iPosEq==-1) alert('empty if condition value not well-specified at control ' + sControlID);
	sTruthValue = sCondition.substr(iPosEq+1);
	sCondition = sCondition.substr(0,iPosEq);
	// Evaluo la condicion
	bConditionIsTrue = isConditionTrue(theForm, sCondition);
	return (sTruthValue.substr(0,1).toUpperCase()=="T"?bConditionIsTrue:!bConditionIsTrue);
}

/**
	* Para verificar la validez de una condicion
	*
	* @ignore
	*/ 
function isConditionTrue(theForm, sConditionID)
{
	// Traigo la condicion que me piden evaluar
	var theCondition = getFormConditionById(theForm, sConditionID);
	if (!theCondition) return false;
	
	// Esta en cache??
	if (theCondition.getAttribute("inCache")=="true")
	{
		// Devuelvo el valor del cache directo...
		return (theCondition.getAttribute("truthValue")=="true"?true:false);
	}
	else
	{
		// Que garron... tengo que evaluar...
		// Busco el primer hijo y trabajo con ese (es decir, a los que sigan no se les da bola - que dicho sea de paso, no deberia haber)
		if (!theCondition.hasChildNodes()) return false;
		var theChild = getFirstChildNode(theCondition);
		
		// Ahora simplemente la evaluo...
		var truthValue = isActualConditionTrue(theForm, theChild);
		
		// Seteo el cache
		theCondition.setAttribute("inCache", "true");
		theCondition.setAttribute("truthValue", (truthValue?"true":"false"));
		
		return truthValue;
	}
}

/**
	* Obtiene la coleccion de condiciones que tiene un formulario particular.
	*
	* @ignore
	*/
function getFormConditions(theForm)
{
	// Busco la data island
	var theIsland = window.document.getElementById(sFVIslandID);
	if (!theIsland) return null;
	
	// Busco las condiciones de este formulario
	var allFormsConditions = theIsland.getElementsByTagName(sTagConditions);
	if (allFormsConditions.length==0) return null;
	allFormsConditions = allFormsConditions[0].getElementsByTagName(sTagConditionsFor);
	if (!allFormsConditions) return null;
	var theConditions = null;
	for (var i=0;i<allFormsConditions.length;i++)
	{
		if (allFormsConditions[i].getAttribute(sAtrConditionsForForm).toUpperCase()==theForm.id.toUpperCase())
		{
			theConditions = allFormsConditions[i].childNodes;
			break;
		}
	}
	
	return theConditions;
}

/**
	* Obtiene la condicion con un id en particular de un formulario en particular
	*
	* @ignore
	*/
function getFormConditionById(theForm, sConditionID)
{
	// Traigo las condiciones de este formulario
	var theConditions = getFormConditions(theForm);
	if (!theConditions) return null;
		
	// Busco la condicion que me estan pidiendo
	var theCondition = null;
	for (var i=0;i<theConditions.length;i++)
	{
	    try{
		    if (theConditions[i].getAttribute(sAtrConditionID)==sConditionID) theCondition = theConditions[i];
		}
		catch(err)
		{
		    if (eval("theConditions[" + i + "]." + sAtrConditionID) == sConditionID) theCondition = theConditions[i];
		}
	}
	
	return theCondition;
}

/**
	* Interna llamada por "isConditionTrue" para hacer su trabajo
	*
	* @ignore
	*/ 
function isActualConditionTrue(theForm, theCondition)
{
	// Dos casos: condicion evaluable directamente (caso base) o condicion compuesta (caso recursivo)
	if (theCondition.nodeName.toUpperCase()==sTagConditionEMPTY.toUpperCase() || theCondition.nodeName.toUpperCase()==sTagConditionNOTEMPTY.toUpperCase() || theCondition.nodeName.toUpperCase()==sTagConditionVALID.toUpperCase() || theCondition.nodeName.toUpperCase()==sTagConditionVALUE.toUpperCase())
	{
		// CASO BASE
		// Busco el control del formulario a validar
		var theControl = formControl(theForm,theCondition.getAttribute(sAtrConditionCtrlID));
		if (!theControl) return false;
		
		// Evaluo...
		if (theCondition.nodeName.toUpperCase()==sTagConditionEMPTY.toUpperCase() || theCondition.nodeName.toUpperCase()==sTagConditionNOTEMPTY.toUpperCase())
		{
			var bIsEmpty = isControlEmpty(theControl);
			return (theCondition.nodeName.toUpperCase()==sTagConditionEMPTY.toUpperCase()?bIsEmpty:!bIsEmpty);
		}
		else if (theCondition.nodeName.toUpperCase()==sTagConditionVALID.toUpperCase())
		{
			return isControlValid(theForm, theControl);
		}
		else if (theCondition.nodeName.toUpperCase()==sTagConditionVALUE.toUpperCase())
		{
			return (theControl.value==theCondition.getAttribute(sAtrConditionCtrlVAL));
		}
		else
		{
			return false;
		}		
	}
	else
	{
		// CASO RECURSIVO
		
		// Si no es de las condiciones permitidas, no vale...
		if (!theCondition.nodeName.toUpperCase()==sTagConditionAND.toUpperCase() && !theCondition.nodeName.toUpperCase()==sTagConditionOR.toUpperCase() && !theCondition.nodeName.toUpperCase()==sTagConditionNOT.toUpperCase()) return false;
		
		// Recorro los hijos de la condicion y evaluo cada uno
		var theChildren = theCondition.childNodes;
		
		// Evaluo recursivamente...
		var bValid;
		switch (theCondition.nodeName.toUpperCase())
		{
			case sTagConditionAND.toUpperCase(): 
				bValid = true;
				break;
			case sTagConditionOR.toUpperCase():
				bValid = false;
				break;
		}
		
		for (var i=0;i<theChildren.length;i++)
		{
			// Si no es de tipo texto, sigo
			if (!nodeIsTypeText(theChildren[i]))
			{
				// Diferentes casos segun la condicion
				switch (theCondition.nodeName.toUpperCase())
				{
					case sTagConditionAND.toUpperCase():
						bValid = bValid && isActualConditionTrue(theForm, theChildren[i]);
						break;
					case sTagConditionOR.toUpperCase():
						bValid = bValid || isActualConditionTrue(theForm, theChildren[i]);
						break;
			  	case sTagConditionNOT.toUpperCase():
			  		bValid = !isActualConditionTrue(theForm, theChildren[i]);
			  		break;
			  }
			}
		}
		return bValid;
	}
}

/**
	* Para obtener el primer nodo hijo de un nodo que no sea de tipo texto (cross-browser)
	*
	* @ignore
	*/
function getFirstChildNode(theNode)
{
	var theChildren = theNode.childNodes;
	for (var i=0;i<theChildren.length;i++)
	{
		if (!nodeIsTypeText(theChildren[i])) return theChildren[i]; // El primero que no sea de tipo texto
	}	
	return null;
}

/**
	* Se explica por si sola...
	*
	* @ignore
	*/
function nodeIsTypeText(theNode)
{
	return (theNode.nodeType==3); // Tipo texto = 3
}

// *** DEPRECATED ***
/*function isChecked(theForm, sControl, theValue)
{
	if (sControl != null)
	{
		var bChecked = false;
		var bAnyChecked = false;
		for (z=0;z<theForm.elements.length;z++)
		{
			ctrl = theForm.elements.item(z);
			if (ctrl.tagName=='INPUT' && (ctrl.getAttribute('type').toUpperCase()=='RADIO' || ctrl.getAttribute('type').toUpperCase()=='CHECKBOX') && ctrl.id==sControl)
			{
				if (ctrl.checked)
					bAnyChecked = true;
				bChecked = bChecked || (ctrl.checked && ctrl.value==theValue);
			}
		}
		if (!bAnyChecked)
			return false;
		else
			return bChecked;
	}
	else
		return false;
}*/

/**
	* Que el texto que se pasa tenga alguna de las extensiones ...
	*
	*/
function hasAnyExtension(sTexto,sExtensions)
{
	// Obtengo las extensiones
	var aExtensions = sExtensions.split(",");
	// Traigo la extension del archivo
	var iPunto = sTexto.lastIndexOf(".");
	// Si no tiene extension, entonces nope...
	if (iPunto==-1) return false;
	var sExtension = sTexto.substr(iPunto+1);
	// Es alguna?
	for (var i=0;i<aExtensions.length;i++)
	{
		if (sExtension.toUpperCase()==aExtensions[i].toUpperCase()) return true;
	}
	// Nope...
	return false;
}

/**
	* Que sea una imagen de alguna de las extensiones y aparte tenga el tamaneo
	* que se pide
	*/
function imageIsOfSizeAndExtension(sId,sTexto,sExtensions,sMinHeight,sMaxHeight,sMinWidth,sMaxWidth)
{
	if (!hasAnyExtension(sTexto,sExtensions)) return false;
	// Tamaneos
	var iMinHeight = -1;
	if (sMinHeight!="") iMinHeight = parseInt(sMinHeight,10);
	var iMaxHeight = -1;
	if (sMaxHeight!="") iMaxHeight = parseInt(sMaxHeight,10);
	var iMinWidth = -1;
	if (sMinWidth!="") iMinWidth = parseInt(sMinWidth,10);
	var iMaxWidth = -1;
	if (sMaxWidth!="") iMaxWidth = parseInt(sMaxWidth,10);
	// Verifico el tamaneo de la imagen
	if (sTexto.length != 0) 
	{
		var oImage = window.document.getElementById(sId+sVSufAuxImage); // La imagen supuestamente preloadeada
		var oNewImage = new Image;
		oNewImage.src = oImage.src;
		if (oNewImage.height<iMinHeight && iMinHeight!=-1) return false;
		if (oNewImage.width<iMinWidth && iMinWidth!=-1) return false;
		if (oNewImage.height>iMaxHeight && iMaxHeight!=-1) return false;
		if (oNewImage.width>iMaxWidth && iMaxWidth!=-1) return false;
		return true;
	}
	else return false;
}

/**
	* Funcion que debe ser llamada desde el input type="file" en el onChange si se utiliza validacion de tipo
	* "imageofsize"
	*/
function fvFileChanged(oFile)
{
	// Hago un preload de la imagen si respeta las extensiones
	if (hasAnyExtension(oFile.value,oFile.getAttribute(sAtrExtensionsAllowed)))
	{
		window.document.getElementById(oFile.id+sVSufAuxImage).src = oFile.value;
	}
}