Effect.HighlightText = Class.create();
Object.extend(Object.extend(Effect.HighlightText.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
    this.start(options);
  },

  setup: function() {
    if(this.element.getStyle('display')=='none') { this.cancel(); return; }

    if(!this.options.endcolor)
      this.options.endcolor = this.element.getStyle('color').parseColor('#000000');
    if(!this.options.restorecolor)
      this.options.restorecolor = this.element.getStyle('color');

    // init color calculations
    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
  },
  update: function(position) {
    this.element.setStyle({color: $R(0,2).inject('#',function(m,v,i){
      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
  },
  finish: function() {
    //this.element.setStyle({color: this.options.restorecolor});
  }
});
//
//
/**
 * @classDescription Clase Base, Permite que una lista de elementos actue como una botonera Radio.
 */
RadioControl = Class.create();
Object.extend(RadioControl.prototype, {
	/**
   * Constructor de RadioControl.
   * @alias RadioControl.initialize
   * @param {String} hidden_input	Id del campo oculto que almacena el valor real de la selección.
   * @param {String} no_valid	Id del elemento HTML que varía de color según la selección sea valida o no.
   * @param {String} no_valid_color	Color con el que se resalta el elemento especificado en 'no_valid' en formato hex. por ej: '#EE5f19'.
   * @param {String} valid_color	Color con el que se reestablece el elemento especificado en 'no_valid' en formato hex. por ej: '#000000'.
   * @memberOf RadioControl
   * @constructor
   */
   initialize: function(hidden_input, no_valid, no_valid_color, valid_color) {
		this.start(hidden_input, no_valid, no_valid_color, valid_color);
   },
   start:function(hidden_input, no_valid, no_valid_color, valid_color){
	   this.buttons=new Array(),
	   this.value=null,
	   this.hidden=hidden_input,
	   this.msg=no_valid,
	   this.noValidColor=no_valid_color,
	   this.validColor=valid_color,
	   this.valid=true,
	   this.autoHighlight=true;
	   /**
	    * Los elementos pertenecientes a esta clase son ignorados
	    */
	   this.disabledClass='disabled',
	   this.listeners= new Array()
   }
});
Object.extend(RadioControl.prototype, {
    findPos: function(elm) {
        var pos = null;
        this.buttons.each(function(current, i) {
            if (current == elm) {
                pos = i;
                return;

            }

        });
        return pos;

    },
    findPosValue: function(val) {
        var pos = null;
        this.buttons.each(function(current, i) {
            if (current.val == val) {
                pos = i;
                return;

            }

        });
        return pos;
    },
    onPress: function(elm) {
        this.value = elm.val;
        $(this.hidden).value = this.value;
        this.validate();
    },
    clickEvent: function(event) {
        this.onPress(Event.element(event));
    },
    removeListeners: function() {
		var buttons = this.buttons;
		this.listeners.each(function(obj, i){
			buttons[i].stopObserving('click', obj);						 
		});

    },
	/**
    * Añade un elemento HTML que formara parte de la lista de items seleccionables, por defecto, ignora los elementos que tengan asignada la clase 'disabled'
    * @alias RadioControl.addControl
    * @param {String} id	Id del elemento HTML
    * @param {String} value Valor real almacenado en el campo oculto al seleccionar este item.
    * @memberOf RadioControl
    */
    addControl: function(id, value) {
        if (!$(id).hasClassName(this.disabledClass)) {
            $(id).val = value;
            $(id).setStyle({
                cursor: 'pointer'

            });
            this.listeners.push(this.clickEvent.bindAsEventListener(this));
            $(id).observe('click', this.listeners[this.listeners.length - 1]);
            this.buttons.push($(id));

        }

    },
	
	highlightOn: function(){
	
		if (this.valid) {
            new Effect.HighlightText(this.msg, {
                startcolor: this.validColor,
                endcolor: this.noValidColor,
                time: 0.5
            });
            this.valid = false;
        }
	},
	
	highlightOff: function(){
	
		if (!this.valid) {
			new Effect.HighlightText(this.msg, {
				startcolor: this.noValidColor,
				endcolor: this.validColor,
				time: 0.5
			});
		}
		this.valid = true;

	},
	
    validate: function() {
        if (this.value == null) {
            /*if (this.valid) {
				if(this.autoHighlight){
                	new Effect.HighlightText(this.msg, {
                   		startcolor: this.validColor,
                    	endcolor: this.noValidColor,
                    	time: 0.5
                	});
				}
                this.valid = false;
            }*/
		
			if (this.autoHighlight) {
				this.highlightOn();
			}
            return false;
			
        }
        /*if (!this.valid) {
			
			if(this.autoHighlight){
            	new Effect.HighlightText(this.msg, {
                	startcolor: this.noValidColor,
                	endcolor: this.validColor,
                	time: 0.5
            	});
			}
            this.valid = true;
            
			this.highlightOff();

        }*/
		if (this.autoHighlight) {
			this.highlightOff();
		}
        return true;

    },
	/**
	 * Actualiza la vista de elementos en base al valor del campo oculto asociado, útil al recargar la página o al establecer valores por defecto en el formulario.
     * @memberOf RadioControl
    */
    checkHidden: function() {
        if ($(this.hidden).value != '') {
            var pos = this.findPosValue($(this.hidden).value);
            this.onPress(this.buttons[pos]);

        }

    }

});
/**
 * @classDescription Extiende RadioControl, la lista de elementos esta formada por imagenes, y una imagen extra se posiciona sobre el elemento seleccionado.
 */
RadioControlImg = Class.create();
Object.extend(Object.extend(RadioControlImg.prototype, RadioControl.prototype), {
	/**
	 * Constructor de RadioControl.
     * @alias RadioControl.initialize
     * @param {String} hidden_input	Id del campo oculto que almacena el valor real de la selección.
     * @param {String} no_valid	Id del elemento HTML que varía de color según la selección sea valida o no.
     * @param {String} no_valid_color	Color con el que se resalta el elemento especificado en 'no_valid' en formato hex. por ej: '#EE5f19'.
     * @param {String} valid_color	Color con el que se reestablece el elemento especificado en 'no_valid' en formato hex. por ej: '#000000'.
	 * @param {String} over_img Id de la imagen que se posiciona sobre los ítems de la lista.
	 * @param {Number} step	Desplazamiento horizontal de 'over_img'.
	 * @param {Number} vertical_step Desplazamiento vertical de 'over_img', Se utiliza cuando la lista de items esta formada por varias filas de elementos. No requerido.
	 * @param {Number} columns	Numero de elementos por fila, No requerido.
	 */
    initialize: function(hidden_input, no_valid, no_valid_color, valid_color, over_img, step, vertical_step, columns) {
        this.start(hidden_input, no_valid, no_valid_color, valid_color);
        //
        this.over = over_img,
        this.step = step,
        this.columns = columns,
        this.vstep = vertical_step

    },
    roundUtil: function(num, div) {
        if (num == null || div == null) {
            return 0;

        }
        var result = Math.floor(num / div)
        return result;

    },
    onPress: function(elm) {
        if (this.columns == undefined || this.columns == 'undefined') {
            this.columns = null

        }
        if (this.vstep == undefined || this.vstep == 'undefined') {
            this.vstep = null;

        }

        var pos = this.findPos(elm);
        $(this.over).style.left = ((pos - this.roundUtil(pos, this.columns) * this.columns) * this.step) + "px";
        $(this.over).style.top = (this.vstep * this.roundUtil(pos, this.columns)) + "px";
        $(this.over).setStyle({
            visibility: 'visible'

        });
        this.value = elm.val;
        $(this.hidden).value = this.value;
        this.validate();
        pvcHandleChange($(this.hidden).name);

    },
    set: function(id) {
        this.onPress($(id));

    }

});		

/**
 * @classDescription Extiende RadioControl, al seleccionar un elemento de la lista, se cambia su classe CSS
 */
RadioControlClass = Class.create();
Object.extend(Object.extend(RadioControlClass.prototype, RadioControl.prototype), {
	/**
	 * Constructor de RadioControlClass.
     * @alias RadioControl.initialize
     * @param {String} hidden_input	Id del campo oculto que almacena el valor real de la selección.
     * @param {String} no_valid	Id del elemento HTML que varía de color según la selección sea valida o no.
     * @param {String} no_valid_color	Color con el que se resalta el elemento especificado en 'no_valid' en formato hex. por ej: '#EE5f19'.
     * @param {String} valid_color	Color con el que se reestablece el elemento especificado en 'no_valid' en formato hex. por ej: '#000000'.
	 * @param {String} overClass nombre de la clase para indicar que un elemento esta seleccionado.
	 */
    initialize: function(hidden_input, no_valid, no_valid_color, valid_color, overClass) {
        this.start(hidden_input, no_valid, no_valid_color, valid_color);
        //
        this.over = overClass

    },
    removeOver: function() {
		this.buttons.invoke('removeClassName', this.over);
		this.buttons.invoke('setStyle', {cursor: 'pointer'});	
    },
	
    onPress: function(elm) {
        var pos = this.findPos(elm);
        this.removeOver();
        $(elm).addClassName(this.over);
		$(elm).setStyle({
                cursor: 'default'
        });
        this.value = elm.val;
        $(this.hidden).value = this.value;
        this.validate();

    }

});
/**
 * @classDescription Crea listas de RadioControlClass que se pueden cambiar mediante un Input tipo Select
 */
MultipleRadioControls = Class.create();
Object.extend(MultipleRadioControls.prototype, {
	/**
     * Constructor de MultipleRadioControls
     * @alias MultipleRadioControls.initialize
	 * @param {String} hidden_input	Id del campo oculto que almacena el valor real de la selección.
     * @param {String} no_valid	Id del elemento HTML que varía de color según la selección sea valida o no.
     * @param {String} no_valid_color	Color con el que se resalta el elemento especificado en 'no_valid' en formato hex. por ej: '#EE5f19'.
     * @param {String} valid_color	Color con el que se reestablece el elemento especificado en 'no_valid' en formato hex. por ej: '#000000'.
	 * @param {String} overClass nombre de la clase para indicar que un elemento esta seleccionado.
	 * @constructor 
	 */
    initialize: function(target_id, hidden_input, no_valid, no_valid_color, valid_color, overClass) {
        this.start(target_id, hidden_input, no_valid, no_valid_color, valid_color, overClass);

    },
    start: function(target_id, hidden_input, no_valid, no_valid_color, valid_color, overClass) {
        this.target = target_id;
        this.hidden = hidden_input;
        this.msg = no_valid;
        this.noValidColor = no_valid_color;
        this.validColor = valid_color;
        this.disabledClass = 'disabled';
        this.over = overClass;
		this.autoHighlight = true;
		/**
		 * Almacena los RadioControlClass añadidos mediente #addList
		 */
        this.lists = new Array();
        this.control = null;
        this.listener = null;

    },
	
	/**
	 * Añade un nuevo RadioControlClass. Ejemplo de uso: MultipleRadioControls.addList({text:'85', val:'85', active:true},{text:'90', val:'90', active:false},{text:'95', val:'95', active:true},{text:'100', val:'100', active:true});
	 * @param {args}	arguments	Admite un número variable de objetos que crean una lista seleccionable(RadioControlClass)
	 * 	El formato de los objetos es el siguiente: {text:'90', val:'90', active:true}
	 *  @param {String} text Valor mostrado
	 *  @param {String} val	Valor real, que luego es enviado en el submit del formulario.
	 *  @param (Boolean) active simula un elemento con class='disabled'
	 *  
	 */
    addList: function() {
        var pos = this.lists.length;
        this.lists[pos] = new Array();
        for (i = 0; i < arguments.length; i++) {
            var elm = arguments[i];
            this.lists[pos].push(elm);
        }

    },
	/**
	 * Añade el Input Select que hace el cambio de lista, el valor de sus 'options', tiene que corresponder con la posicion de las listas en el array #lists
	 * @param {Object} id	Id del Input tipo Select
	 */    
	 addSelectListener: function(id) {
        this.listener = id;
        var _parent = this;
        $(this.listener).observe('change', this.checkHidden.bindAsEventListener(this)); 
    },
	
    validate: function() {
        if (this.control != null) {
            return this.control.validate();

        }
        return false;

    },
	/**
	 * @see RadioControl#checkHidden
	 */
    checkHidden: function() {
        this.showList($(this.listener).value);
        this.control.checkHidden();

    },
	/**
	 * Muestra un listado de elementos seleccionables.
	 * @param {Object} num El número de listado a mostrar almacenados en 'lists'
	 */
    showList: function(num) {
		if(typeof num == 'object') num = Event.element(num).value;
		var bValueFound = false;
		var selectedValue = $(this.hidden).value;
        var out = '<ul id=\'ctl00$MainContent$ProductDetail$VariantChooser:VariantSize_list\'>\n';
        var list = this.lists[num];
        //alert(this.lists[0]);
        var _parent = this;
        list.each(function(elm) {
            if (elm.active) {
                if(selectedValue == elm.val)
                {
                    out += '<li id="talla_' + elm.val + '" style="cursor:default" class="select">' + elm.text + '</li>';
                    bValueFound = true;
                }
                else
                    out += '<li id="talla_' + elm.val + '">' + elm.text + '</li>';

            } else {
                out += '<li id="talla_' + elm.val + '" class="' + _parent.disabledClass + '" >' + elm.text + '</li>';

            }
            out += '\n';

        });
        out += '</ul>\n';
        if (this.control != null) {
            this.control.removeListeners();

        }
        this.control = null;
        $(this.target).innerHTML = out;
        this.control = new RadioControlClass(this.hidden, this.msg, this.noValidColor, this.validColor, this.over);
		this.control.autoHighlight = this.autoHighlight;
        list.each(function(elm) {
            _parent.control.addControl('talla_' + elm.val, elm.val);

        });
		
		if(!bValueFound)
		{
		    $(this.hidden).value = '';
		    this.value = null;
		}
		else
		{
		    $(this.hidden).value = selectedValue;
		    this.value = selectedValue;
	    }
        //_parent.control.checkHidden();
    }
});

/**
 * Valida el valor de un input text
*/
TextValidator = Class.create();
Object.extend(TextValidator.prototype, {
	/**
	 * Constructor de TextValidator
	 * @param {Object} text_id	Id del Campo a validar
	 * @param {Object} options	Opciones variables, consultar #setOptions
	 * @constructor
	 */
    initialize: function(text_id, options) {
        this.start(text_id, options);
    },
    start: function(text_id, options) {
        this.input_id = text_id;
		this.listeners = new Array();
		this.keyDownListener = null;
		this.lastval = '';
		this.valid = true;
		this.errorCode=1;
		this.related=new Array();
		this.autoHighlight=true;
		this.ignore=false;
		this.effect=null;
		/**
		 * Para ejecutar la validación del campo automaticamente hay que fijar el valor a 'keyup'
		 */
		this.validateOn = null;
		//
		this.setOptions(options);
		//
		this.lastval = $F(this.input_id);
		//if(this.useMask){
			this.keyDownListener = this.setLastVal.bindAsEventListener(this);
			$(this.input_id).observe('keydown',this.keyDownListener);
			$(this.input_id).observe('focus',this.keyDownListener);
			//
			this.listeners.push(this.applyMask.bindAsEventListener(this));
		    $(this.input_id).observe('keyup',this.listeners[0]);
		//}
    },
	/**
	 * Uso interno, llamada por el constructor
	 * @param {Object} options Opciones variables de configuración.
	 */
	addRelated: function(){
		for (var i = 0; i < arguments.length; i++) {
			this.related.push(arguments[i]);			
		}
	},
	setOptions: function(options) {
		this.options = {
			/**
			 * Id del Elemento HTML que cambia de color según el campo sea válido o no.	
			 */
		    highlightId:null,
			/**
			 * Color de 'highlightId' al no pasar la validacion.
			 */
			noValidColor:'#EE5f19',
			/**
			 * Color de 'highlightId' al pasar la validacion.
			 */
			validColor:'#000000',
			/**
			 * Tipos de validación, admite: 'empty','number','alpha','alphanum' y 'email'
			 */
			validType:'empty',
			/**
			 * Inpide la entrada de caractes no válido, útil con validaciones simples, solo números, solo letras...
			 */
			useMask:false,
			/**
			 * Requiered:false indica que el input puede quedar vacio.
			 */
			required:true,
			/**
			 * Mínimo de caracteres, útil por ejemplo, con el código postal.
			 */
			minChars:null,
			/**
			 * Máximo de caracteres, útil por ejemplo, con el código postal.
			 */
			maxChars:null,
			/**
			* Valor numérico comprendido entre minValue y maxValue
			*/
			minValue:null,
			maxValue:null
		};
		Object.extend(this.options, options || {});
	},
	
	removeListeners: function() {
		$(this.input_id).stopObserving('keyup', this.listeners[0]);
    },
	
	removeAllListeners: function() {
		$(this.input_id).stopObserving('keyup', this.listeners[0]);
		$(this.input_id).stopObserving('keydown',this.keyDownListener);
		$(this.input_id).stopObserving('focus',this.keyDownListener);
    },
	highlightOn: function(){
		if (this.valid) {
                if (this.options.highlightId != null && this.options.noValidColor != null && this.options.validColor != null) {
                    this.effect = new Effect.HighlightText(this.options.highlightId, {
                        startcolor: this.options.validColor,
                        endcolor: this.options.noValidColor,
                        time: 0.5
                    });

                }
                this.valid = false;
            }
	},
	highlightOff: function(){
		if (!this.valid) {
                if (this.options.highlightId != null && this.options.noValidColor != null && this.options.validColor != null) {
                    this.effect = new Effect.HighlightText(this.options.highlightId, {
                        startcolor: this.options.noValidColor,
                        endcolor: this.options.validColor,
                        time: 0.5
                    })

                }
                this.valid = true;
            }
	},
	cancel:function(){
		if(this.effect == null) return;
		this.effect.cancel();
		this.valid=true;
	},

    validate: function() {
		if(this.ignore) return true;
			if (!this.validAll()) {
				//true, false, true
				if(this.autoHighlight){
					this.highlightOn();
				}
				return false;
			}
			if (this.validAll()) {
				//false, true, false
				if(this.autoHighlight){
					this.highlightOff();
				}
			//}
			}
			return true;	
    },
	/**
	 * Validación del tipo de datos, esta funcion se puede sobreescribir para ejecutar una validación personalizada
	 * Por ejemplo:
	 * TextValidator.validReg = function(str) {
			if(str==undefined) str=$F(this.input_id);
			return !/[^\d-]/.test(str); //admite números y guiones para teléfonos.
	   }
	 * @param {Object} str Opcional
	 */
	validReg: function(str) {
		if(str==undefined) str=$F(this.input_id);
        var re = false;
       	switch (this.options.validType.toLowerCase()) {
            case 'number':
            re = !/[^\d]/.test(str);
            break;
            case 'alpha':
            re = /^[a-zA-Z]+$/.test(str);
            break;
            case 'alphanum':
            re = !/\W/.test(str);
            break;
            case 'email':
            re = /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(str);
            break;
			 case 'empty':
            re = !str.blank();
            break;
	   }
       return re;
    },
	
	isEmpty:function(){
		return $F(this.input_id).blank();	
	},
	isRequired:function(){
		return this.options.required;
	},
	validMinChars:function(){
		if($F(this.input_id).length < this.options.minChars && this.options.minChars!=null){
	   		return false;	
	   }
	   return true;
	},
	
	validMinValue:function(){
	    if($F(this.input_id) < this.options.minValue && this.options.minValue!=null){
	   		return false;	
	   }
	   return true;
	},
	
	validMaxValue:function(){
	    if($F(this.input_id) > this.options.maxValue && this.options.maxValue!=null){
	   		return false;	
	   }
	   return true;
	},
	
	validMaxChars:function(){
	    if($F(this.input_id).length > this.options.maxChars && this.options.maxChars!=null){
	   		return false;	
	   }
	   return true;
	},
	validAll:function(){
		if(!this.isRequired() && this.isEmpty()){
			return true;
		}
		if(this.isRequired() && this.isEmpty()){
			return false;
		}
		if(!this.validReg()) return false;
		if(!this.validMinChars()) return false;
		if(!this.validMaxChars()) return false;
		if(!this.validMinValue()) return false;
		if(!this.validMaxValue()) return false;
		return true;
	},
	
	getValue: function(){
		return $F(this.input_id);
	},
	
    getLastVal: function() {
        return this.lastval;

    },
	
	setLastVal: function(event){
		this.lastval = $F(this.input_id);
	},
	
	applyMask: function(event) {
		if(this.options.useMask){
    		if (event.keyCode == 8) {
        		var current = $F(this.input_id);
        		//update lastval
        		this.lastval = current;
        		if (this.validateOn == 'keyup') {
					return this.validate();
				}
    		}
    		//var char = current.charAt(current.length-1);
    		if (!this.validReg()) {
        		$(this.input_id).value = this.lastval;
			} else {
        		this.lastval = current;
    		}
		}
		if (this.validateOn == 'keyup') {
			return this.validate();
		}
	}
});

/**
 * Valida el valor de varios inputs text relacionados, por ej. una fecha.
*/
var MultipleText = Class.create();
Object.extend(MultipleText.prototype, {
	/**
	 * Constructor de MultipleText
	 * @param {String} highlight_id	 Id del Elemento HTML que cambia de color según el campo sea válido o no.
	 * @param {Object} options	Opciones variables, consultar TextValidator#setOptions
	 * @constructor
	 */
	initialize: function(highlight_id, options) {
        this.inputs = new Array();
		this.listeners = new Array();
		this.highlightId = highlight_id; 
		this.valid = true;
		this.setOptions(options);
		this.validateOn = null;
		this.autoHighlight=true;
		this.ignore=false;
		this.effect=null;
    },
	
	setOptions: function(options) {
		this.options = {
		    highlightId:null, //Sin uso
			noValidColor:'#EE5f19',
			validColor:'#000000',
			validType:'empty',
			useMask:true,
			required:true,
			minChars:null,
			maxChars:null
		};
		Object.extend(this.options, options || {});
	},
	/**
	* Añade un input text, todos los inputs añadidos de esta manera estan realicionados.
	* @param {string} id Id del Input.
	* @param {Object} options	Opciones variables para cada input añadido(tipo de validación, núm. caracteres, etc), consultar TextValidator#setOptions
	*/
	addInput: function(id, options) {
		var add_options = {}; 
		Object.extend(add_options, this.options);
		var input = new TextValidator(id, Object.extend(add_options, options || {}));
	
		input.autoHighlight = this.autoHighlight;
		//input.removeListeners();
        this.listeners.push(this.keyUpEvent.bindAsEventListener(this));
        $(input.input_id).observe('keyup', this.listeners[this.listeners.length - 1]);
        this.inputs.push(input);
    },
	
	cancel:function(){
		if(this.effect == null) return;
		this.effect.cancel();
		this.valid=true;
	},
	
	highlightOn: function(){
		if (this.valid) {
			if (this.highlightId != null && this.options.noValidColor != null && this.options.validColor != null) {
				this.effect = new Effect.HighlightText(this.highlightId, {
					startcolor: this.options.validColor,
					endcolor: this.options.noValidColor,
					time: 0.5
				});
						
			}
			this.valid = false;

		}
	},
	highlightOff: function(){
		if (!this.valid) {
			if (this.highlightId != null && this.options.noValidColor != null && this.options.validColor != null) {
				this.effect = new Effect.HighlightText(this.highlightId, {
					startcolor: this.options.noValidColor,
					endcolor: this.options.validColor,
					time: 0.5
				})
						
			}
			this.valid = true;
		}
	},
	
	keyUpEvent: function(event) {
    	if (!this.validateInputs()) {
			if(this.validateOn!='keyup') return;
			if(!this.autoHighlight) return;
			this.highlightOn();
		}else{
			if(this.validateOn!='keyup') return;
			if(!this.autoHighlight) return;
			this.highlightOff();
		}
	},
	
	validateInputs:function(){
		var valid = true;
        this.inputs.each(function(elm) {
            var err = elm.validate();
            if (!err) {
                valid = false;
            }
            return;
        });
        return valid;
	},
	validate:function(){
		if(this.ignore) return true;
		this.validateOn='keyup';
		this.keyUpEvent();
		return this.validateInputs();
	}
});
/**
 * Valida el valor de un SELECT, no se supera la validación cuando el OPTION seleccionado tiene value=""
 * Extiende TextValidator
*/
SelectValidator = Class.create();
Object.extend(SelectValidator.prototype, TextValidator.prototype);
Object.extend(SelectValidator.prototype, {
	/**
	 * Constructor de SelectValidator
	 * @param {Object} text_id el Id del SELECT
	 * @param {Object} options, consultar TextValidator#setOptions
	 */
    initialize: function(text_id, options) {
        this.start(text_id, options);
    },
    start: function(text_id, options) {
        this.input_id = text_id;
		this.listeners = new Array();
		this.lastval = '';
		this.valid = true;
		this.errorCode=1;
		this.related= new Array();
		this.autoHighlight=true;
		this.ignore=false;
		this.effect=null;
		//
		this.setOptions(options);
		//
		this.lastval = $F(this.input_id);
		//if(this.useMask){
			this.listeners.push(this.applyMask.bindAsEventListener(this));
			$(this.input_id).observe('change',this.listeners[0]);
		//}
    },
	setOptions: function(options) {
		this.options = {
		    highlightId:null,
			noValidColor:'#EE5f19',
			validColor:'#000000',
			validType:'empty',
			useMask:false,
			required:true,
			minChars:null,
			maxChars:null
		};
		Object.extend(this.options, options || {});
		
		//forzar opciones
		Object.extend(this.options, {
			validType:'empty',
			useMask:false,
			required:true
		});
	},
	 validate: function() {
	 	if(this.ignore) return true;
	 	if($(this.input_id).disabled){
			this.highlightOff();
			return true;
		}
		if (!this.validAll()) {
            //true, false, true
			if (this.autoHighlight) {
				this.highlightOn();
			}
            return false;
        }
        if (this.validAll()) {	
            //false, true, false
			if (this.autoHighlight) {
				this.highlightOff();
			}
        }
        return true;

    }
});

/**
 * Convierte un div en un input_text, el nombre enviado por GET/POST es el id del div
*/
EditableText = Class.create();
Object.extend(EditableText.prototype, {
	/**
	 * Constructor de EditableText
	 * @param {String} field_id, id del div
	 * @param {String} input_class, clase del input text
	 * @param {Object} options, admite format y tabIndex, consultar this.options.
	 * @constructor 
	 */
	 initialize: function(field_id, input_class, options) {
	 	this.fieldId = field_id;
		this.fieldHTML = $(this.fieldId).innerHTML;
		this.inputClass = input_class;
		
		this.options = {
			/** 
			 * El formato del html del input text: {0}value, {1}name:field_id{2}id:field_id, {3}class, {4}tabindex
			 */
		    format:'<input type="text" value="{0}" name="{1}" id="{2}_editable" class="{3}" {4}/>',
			/**
			 * Orden de tabulación en caso de que se desee indicar.
			 */
			tabIndex:null
		};
		
		Object.extend(this.options, options || {});
		new Insertion.After(this.fieldId, '<input type="hidden" value="'+this.getValue()+'" name="'+this.fieldId+'" id="'+this.fieldId+'_hidden" />');
	 },
	 
	 printf : function() { 
  		var num = arguments.length; 
  		var str = arguments[0];   
  		for (var i = 1; i < num; i++) { 
    		var pattern = "\\{" + (i-1) + "\\}"; 
    		var re = new RegExp(pattern, "g"); 
    		str = str.replace(re, arguments[i]); 
 		} 
 		return str; 
	 },
	
	 getValue:function(){
	 	if($(this.fieldId+'_hidden')!=null){
			return $(this.fieldId+'_hidden').value;
		}
	 	if($(this.fieldId+'_editable')==null){
			return $(this.fieldId).innerHTML.strip();
		}
	 	return $F(this.fieldId+'_editable');
	 },
	 /**
	  * Dibuja el input, sustituye el contenido del div y lo incluye en el atributo value
	  */
	 showInput: function(){
	 	
	 	$(this.fieldId).setStyle({
			visibility: 'visible'
		});
		var tabindex='';
		if(this.options.tabIndex) tabindex='tabindex="'+this.options.tabIndex+'"';
	 	var input_html = this.printf(this.options.format, this.getValue(), this.fieldId, this.fieldId, this.inputClass, tabindex);
	 	$(this.fieldId).update(input_html);
		$(this.fieldId+'_hidden').remove();
	 }
});
/**
 * Compara el valor de 2 o más inputs, extiende TextValidator
*/
var CompareText = Class.create();
Object.extend(CompareText.prototype, TextValidator.prototype);
Object.extend(CompareText.prototype,{
	/**
	 * Constructor de CompareText
	 * @param (Arguments)	número variable de objectos tipo "Validator", luego son comparados entre si.
	 * @constructor
	 */
	initialize:function(){
		this.inputs = new Array();
		this.options = {
		    highlightId:null,
			noValidColor:'#EE5f19',
			validColor:'#000000'
		};
		this.valid = true;
		this.autoHighlight = true;
		this.errorCode=2;
		for(var i=0; i<arguments.length; i++){
			this.inputs.push(arguments[i]);
		}
	},
	cancel:function(){
		this.inputs.each(function(input){
			input.cancel();
		});
	},
	highlightOn: function(){
		if (this.valid) {
			if (typeof this.inputs[0] == 'object') {
				this.inputs.each(function(input){
					input.highlightOn();
				});
				this.valid = false;  
			}
		}
	},
	highlightOff: function(){
		if (!this.valid) {
			if (typeof this.inputs[0] == 'object') {
				this.inputs.each(function(input){
					input.highlightOff();
				});
			}
			this.valid = true;	
		}
	},
	checkValid:function(){
		var val=true;
		if (typeof this.inputs[0] == 'object') {
			var firstStr = this.inputs[0].getValue();
		}
		else {
			var firstStr = $F(this.inputs[0]);
		}
		this.inputs.each(function(input, index){
			if (typeof input == 'object') {
				var v = input.getValue();
			}
			else {
				var v = $F(input);
			}
			if (v != firstStr) {
				val = false;
				return;
			}
		});
		return val;
	},
	/**
	 * Devuelve true en caso de que todos los objetos parasados al constructor tengan el mismo valor en el campo value
	 */
	validate:function(){
		var val=this.checkValid();
		return val;
		
	}
});
/**
 * Comprueba si un checkbutton esta seleccionando o no, extiende TextValidator
*/
CheckValidator = Class.create();
Object.extend(Object.extend(CheckValidator.prototype, TextValidator.prototype), {
	validate: function() {
		if(this.ignore) return true;
			if (!$(this.input_id).checked) {
				//true, false, true
				if(this.autoHighlight){
					this.highlightOn();
				}
				return false;
			}
			if ($(this.input_id).checked) {
				//false, true, false
				if(this.autoHighlight){
					this.highlightOff();
				}
			//}
			}
			return true;	
    }
});
/*END VALIDATOR*****************************************************************************************************/
/**
 * Muestra el resultado de la multiplicación de el número introducido en un input 
 * por un valor indicado, extiende TextValidator
 */
SumControl = Class.create();
Object.extend(Object.extend(SumControl.prototype, TextValidator.prototype), {

	 /**
	  * Constructor de SumControl
	  * @param {String} text_id el elemento que recibe el multiplicador(veces que se suma)
	  * @param {Number} val	el valor del multiplicando(numero a sumar)
	  * @param {Object} options highlightId recibe el id del elemento html donde se 'dibuja' el resultado de la multiplicación
	  * @constructor
	  */
	initialize: function(text_id, val, options) {
        this.start(text_id, options);
		//	
		this.val = val;
		this.options = {};
		Object.extend(this.options,{
				validType: 'number',
				format : '{0} &#8364;', //multiplicación y simbolo del euro.
				useMask:true,
				useComma:true
		});
		Object.extend(this.options, options);
		
		this.listeners.push(this.keyUpEvent.bindAsEventListener(this));
		$(this.input_id).observe('keyup', this.listeners[this.listeners.length-1]);
    },
	validate:function(){
		return !this.isEmpty();
	},
	getType:function(){
		return $(this.input_id).type;
	},
	getHandler:function(){
		switch(this.getType()){
		case 'text':
			return 'keyup';
			break;
		case 'select-one':
			return 'change';
		}
	},
	printf : function() { 
  		var num = arguments.length; 
  		var str = arguments[0];   
  		for (var i = 1; i < num; i++) { 
    		var pattern = "\\{" + (i-1) + "\\}"; 
    		var re = new RegExp(pattern, "g"); 
    		str = str.replace(re, arguments[i]); 
 		} 
 		return str; 
	},
	getSum: function(){		
		var num=$F(this.input_id); 
			
		if(String(Number(num))=='NaN'){
			num = this.getLastVal();
		}
		if(num.blank()){
			num = 0;
		}
		num = num*this.val;
		var dec = Number(num)*100;
		dec = Math.round(dec);
		num = dec/100;
		return num;
	},
	keyUpEvent:function(event) {
		var num = this.getSum();
		if(this.options.highlightId!=null){
			var rIn='.';
			var rOut=',';
			if(!this.options.useComma){
				rOut='.';
			}
			$(this.options.highlightId).innerHTML = this.printf(this.options.format, String(num).replace(rIn,rOut));
		}
		return num;
	},
	update:function(){
		var num = this.keyUpEvent();	
		return num;
	},
	removeListeners:function(){
		for(i=1;i< this.listeners.length; i++){
			$(this.input_id).stopObserving('keyup', this.listeners[i]);
		}
	}
});
/**
 * Muestra el resultado de la multiplicación de el número indicado en el value de un Option en un SELECT 
 * por un valor indicado
 */
SumSelectControl = Class.create();
Object.extend(SumSelectControl.prototype, {
		 /**
	  * Constructor de SumControl
	  * @param {String} select_id	El id del SELECT, el atributo value de cada option es el multiplicador
	  * @param {String} highlight_id	El id del elemento html donde se muestra el resultado(un div, un span, etc...)
	  * @param {Number} val		el mutiplicando
	  * @constructor
	  */
	 initialize: function(select_id, highlight_id, val) {
        this.input_id= select_id,
		this.listeners= new Array();	
		this.val= 1;
		this.highlightId= highlight_id;
		this.format= '{0} &#8364;';
		this.useComma=true;
		this.listeners.push(this.keyUpEvent.bindAsEventListener(this));
		$(this.input_id).observe('change', this.listeners[this.listeners.length-1]);
    },
	
	printf : function() { 
  		var num = arguments.length; 
  		var str = arguments[0];   
  		for (var i = 1; i < num; i++) { 
    		var pattern = "\\{" + (i-1) + "\\}"; 
    		var re = new RegExp(pattern, "g"); 
    		str = str.replace(re, arguments[i]); 
 		} 
 		return str; 
	},
	
	getType:function(){
		return $(this.input_id).type;
	},
	
	getHandler:function(){
		switch(this.getType()){
		case 'text':
			return 'keyup';
			break;
		case 'select-one':
			return 'change';
		}
	},

	getSum: function(){		
		var num=$F(this.input_id); 
			
		if(String(Number(num))=='NaN' || num.blank()){
			num = 0;
		}
		num = num*this.val;
		var dec = Number(num)*100;
		dec = Math.round(dec);
		num = dec/100;
		return num;
	},
	
	keyUpEvent:function(event) {
		var num = this.getSum();
		var rIn='.';
		var rOut=',';
		if(!this.useComma){
			rOut='.';
		}
		$(this.highlightId).innerHTML = this.printf(this.format, String(num).replace(rIn,rOut));
		return num;
	},
	update:function(){
		var num = this.keyUpEvent();	
		return num;
	},
	
	removeListeners:function(index){
		if(index){
			$(this.input_id).stopObserving('change', this.listeners[index]);
			return;
		}
		for(i=0;i< this.listeners.length; i++){
			
			$(this.input_id).stopObserving('change', this.listeners[i]);
		}
	}
});
/**
 * Muestra la suma del resultado producido por varios SumControl/SumSelectControl, tambien puede
 * sumar el resultado de otras SumList
 */
SumList = Class.create();
Object.extend(SumList.prototype, {
	/**
	 * Constructor de SumList
	 * @param {String} highlight_id		Id del elemento HTML donde se muestra el resultado
	 * @constructor
	 */
    initialize: function(highlight_id) {
        this.highlightId = highlight_id,
        this.format = '{0} &#8364;',
        this.controls = new Array(),
        this.periodical = null,
        this.listeners = new Array(),
		this.useComma = true;
        this.objType = 'SumList';

    },
	/**
	 * Se utiliza para añadir Objectos que seran sumados.
	 * @param {Object} obj	El objeto admitido puede ser del tipo SumControl, SumSelectControl o otra SumList
	 */
    addControl: function(obj) {
        if (String(obj.objType) == 'undefined' || obj.objType != this.objType) {
            obj.removeListeners(1);
            this.listeners.push(this.keyUpEvent.bindAsEventListener(this));
            $(obj.input_id).observe(obj.getHandler(), this.listeners[this.listeners.length - 1]);
            this.controls.push(obj);
            return;

        }
        this.addSumList(obj);

    },
    removeListeners: function() {
        for (i = 0; i < this.listeners.length; i++) {
            var listener = this.listeners[i];
            this.controls.each(function(obj) {
                $(obj.input_id).stopObserving(obj.getHandler(), listener);

            });

        }
        this.listeners = new Array();

    },
    addSumList: function(obj) {
        /*obj.removeListeners();*/
        this.controls = this.controls.concat(obj.controls);
        var listeners = this.listeners;
        var _parent = this;
        this.controls.each(function(o) {
            listeners.push(_parent.keyUpEvent.bindAsEventListener(_parent));
            var listener = listeners[listeners.length - 1];
            $(o.input_id).observe(o.getHandler(), listener);

        });

    },
    printf: function() {
        var num = arguments.length;
        var str = arguments[0];
        for (var i = 1; i < num; i++) {
            var pattern = "\\{" + (i - 1) + "\\}";
            var re = new RegExp(pattern, "g");
            str = str.replace(re, arguments[i]);

        }
        return str;

    },
    getSum: function() {
        var num = 0;
        this.controls.each(function(obj) {
            num += obj.update();

        });
        //return num;
        var dec = Number(num) * 100;
        dec = Math.round(dec);
        num = dec / 100;
        return num;

    },
    keyUpEvent: function() {
        var num = this.getSum();
		var rIn='.';
		var rOut=',';
		if(!this.useComma){
			rOut='.';
		}
        $(this.highlightId).innerHTML = this.printf(this.format, String(num).replace(rIn, rOut));
        return num;

    },
    update: function() {
        return this.keyUpEvent();

    }

});

/*END SUMS***********************/

/**
 * Relaciona 2 SELECTS, el contenido de target varia en función del value 
 * indicado en un segundo SELECT
 */
RelatedSelects = Class.create();
Object.extend(RelatedSelects.prototype, {
	/**
	 * Constructor de RelatedSelects
	 * @param {String} target_id		Id del SELECT cuyo contenido varia
	 * @constructor 
	 */
    initialize: function(target_id) {
        this.start(target_id);

    },
    start: function(target_id) {
        this.target = target_id;
        this.lists = new Array();
		this.formats = new Array();
        this.listener = null;
		this.defaultFormat="";

    },
	
	/**
	 * Añade una nueva lista de options(almacenados en un array), el primer arguento es el índice, se puede usar de varias maneras, por ej:
	 * 	addList(1, {val:1, text:'provincia 1'},{val:2, text:'provincia 2'},{val:3, text:'provincia 3'});
	 * 	En este caso, se añaden 3 options que se muestran en al escoger el item con el value="1" del segundo select
	 *  Cada option es un un objeto con val, el value, y text, el texto dentro de cada<option>texto texto texto</option>
	 *  
	 *  Se pueden utilizar valores string como value, por ej:
	 * 	addList('listado_1', {val:1, text:'provincia 1'},{val:2, text:'provincia 2'},{val:3, text:'provincia 3'}); 
	 * 
	 *  Permite la combinacion de valores númericos y string, ya que javascript permite arrays mixtos de indices numéricos y asociativos.
	 *  
	 *  Se puede pasar como argumento un array que contenga objetos tipo {val:1, text:'provincia 1'} por ej:
	 *  var arr = new Array();
	 *		arr.push({val:1, text:'provincia  1'});
	 *		arr.push({val:2, text:'provincia  2'});
	 *		RelatedSelects.addList(2, prov_ita);
	 *
	 *	Si no se pasa como primer argumento un numero o string para indicar el índice,
	 *	la lista de options es almacenada en la siguiente posición del array, por ej:
	 *  addList({val:1, text:'provincia 1'},{val:2, text:'provincia 2'},{val:3, text:'provincia 3'}); 
	 *  posición 1
	 *	addList({val:3, text:'provincia 4'},{val:4, text:'provincia 5'},{val:5, text:'provincia 6'}); 
	 *  posición 2
	 *  etc...
	 */
    addList: function() {
		var pos = this.lists.length;
		var start=0;
		if(typeof arguments[0] == 'number' || typeof arguments[0] == 'string'){
			pos = arguments[0];
			start=1;
		}
        this.lists[pos] = new Array();
		for (i = start; i < arguments.length; i++) {
			if(typeof arguments[i] == 'string'){
			this.formats[pos] = arguments[i];
			}else if (arguments[i].length != undefined) {
				for (z = 0; z < arguments[i].length; z++) {
					var elm = arguments[i][z];
					this.lists[pos].push(elm);
				}
			}else{
				var elm = arguments[i];
				this.lists[pos].push(elm);
			}
		}
    },
	/**
	 * Sirve para indicar el select que produce el cambio de options en el select objetivo.
	 * Si una opcion deja value en blanco o no tiene una lista de opciones relacionadas al índice indicado en value
	 *  se vacia el select objetivo y se deja desactivado.
	 * @param {String} id
	 */
	addSelectListener: function(id) {
        this.listener = id;
        $(this.listener).observe('change', this.showList.bindAsEventListener(this)); 
    },
	/**
	 * @see RadioControl#checkHidden
	 */
    checkHidden: function() {
        this.showList($(this.listener).value);
        //this.control.checkHidden();

    },
	/**
	 * Muestra un listado de elementos seleccionables.
	 * @param {Object} num El número de listado a mostrar almacenados en 'lists'
	 */
    showList: function(index) {
		if(typeof index == 'object') index = Event.element(index).value;
        var out = '';
		var cont=1;
		var target = $(this.target);
		$(this.target).length=0;
		$(this.target).remove(0);
		if(this.defaultFormat != null){
			$(this.target).options[0] = new Option(this.defaultFormat,"");
		}else{
			cont=0;
		}
		if (index.blank() || this.lists[index]==undefined || this.lists[index]==null) {
			$(this.target).disable();
		}
		else {
			var format = this.formats[index];
			if(format){
				$(this.target).options[0] = new Option(format,"");
			}
			var list = this.lists[index];
			var _parent = this;
			list.each(function(obj){
			
				target.options[cont]=new Option(obj.text, obj.val);
				cont++;
			});
			$(this.target).enable();
		} 
    }
});
//
/**
 * @classDescription Agrupa un conjunto de controles, solo permite el submit en cuanto estos pasan su validación.
 * Se pueden añadir, controles, un mensaje extra de alerta e inputs susceptibles a la validación cuando se pulsa la tecla 'enter'
 *
 */

FormValidator = Class.create();
Object.extend(FormValidator.prototype, {
	/**
	 * 
	 * @param {Object} form_id El ide del formulario, intercepta su submit.
	 */
    initialize: function(form_id) {
        this.formId = form_id,
        this.controls = new Array(),
		this.controls[0] = new Array(),
        this.inputs = new Array(),
        this.extraMsg = new Array(),
        this.listener = null,
        this.focused = null,
		this.autoHighlight = true;
		this.isAlert=false;
		this.lastErrorIndex=null;
		this.currentControls = null;
		this.msgText = new Array();
		this.action = $(this.formId).action;

		this.enableFocusListener();
		
       //var _parent = this;
        /*$(this.formId).onsubmit = function(event) {
			alert(_parent.focused);
			var focus_num = _parent.findInput(_parent.focused);
			alert(focus_num);
            if(focus_num != null) {
                var err = _parent.validate();
                return false;
            }
            return true;
        }*/
        
        /*
		$(this.formId).onsubmit = function(){
			return false;	
		}
		*/
		
		$(this.formId).observe('submit', this.handleOnSubmit.bindAsEventListener(this));

    },
	
	handleOnSubmit:function(event){
	    
	    //if(!document.all)
            //event.preventDefault();
            
        var id = this.focused;
        
        //Submit form if Search
        if(id && (id.indexOf('SearchTextBox') > 0))
        {
            if(($(id)).value.length > 0)
				if(!document.all)
					event.preventDefault();
                $(this.formId).submit();
				return true;
        }
        else
        {
            //Restore form action because search form sets it to Search page
			var searchAction = $(this.formId).action;
            $(this.formId).action = this.action;
        }
           
		var focus_num = this.findInput(this.focused);
		//alert(focus_num);
        if(focus_num != null) {
			if(!document.all) event.preventDefault();
		   //alert("validate");
           var valid = this.validate();
		   if(valid){
			 $(this.formId).action = this.action;  
			 $(this.formId).submit();
		  }
           return false;
        }
        $(this.formId).action = searchAction;
		$(this.formId).submit();
        return false;
	},
    /**
	*Añade objetos de validación, como TextValidator, RadioControlClass...
	* @alias FormValidator.addControl
	* @param {args} arguments Núm. Variable de objetos tipo TextValidator y RadioControl.
	*/
    addControl: function() {
        //this.controls.push(elm);
		var len = arguments[0];
		var pos = 0;
		if(typeof arguments[0]!='number'){
			len = 0;
		}else{
			this.controls[len] = new Array();
			pos = 1;
		}
		//var len = this.controls.length;
		//this.controls[len] = new Array();
		for (var i = pos; i < arguments.length; i++) {
			if (typeof arguments[i] == 'string') {
				this.msgText[len] = arguments[i];
			}else {
				arguments[i].autoHighlight = this.autoHighlight;
				this.controls[len].push(arguments[i]);
			}
					
		}
    },

	/**
	*Añade inputs susceptible a la validación cuando se pulsa la tecla 'enter', por ej: campos de texto.
	* @param {args} arguments Núm. Variable de ids(String).
	*/
    addInput: function() {
        //this.inputs.push(id);
		for (var i = 0; i < arguments.length; i++) {
			this.inputs.push(arguments[i]);			
		}
    },

	/**
	*Añade un solo mensaje de alerta
	@param {string} id Id de elemento HTML
	*/
    addAlert: function(id) {
        this.extraMsg.push(id);
    },

	findInput: function(val) {
        var pos = null;
        this.inputs.each(function(current, i) {
            if (current == val) {
                pos = i;
                return;
            }
        });
        return pos;
    },

	checkHidden: function() {
        this.controls.each(function(elms, controls_index) {
			elms.each(function(elm){
            	if (typeof elm.checkHidden == 'function') {
                	elm.checkHidden();
            	}
			});
        });
    },

	checkValid: function() {
        var valid = true;
		var errorIndex = null;
		var autoHighlight = this.autoHighlight;
		var stop=false;
		var i=0;
		var controls = this.controls;
		while(i<this.controls.length && !stop){
			this.controls[i].each(function(elm){
            	var err = elm.validate();

            	if (!err) {			 		
					valid=false;
            	}
			});
			if (!valid) {
				stop = true;
			}else{
				i++;
			}
		}
		
		if(typeof this.msgText[i]!='undefined') $(this.extraMsg[0]).update(this.msgText[i]);
		this.currentControls = this.controls[i];
		if(valid){
			return valid;
		}
		
		this.controls[i].each(function(elm) {
			var err = elm.validate();

            if (!err) {
				if (!autoHighlight) {
					elm.highlightOn();
				}
            }else{
				if(!autoHighlight) {
					elm.highlightOff();
				}
			}
        });
		return valid;
    },
    checkCurrentControls:function(){
		
		var valid = true;	
		var autoHighlight = this.autoHighlight;
		
		this.currentControls.each(function(elm){
			var err = elm.validate();
            if (!err) {
				if (!autoHighlight) {
					elm.highlightOn();
					
				}
				valid=false;
            }else{
				if(!autoHighlight) {
					elm.highlightOff();
				}
			}
        });
		return valid;
	},
	
	validate: function(ops) {
		var  options = {};
		options.cancelSubmit=false;
		options = Object.extend(ops || {});
	    var valid = this.checkValid();
        if (valid) {
        
           //$(this.formId).submit();
		   //alert("submit");
			//return true;
			//alert("validate");
			if($(this.listener))
			{
			    //alert("listener");
			    if($(this.listener).tagName == "A"){
					//alert("A");
			        return true;
			        //eval($(this.listener).attributes["href"].nodeValue);
				}else{
					//alert("submit");
					if(!options.cancelSubmit)$(this.formId).submit();		
				}
               	return false;
            }
			

        } else {
            if (this.extraMsg.length != 0 && !this.isAlert) {
                $(this.extraMsg[0]).setStyle({
                    opacity: 0,
                    visibility:'visible'

                });
                this.appearMsg();
				this.isAlert=true;
            }
        }
		return false;
        /*alert($(this.formId).serialize());*/
    },
    appearMsg: function() {
        _parent = this;
		$(this.extraMsg[0]).setStyle({
        	opacity: 0,
            visibility:'visible'

        });
        new Effect.Appear(this.extraMsg[0], {
            from: 0,
            to: 1,
            afterFinish: function(obj) {
				var val = _parent.checkCurrentControls();
                if (!val) {
                    _parent.fadeMsg(_parent.extraMsg[0]);
					
				}else{
                    $(_parent.extraMsg[0]).setStyle({
                       opacity: 0,
                       //display:'none'
					   visibility:'hidden'
                    });
					_parent.isAlert=false;
                }
            }
        });
		
    },

	fadeMsg: function() {
        _parent = this;
        new Effect.Fade(this.extraMsg[0], {
            from: 1,
            to: 0,
            afterFinish: function(obj) {
				obj.element.setStyle({
                       opacity: 0        
                });
                if (!_parent.checkCurrentControls()) {
                    _parent.appearMsg(_parent.extraMsg[0]);

				}else{
                    $(_parent.extraMsg[0]).setStyle({
                        opacity: 0,
                        visibility:'hidden'
                    });
					_parent.isAlert=false;
                }
            }
        });
    },
    /**
	* Añade elementos que funcionan como un input tipo submit.
	* @param {string} id Id del elemento HTML.
	*/
    addButtonListener: function(button_id) {
        //this.listener = button_id;
		//$(this.listener).observe('click', this.validate.bindAsEventListener(this));
		
		var _parent = this;
		var elm = button_id;
		
		if($(elm).tagName == "A")
		{
			_parent.listener = elm;
			
		    /*
            $(elm).observe('focus', function(event) {
                _parent.focused = Event.element(event).id;
                _parent.listener = elm;
                _parent.validate();
            });
            $(elm).observe('blur', function(event) {
                _parent.focused = null;
            });
            */

		}
	    else
	    {
	        _parent.listener = elm;
            $(elm).observe('click', this.validate.bindAsEventListener(this));
        }
		
		
    },
	
	enableFocusListener: function() {
        var form = $(this.formId);
        var _parent = this;
        form.getInputs('text').each(function(elm) {
            $(elm).observe('focus', function(event) {
                _parent.focused = Event.element(event).id;
            });
            $(elm).observe('blur', function(event) {
                _parent.focused = null;
            });
        });
		 form.getInputs('password').each(function(elm) {
            $(elm).observe('focus', function(event) {
                _parent.focused = Event.element(event).id;
            });
            $(elm).observe('blur', function(event) {
                _parent.focused = null;
            });
        });
    }
});