Estás mirando la versión 3 de mi sitio web, para ver la última versión por favor anda a juque.cl

juque

Juan Pablo Aqueveque: Ingeniero de Sistemas, Diseñador y Desarrollador Web que reside en Temuco, Chile.

Javascript: Enviar sólo una vez

Publicado por Juan Pablo el 21.Abr.2007 | Comentarios (6)

Es muy común que el usuario—y sobre todo aquel impaciente—le de más de una vez clic al botón “enviar” cuando se enfrenta a un formulario; el script no responde, la red está lenta o el computador del cliente es una tortuga con pantalla y teclado; esto genera más peticiones de las necesarias a nuestro servidor o si el desarrollador no hizo bien su trabajo puede incluso provocar errores lógico en la aplicación. Pero ¿cómo podemos solucionar el problema?, mhhhh JavaScript puede darnos algo de ayuda.

Javascript: no molestes

JavaScript debe ser usado para mejorar la experiencia de usuario, debe ser un apoyo a nuestra aplicación, Javascript no puede ser el condicionante para que nuestra página funcione, eso es lo que se llama javascript no intruso o javascript unobtrusive como bien lo definió el admirable Christian Heilmann (cuyo libro “Beginning JavaScript with DOM Scripting and Ajax - From Novice to Professional” recomiendo mucho). La consigna es: usar pero no abusar, se debe tener cuidado que la página tenga el mismo resultado para el usuario con o sin Javascript.

Requerimientos

Solución

Nos centraremos sólo en el botón de envío, es decir:

<input type="submit" name="enviar" id="enviar" value="Enviar" />

Comenzaremos el modelamiento o desarrollo de nuestro pequeño objeto enviarUnaVez:

var enviarUnaVez = {
	ini: function() 
	{
		var form = document.forms[0];
		if ( form != null )
		{
			var enviar = form.enviar;
			form.onsubmit = function()a
			{
				enviar.disabled = true;
				enviar.value = "Procesando ...";
			}
		}
		 
	}
}

Si te parece extraña la notación te la presento, se llama Object Literal. El método ini hará todo lo que queremos, tomará el formulario 0 de la página (ojo si tienes más de uno), luego se activarán dos asignaciones al momento de enviar el formulario (onsubmit), se deshabilitará el botón enviar y le cambiaremos su contenido con el texto “Procesando...”. Ya tenemos todo lo que queríamos hacer con el botón enviar, pero falta algo... ese toque delicado y sutil que dará a nuestro javascript el apelativo de Señor Invisible ante el XHTML.

Javascript tiene una gran cantidad de manejadores de eventos que nos dan la posibilidad de activar n cantidad de funciones al momento de que ocurra x cosa, uno de estos manejadores es el window.onload. Su sintaxis es:

window.onload = función;

Volviendo a nuestra pequeño objeto enviarUnaVez podemos hacer lo siguiente:

window.onload = enviarUnaVez.ini;

Lo que quiere decir, al momento de cargar la página adjunta el método enviarUnaVez.ini perteneciente al objeto enviarUnaVez. La asignación funcionará perfectamente y hasta aquí tendríamos el 100% de nuestro objetivo inicial, pero..., ¿qué ocurre si en la página ya tengo funciones que se ejecutan al momento de cargar la página, dicho de otras palabras el manejador window.onload ya está ocupado por otra función o librería Javascript? — tenemos problemas.

Entra al ring: addLoadEvent

Creada por Simon Willison en mayo del 2004, esta función agrega funciones (valga la redundancia) a un window.onload ya ocupado por otras, es decir, podemos agregar infinitas funciones sin problemas. Muy bien, agreguemos la nueva función como un método más a nuestro objeto enviarUnaVez:

var enviarUnaVez = {
	mensaje : "Procesando...",
	ini: function() 
	{
		var form = document.forms[0];
		if ( form != null )
		{
			var enviar = form.enviar;
			form.onsubmit = function() 
			{
				enviar.disabled = true;
				enviar.value = enviarUnaVez.mensaje;
			}
		}
		 
	},
	addLoadEvent: function(func) 
	{
		var oldonload = window.onload;
		if ( typeof window.onload != 'function' ) 
		{
			window.onload = func;
		} 
		else 
		{
			window.onload = function() 
			{
				if ( oldonload ) 
				{
					oldonload();
				}
				func();
			}
		}
	}
}

Además del nuevo método hemos agregado un variable llamada mensaje, la cual contendrá el valor del value cambiado.

Nuestra pequeña aplicación finaliza llamando al objeto, ésta es la última línea de nuestro código:

enviarUnaVez.addLoadEvent(enviarUnaVez.ini);

Ahí lo tienes, ¡jamás tocamos el XHTML!.

Algunos podrán pensar que estamos matando moscas con un tanque, pero es la forma correcta de sazonar nuestra páginas web con un javascript que mejore la experiencia del usuario (y la nuestra también — dado el ejemplo).

En el tutorial está implícito el desarrollo de Javascript basado en prototipos, hemos modelado un objeto completamente aislado (encapsulado) de todas las otras funciones, objetos o librerías que nuestra página pudiese tener. Además de ser una forma elegante y limpia de escribir javascript el object literal nos da la posibilidad de hacer crecer nuestros objetos infinitamente y asegurar una coexistencia plena con otros objetos que pudiesen sumarse en la vida nuestras páginas webs.

Demo y Descarga

Como ya es costumbre, dejo un demo y la respectiva descarga del script. Hasta un próximo tutorial de Javascript.

Enlace Permanente, Comentarios (6), Publicada en: JavaScript

Comentarios

1. Pendol
21.Abr.2007

Siempre me habia preguntado como evitar este problema. Para solucionarlo (o intentar solucionarlo, mejor dicho) utilizaba PHP, pensando que dicho lenguaje era la herramienta adecuada, sin embargo no me daba resultados satisfactorios.

Muchas gracias por compartir esta excelente solución.

2. Mark
21.Abr.2007

Nomás como advertencia, una vez intenté aplicar este método en Movable Type y los comentarios dejan de funcionar si le pones el "disabled", puedes cambiar el "value" sin problemas.

3. 0x01
21.Abr.2007

Que opinas de frameworks de trabajo como Jquery o Prototype ...

¿ Te han facilitado la vida ?

Saludos

4. juan pablo
21.Abr.2007

He usado ambas librerías, eso si jQuery más que Prototype, pero prefiero --por ahora-- aplicar mi conocimiento en JS y hacer mis propia herramientas.

Pero para quien se inicie en el mundo del JS recomiendo que sepa pescar, antes de que una librería sólo le de pescados.

5. novice
28.May.2007

Hola, es muy útil tu código pero hasta ahora no lo puedo implementar de la manera que lo haces en el demo que muestras, necesito mostrar esos mensajes y desabilitar el botón después de presionarlo, ojala me puedas ayudar por favor o que puedas subir el código del demo igual para saber como llamar a la función, etc. Por favor S.O.S.

6. Loan
5.Jun.2007

votsorg, pefrect!