/*
Lenovo LA Script Library
Author: Juan Ignacio Dopazo (jdopazo@lenovo.com)
Owner: Diego Darriba (darrbad@lenovo.com)

Copyright (c) 2009, Lenovo. All rights reserved.
*/
var LNV = {
	
	/* Devuelve si needle se encoentra en el arreglo/objeto haystack */
	inArray: function (needle, haystack) {
		var i,
			length = haystack.length;
		for (i = 0; i < length; i = i + 1) {
			if (haystack[i] == needle) {
				return true;
			}
		}
		return false;
	},
	
	indexOf: function (needle, haystack) {
		var i,
			length = haystack.length;
		for (i = 0; i < length; i = i + 1) {
			if (haystack[i] == needle) {
				return i;
			}
		}
		return -1;
	},

	math: {
		/* Redondea number hacia arriba */
		roundUp: function (number) {
			var result = Math.round(number);
			result += (number % 1 > 0 && number % 1 < 0.50) ? 1 : 0;
			return result;
		}
	},
	
	util: {},
	
	widget: {},
	
	debug: {
		messages: {},
		log: function () {}
	},
		
	fill_LA_mailto: function () {
		this.get("LA_mailto").innerHTML = '<a href=\"mailto:?body=' + window.location.href + '" class="fbox">Enviar esta p&aacute;gina por e-mail<\/a>';
	},

	get: function (id) {
		return document.getElementById(id);
	},
	
	getByTag: function (tagName) {
		return document.getElementsByTagName(tagName);
	},
	
	preloadImages: function () {
		var imgs = [],
			arg = arguments,
			current = 0,
			i,
			j;
		for (i = 0; i < arg.length; i = i + 1) {
			if (arg[i].constructor == Array) {
				for (j = 0; j < arg[i].length; j = j + 1) {
					this.preloadImages(arg[i][j]);
				}
			} else if (arg[i].constructor == String) {
				current = imgs.length;
				imgs[current] = new Image();
				imgs[current].src = arg[i];
			}
		}
	}
};
LNV.events = function () {
	
	var EventCache = (function () {
		var listEvents = [];
		return {
			listEvents: listEvents,
			add: function (node, sEventName, fHandler) {
				listEvents.push(arguments);
			},
			flush: function () {
				var i, 
					item,
					removeEventListener = document.getElementsByTagName("body").removeEventListener ? true : false,
					detachEvent = document.getElementsByTagName("body").detachEvent ? true : false;
				for (i = listEvents.length - 1; i >= 0; i = i - 1) {
					item = listEvents[i];
					if (removeEventListener) {
						item[0].removeEventListener(item[1], item[2], item[3]);
					}
					if (item[1].substring(0, 2) != "on") {
						item[1] = "on" + item[1];
					}
					if (detachEvent) {
						item[0].detachEvent(item[1], item[2]);
					}
					item[0][item[1]] = null;
				}
			}
		};
	})(),
	
	_add = function (obj, type, fn, preventDefault) {
		preventDefault = preventDefault || false;
		obj["e" + type + fn] = fn;
		if (obj.addEventListener) {
			obj.addEventListener(type, function (e) {
				if (preventDefault) {
					e.preventDefault();
				}
			}, false);
			obj.addEventListener(type, fn, false);
			EventCache.add(obj, type, fn);
		} else if (obj.attachEvent) {
			obj[type + fn] = function () { 
				obj["e" + type + fn](window.event);
				return !preventDefault;
			};
			obj.attachEvent("on" + type, obj[type + fn]);
			EventCache.add(obj, type, fn);
		} else {
			obj["on" + type] = obj["e" + type + fn];
		}
	};
	
	_add(window, 'unload', EventCache.flush);
	
	return {
		add:	_add,
		
		remove: function (object, type, func) {
			if (object.removeListener) {
				object.removeListener(type, func);
			} else if (object.detachEvent) {
				object.detachEvent(type, func);
			} else {
				object["e" + type + func] = function () {};
			}
		}
	};
}();
LNV.util.dom = (function () {
	var _docAll = document.all ? true : false,
		classId = _docAll ? "className" : "class", /* According to the browser the "class" attribute might be "className" or "class" */
		none = "none",

	createElement = function (elementName) {
		/* wrapper for better minification */
		return document.createElement(elementName);
	},

	_select = (function () {
		var option = "option", // for better minification
		
		_add = function (combo, text, value) {
			/* Note by jdopazo:
			 Lazy initialization for the function _add()
			 I create a <select> element that I never attach to the dom
			 and try to attach an <option> element to it with try...catch
			 This way I avoid using try...catch every time this function is called */
			var testSelect = createElement("select"),
				testOption = createElement(option),
				standards = false;
			try {
				testSelect.add(testOption, null); //standards compliant
				standards = true;
			} catch (ex) {
				testSelect.add(testOption); // IE only
			}
			if (standards) {
				_add = function (combo, text, value) {
					var newOption = createElement(option);
					newOption.text = text;
					if (value) {
						newOption.text = value;
					}
					combo.add(newOption, null);
				};
			} else {
				_add = function (combo, text, value) {
					var newOption = createElement(option);
					newOption.text = text;
					if (value) {
						newOption.value = value;
					}
					combo.add(newOption);
				};
			}
			_add(combo, text, value);
		},
		
		_fill = function (combo, values) {
			if (values && values.constructor == Array) {
				var valueLength = values.length,
					i,
					x;
				for (i = 0; i < valueLength; i = i + 1) {
					_add(combo, values[i]);
				}
			} else {
				for (x in values) {
					if (values.hasOwnProperty(x)) {
						_add(combo, x, values[x]);
					}
				}
			}
		},
		
		_clear = function (combo) {
			combo.options.length = 0;
		};
		
		return {
			add:		_add,
			fill:		_fill,
			clear:		_clear
		};
	}());
		
	return {
		/* Returns the document inside the iframe with id frameId */
		getFrameById: function (frameId) {
			var iframe = LNV.get(frameId);
			return iframe.contentDocument ||
					iframe.contentWindow.document ||
					iframe.document ||
					null;
		},
		
		docAll: _docAll,
		
		/* Setea la clase de element */
		setClass: function (element, sClass) {
			element.className = sClass;
		},
		
		addClass: function (element, sClass) {
			var classes = [];
			if (element.className) {
				classes = element.className.split(" ");
			}
			if (!LNV.inArray(sClass, classes)) {
				classes.push(sClass);
				element.className = classes.join(" ");
			}
		},
		
		removeClass: function (element, sClass) {
			var classes = [],
				i = 0;
			if (element.className) {
				classes = element.className.split(" ");
			}
			while (i < classes.length) {
				if (classes[i] == sClass) {
					classes.splice(i, 1);
				} else {
					i = i + 1;
				}
			}
			element.className = classes.join(" ");
		},
		
		hasClass: function (element, sClass) {
			var hasClass = false,
				classes,
				i;
			if (element.className) {
				classes = element.className.split(" ");
				i = 0;
				while (i < classes.length && !hasClass) {
					if (classes[i] == sClass) {
						hasClass = true;
					}
					i = i + 1;
				}
			}
			return hasClass;
		},
		
		hide: function (element) {
			element.style.display = none;
		},
		
		show: function (element) {
			element.style.display = "";
		},
		
		toggle: function (element) {
			var es = element.style;
			es.display = es.display == none ? "" : none;
		},
		
		create: createElement,
		
		select: _select
	};
}());
LNV.util.ajaxInternals = (function () {
	var _getActiveXParser = function (type) {
		var freeThreadedDOM = "Msxml2.FreeThreadedDOMDocument.",
			domDocument = "Msxml2.DOMDocument.",
			test;
		try {
			test = new window.ActiveXObject(domDocument + "6.0");
			_getActiveXParser = function (type) {
				if (type == "xsl") {
					return new window.ActiveXObject(freeThreadedDOM + "6.0");
				} else {
					return new window.ActiveXObject(domDocument + "6.0");
				}
			};
		} catch (e) {
			try {
				test = new window.ActiveXObject("Msxml2.DOMDocument.3.0");
				_getActiveXParser = function (type) {
					if (type == "xsl") {
						return new window.ActiveXObject(freeThreadedDOM + "3.0");
					} else {
						return new window.ActiveXObject(domDocument + "3.0");
					}
				};
			} catch (ex) {
				LNV.debug.log(2);
			}
		}
		return _getActiveXParser(type);
	},
	
	_getAjaxObject = function () {
		var hostname = window.location.host,
			msxml = "Microsoft.XMLHTTP",
			test;
		if ((window.location.protocol == "file:" || hostname == "localhost" || hostname == "127.0.0.1") && window.ActiveXObject) {
			_getAjaxObject = function () {
				return new window.ActiveXObject(msxml);
			};
		} else {
			try {
				test = new XMLHttpRequest();
				_getAjaxObject = function () {
					return new XMLHttpRequest();
				};
			} catch (e) {
				try {
					test = new window.ActiveXObject(msxml);
					_getAjaxObject = function () {
						return new window.ActiveXObject(msxml);
					};
				} catch (ex) {
					LNV.debug.log(1);
				}
			}
		}
		return _getAjaxObject();
	};

	return {
		transactions: [],
		
		Transaction: function (request, errorHandler) {
			this.request = request;
			this.errorHandler = errorHandler;
		},
		
		checkTimeout: function (transactionId) {
			var transaction = this.transactions[transactionId],
				request = transaction.request;
			if (request.readyState !== 4) {
				request.abort();
				transaction.errorHandler('timeout', 408, request);
			}
			this.transactions[transactionId] = null;
		},
		
		getActiveXParser: _getActiveXParser,
		
		getAjaxObject: _getAjaxObject
	};
}());

LNV.util.ajax = function (settings) {
	var xhr = LNV.util.ajaxInternals.getAjaxObject(), /* XMLHttpRequest object o equivalente */
	success = settings.success,

	Errors = {
		timeout: 'timeout',
		noObject: 'Can\'t create object',
		noStatus: 'Bad status'
	},
	
	xml = "xml",
	xsl = "xsl",

/* Parsea un XML
   En Internet Explorer instancia un objeto ActiveX llamado MSXML. En el resto usa XMLHttpRequest.responseXML */
	parseXML = function (xmlFile, type) {
		var xmlDoc = null;
		/* La eleccion de versiones 6.0 y 3.0 es adrede.
		   La version 4.0 es especifica de windows 2000 y la 5.0 viene unicamente con Microsoft Office
		   La version 6 viene con Windows Vista y uno de los service pack de XP, por lo que el usuario quizas no la tenga
		   Se la usa porque es considerablemente mas rapida */
		if (window.ActiveXObject) {
			xmlDoc = LNV.util.ajaxInternals.getActiveXParser(type);
			xmlDoc.async = false;
			xmlDoc.loadXML(xmlFile.responseText);
			if (xmlDoc.parseError.errorCode !== 0) {
				settings.error(Errors.noStatus, xmlDoc.parseError, xhr);
			}
		} else {
			xmlDoc = xmlFile.responseXML;
		}
		return xmlDoc;
	},

	getResultByContentType = function () {
		var contentType = settings.dataType || xhr.getResponseHeader('Content-type');
		switch (contentType) {
		case 'application/xml':
		case xml:
		case xsl:
			return parseXML(xhr, contentType);
		default:					
			return xhr.responseText;
		}
	},

	/* Abre una transaccion AJAX */
	open = function (destino) {
		if (settings.async === true) {
			xhr.onreadystatechange = function () {
				if (xhr.readyState === 4) {
					/* Normalmente deberia chequearse unicamente el status == 200, pero cuando se hace una transaccion local el status en IE termina siendo 0
					 por lo que con revisar que exista la respuesta alcanza */
					if (xhr.status === 200 || xhr.responseText || xhr.responseXML) { 
						settings.success(getResultByContentType());
					} else if (xhr.status === 408) {
						settings.error(Errors.timeout, xhr.status, xhr);
					} else {
						settings.error(Errors.noStatus, xhr.status, xhr); 
					}
				}
			};
		}
		/* Cuando la transacci�n se hace en un filesystem local y el archivo de destino no existe,
		   no se llega a pasar por el evento onreadystatechange sino que puede lanzar una excepci�n en algunos navegadores */
		try {
			xhr.open(settings.method, settings.url, settings.async);
			xhr.send(null);
		} catch (e) {
			settings.error(Errors.noStatus, 404, xhr); 
		}
		var result = false,
			ajaxInternals,
			index;
		if (settings.async === false) {
			result = getResultByContentType();
		} else {
			/* Ver notas en la declaracion de LNV.util.ajaxInternals.checkTimeout */
			ajaxInternals = LNV.util.ajaxInternals;
			index = ajaxInternals.transactions.length;
			ajaxInternals.transactions[index] = new ajaxInternals.Transaction(xhr, settings.error);
			window.setTimeout((function () {
				ajaxInternals.checkTimeout(index);
			}), settings.timeout);
		}
		return result;
	},
	
	result = null;
	
	settings.timeout	= settings.timeout || 10000; /* Tiempo que tarda en cancelarse la transaccion */
	settings.method		= settings.method || "GET"; /* Metodo para enviar informacion al servidor */
	settings.async		= settings.async || true;
	settings.complete	= settings.complete || function () {};
	settings.success	= function (result) {
		if (success) {
			success(result);
		}
		settings.complete();
	};
	settings.error		= function (a, b, c) {
		settings.error(a, b, c);
		settings.complete();
	};

	if (xhr) {
		/* Esto corrije el problema de ausencia de tipos mime en Stage solo si existe el metodo overrideMimeType (no existe en IE) */
		if (settings.dataType && (settings.dataType === "xml" || settings.dataType === "xsl") && xhr.overrideMimeType) {
			xhr.overrideMimeType('text/xml');
		}
		if (settings.url) {
			result = open(settings.url);
		}
	}
	return result;
};
LNV.util.XML = function (xmlObject) {
	var NodeCollection = function (xmlObject) {
		var nodeTypeElement = 1,
			nodeTypeText	= 3,
		
		/*
			nodeCollection must allways be an array of XML nodes event if it contains only one element
		*/
			nodeCollection = [xmlObject],
			collectionLength = 1,
		
		setCollection = function (newCollection) {
			nodeCollection = newCollection;
			collectionLength = newCollection.length;
		},
		
		getChildren = function (xmlNode) {
			var childNodes = xmlNode.childNodes,
				childs = [],
				nodesLength = childNodes.length,
				i;
			for (i = 0; i < nodesLength; i = i + 1) {
				if (childNodes[i].nodeType == nodeTypeElement) {
					childs[childs.length] = childNodes[i];
				}
			}
			return childs;
		},
		
		findPath = function (collection, path) {
			var tag = path.shift(),
				coLength = collection.length,
				newCollection = [],
				node,
				i;
			for (i = 0; i < coLength; i = i + 1) {
				node = collection[i].firstChild;
				while (node) {
					/* NOTA IMPORTANTE: chequear qu� sucede con los namespaces de XML para filtrarlos de esta manera */
					if (node.nodeName == tag) {
						newCollection[newCollection.length] = node;
					}
					node = node.nextSibling;
				}
			}
			if (path.length > 0 && newCollection.length > 0) {
				return findPath(newCollection, path);
			} else {
				return newCollection;
			}
		};
		
		this.children = function () {
			var children = [],
				i,
				j,
				nodeChilds,
				nodeChildsLength;
			for (i = 0; i < collectionLength; i = i + 1) {
				nodeChilds = getChildren(nodeCollection[i]);
				nodeChildsLength = nodeChilds.length;
				for (j = 0; j < nodeChildsLength; j = j + 1) {
					children[children.length] = nodeChilds[j];
				}
			}
			setCollection(children);
			return this;
		};
		
		this.firstChild = function () {
			var first = [],
				i;
			for (i = 0; i < collectionLength; i = i + 1) {
				first[first.length] = getChildren(nodeCollection[i])[0];
			}
			setCollection(first);
			return this;
		};
		
		this.parent = function () {
			var parents = [],
				i;
			for (i = 0; i < collectionLength; i = i + 1) {
				parents[parents.length] = nodeCollection[i].parentNode;
			}
			setCollection(parents);
			return this;
		};
		
		this.withChild = function (childName, childValue) {
			var result = [],
				node,
				i;
			if (childName.constructor == String) {
				for (i = 0; i < collectionLength; i = i + 1) {
					node = nodeCollection[i].firstChild;
					while (node) {
						if (node.nodeName == childName && node.firstChild && node.firstChild.nodeValue == childValue) {
							result[result.length] = nodeCollection[i];
						}
						node = node.nextSibling;
					}
				}
			} else if (childName.constructor == Number) {
				for (i = 0; i < collectionLength; i = i + 1) {
					node = nodeCollection[i].childNodes[childName];
					if (node && node.firstChild && node.firstChild.nodeValue == childValue) {
						result[result.length] = nodeCollection[i];
					}
				}
			}
			setCollection(result);
			return this;
		};
		
		this.find = function (query) {
			var result = findPath(nodeCollection, query.split("/"));
			setCollection(result);
			return this;
		};
		
		this.nth = function (index) {
			var result = [],
				i;
			for (i = 0; i < collectionLength; i = i + 1) {
				var children = getChildren(nodeCollection[i]);
				if (children[index]) {
					result[result.length] = children[index];
				}
			}
			setCollection(result);
			return this;
		};
		
		this.each = function (action) {
			for (var i = 0; i < collectionLength; i = i + 1) {
				action.call(nodeCollection[i]);
			}
			return this;
		};
		
		this.get = function () {
			return (collectionLength == 1) ? nodeCollection[0] : nodeCollection;
		};
		
		this.val = function () {
			var value = "",
				i,
				children;
			if (collectionLength == 1 && nodeCollection[0].firstChild && nodeCollection[0].firstChild.nodeType == nodeTypeText) {
				value = nodeCollection[0].firstChild.nodeValue;
			} else if (collectionLength > 1) {
				value = [];
				for (i = 0; i < collectionLength; i = i + 1) {
					children = getChildren(nodeCollection[i]);
					if (children.length == 1 && children[0].firstChild.nodeType == nodeTypeElement) {
						value[value.length] = children[0].firstChild.nodeValue;
					}
				}
			}
			return value;
		};
	};

	return new NodeCollection(xmlObject);
};
LNV.util.xsl = (function () {
	
	var _transform = function (xml, xsl, parameters) {
		parameters = parameters || {};
		if (window.XSLTProcessor) {
			_transform = function (xml, xsl, parameters) {
				var xsltProcessor = new window.XSLTProcessor(),
					intnode,
					paramName;
				xsltProcessor.importStylesheet(xsl);
				for (paramName in parameters) {
					if (parameters.hasOwnProperty(paramName)) {
						xsltProcessor.setParameter(null, paramName, parameters[paramName]);
					}
				}
				intnode = document.createElement("div");
				intnode.appendChild(xsltProcessor.transformToFragment(xml, document));
				return intnode.innerHTML;
			};
		} else if (window.ActiveXObject) {
			_transform = function (xml, xsl, parameters) {
				var xsltThread = new window.ActiveXObject("Msxml2.XSLTemplate.6.0"),
					xsltProc,
					paramName;
				xsltThread.stylesheet = xsl;
				xsltProc = xsltThread.createProcessor();
				xsltProc.input = xml;
				for (paramName in parameters) {
					if (parameters.hasOwnProperty(paramName)) {
						xsltProc.addParameter(paramName, parameters[paramName]);
					}
				}
				xsltProc.transform();
				return xsltProc.output;
			};
		}
		return _transform(xml, xsl, parameters);
	},
	
	transformAction = function (xml, xsl, parameters, target) {
		var xmlDoc, xslDoc,
		
		checkReady = function () {
			if (xmlDoc && xslDoc) {
				target.innerHTML = _transform(xmlDoc, xslDoc, parameters);
			}
		};
		if (target) {
			if (xml.constructor == String || xsl.constructor == String) {
				if (xml.constructor == String) {
					LNV.ajax({
						url: xml,
						dataType: 'xml',
						success: function (result) {
							xmlDoc = result;
							checkReady();
						}
					});
				} else {
					xmlDoc = xml;
				}
				if (xsl.constructor == String) {
					LNV.ajax({
						url: xsl,
						dataType: 'xml',
						success: function (result) {
							xslDoc = result;
							checkReady();
						}
					});
				} else {
					xslDoc = xsl;
				}
			} else {
				xmlDoc = xml;
				xslDoc = xml;
				checkReady();
			}
			/* TODO: debug when parameters are wrong */
		} else {
			return _transform(xml, xml, parameters);
		}
	};
	
	return {
		transform: transformAction
	};
}());
LNV.util.urlHandler = function () {
	var getSettedVars = function (params) {
		var settedVars = params[0];
		if (params.length === 2) {
			settedVars = {};
			settedVars[params[0]] = params[1];
		}
		return settedVars;
	},
	
	update = function (newQuery) {
		if (!(newQuery === "" && parent.location.hash === "")) {
			parent.location.hash = newQuery;
		}
	};

	return {
		getQuery: function () {
			return parent.location.hash.substr(1);
		},
	
		getVars: function () {
			var variables = {},
				query = this.getQuery(),
				i,
				queryarray,
				currentVar;
			if (query.length > 1) {
				queryarray = query.split("&");
				for (i = 0; i < queryarray.length; i = i + 1) {
					currentVar = queryarray[i].split("=");
					variables[currentVar[0]] = currentVar[1];
				}
			}
			return variables;
		},
	
		set: function () {
			var x,
				variables = this.getVars(),
				settedVars = getSettedVars(arguments),
				newquery = [];
			for (x in settedVars) {
				if (settedVars.hasOwnProperty(x)) {
					variables[x] = settedVars[x];
				}
			}
			for (x in variables) {
				if (variables.hasOwnProperty(x)) {
					newquery.push(x + "=" + variables[x]);
				}
			}
			update(newquery.join("&"));
		},
	
		get: function (varName) {
			return this.getVars()[varName] || undefined;
		},
	
		remove: function () {
			var variables = this.getVars(),
				newQuery = [],
				x;
			for (x in variables) {
				if (variables.hasOwnProperty(x) && !LNV.inArray(x, arguments)) {
					newQuery.push(x + "=" + variables[x]);
				}
			}
			update(newQuery.join("&"));
		},
	
		flush: function () {
			update("");
		},
	
		flushAndSet: function () {
			var newQuery = [],
				settedVars = getSettedVars(arguments),
				x;
			for (x in settedVars) {
				if (settedVars.hasOwnProperty(x)) {
					newQuery.push(x + "=" + settedVars[x]);
				}
			}
			update(newQuery.join("&"));
		},
	
		isSet: function (varName) {
			return (this.getVars()[varName]) ? true : false;
		}
	};
}();
LNV.util.form = {
	validation: {
		validate: function (form) {
			var validateFilled		= "validate-filled",
				validateRegex		= "validate-regex",
				validateNumbersOnly	= "validate-numbers-only",
				validateEmail		= "validate-email",
				validateEqualTo		= "validate-equal-to",
				
				tooltipClass		= "form-validation-tooltip",
				
				
				formElements		= [],
				formLength			= 0,
				
				dom = LNV.util.dom,
				
				i,
				regex,
					
			pushElements = function (container, elementTag, targetArray) {
				var elements = container.getElementsByTagName(elementTag),
					elementsLength = elements.length,
					i;
				for (i = 0; i < elementsLength; i = i + 1) {
					targetArray[targetArray.length] = elements[i];
				}
			},
			
			displayError = function (element, errorType) {
				var message = "<strong>Error: </strong>" + LNV.dictionary.form.validation[errorType],
					container = element.parentNode,
					divs = container.getElementsByTagName("div"),
					tooltip = null,
					i;
				for (i = 0; i < divs.length; i = i + 1) {
					if (dom.hasClass(divs[i], tooltipClass)) {
						tooltip = divs[i];
						break;
					}
				}
				if (!tooltip) {
					tooltip = document.createElement("div");
					tooltip.className = tooltipClass;
					tooltip.innerHTML = message;
					container.appendChild(tooltip);
				} else {
					tooltip.innerHTML = message;
					dom.show(tooltip);
				}
			},
			
			hideError = function (element) {
				var container = element.parentNode,
					divs = container.getElementsByTagName("div"),
					tooltip = null,
					i;
				for (i = 0; i < divs.length; i = i + 1) {
					if (divs[i].className == tooltipClass) {
						tooltip = divs[i];
						break;
					}
				}
				if (tooltip) {
					dom.hide(tooltip);
				}
			},
			
			/* Validation per se */
			validateElement = function () {
				var validates = true,
					reg1,
					reg2,
					that = this,
					value = (that.nodeName == "SELECT" && that.selectedIndex > -1) ? that.options[that.selectedIndex].text :
							that.value;
				if (that.style.visibility !== "hidden") {
					/* empty elements */
					if (dom.hasClass(that, validateFilled)) {
						if ((that.nodeName === "INPUT" && value.length === 0) || 
							(that.nodeName == "SELECT" && that.selectedIndex === 0)) {
							displayError(that, validateFilled);
							validates = false;
						}
					}
					/* elements with a value based on regex */
					if (validates && dom.hasClass(that, validateRegex)) {
						regex = new RegExp(window.unescape(that.alt), "i");
						if (regex.test(value) === false) {
							displayError(that, validateRegex);
							validates = false;
						}
					/* email validation */
					} else if (validates && dom.hasClass(that, validateEmail)) {
						reg1 = new RegExp("(@.*@)|(\\.\\.)|(@\\.)|(\\.@)|(^\\.)");
						reg2 = new RegExp("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.\\_]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$");
						if (!(!reg1.test(value) && reg2.test(value))) {
							displayError(that, validateEmail);
							validates = false;
						}
					} else if (validates && dom.hasClass(that, validateEqualTo)) {
						if (value != LNV.get(that.alt).value) {
							displayError(that, validateEqualTo);
							validates = false;
						}
					} else if (validates && dom.hasClass(that, validateNumbersOnly)) {
						if (window.isNaN(value)) {
							displayError(that, validateNumbersOnly);
							validates = false;
						}
					}
				}
				if (validates) {
					hideError(that);
				}
				return validates;
			},
			
			formOnSubmit = function () {
				var i,
					regex,
					doesValidate = true,
					validationResult;
				
				for (i = 0; i < formLength; i = i + 1) {
					validationResult = validateElement.call(formElements[i]);
					if (doesValidate) {
						doesValidate = validationResult;
					}
				}
				if (doesValidate) {
					this.submit();
				}
			};
			
			pushElements(form, "input", formElements);
			pushElements(form, "textarea", formElements);
			pushElements(form, "select", formElements);
			formLength = formElements.length;
								   
			for (i = 0; i < formLength; i = i + 1) {
				LNV.events.add(formElements[i], "change", validateElement);
				LNV.events.add(formElements[i], "blur", validateElement);
			}
			LNV.events.add(form, "submit", formOnSubmit, true);
		}
	}
};
/* Capa de abstraccion para cookies */
LNV.util.cookie = {
	set: function (name, value, days) {
		var expires = "",
			date;
		if (days) {
			date = new Date();
			date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
			expires = "; expires=" + date.toGMTString();
		} 
		document.cookie = name + "=" + value + expires + "; path=/";
	},
	get: function (name) {
		var nameEQ = name + "=",
			ca = document.cookie.split(';'),
			calength = ca.length,
			c,
			i;
		for (i = 0; i < calength; i = i + 1) {
			c = ca[i];
			while (c.charAt(0) === " ") {
				c = c.substring(1, c.length);
			}
			if (c.indexOf(nameEQ) === 0) {
				return c.substring(nameEQ.length, c.length);
			}
		}
		return null;
	},
	remove: function (name) {
		this.set(name, "", -1);
	},
	isSet: function (name) {
		return (this.get(name) !== null);
	}
};