/*----------------------------------------------------------------------------------------
Autor: http://www.niquelao.net
Puedes utilizar líbremente este script respetando estas línea de comentarios.
También puedes modificarlo con total libertad, siempre y cuando nos envíes las
modificaciones que introduzcas, y nos menciones en el resultado.
Cualquier mejora siempre será bienvenida.
----------------------------------------------------------------------------------------*/

// Se revisan todos los formularios del documento, así como todos los campos que vamos
// a controlar mediante este script.
var forms      = document.getElementsByTagName('form');
var inputs     = document.getElementsByTagName('input');
var textareas  = document.getElementsByTagName('textarea');
var selects    = document.getElementsByTagName('select');
var labels     = document.getElementsByTagName('label');
var valorinicial   = new Array();
var obligatorio    = new Array();
var tipo           = new Array();
var labelestilo    = new Array();
var campoestilo    = new Array();
var tipocontenido  = new Array();
var longitudminima = new Array();
// Variables y términos a buscar en el HTML con supuesta carga semántica
	// Para que sea obligatorio un campo se utiliza for_req
	// Para comprobar que sea un correo electrónico se usa for_mail
	// Para comprobar que sea un número se usa for_num
	// Para comprobar que tenga longitud mínima se usa for_min
		// En el marcado se pondrá tras la palabra utilizada en esta variable la longitud.
		// ej: minimo8 si queremos que tenga como mínimo 8 caracteres
var for_req    = '*';      // Para poner en cualquier parte del label (clase o contenido) o en la clase del campo
var for_mail   = 'mail';   // Para poner en cualquier parte del label (clase o contenido) o del campo
var for_num    = 'numero'; // Para poner en cualquier parte del label (clase o contenido) o del campo
var for_min    = 'minimo'; // Para poner en la clase del label o del campo

// Las clases para identificar los errores con css
var labelerror = 'error';
var fielderror = 'error';

// Se asignan a los campos en los que se puede introducir texto las funciones
// necesarias para vaciar su contenido o restaurarlo al original según las circunstancias.
// Además se comprueba el formato y si son obligatorios, almacenando dicha información.
function formulario() {
	for (var i = 0; i < inputs.length; i++) {
		if((inputs[i].type == 'text') || (inputs[i].type == 'password')) { 
			valorinicial[inputs[i].id]=inputs[i].value;
			inputs[i].onfocus = function() {vacia(this.id,this.value)}
			inputs[i].onblur = function() {restaura(this.id,this.value)}
		}
	}
	for (var i = 0; i < textareas.length; i++) { 
		valorinicial[textareas[i].id]=textareas[i].value;
		textareas[i].onfocus = function() {vacia(this.id,this.value)}
		textareas[i].onblur = function() {restaura(this.id,this.value)}
	}
	for (var i = 0; i < selects.length; i++) { 
		valorinicial[selects[i].id]=selects[i].value;
	}
	for (var i = 0; i < forms.length; i++) {
		// Al ir a enviarse el formulario , se restauran los estilos
		// y se comprueba que los campos obligatorios se han rellenado.
		forms[i].onsubmit = function() {clear(this.id);comprobacionyenvio(this.id);return false}
	}
	// Dando por sentado que el marcado es el correcto y que todos los campos de formulario
	// poseen su correspondiente label asociado, revisamos los labels para identificar
	// dicho campo. Posteriormente, esta información se guardará en el caso de que 
	// encontremos un campo obligatorio o un formato a emplear
	for (var i = 0; i < labels.length; i++) {
		asociado = labels[i].htmlFor;
		var elasociado = document.getElementById(asociado);
		contlabel = labels[i].innerHTML;
		if((labels[i].className.indexOf(for_req) > -1) || (contlabel.indexOf(for_req) > -1) || (elasociado.className.indexOf(for_req) > -1)){
			obligatorio[asociado] = true;
		}
		if(labels[i].className.indexOf(for_min) > -1){
			var inicio = labels[i].className.indexOf(for_min);
			var fin = labels[i].className.indexOf(' ');
			var hasta = 5;
			if ( fin > (inicio+6)) {
				hasta = fin-inicio;
				hasta = hasta-6;
			}
			longitudminima[asociado] = labels[i].className.substr(inicio+6,hasta);
			var mi = true;
		}else if(elasociado.className.indexOf(for_min) > -1){
			var inicio = elasociado.className.indexOf(for_min);
			var fin = elasociado.className.indexOf(' ');
			var hasta = 5;
			if ( fin > (inicio+6)) {
				hasta = fin-inicio;
				hasta = hasta-6;
			}
			longitudminima[asociado] = elasociado.className.substr(inicio+6,hasta);
			var mi = true;
		}
		if((labels[i].className.indexOf(for_mail) > -1) || (contlabel.indexOf(for_mail) > -1) || (elasociado.className.indexOf(for_mail) > -1) ){
			tipocontenido[asociado] = for_mail;
			var ma = true;
		}
		if((labels[i].className.indexOf(for_num) > -1) || (contlabel.indexOf(for_num) > -1) || (elasociado.className.indexOf(for_num) > -1) ){
			tipocontenido[asociado] = for_num;
			var nu = true;
		}
		if(obligatorio[asociado] || mi || ma || nu) {
			labelestilo[asociado] = labels[i].className;
			campoestilo[asociado] = elasociado.className;
		}
	}
}

// Se vacían los campos únicamente cuando su contenido sea el mismo que el inicial
function vacia(id,valor){
		var targetElement = document.getElementById(id);
	var tipo = targetElement.type;
	switch ( tipo ) { 
		case 'text':
			if (valorinicial[id] == valor)
				targetElement.value = '';
			break
		case 'password':
			if (valorinicial[id] == valor)
				targetElement.value = '';
			break
		case 'textarea':
			if (valorinicial[id] == valor) {
				targetElement.innerHTML = '';
				targetElement.value = '';
			}
			break
	}
}

// Se restaura el contenido de los campos en el caso
// de no haber introducido nada o únicamente espacios en blanco
function restaura(id){
    var targetElement = document.getElementById(id);
	var tipo = targetElement.type;
	switch ( tipo ) { 
		case 'text':
			if (targetElement.value.replace(/ /g, '') == '')
				targetElement.value = valorinicial[id];
				break
		case 'password':
			if (targetElement.value.replace(/ /g, '') == '')
				targetElement.value = valorinicial[id];
				break
		case 'textarea':
			revisa = targetElement.value.replace(/ /g, '');
			// Se elimina saltos de línea y tabulaciones
			revisa = revisa.replace(/\n/g, '')
			revisa = revisa.replace(/\t/g, '')
			revisa = revisa.replace(/\r/g, '')
			if (revisa == '') {
				targetElement.innerHTML = valorinicial[id];
				targetElement.value = valorinicial[id];
			}
			break
	}
}

// Se devuelve el identificador del elemento parental del tipo que se le indique
// respecto al elemento que se le pase (un poco lío... ¿verdad?)
function padre(element, pTagName) {
	if (element == null) return null;
	else if (element.nodeType == 1 && element.tagName.toLowerCase() == pTagName.toLowerCase())
		return (element.id)
	else
		return padre(element.parentNode, pTagName);
}

// Se obtiene el texto incluido en un elemento eliminando las etiquetas que pudiera haber
function obten_texto(objeto) {
	if (objeto.nodeType == 3) return objeto.nodeValue;
	var texto = new Array(),i=0;
	while(objeto.childNodes[i]) {
		texto[texto.length] = obten_texto(objeto.childNodes[i]);
		i++;
	}
	return texto.join("");
}

// Se restauran los estilos a los iniciales en el formulario en cuestión
function clear(id) {
	var targetElement = document.getElementById(id);
	for (var i = 0; i < labels.length; i++) {
		if(padre(labels[i], 'form') == id){
			asociado = labels[i].htmlFor;
			elasociado = document.getElementById(asociado);
			labels[i].className = labelestilo[asociado]
			elasociado.className = campoestilo[asociado]
		}
	}
}

// Se controla que los campos obligatorios no sean como los valores originales
function comp_obligatorio(valor,asociado,i) {
	var elasociado = document.getElementById(asociado);
	if(valor) {
		if((valorinicial[elasociado.id] == elasociado.value) || (elasociado.type == 'textarea' && valorinicial[elasociado.id] == elasociado.innerHTML) || (elasociado.type == 'checkbox' && !elasociado.checked)){
			var error = true;
			labels[i].className = labelerror;
			elasociado.className = fielderror;
		}
	}
	return error;
}
// Se controla que lo itroducido sea un correo electrónico
function comp_email(asociado,i) {
	var elasociado = document.getElementById(asociado);
	if(!(elasociado.value == valorinicial[elasociado.id]) && (tipocontenido[asociado] == for_mail) && ((elasociado.value.indexOf('@') < 1) || (elasociado.value.indexOf('www.') > -1) || (elasociado.value.indexOf('.') < 2) || (elasociado.value.indexOf('.') < elasociado.value.indexOf('@')+2) || (elasociado.value.length < 5) || (elasociado.value.indexOf('@') == (elasociado.value.length)-1) || (elasociado.value.indexOf('.') == (elasociado.value.length)-2))) {
		var error = true;
		labels[i].className = labelerror;
		elasociado.className = fielderror;
	}
	return error;
}

// Se controla que lo itroducido sea un número (tras eliminar los espacios en blanco)
function comp_num(asociado,i) {
	var elasociado = document.getElementById(asociado);
	if(!(elasociado.value == valorinicial[elasociado.id]) && (tipocontenido[asociado] == for_num)) {
		if((isNaN(elasociado.value.replace(/ /g, '')))) {
			var error = true;
			labels[i].className = labelerror;
			elasociado.className = fielderror;
		}else{
			elasociado.value = elasociado.value.replace(/ /g, '')
		}
	}
	return error;
}
// Se controla que lo itroducido tenga una longitud mínima
function comp_longitud(asociado,longitud,minima,i) {
	var elasociado = document.getElementById(asociado);
	if(!(elasociado.value == valorinicial[elasociado.id]) && longitud < minima) {
		var error = true;
		labels[i].className = labelerror;
		elasociado.className = fielderror;
	}
	return error;
}
// Se comprueba todo y se obra en consecuencia
function comprobacionyenvio(id) {
    var targetElement = document.getElementById(id);
	for (var i = 0; i < labels.length; i++) {
		asociado = labels[i].htmlFor;
		var elasociado = document.getElementById(asociado);
	}
	var new_stock = document.createElement('ul');
	new_stock.id = 'lista_errores';
	var contador = 0;
	for (var i = 0; i < labels.length; i++) {
		var especial = new Array();
		if(padre(labels[i], 'form') == id){
			asociado = labels[i].htmlFor;
			var elasociado = document.getElementById(asociado);
			if(comp_obligatorio(obligatorio[asociado],asociado,i)) {
					var error = true;
					especial.splice(especial.length-1,0,'es obligatorio');
			}
			if(comp_email(asociado,i)) {
					var error = true;
					especial.splice(especial.length-1,0,'ha de ser un correo electrónico válido');
			}
			if(comp_longitud(asociado,elasociado.value.length,longitudminima[asociado],i)){
					var error = true;
					var texto = 'ha de tener un mínimo de ';
					if(comp_num(asociado,i) || (tipocontenido[asociado] == for_num)) {
						texto = texto + longitudminima[asociado] + ' dígitos';
					}else{
						texto = texto + longitudminima[asociado] + ' caracteres';
					}
					especial.splice(especial.length-1,0,texto);
			}
			if(comp_num(asociado,i)) {
					var error = true;
					especial.splice(especial.length-1,0,'ha de ser un número');
			}
		}
		if(especial.length > 0){
			// Obtenemos el texto del label
			var texto_etiqueta = obten_texto(labels[i]).replace(for_req,'');
			// Eliminamos el contendido del control por si hay asociación implícita
			texto_etiqueta = texto_etiqueta.replace(elasociado.innerHTML,'');
			if(especial.length == 1 || especial.length == 2) {
				var texto = document.createTextNode(texto_etiqueta + ' ' + especial.join(" y "));
			}else if(especial.length >= 3){
				var add = especial.pop();
				var texto = document.createTextNode(texto_etiqueta + ' ' + especial.toString() + ' y '  + add);
			}
			var new_item = document.createElement('li');
			// En IE aparecen dos espacios que hemos de eliminar
			texto.nodeValue = texto.nodeValue.replace('  ',' ');
			new_item.appendChild(texto);
			new_stock.appendChild(new_item);
			contador++;
		}
	}
	if (!error){
		document.forms[targetElement.id].submit()
	}else {
		if (document.getElementById('cont_error' + targetElement.id))
			targetElement.removeChild(document.getElementById('cont_error' + targetElement.id));
		var contenedor_error = document.createElement('div');
		contenedor_error.id = 'cont_error' + targetElement.id;
		contenedor_error.className = 'contenedor_error';
		var error_alert = document.createElement('p');
		error_alert.id = 'error_alert' + targetElement.id;
		if (contador > 1) {
			var texto_de_alerta = 'Compruebe los datos introducidos, pues se han encontrado los siguientes errores:';
		}else{
			var texto_de_alerta = 'Compruebe los datos introducidos, pues se ha encontrado el siguiente error:';
		}
		var error_alert_text = document.createTextNode(texto_de_alerta);
		error_alert.insertBefore(error_alert_text,error_alert.firstChild);
		contenedor_error.insertBefore(new_stock,contenedor_error.firstChild);
		contenedor_error.insertBefore(error_alert,contenedor_error.firstChild);
		targetElement.insertBefore(contenedor_error,targetElement.firstChild);
		var ancla = location.href;
		if(ancla.indexOf('#') > -1) {
			ancla = ancla.substring(0,ancla.indexOf('#'));
		}
		location.href = ancla + "#error_alert" + targetElement.id
	}
}

function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
        window.onload = func;
    } else {
        window.onload = function() {
            if (oldonload) {
                oldonload();
            }
            func();
        }
    }
}

addLoadEvent(
	function() {
		formulario();
	}
)
