Asociar eventos generados en el documento

Categories:

En esta ocasión vamos a ver que los eventos nos permiten ejecutar código de JavaScript cuando se realice una acción en la interfaz.

¿Qué es un evento?

Un evento es una interacción que un usuario tiene con el documento.
Algunos eventos que se pueden realizar son:

Evento

Descripción

click

Inicia cuando se presiona un elemento determinado.

mouseover

Inicia cuando se posiciona el cursor sobre un elemento determinado.

mouseout

Inicia cuando el cursor sale un elemento determinado.

mousemove

Inicia cuando el cursor realiza algún movimiento sobre el elemento determinado.

mousedown

Inicia cuando se presiona el botón izquierdo del mouse. Este evento se dispara antes que click.

mouseup

Inicia cuando se suelta el botón izquierdo del mouse. Este evento se dispara después que mousedown y antes que click.

keydown

Inicia cuando la tecla se presiona (antes que keypress).

keypress

Inicia cuando una tecla se mantiene presionada.

keyup

Inicia cuando la tecla se suelta.

focus

Inicia cuando se enfoca un elemento.

change

Inicia cuando se pierde el foco y el valor ha cambiado.

blur

Inicia cuando se pierde el foco del elemento.

submit

Inicia cuando se presiona el botón submit (generalmente al enviar un formulario).

¿Cómo asociamos los eventos con el documento?

Para asociar un evento con código de JavaScript lo podemos hacer de dos formas:

  1. Funcionalidad en línea.
  2. UJS – Unobtrusive JavaScript – Javascript no obstructivo.

En cualquiera de las formas anteriores necesitamos a realizar tres pasos:

  1. Seleccionar el elemento con el que vamos a trabajar.
  2. Elegir el evento que vamos utilizar para desencadenar un comportamiento – ¿qué tiene que hacer el usuario para que se ejecute el código?
  3. Asociar el comportamiento a realizar al evento.

Funcionalidad en línea

  1. Seleccionamos el elemento directamente en el HTML – vamos a agregar un atributo en la etiqueta -.
  2. Para asignar el evento vamos a utilizar el nombre del evento – precedido por la palabra on – como atributo de la etiqueta html seleccionada.
  3. El comportamiento deseado se puede asignar directamente como valor del atributo o se puede tener dentro de una función u objeto.

<!--
Se puede incluir el código directamente
como valor del atributo.
-->

<p id='parrafo' onclick='alert("foo")'>
  Ejemplo
</p>

<!--
También se pueden 
utilizar funciones u objetos y se
mandan llamar.
-->

<p id='parrafo' onclick='parrafo_click()'>
Ejemplo
</p>

<script>
  function parrafo_click() {
     alert("foo")
  }
</script>

<!DOCTYPE html>
<html>
	<head>
		<meta charset='utf-8'>
		<style>
			body { background-color: #f2f2f2; color: #171717; font-family: "helvetica neue", helvetica, arial, sans-serif; font-size: 12px;}
			.contenedor {display:block;overflow:hidden;width:800px;height:520px;margin:25px auto; padding-top: 3em; }
			.mensaje {float:left; margin-left: 4em; margin-right: 1em;}
			.formulario {float: left;}
			form {margin-top: 3em;}
			#mensajeUsuario {border-radius: 10px; position: absolute; top: 0; width: 23em; padding: .5em 2em; color: #000; margin: .5em 0;}
			#valido {border-radius: 10px; position: absolute; top: 0; width; 23em; padding: 1em 2em; color: #000; margin: 2em 0; background: #DFD; border: 1px solid #6C6;}
			input, textarea {display: inline-block; border: 1px solid #ccc; border-radius: 5px; padding: 5px; width: 19em;}
      input[type='submit'] {background: #f2f2f2;}
			label {width: 6em; display: inline-block; padding-top: 1em;}
			.required:after {content: " * "; color: red;}
		</style>
	</head>
	<body> 
		<div class='contenedor'>
			<div class='mensaje'>
			</div>
			<div class='formulario'>
				<p></p>
				<div id='mensajeUsuario' style='display: none;'></div>
				<form action='#' method='post' onsubmit='return validar();'>
						<label class='required'>Nombre</label><br>
						<input type='text' id='nombre' name='nombre'><br>
						<label class='required'>Correo</label><br>
						<input type='text' id='email' name='email'><br>
						<label class='required'>Mensaje</label><br>
						<textarea id='mensaje' name='mensaje' rows='13'></textarea><br>
						<input type='submit' name='enviar'  value='Enviar'/><br>
				</form> 				 
				</div>
			</div>
		<script>
		function validar() {
			validarNombreCompleto =  /^[a-zA-Z -]{2,}$/;
			validarCorreo = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
			errores = 0;
			mensajeError = "";    			
			enviar = false;
			nombre = document.getElementById('nombre');
			email = document.getElementById('email');
			mensaje = document.getElementById('mensaje');

			if (!validarNombreCompleto.test(nombre.value)) {
				mensajeError += "Falta el nombre.<br />"; 
				nombre.style.border = "1px solid #C66";
				errores += 1;
			} else {
				nombre.style.border = "1px solid #CCC";
			}
			
			if (!validarCorreo.test(email.value)) {
				mensajeError += "La dirección de correo no parece válida.<br />";
				email.style.border = "1px solid #C66";
				errores += 1;
			} else {
				email.style.border = "1px solid #CCC";
			}
			
			if (mensaje.value == "" ) {
				mensajeError += "Escribe un mensaje.<br />";
				mensaje.style.border = "1px solid #C66";
				errores += 1;				
			} else {
				mensaje.style.border = "1px solid #CCC";
			}
           


			if (errores > 0) {
          mensajeUsuario.innerHTML = "<p>" + mensajeError + "</p>";
			   	mensajeUsuario.style.backgroundColor =  "#FDD";
			   	mensajeUsuario.style.border =  "solid 1px #C66";	
          mensajeUsuario.style.display = "";   
			} else {
          mensajeUsuario.innerHTML = "<p>¡Gracias!</p>";
			   	mensajeUsuario.style.backgroundColor =  "#DFD";
			   	mensajeUsuario.style.border =  "solid 1px #6C6";	
          mensajeUsuario.style.display = "";   
          enviar = true;
			}

      return false;
      
      /*
      En este caso regresamos false en lugar de enviar
      para evitar que el formulario se envíe.
      
			return enviar;
      */			
		}
		</script>
	</body>
</html>

UJS – Unobtrusive JavaScript / JavaScript no obstructivo

  1. Seleccionamos un nodo utilizando el DOM.
  2. En el nodo seleccionado utilizamos el método addEventListener(‘evento’, funcion) *.
  3. Definimos el código de la función que se va a realizar cuando se desencadene el evento.

var parrafo = document.getElementById("parrafo")

parrafo.addEventListener("click", parrafo_click)

function parrafo_click() {
   alert("foo")
}

<!DOCTYPE html>
<html>
	<head>
		<meta charset='utf-8'>
		<style>
			body { background-color: #f2f2f2; color: #171717; font-family: "helvetica neue", helvetica, arial, sans-serif; font-size: 12px;}
			.contenedor {display:block;overflow:hidden;width:800px;height:520px;margin:25px auto; padding-top: 3em; }
			.mensaje {float:left; margin-left: 4em; margin-right: 1em;}
			.formulario {float: left;}
			form {margin-top: 3em;}
      .campo_error {border: 1px solid #C66;} 
      .campo_correcto {border: 1px solid #CCC;}
      .mensaje_error {background-color: #FDD; border: 1px solid #C66; }
      .mensaje_correcto { background-color: #DFD; border: 1px solid #6C6; }
			#mensaje_usuario {border-radius: 10px; position: absolute; top: 0; width: 23em; padding: .5em 2em; color: #000; margin: .5em 0;}
			#valido {border-radius: 10px; position: absolute; top: 0; width; 23em; padding: 1em 2em; color: #000; margin: 2em 0; background: #DFD; border: 1px solid #6C6;}
			input, textarea {display: inline-block; border: 1px solid #ccc; border-radius: 5px; padding: 5px; width: 19em;}
      input[type='submit'] {background: #f2f2f2;}
			label {width: 6em; display: inline-block; padding-top: 1em;}
			.required:after {content: " * "; color: red;}
		</style>
	</head>
	<body> 
		<div class='contenedor'>
			<div class='formulario'>
				<div id='mensaje_usuario' style='display: none;'></div>
				<form action='#' method='post'>
						<label class='required'>Nombre</label><br>
						<input type='text' id='nombre' name='nombre'><br>
						<label class='required'>Correo</label><br>
						<input type='text' id='email' name='email'><br>
						<label class='required'>Mensaje</label><br>
						<textarea id='mensaje' name='mensaje' rows='13'></textarea><br>
						<input id='enviar' type='submit' name='enviar'  value='Enviar'/><br>
				</form> 				 
				</div>
			</div>
		<script>
    var boton_envio = document.getElementById('enviar');
    var campo_nombre = document.getElementById('nombre');
    var campo_email = document.getElementById('email');
    var campo_mensaje = document.getElementById('mensaje');
    var mensaje_usuario = document.getElementById('mensaje_usuario');
    var valido = [];
    boton_envio.disabled = true;
    // Al desenfocar el campo se valida el contenido
    campo_nombre.addEventListener('blur', validar_nombre);
    campo_email.addEventListener('blur', validar_email);
    campo_mensaje.addEventListener('blur', validar_mensaje);
    // Al desenfocar el campo se verfica si se habilita el botón de envío
    campo_nombre.addEventListener('blur', habilitar_boton);
    campo_email.addEventListener('blur', habilitar_boton);
    campo_mensaje.addEventListener('blur', habilitar_boton);
    
    
    function agregar_campo_valido(campo) {
      valido.push(campo)
    }
    
    function quitar_campo_valido(campo) {
      if (valido.indexOf(campo) !== 1) {
        valido.splice(valido.indexOf(campo),1)
      }
    }
    
    function validar_nombre() {
      validarNombreCompleto =  /^[a-zA-Z -]{2,}$/;
			if (!validarNombreCompleto.test(this.value)) {
        mostrar_mensaje(true, "Escribe tu nombre.");
				this.className = 'campo_error';
        quitar_campo_valido('nombre');        
			} else {
				this.className = 'campo_correcto';
        agregar_campo_valido('nombre');
			}    
    }
    
    function validar_email() {
			validarCorreo = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;		
			if (!validarCorreo.test(this.value)) {
        mostrar_mensaje(true, "La dirección de correo no parece válida.");
				this.className = 'campo_error';
        quitar_campo_valido('email');
			} else {
				this.className = 'campo_correcto';
        agregar_campo_valido('email')
			}      
    }
    
    function validar_mensaje() {
			if (this.value == "" ) {
        mostrar_mensaje(true, "Escribe un mensaje.");
				this.className = 'campo_error';
        quitar_campo_valido('mensaje');        
			} else {
				this.className = 'campo_correcto';
        agregar_campo_valido('mensaje');
			}
    }
    
    function habilitar_boton() {
      if (document.getElementsByClassName('campo_error').length == 0 && valido.length == 3) {
        boton_envio.disabled = false;
        mostrar_mensaje(false, "¡Gracias!");        
      } else {
        boton_envio.disabled = true;        
      }
    }
    
    function mostrar_mensaje(error, mensaje) {
      mensaje_usuario.innerHTML = "<p>" + mensaje + "</p>";      
      if (error) {
        mensaje_usuario.className = "mensaje_error";
      } else {
        mensaje_usuario.className = "mensaje_correcto";
      }
      mensaje_usuario.style.display = "";             
    }
		</script>
	</body>
</html>

* addEventListener no es compatible con Oldie – IE6, IE7, IE8 – si se quiere un comportamiento similar para estas versiones se tiene que utilizar attachEvent.

<!DOCTYPE html>
<html>
	<head>
		<meta charset='utf-8'>
		<style>
			body { background-color: #f2f2f2; color: #171717; font-family: "helvetica neue", helvetica, arial, sans-serif; font-size: 12px;}
			.contenedor {display:block;overflow:hidden;width:800px;height:520px;margin:25px auto; padding-top: 3em; }
			.mensaje {float:left; margin-left: 4em; margin-right: 1em;}
			.formulario {float: left;}
			form {margin-top: 3em;}
      .campo_error {border: 1px solid #C66;} 
      .campo_correcto {border: 1px solid #CCC;}
      .mensaje_error {background-color: #FDD; border: 1px solid #C66; }
      .mensaje_correcto { background-color: #DFD; border: 1px solid #6C6; }
			#mensaje_usuario {border-radius: 10px; position: absolute; top: 0; width: 23em; padding: .5em 2em; color: #000; margin: .5em 0;}
			#valido {border-radius: 10px; position: absolute; top: 0; width; 23em; padding: 1em 2em; color: #000; margin: 2em 0; background: #DFD; border: 1px solid #6C6;}
			input, textarea {display: inline-block; border: 1px solid #ccc; border-radius: 5px; padding: 5px; width: 19em;}
      input[type='submit'] {background: #f2f2f2;}
			label {width: 6em; display: inline-block; padding-top: 1em;}
			.required:after {content: " * "; color: red;}
		</style>
	</head>
	<body> 
		<div class='contenedor'>
			<div class='formulario'>
				<div id='mensaje_usuario' style='display: none;'></div>
				<form action='#' method='post'>
						<label class='required'>Nombre</label><br>
						<input type='text' id='nombre' name='nombre'><br>
						<label class='required'>Correo</label><br>
						<input type='text' id='email' name='email'><br>
						<label class='required'>Mensaje</label><br>
						<textarea id='mensaje' name='mensaje' rows='13'></textarea><br>
						<input id='enviar' type='submit' name='enviar'  value='Enviar'/><br>
				</form> 				 
				</div>
			</div>
		<script>
    var boton_envio = document.getElementById('enviar');
    var formulario = document.getElementsByTagName('form')[0];
    var campo_nombre = document.getElementById('nombre');
    var campo_email = document.getElementById('email');
    var campo_mensaje = document.getElementById('mensaje');
    var mensaje_usuario = document.getElementById('mensaje_usuario');
    var valido = [];
    boton_envio.disabled = true;
    
    
    if (formulario.addEventListener) {
      campo_nombre.addEventListener('blur', validar_nombre);
      campo_email.addEventListener('blur', validar_email);
      campo_mensaje.addEventListener('blur', validar_mensaje);
      campo_nombre.addEventListener('blur', habilitar_boton);
      campo_email.addEventListener('blur', habilitar_boton);
      campo_mensaje.addEventListener('blur', habilitar_boton);      
      formulario.addEventListener('submit', detener);
    } else {
      campo_nombre.attachEvent('onblur', validar_nombre);
      campo_email.attachEvent('onblur', validar_email);
      campo_mensaje.attachEvent('onblur', validar_mensaje);
      campo_nombre.attachEvent('onblur', habilitar_boton);
      campo_email.attachEvent('onblur', habilitar_boton);
      campo_mensaje.attachEvent('onblur', habilitar_boton);
      formulario.attachEvent('onsubmit', detener);
    }

    function detener(e) {      
      e.preventDefault();
      return false;
    }
    
    function agregar_campo_valido(campo) {
      valido.push(campo);
    }
    
    function quitar_campo_valido(campo) {
      if (valido.indexOf(campo) !== 1) {
        valido.splice(valido.indexOf(campo),1);
      }
    }
  
    function validar_nombre() {
      validarNombreCompleto =  /^[a-zA-Z -]{2,}$/;
			if (!validarNombreCompleto.test(this.value)) {
        mostrar_mensaje(true, "Escribe tu nombre.");
				this.className = 'campo_error';
        quitar_campo_valido('nombre');
			} else {
				this.className = 'campo_correcto';
        agregar_campo_valido('nombre');
			}    
    }
    
    function validar_email() {
			validarCorreo = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;		
			if (!validarCorreo.test(this.value)) {
        mostrar_mensaje(true, "La dirección de correo no parece válida.")
				this.className = 'campo_error'
        quitar_campo_valido('email')        
			} else {
				this.className = 'campo_correcto'
        agregar_campo_valido('email')        
			}      
    }
    
    function validar_mensaje() {
			if (this.value == "" ) {
        mostrar_mensaje(true, "Escribe un mensaje.");
				this.className = 'campo_error';
        quitar_campo_valido('mensaje');
			} else {
				this.className = 'campo_correcto';
        agregar_campo_valido('mensaje');     
			}
    }
    
    
    function habilitar_boton() {
      if (document.getElementsByClassName('campo_error').length == 0 && valido.length == 3) {
        boton_envio.disabled = false;
        mostrar_mensaje(false, "¡Gracias!");
      } else {
        boton_envio.disabled = true;
      }
    }
    
    function mostrar_mensaje(error, mensaje) {
      mensaje_usuario.innerHTML = "<p>" + mensaje + "</p>";      
      if (error) {
        mensaje_usuario.className = "mensaje_error";
      } else {
        mensaje_usuario.className = "mensaje_correcto";
      }
      mensaje_usuario.style.display = "";             
    }

		</script>
	</body>
</html>

Por último

Como vimos un elemento puede tener distinta funcionalidad asociada incluso en el mismo evento.
También es posible eliminar el registro del evento si queremos que la funcionalidad se desencadene un determinado número de veces.

Si no quieres teclear puedes descargar los ejemplos del formulario.

Lo que sigue es conocer un poco más acerca de los eventos y cómo trabajar con ellos en JavaScript.