Ago 18 2008

Aprendamos a escribir funciones recursivas {

Utilizaremos JavaScript para estos ejemplos de recursividad.

Una función es recursiva cuando en su cuerpo hay un llamado a si misma, un ejemplo clásico es la operación matemática potencia, primero veamos la función no recursiva que defina la potencia:

function potencia(base, exponente) {
	 if(exponente == 0) { //caso límite de exponente cero
		return 1
	 } else {
		return base * potencia(base, exponente -1) //llamado recursivo
	 }
}


Para este caso tomaremos sólo las potencias de exponente positivo para no aumentar la complejidad del ejemplo.

Lo que haremos a continuación será analizar la función para convertirla en recursiva, primero los casos límite, sabemos que el resultado de toda potencia de exponente 0 es 1, entonces ese será nuestro primer chequeo.

Luego estudiemos la función a partir de un ejemplo, sea en este caso 24:

  • 24 = 2 * 2 * 2 * 2 = 16
  • 2 * 2 * 2 * 2 = 2 * (23) = 2 * 8 = 16
  • 2 * (23) = 2 * (2 * (22)) = 2 * (2 * 4) = 16

Visto lo anterior, podemos afirmar que xy = x * (xy-1) de donde claramente se desprende la recursividad, en palabras, potencia de x a la y = x por potencia de x a la y -1, vamos el código:

function potencia(base, exponente) { if(exponente == 0) { //caso límite de exponente cero return 1; } else { while(exponente >= 1) { return base * potencia(base, exponente -1); //llamado recursivo } } } 

Tal vez en este caso no es muy notorio, pero una de las principales ventajas de utilizar algoritmos recursivos es la disminución de la cantidad de líneas de código necesarias.

Estudiemos el caso de la sucesión de Fibonacci, otro ejemplo clásico de algoritmo recursivo.

Cada término de la sucesión de Fibonacci es la suma de los 2 términos predecesores, sabiendo que los primero términos, por definición son 0 y 1, entonces sabemos que los primeros 10 términos de la sucesión son:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Ahora podemos afirmar que además de los términos primarios f0 = 0, f1 = 1, un término enésimo se define como fn = fn-1 + fn-2

Veamos una función recursiva que calcule el término n de la sucesión de Fibonacci:

function fibonacci(n) {
	if(n==0 || n== 1) { // casos límite 
		return n; 
	} else { 
		return fibonacci(n-1) + fibonacci(n-2); // suma del término anterior y su predecesor 
	} 	
}

Si llamamos a la función anterior en un bucle podremos obtener la sucesión hasta el término especificado en el bucle, por ejemplo:

var fib = "F: "; 
for(i = 0; i<= 9; i++) { 
	fib += fibonacci(i) + " | "; 
} 
document.write(fib);

Nos escribirá los primeros 10 términos de la sucesión de Fibonacci: F: 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 |

}


Ago 07 2008

Validar formularios web con JavaScript y Expresiones Regulares {

Tag: JavaScript

En este post vamos a validar un formulario web con 3 campos, un campo Nombre que será obligatorio, un campo Email que será obligatorio y un campo numérico que será opcional pero sólo podrá contener números.

Para validar los campos email y numérico utilizaremos expresiones regulares, ya que es la manera más fácil, y a mi entender correcta, de validar el contenido de un campo.

En el formulario web utilizamos el evento onsubmit junto con una función de JavaScript que retorne true cuando la validación de los campos sea correcta, para que el formulario no complete el submit en caso de un error en la validación al onsubmit no le escribiremos sólo el nombre de la función, sino que utilizaremos return junto con el nombre de la misma.

function validar(form) {
	var emailRegEx = /^((\w|\.){2,}@)\w{3,}\.\w{2,4}((\.(\w{2}))?)?$/
	var numericoRegEx = /^\d*$/
 
	if(form.txtNombre.value == "") {
		form.txtNombre.focus();
		alert("El campo 'Nombre' es obligatorio!");
		return false;
	}
	if(form.txtEmail.value == "") {
		form.txtEmail.focus();
		alert("El campo 'Email' es obligatorio!");
		return false;
	} else {
		if(!form.txtEmail.value.match(emailRegEx)) {
			form.txtEmail.focus();
			form.txtEmail.value = "";
			alert("Debe ingresar una dirección de email válida.");
			return false;
		}
	}
	if(form.txtNumero.value !== "") {
		if(!form.txtNumero.value.match(numericoRegEx)) {
			alert("El campo 'Campo numérico' sólo puede contener números.");
			form.txtNumero.focus();
			form.txtNumero.value = "";
			return false;
		}
	}
	return true;
}

La función que tenemos arriba de estas líneas hace una validación y muestra el mensaje de error al estilo antiguo: con un messagebox, en javascript alert(); pero en estos días que están de moda los formularios que usan tecnología ajax, adaptaremos la función para que en lugar de mostrar el error en el messagebox, lo muestre en una celda de la tabla que contiene los campos del formulario, para ello recurriremos a la función de javascript document.getElementById(ElementId);

function validar2(form) {
	var emailRegEx = /^((\w|\.){2,}@)\w{3,}\.\w{2,4}((\.(\w{2}))?)?$/
	var numericoRegEx = /^\d*$/
 
	if(form.txtNombre.value == "") {
		form.txtNombre.focus();
		mostrar("El campo 'Nombre' es obligatorio!");
		return false;
	}
	if(form.txtEmail.value == "") {
		form.txtEmail.focus();
		mostrar("El campo 'Email' es obligatorio!");
		return false;
	} else {
		if(!form.txtEmail.value.match(emailRegEx)) {
			form.txtEmail.focus();
			form.txtEmail.value = "";
			mostrar("Debe ingresar una dirección de email válida.");
			return false;
		}
	}
	if(form.txtNumero.value !== "") {
		if(!form.txtNumero.value.match(numericoRegEx)) {
			mostrar("El campo 'Campo numérico' sólo puede contener números.");
			form.txtNumero.focus();
			form.txtNumero.value = "";
			return false;
		}
	}
	return true;
}
 
function mostrar(error) {
	document.getElementById('Errores').innerHTML = error;
	document.getElementById('Errores').style.background = "#ffcccc";
}

Haz click aquí para ver este ejemplo funcionando.

}


Jul 28 2008

Como reemplazar texto de un documento usando JavaScript y expresiones regulares {

Tag: JavaScript, RegEx

Seguramente todos han visto alguna vez una página que resalta las palabras clave nuestra búsqueda, y eso es lo que podemos lograr con estas 2 funciones de JavaScript y las siempre útiles expresiones regulares, por supuesto se puede hacer todo en una misma función, pero la idea es poder reusar el código.

La primera función se encargará de extraer el valor de un parámetro de nuestra URL usando expresiones regulares y sólo devolverá el valor. Se tuvo en cuenta que un parámetro de URL siempre estará precedido por uno de estos signos: ? ó & y que el valor del mismo se encontrará precedido del signo = y podrá ser sucedido por uno de los siguientes: & ó #.
A la hora de devolver el valor del parámetro seleccionado se utiliza una nueva expresión regular para reemplazar los signos + ó %20 por espacios en blanco, y en caso de que no se encuentre el parámetro devuelve un string vacío.

function leerParametros() {
	var parametro = 's'; //nombre del parámetro con las palabras de la búsqueda
	var regex = new RegExp('(\\?|&)('+ parametro + '=)([^&#]*)', 'i'); //regex para extraer el valor del parámetro
	var resultado = regex.exec(window.location.href); //ejecuta la regex sobre nuestra URL actual
 
	if(resultado != null) {
		replaceRegex = new RegExp('\\+|%20', 'g'); //regex para reemplazar signos por espacios
		return resultado[3].replace(replaceRegex, ' '); // devuelve la 3 coincidencia de la regex con el reemplazo para los espacios
	} else {
		return ""; //si la regex no encuentra el parámetro se devuelve un string vacío
	}
}

Luego utilizamos la función que realmente va a resaltar nuestras palabras clave, lo que haremos será obtener el valor del parámetro con la función anterior y mediante una expresión regular rodearemos cada instancia del texto con un tag <span> que tendrá un atributo style para darle la apariencia mediante css.

En esta expresión regular utilizamos paréntesis para poder capturar la coincidencia de texto como $1, ya que sino la estaríamos reemplazando por el texto buscado y es muy posible que no se respete la capitalización del texto original.

function resaltar() {
	var textoOriginal = leerParametros(); //obtiene el valor del parámetro
	var textoNuevo = "<span style=\"background-color: #ff0; font-weight: bold;\">$1</span>"; //define el texto a insertar por cada coincidencia de la regex
	var regex = new RegExp('('+textoOriginal+')', 'ig'); regex con modificadores ig, o sea no sensible a mayúsculas y minúsculas (i) y reemplazar todas las existencias (g)
	document.body.innerHTML = document.body.innerHTML.replace(regex, textoNuevo); //reemplazo sobre el html del body
}

Por último sólo resta hacer el llamado en el documento de destino, para lo cual lo ideal sería asignar la función resaltar() al evento onload del documento, pero eso no me funcionó, por lo que lo inserté al final del mismo:

		<script type="text/javascript">
				resaltar();
		</script>
	</body>
</html>

Sigue este enlace para ver el ejemplo funcionando.

}


Página 1 de 11