Hoy vamos a ver cómo crear un formulario web que, además de estar validado, tenga la virtud de poder ser ampliado con muy poco esfuerzo y que todas sus funcionalidades sigan en marcha.
Primero aclarar que con HTML5 los campos de tipo entrada pueden validarse automáticamente con la propiedad required (para comprobar que no estén vacíos) o, por ejemplo en el caso de un campo de entrada de email, con type=”email” poder testar que se escribe una dirección de correo correctamente. Esto está bien si supiéramos de antemano que todos nuestros visitantes usan un navegador que soporta HTML5. Pero, como sabemos, esto, desgraciadamente, no es así en más de las ocasiones de las que imaginamos. Conozco gente que todavía usa Internet Explorer 7.
Dicho esto, vamos a confeccionar este formulario a la vieja usanza, es decir, validado con JavaScript. Así que no me enrollo más y comenzamos con el código del HTML.

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
	<title>Ejemplo POO Javascript</title>
	<link rel="stylesheet" type="text/css" href="css/estilo.css"/>
</head>


<body>

	<h1>Ejemplo POO Javascript</h1>

	<fieldset><legend>Formulario POO javascript</legend>
		<form id="formulario" method="POST" action="ejemplo.php">
			Nombre *:
				<br />
				<input class="negro" name="campo" type="text" id="nombre" />
				<br/>
				<br/>
			Email *:
				<br />
				<input  class="negro" name="campo" type="text" id="email"/>
				<br/>
				<br/>
			Teléfono:
				<br />
				<input  class="negro" name="telefono" type="text" id="telefono"/>
				<br/>
				<br/>
			Comentario *:
				<br/>
				<textarea class="negro" name="campo" id="comentario" ></textarea>
				<br/>
				<br/>
			<noscript>
				<input type="submit" id="enviar" value="Enviar"/>
			</noscript>
			<button type="button" id="enviar">Enviar</button>
			<button type="reset" id="borrar">Borrar</button>
		</form>
		<br />
		<p id="mensaje"></p>
		<br />
		<progress id="progreso" max="100" value="0">Progreso</progress>
	</fieldset>
</body>

<script type="text/javascript" src="js/script.js"></script>

</html>

Como vemos se trata de un formulario que contiene cuatro campos, tres obligatorios y uno opcional. El método action del form apunta a una supuesta página de envío que, en este ejemplo, solo está a modo de test para comprobar que el formulario funciona como debe hacerlo.
Lo realmente importante de aquí son los class, name e id de los campos así como, por supuesto, sus valores. Observamos que todos los campos obligatorios tienen el mismo class y el mismo name. Los id, sin embargo, hacen alusión al objetivo de cada uno de ellos. Bien, queda claro que el llamarles así ha sido de mi elección. Tú puedes llamarlos como quieras, eso sí, respetando que se repita en todos los campos obligatorios así como tenerlo en cuenta a la hora de ser referenciados desde nuestro archivo js, el cual, cargamos al final de nuestro archivo, antes del cierre.
Fuera del formulario tenemos una etiqueta de párrafo vacía con id mensaje que usaremos para ir informando al usuario si algo no está correcto. Además hemos puesto una barra de progreso que irá indicando visualmente qué tanto por ciento correcto se ha rellenado del formulario.
También hemos indicado en el head una hoja de estilos externa que veremos más adelante.
Vamos entonces paso a paso con nuestro archivo script.js, que lo tendremos dentro de una carpeta llamada js tal y como lo hemos indicado en el HTML.

//------añadir listeners sobre el evento onblur de cada campo del formulario
//------con nombre "campo"

var elementos = document.getElementsByName("campo");

// Recorremos todos los elementos
for (var i=0; i < elementos.length; i++) {

      // Añadimos el evento onblur a cada campo del formulario con nombre "campo"
	  //llamando a la funcion crearEvento que los añade dinámicamente
      crearEvento(elementos[i], "blur");
	  
}

//Esta función es llamada desde el bucle for anterior y añade dinámicamente
//los eventos a los elementos que se le pasan como argumento. En este caso todos
//los elementos con nombre "campo"
function crearEvento(elemento, evento) {
	
	if (elemento.addEventListener) {
	elemento.addEventListener(evento, 
		function(){var lanzando = new comprobarCampo(elemento);}, false);	  
	} 
	//-----Para IE
	else {
	elemento.attachEvent("on" + evento, 
		function(){var lanzando = new comprobarCampo(elemento);});
	}
}

Lo primero que hacemos es añadir dinámicamente un evento blur a todos los elementos de nuestro formulario que tengan el nombre campo que, como ya sabemos, son aquellos campos obligatorios de nuestro formulario. Para ello primero los guardamos en un array llamado elementos, y después los recorremos llamando a la función crearEvento pasándole como argumentos tanto el mismo elemento como el evento a escuchar. Esta función es la que se encarga de hacer el trabajo dinámicamente. Observamos que dentro de esta función tenemos un condicional ya que, Internet Explorer, como siempre, hace las cosas distintas a los demás navegadores. Internet Explorer no dispone de un método addEventListener, así que debemos hacerlo con attachEvent.
Con este evento controlaremos cuándo un usuario pasa de un campo a otro dentro del formulario y llamaremos a la función comprobarCampo pasándole como argumento el propio elemento.

//clase que comprueba el contenido del campo individual que se le pasa como
//argumento
var comprobarCampo = function(campo){
		
	this.campo = campo;
		
	if (this.campo.value == ""){
			
		ponerImagen(this.campo, "error");
				
				
	}
		
	else if (this.campo.id == "email" && 
	!(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(this.campo.value)))
	{
		
		ponerImagen(this.campo, "error");
				
				
	}
		
	else{
		
		ponerImagen(this.campo, "ok");
				
	}

		progreso();
		mensajes();
}

La función comprobará que el campo que se le pasa no esté vacío y que, en caso de que sea el campo que contiene el email, compruebe la sintaxis de la dirección de correo a través de una expresión regular. Vemos que, tanto si se supera la comprobación como si no, se llama a una función ponerImagen pasando como argumentos el elemento campo en cuestión y un string que indica si ha ocurrido un error o todo es ok. Además llamamos consecutivamente a las funciones progreso y mensajes. Veámoslas.

var ponerImagen = function(campo,estado){

		this.campo = campo;
		this.estado = estado;
						
		var imagen = document.createElement("img");
		imagen.className = "image";
		
		if (estado == "error"){
			
			if(this.campo.nextSibling.className == "image"){			
				borrarImagenIndividual(this.campo.nextSibling);
				imagen.src = "img/error.png";
				this.campo.className = "rojo";
				this.campo.style.border = "2px solid red";
				var padre = this.campo.parentNode
				padre.insertBefore(imagen, this.campo.nextSibling);			
			}
			else{
				imagen.src = "img/error.png";
				this.campo.className = "rojo";
				this.campo.style.border = "2px solid red";
				var padre = this.campo.parentNode
				padre.insertBefore(imagen, this.campo.nextSibling);
			}
		
		}
		else{
		
			if(this.campo.nextSibling.className == "image"){			
				borrarImagenIndividual(this.campo.nextSibling);
				imagen.src = "img/ok.png";
				this.campo.className = "verde";
				this.campo.style.border = "2px solid green";
				var padre = this.campo.parentNode
				padre.insertBefore(imagen, this.campo.nextSibling);
			}
			else{
				imagen.src = "img/ok.png";
				this.campo.className = "verde";
				this.campo.style.border = "2px solid green";
				var padre = this.campo.parentNode
				padre.insertBefore(imagen, this.campo.nextSibling);
			}
					
		}

}

Esta función crea dinámicamente una etiqueta image a la que damos un nombre de clase llamado image. Dependiendo de si el string indica error o no, usará un png de 24×24 para mostrarlo al lado del campo input correspondiente. Las imágenes son de tu elección, y están alojadas dentro de una carpeta img como puede verse en la ruta. Para comprobar si el campo disponía anteriormente de una imagen a su lado usamos this.campo.nextSibling.className == “image”. Si ya existía una la borramos con la función borrarImagenIndividual pasándole el target en cuestión. Si no había ninguna entonces le añadimos la nueva que le corresponda.
Usamos un estilo dinámico para el contorno del input. Si hay error rojo, sino verde.
El código para borrarImagenIndividual es simplemente:

var borrarImagenIndividual = function(elemento){
	
	elemento.parentElement.removeChild(elemento);

}

Sigamos con las funciones progreso y mensajes.

var progreso = function(){

	this.elementos = document.getElementsByName("campo");
	this.porcentaje = Math.round((100 / elementos.length) * Math.pow(10, 2)) / Math.pow(10, 2);
	this.barra_progreso = document.getElementById("progreso");
	this.contador = 100;
		
	// Recorremos todos los elementos
	for (var i=0; i < elementos.length; i++) {	
				
		if (elementos[i].value == ""){			
			
			contador -= porcentaje;
				
		}		
		else if (elementos[i].id == "email" 
		&& !(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(elementos[i].value))){
			
			contador -= porcentaje;
		
		}
		
		barra_progreso.value = contador;

	}	

}

La función progreso calcula dinámicamente el porcentaje de campos a rellenar en base a la cantidad de campos obligatorios del formulario. Ponemos una variable contador a 100, es decir, el total de la barra de progreso. A partir de ahí, recorriendo todos los elementos obligatorios del formulario, irá restando la variable porcentaje a la variable contador para determinar qué tanto por ciento está correctamente cumplimentado. El resultado se lo aplicamos a la barra de progreso que tenemos en nuestro HTML para que lo muestre visualmente.

var mensajes = function(){
	
	this.pMensaje = document.getElementById("mensaje");
	pMensaje.innerHTML = "";
	this.elementos = document.getElementsByName("campo");
	this.mensaje1 = "";
	this.mensaje2 = "";
	
	for (var i=0; i < elementos.length; i++) {		
		
		if (elementos[i].value == ""){			
			
			mensaje1 = "Por favor, rellene todos los campos obligatorios"; 
				
		}		
		else if (elementos[i].id == "email" && 
		!(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(elementos[i].value))){
			
			mensaje2 = "Por favor, introduzca una dirección de email correcta";
		
		}

	}	

	pMensaje.innerHTML = mensaje1 + "<br />" + mensaje2;
}

La función mensajes se encargará de recorrer todos los elementos obligatorios del formulario y, en caso de error, añadir dinámicamente un texto informativo dentro de la etiqueta párrafo vacía con id mensaje que tenemos en nuestro HTML. Previamente limpiamos el contenido por si ya existiera alguno. Además, como cabe la posibilidad de que hayan varios mensajes distintos, declaramos una variable por cada comprobación y las concatenamos al final para mostrarlo.
Vamos ahora con el botón borrar de nuestro formulario:

//listener sobre el evento onclick del botón borrar formulario

if (document.getElementById("borrar").addEventListener){

	document.getElementById("borrar").addEventListener("click", function evento(){
		
		borrarTodasImagenes("image");
		
		var elementos = document.getElementsByName("campo");
		
		for (var i=0; i < elementos.length; i++) {
			
			elementos[i].className = "negro";
			elementos[i].style.border = "1px solid black";
		}

	} , true);

}
//-----Para IE
else if (document.getElementById("borrar").attachEvent){

	document.getElementById("borrar").attachEvent("onclick", function evento(){
	
		borrarTodasImagenes("image");
	
		var elementos = document.getElementsByName("campo");
		
		for (var i=0; i < elementos.length; i++) {
			
			elementos[i].className = "negro";
			elementos[i].style.border = "1px solid black";
		}
	
	});

}

Añadimos dinámicamente, como ya hicimos anteriormente, el evento click tanto para IE como para el resto de navegadores. Aparte de resetear el formulario, el botón devolverá el contorno negro a los input y se encargará de borrar todas las imágenes que hubieran de error u ok llamando a la función borrarTodasImagenes , pasando como argumento, en este caso, el nombre de clase que queremos eliminar (image).
La función borrarTodasImagenes quedaría así:

var borrarTodasImagenes = function(clase){

	this.clase = clase;

	var elementos = document.getElementsByClassName(this.clase);
	
	// Recorremos todos los elementos
	for(var k = elementos.length-1; k >= 0; --k){
		elementos[k].parentElement.removeChild(elementos[k]);
	}

}

Vamos ya con el botón enviar:

//listener sobre el evento onclick del botón enviar formulario

if (document.getElementById("enviar").addEventListener){

	document.getElementById("enviar").addEventListener("click", function evento(){
	
	var elementos = document.getElementsByName("campo");
	var lanzando = new comprobarTodo(elementos);
	
	

	} , true);

}
//-----Para IE
else if (document.getElementById("enviar").attachEvent){

	document.getElementById("enviar").attachEvent("onclick", function evento(){
	
	
	var elementos = document.getElementsByName("campo");
	var lanzando = new comprobarTodo(elementos);
	
	
	});

}

Igualmente asociamos el evento click al botón como hemos hecho hasta ahora, recuperamos todos los input obligatorios del formulario y se los pasamos como argumento a la función comprobarTodo.

//clase para comprobar todo el formulario al intentar enviarlo
var comprobarTodo = function(elementos){
	
	this.ok = true;
	this.elementos = elementos;
	borrarTodasImagenes("image");
	
	// Recorremos todos los elementos
	for (var i=0; i < elementos.length; i++) {
		
		if (elementos[i].value == ""){
			
			this.ok = false;
			ponerImagen(elementos[i], "error");
		
		
		}
		else if (elementos[i].id == "email" 
		&& !(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(elementos[i].value))){
		
			this.ok = false;
			ponerImagen(elementos[i], "error");
		
		}
		else{
		
			ponerImagen(elementos[i], "ok");
		
		}		
	  
	}

	if (this.ok == true){
	
		document.getElementById("formulario").submit();
	
	}

}

Esta última función lo que hace es recorrer todos los input obligatorios y llamar a la función ponerIMagen tanto si está rellenado correctamente como si no. En el caso de que todo esté ok, el formulario será enviado.
Para terminar veamos nuestro CSS:

img {
	padding-left: 10px;
}
input{
	height:30px;
    font-size:14pt;
}

input,textarea{
	padding:10px;
	transition: all 0.15s ease-in-out;
	border-radius:3px;
	border:1px solid rgba(0,0,0,0.2);
}
#mensaje{
	font-weight:bold;
	color:red;
	font-size:10pt;
}
        
.rojo:focus {box-shadow: 0 0 5px rgba(255,0,0,1);border:1px solid rgba(255,0,0,0.8);}
.verde:focus {box-shadow: 0 0 5px rgba(0,255,0,1);border:1px solid rgba(0,255,0,0.8);}
.negro:focus {box-shadow: 0 0 5px rgba(178,166,167,1);border:1px solid rgba(0,0,0,0.8);}


progress[value] {
/* Eliminamos la apariencia por defecto */
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;

/* Quitamos el borde que aparece en Firefox */
border: none;
border-radius:5px;

/* Aplicamos las dimensiones */
width: 250px;
height: 20px;

/* Aplicamos color a la barra */
color: green;
}

/* Compatibilidad de color en Firefox y Chrome */
progress::-moz-progress-bar { background: #00A693; }
progress::-webkit-progress-value { background: #00A693; }

Lo más importante a destacar en este archivo es el aspecto personalizado que le damos a nuestra barra de progreso así como las clases rojo, verde y negro que le van a dar al input un efecto glow muy atractivo cuando el foco esté sobre él. Estas clases, si repasamos nuestro código anterior, veremos que se aplican dinámicamente cuando un campo es erróneo, cuando es ok o cuando se resetea con el botón borrar respectivamente.
Pues ya está. Terminado.
Ahora podemos añadir todos los input obligatorios que queramos a nuestro formulario, teniendo en cuenta fundamentalmente que su name debe ser campo y su class negro. De esta forma, todas las funcionalidades de nuestro código JavaScript serán aplicadas automáticamente sin hacer nada más. Bien es cierto que en este ejemplo solo tenemos en cuenta la comprobación de que el campo no esté vacío y que, en el caso de ser el campo email, sea una dirección de correo correcta, pero añadir nuevas validaciones no es nada complicado dado cómo tenemos estructurado nuestro código. Es obvio que nuestro formulario es quizás demasiado redundante en sus validaciones (imágenes, textos, barra de progreso), pero puedes adaptarlo fácilmente a tus necesidades sin demasiado esfuerzo. Además debemos tener en cuenta que por muy inteligente que sea nuestro JavaScript, debemos validarlo en el PHP destino para evitar posibles inyecciones de código no deseadas. Pero eso lo dejo para vosotros 🙂

Android Kit Kat 4.4 ya está aquí

Publicado: febrero 7, PM en Enlaces, Noticias
Etiquetas:,

Como lo prometido es deuda vamos a ver, resumidas, las novedades que nos trae esta nueva versión del pequeño, pero enorme, robot verde.
Lo nuevo que nos aporta Kit Kat 4.4 no solo es a nivel de experiencia de usuario sino, por supuesto, también a nivel de desarrollo. Todo está preparado para dar un salto cualitativo en las funcionalidades de los dispositivos que ya disfrutan, a fecha de hoy, de sus excelencias, como pueden ser el Samsung Galaxy s4, HTC One, Nexus 4, 7 o 10 entre otros muchos que estarán disponibles en un breve lapso de tiempo.
Sin más veamos cuáles son algunas de esas novedades:

1) LAUNCHER RENOVADO: Google Now se incorpora a la pantalla de inicio totalmente mejorada y con nuevas opciones. Los iconos son ahora algo más grandes y algunos han sido rediseñados para que se vean mejor. La barra de notificaciones es ahora transparente lo que permite que el fondo de pantalla se extienda por toda la superficie dando lugar a una estética mejorada.

2) MEJORAS INTERNAS: La multitarea es ahora más veloz que nunca. Las aplicaciones en segundo plano consumen menos memoria. Con Chromium WebView se facilita a los desarrolladores una manera más sencilla de generar y mostrar contenido basado en internet. Se incluye más soporte HTML5, CSS3 y JavaScript. El sistema ha sido diseñado para adaptarse perfectamente tanto a dispositivos de gama baja como de gama alta. Todas las aplicaciones y funcionalidades de la versión han sido rediseñadas para lograrlo. Nuevo soporte NFC. Sistema inteligente de reproducción de video adaptativa que alterna entre resoluciones en base a la conexión WIFI para conseguir la mejor opción de visionado.

3) LA NUBE: Función Cloud Print incorporada. Google drive permite el acceso a sus carpetas a través de aplicaciones como QuickOffice.

4) MAIL: Actualizado con nuevos gestos y opciones para gestionar los correos.

5) APP TELÉFONO: Se identifica a los números de las llamadas recibidas y realizadas comparándolas con los de las empresas. De esta forma se pueden evitar llamadas comerciales no deseadas. Importación y exportación de contactos desde la tarjeta SD o desde una cuenta en la nube. Los contactos pueden ser ordenados en grupos y categorías.

6) APP MENSAJES SMS: Desaparece. Ahora los mensajes se envían a través de Google Now.

7) GOOGLE+ FOTOS: Nueva aplicación para editar, cargar y compartir imágenes. Dispone de un potente paquete de herramientas de edición de imágenes como por ejemplo poder crear una película uniendo varias fotos. Igualmente están disponibles un sinfín de filtros.

8) HDR+ FOTOS: Trabaja junto a la App Google+ Fotos y permite tomar imágenes espectaculares. Se accede a través de la App Cámara y usa una opción al estilo ráfaga que reconstruye y elige el mejor disparo de una amplia gama de imágenes.

9) INTERFAZ INTELIGENTE: Opción pantalla completa al leer un libro o ver un vídeo. Se muestra la portada del álbum o la película que se esté viendo como pantalla de bloqueo mientras se hace streaming a otro dispositivo. Nueva App de descargas con nuevas funcionalidades que facilitan el seguimiento. Notificaciones renovadas más atractivas y que se pueden usar con otras apps.

Bueno, hecho este repaso a lo más importante solo me queda dejar un enlace a las novedades que presenta esta versión desde el punto de vista del desarrollador:
Developer Android Kit Kat
Espero que os haya gustado y que fomente vuestro interés por este nuevo paso en la carrera del gigante Android.

La disputa sobre qué sistema operativo para dispositivos móviles es mejor siempre me ha parecido un tanto maniquea. Todos tienen su pro y su contra, como casi todo en la vida. Ser un fanático de uno de ellos creo que no es razonable porque los fanatismos son el árbol que no te deja ver el bosque. Pero si me tuviera que decantar por uno hoy día, ahora mismo, diría sin lugar a dudas que prefiero Android. ¿Por qué?. Pues porque es flexible, código abierto, porque ha demostrado que mejora día a día en cada nueva actualización o versión, porque es sencillo, potente, amigable y muchas otras cosas más. Pero sobre todo porque las aplicaciones se programan en Java (una variación llamada Dalvik), un lenguaje multiplataforma y uno de los de mi devoción. Para ser honestos la verdad es que a Android le quedan muchas cosas por limar, sobre todo en lo que respecta a la seguridad. Google Play sigue manteniendo a día de hoy un agujero muy difícil de tapar dada la enorme cantidad de aplicaciones que mantiene. Estoy seguro que tarde o temprano se resolverá pero, desde luego, es un hándicap muy peliagudo. Sin embargo, Android 4.4 Kit Kat ya está aquí para hacer las delicias de los que apostamos por este sistema. En breve espero hacer un repaso de las novedades que nos ofrecerá esta nueva versión del robot verde.
¿Por qué no iOS? Desde luego se trata de un sistema de una robustez incontestable, de un acabado casi perfecto, de una potencia sin igual. Un sistema a prueba de balas. Pero lo que no me convence es, entre otras cosas y resumiendo, que tenga que usar un lenguaje propietario como Objective C & Cocoa. Vale que existen herramientas como Corona SDK y Lua para ponernos las cosas más fáciles, pero aún así no me gusta ese mundo cerrado y arisco con todo lo que sea distinto.
En cuanto a Windows Phone 8 ¿Por qué no? Cierto es que los de Redmond han hecho un trabajo excelente pese a las críticas que ha recibido su nueva versión. Su interfaz y su usabilidad no pueden dejar a nadie indiferente. Hablamos de una filosofía de aplicaciones interconectadas entre sí que es abrumadora. Es verdad que las cifras que se esperaban, en cuanto a dispositivos que utilizarían este sistema no ha cubierto las expectativas, pero no por ello debemos echarlo por tierra cuando demuestra tener un futuro prometedor si continúan así. Lo malo es que para poder desarrollar aplicaciones para la Windows Store, sí o sí debes tener instalado Windows 8. Y si además quieres programar nuevas funcionalidades solo están disponibles si lo haces desde Windows 8.1, su última actualización hasta la fecha. No me convence esta forma de obligar al programador a pasar por taquilla.
En fin, ya solo quedas tú y tu opinión. Por supuesto puedes elegir cualquier otro sistema distinto a los tres expuestos. Adelante.

Decorator Patrón de diseño

Decorator Patrón de diseño

Los patrones de diseño son esenciales en el desarrollo de software. La famosa banda de los cuatro formada por Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides es toda una referencia en el campo del diseño orientado a objetos. No solo basta con el conocimiento de los patrones sino saber cómo y cuándo emplearlos. Como sabemos, no existen para complicar la vida del programador, sino todo lo contrario. Se intenta garantizar con ellos la efectividad en la resolución de problemas comunes en todo desarrollo de software complejo así como la reusabilidad de los mismos en futuros proyectos. Es evidente que se trata de un tema con enjundia que conviene siempre tener a mano. Por ello voy a dejaros un enlace al canal de youtube de Alexys Lozada, un muchacho que ha realizado un excelente trabajo sobre patrones de diseño y que muestra, con sus videotutoriales de ejemplo, nada menos que 19 de ellos usando Java como lenguaje de programación.
Además, en el canal podréis encontraros, siempre dentro del mundo de Java, con otros temas tan interesantes como la recursividad, manejo de excepciones y estructura de datos.
Imprescindible.
http://www.youtube.com/user/Alexyslozada
Los códigos de los videotutoriales pueden obtenerse desde aquí:
https://github.com/alexyslozada/CursoPatronesDiseno

Desde hace algún tiempo he comprobado que hay muchos desarrolladores que al tratar de implementar un sistema de autenticación en CakePHP con AuthComponent tienen problemas y no funciona como debería. Sea por motivos de versión del framework o, simplemente, porque no está bien implementado el código, la cuestión es que la aplicación no funciona.
Vamos entonces a ver a continuación cómo programar un sistema de autenticación sin la necesidad del AuthComponent.
Partimos de que tenemos una base de datos conectada correctamente a través de la configuración de nuestro archivo database.php y, además, suponemos que tenemos ya una aplicación en CakePHP que debemos proteger de usuarios no autenticados.
Con lo primero que debemos contar es con una tabla en nuestra base de datos que yo he llamado users. Esta tabla cuenta a su vez con tres campos: id, username y password. El campo id será nuestra clave primaria autoincremental y los otros dos campos de tipo varchar.
Una vez hecho esto, vamos con el código. Abrimos nuestro archivo AppController que se encuentra en la ruta CarpetaAplicacion/app/Controller donde CarpetaAplicacion es el nombre de la carpeta donde guardas tu proyecto. Escribimos el siguiente código:

<?php

App::uses('Controller','Controller');

class AppController extends Controller {

public$components=array('Session');

    // Comprobar si el usuario está logueado
    function authenticate()
    {
        // Comprobamos si la variable de sesión existe. Si es así quiere decir que el usuario se ha logueado
       //correctamente y se le redirecciona a la aplicación.
      //Si no existe se le devuelve al login.
        if(!$this->Session->check('User'))
        {
            $this->redirect(array('controller'=>'users','action'=>'autenticar'));
            exit();
        }

    }
 
    //Autenticación obligatoria si se quiere entrar a cualquier parte de la aplicación
    function afterFilter()
    {
        if($this->action!='autenticar')
        {
            $this->authenticate();
        }
    }
}

La función afterFilter va a permitirnos controlar cuándo un usuario intenta entrar en una zona donde se ejecuta una acción distinta a ‘autenticar’. Inmediatamente llama a la función authenticate que nos va a permitir saber si se ha creado ya una sesión de usuario. Si es así significará que el usuario esta autenticado, con lo que automáticamente será redireccionado al index de la aplicación. Si no es así se le redireccionará de nuevo a la acción autenticar del controlador users (lo veremos a continuación) que, por supuesto, contará con una vista que contendrá el formulario de login. Sigamos.
Ahora vamos a crear, dentro de la carpeta de nuestros modelos, un archivo con el nombre User.php. La ruta será CarpetaAplicacion/app/Model/User.php. Escribimos lo siguiente:

<?php
App::uses('AppModel','Model');
/**
 * User Model
 *
 */
class User extends AppModel {

   var$name='User';

/**
 * Display field
 *
 * @var string
 */

   public$displayField='username';

   var$validate=array(
       'username'=>array(
                    'rule'=>array('minLength',1),
                    'required'=>true,
                    'allowEmpty'=>false,
                    'message'=>'Por favor, introduce un nombre'
                    ),
       'password'=>array(
                    'rule'=>array('minLength',1),
                    'required'=>true,
                    'allowEmpty'=>false,
                    'message'=>'Por favor, introduce la contraseña'
                    ),

   );

}

Lo que hemos hecho es crear nuestra clase modelo que conectará con nuestra tabla users de la BD. También usamos la validación de los campos username y password del formulario que posteriormente crearemos en nuestra View.
Continuamos. Volvemos a nuestra carpeta de controladores y creamos un archivo llamado UsersController.php. La ruta será CarpetaAplicacion/app/Controller/UsersController.php. Aquí escribimos ahora el siguiente código:

<?php
App::uses('AppController','Controller');
/**
 * Users Controller
 *
 * @property User $User
 * @property PaginatorComponent $Paginator
 */
class UsersController extends AppController {

/**
 * Components
 *
 * @var array
 */
    public$components=array('Session');
 
    publicfunction autenticar(){
        // Aunque los campos username y password tienen validación para que no estén vacíos,
// volvemos a asegurarnos con el condicional que el campo username del formulario tiene
        //algún valor
        if(empty($this->data['User']['username'])==false)
        {
    	 //Consulta SQL para buscar al usuario con sus credenciales en la BD
$user=$this->User->find('all',array('conditions'=>array(
                'User.username'=>$this->data['User']['username'],
                'User.password'=>$this->data['User']['password'])));
         //Si se ha encontrado al usuario en la consulta
         if($user!=false)
         {
          //Si existe se redirecciona al usuario a la aplicación creando una variable de sesión 
          $this->Session->setFlash(__('Gracias por loguearse!'));
          $this->Session->write('User',$user);
          $this->Redirect(array('controller'=>'ControllerDeTuAplicacion','action'=>'index'));
          exit();
         }
         else
         {
//Si los datos no son correctos se comunica al usuario y se le devuelve al mismo
          //formulario de login
          $this->Session->setFlash(__('Nombre de usuario y/o password incorrectos'));
          $this->Redirect(array('action'=>'autenticar'));
          exit();
         }
        }
    }
}

Veamos qué hace nuestra clase controller. Es imprescindible, como en el archivo AppController, tener cargado el componente Session. Como podemos ver lo tenemos en nuestra variable pública $components. Lo primero que va a hacer la clase es comprobar que se han pasado datos en el campo username desde el formulario. Es cierto que los campos ya están validados desde nuestro Model, pero siempre es interesante comprobarlo también aquí. Si no es correcto, es decir, si el campo está vacío, entonces se redirecciona de nuevo al mismo formulario. De esto se encarga nuestro Model como sabemos, ya que al no haber ninguna variable Session creada reaccionará en consecuencia. Si, por el contrario, hay datos, se ejecuta una consulta en la BD para comprobar que, efectivamente, el usuario y password existen. Si no existen, entonces se le redireccciona al usuario de nuevo a la acción autenticar que hará que nuestro afterFilter del archivo AppController (¿Recuerdas?) compruebe que exista una variable de sesión. Como no es así se le reenvía automáticamente de nuevo al formulario con un mensaje flash indicando que uno o los dos campos no son correctos. Si existe el usuario, entonces se le redirecciona a la página index de la aplicación, no sin antes crear la variable de sesión que nos permitirá superar con éxito el método authenticate de nuestro AppController que es llamado automáticamente desde nuestro vigilante afterFilter.
Ya lo único que nos queda es crear nuestra View que mostrará el formulario para poder loguearse. Vamos a la ruta CarpetaAplicacion/app/View y creamos la carpeta Users. Despues, dentro de ella, creamos el archivo autenticar.ctp con el siguiente código:

<div>
<?php echo $this->Form->create('User'); ?>
	<fieldset>
		<legend><?php echo __('Login aplicación'); ?></legend>
	<?php
		echo $this->Form->input('username');
		echo $this->Form->input('password');
	?>
	</fieldset>
<?php echo $this->Form->end(__('Continuar')); ?>
</div>

Como se puede observar se trata de un simple formulario muy sencillo donde no creo que haya nada que explicar. Pues ya está, con esto hemos terminado. Ahora tenemos un sistema que permite proteger el acceso a nuestra aplicación de todos aquellos usuarios que, previamente, no estén en la base de datos. Obviamente, para poder probarlo, necesitamos entonces tener al menos un usuario en nuestra tabla users. Este ejemplo no contempla la posibilidad de registrarse pero creo que, con este punto de partida, no es nada complicado implementarlo. Pero eso lo dejo para vosotros 🙂 Un saludo.-

He decidido compartir con vosotros un ejercicio que suelo poner a mis alumnos de JavaScript. Se trata de implementar el típico mensaje de autosugerencia cuando escribimos algo en una entrada de texto destinada a tal fin. Vamos a comenzar creando un archivo HTML que puedes llamar como quieras, aunque en mi caso le he llamado index.html para seguir la costumbre ya que se trata del punto de entrada. Si estás usando un IDE como Aptana, Dreamweaver o cualquier otro, crea un nuevo proyecto y añade este archivo. Si eres de los que prefiere hacer las cosas “a pelo”, pues crea el archivo en el mismo escritorio y solucionado.
Bien, vamos allá. Escribimos en el susodicho archivo lo siguiente:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Autosugerencia</title>
</head>

<body>

Escribe una palabra: <input type="text" id="palabra"/>

<ul id="suggest"></ul>

</body>

<script type="text/javascript" src="js/autosugerencia.js"></script>

</html>

Simplemente, como podemos ver, este archivo contiene un campo de entrada de texto con el id palabra, y una lista desordenada vacía con el id suggest. Al final, antes del cierre de la etiqueta HTML, cargamos el JavaScript que se encargará de todo dentro de una carpeta llamada js. Al archivo le he llamado autosugerencia.js, tú puedes llamarle como quieras, siempre y cuando en el paso siguiente crees ese archivo con el mismo nombre. Con solo esto en el HTML es con lo que vamos a trabajar.
Ahora creamos una carpeta llamada js y dentro un archivo llamado autogerencia.js en mi caso o, como ya he advertido, con el nombre que hayas decidido ponerle en el HTML. Entonces, una vez creado, escribimos el siguiente código:

// JavaScript Document

var palabras = ["enero", "febrero", "marzo", "abril", "mayo", "junio",
				"julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"];

document.getElementById("palabra").addEventListener("keyup", autosugerir, false);

function autosugerir(){

	var contador = 0;

	var escribiendo = document.getElementById("palabra").value.toLowerCase();

	document.getElementById("suggest").innerHTML="";

		if (escribiendo != ""){

			var caracteres = escribiendo.length;

			for (x=0; x < palabras.length; x++){

				var pArray = new String(palabras[x]);

				var sugerencia = pArray.substring(0,caracteres);

				if (sugerencia == escribiendo){

					contador++;
					var ul = document.getElementById("suggest");
					var new_li = document.createElement('li');
					new_li.className = pArray;
					new_li.style.cursor = "pointer";
					new_li.innerHTML = "Quizás quiso decir " + pArray;
					ul.appendChild(new_li);
					new_li.addEventListener("click", aceptar, false);

				}

			}

			if (contador == 0){

				var ul = document.getElementById("suggest");
				var new_li = document.createElement('li');
				new_li.innerHTML = "No hay sugerencias";
				ul.appendChild(new_li);

			}

		}

		else {

			var ul = document.getElementById("suggest");
			var new_li = document.createElement('li');
			new_li.innerHTML = "No hay sugerencias";
			ul.appendChild(new_li);

		}

}

function aceptar(){

		document.getElementById("suggest").innerHTML="";
		var palabraSeleccionada = this.className;
		var cajaTexto = document.getElementById("palabra");
		cajaTexto.value = palabraSeleccionada;

}

Veamos el código paso a paso.
Lo lógico sería que toda la información que va a ser auto sugerida fuera suministrada por una base de datos pero, para no complicar el ejemplo, vamos a hacerlo desde un array. Eso es precisamente lo que hacemos al comienzo, declarar un array que contiene los meses del año. Acto seguido vinculamos un listener en tiempo de ejecución al campo de texto donde el usuario irá escribiendo. Como vemos, al método addEventListener encargado de ello, se le pasan tres argumentos. El primero es el tipo de evento, el segundo la función destino que se ejecutará cuando el evento se produzca, y el tercero es un argumento booleano opcional. Si es true, todos los eventos del tipo especificado serán lanzados al listener registrado antes de comenzar a ser controlados por algún EventTarget que esté por debajo en el arbol DOM del documento.
Como vemos, el evento que vamos a “escuchar” es el keyup, es decir, cuando el usuario termine de pulsar una tecla. La función de llamada será autosugerir, y el último argumento lo ponemos a false, ya que no queremos que reaccione como hemos explicado hace un momento.
Hasta ahora lo único que tenemos son los datos para sugerir y un escuchador de eventos que estará alerta vigilando cuándo se pulsa una tecla sobre el campo de texto de nuestro HTML.
Bien, veamos ahora qué hace la función autosugerir que es la que va a realizar todo el trabajo. Primero iniciamos una variable contador a cero, después guardamos en la variable escribiendo el resultado de capturar el contenido del campo de texto y convertirlo directamente a minúsculas con la función de JavaScript toLowerCase(). Para asegurarnos que la lista desordenada se encuentra vacía, lo hacemos en la siguiente línea. Ahora, con el condicional, comprobamos que la variable escribiendo no esté vacía, es decir, que haya algún dato en el campo de texto. Si lo hay, guardamos en la variable caracteres la longitud de caracteres, valga la redundancia, de lo que haya escrito en el campo de texto. Seguidamente, con el bucle for, vamos a iterarnos desde cero hasta el total de elementos contenidos en nuestro array. Dentro de este bucle es donde se haya el meollo de la cuestión. Veamos.
Lo primero es guardar en la variable pArray el elemento del array situado en la posición x (variable que, como sabemos, ira aumentando en cada iteración y que comienza por cero). Después, en la variable sugerencia, guardamos el resultado de substraer del contenido de nuestra variable pArray (que, recordemos, contendrá un elemento del array distinto en cada iteración) los caracteres que existan entre cero y el total de caracteres escritos por el usuario hasta ese momento, que ya guardamos anteriormente en la variable caracteres. En el condicional comprobamos si existe alguna coincidencia entre el trozo que hemos obtenido del elemento de nuestro array y lo que haya escrito el usuario. Si es así, aumentamos la variable contador en uno (ya veremos para qué), capturamos la lista desordenada de nuestro HTML en la variable ul y creamos en tiempo de ejecución una etiqueta HTML li en nuestra variable new_li. A continuación le añadimos un nombre de clase que hacemos igual a lo que contenga en ese momento nuestra variable pArray, le añadimos un estilo de cursor y un texto que mostrará la sugerencia obtenida. Para que la etiqueta li creada en tiempo de ejecución pueda aparecer en el HTML, debemos añadirla con appendChild a nuestra lista desordenada. Finalmente, añadimos un listener a la etiqueta li que controlará el evento click sobre cualquiera de ellas y disparará la función aceptar que veremos en un momento. Como ya he comentado, en este bucle for se encuentra la lógica más importante del programa y hará que se muestren todas y cada una de las coincidencias encontradas entre lo que escribamos y nuestro array.
Después del bucle for vemos otro condicional que comprueba si la variable contador es igual a cero. Si recordamos, esta variable la inicializamos así al comienzo de nuestra función. Esto nos sirve para controlar si se ha encontrado alguna sugerencia o no dentro del bucle for, ya que, como hemos visto, la variable va sumando uno cada vez que se encuentra con una coincidencia. Si no es así, la variable seguirá valiendo cero y, por lo tanto, mostramos un mensaje de ello al usuario a través de una etiqueta li creada en tiempo de ejecución y que añadimos a nuestra lista desordenada en el HTML. También, en el else del if contenedor, mostramos lo mismo si la variable escribiendo se encuentra vacía (esto ocurrirá si el usuario escribe algunos caracteres y, posteriormente, decide borrarlos todos). Con esto tenemos visto toda la función autosugerir completa.
Al final del archivo nos encontramos con la función aceptar vinculada a cada una de las etiquetas li que se creen en tiempo de ejecución. Con esto haremos que si un usuario desea aceptar cualquier sugerencia mostrada haciendo clic sobre ella, se muestre automáticamente en el campo de texto. Como vemos, vaciamos la lista desordenada, guardamos en la variable palabraSeleccionada el nombre de la clase que tenga la etiqueta y que, a su vez, será igual al elemento del array, capturamos en la variable cajaTexto el campo de texto de nuestro HTML y, finalmente, le asignamos el valor de la variable palabraSeleccionada.
Y con esto ya lo tenemos.
Ahora podemos probarlo y si, por ejemplo, escribimos solo la letra m en nuestra entrada de texto, veremos como mágicamente aparecen las sugerencias de los meses marzo y mayo.
Como dije al principio, lo suyo es que la fuente de datos se encuentre en una BD y que, además, obtengamos esos datos mediante Ajax. Teniendo este código como punto de partida no es demasiado complicado implementarlo.
Pero eso lo dejo para vosotros 🙂
Espero que os haya gustado y os sea de utilidad.

Aplicación Google Play

Aplicación Google Play – Mi lista de la compra

Os quiero presentar esta aplicación desarrollada para Android que programé hace algún tiempo. Se trata de una aplicación muy sencilla pero útil que nos permite crear nuestra lista de la compra y controlar el gasto en todo momento. Nos permite ir creando entradas de productos distribuidos en cinco categorías, modificarlas o eliminarlas. Podemos indicar el número de unidades a comprar y su precio, lo que nos mostrará automáticamente el precio total por producto. Si deseamos conocer cuál es el importe total de la compra lo tenemos disponible en cualquier momento. Además podemos ordenar nuestra lista alfabéticamente de mayor a menor o viceversa. En el momento de la compra podemos ir tachando los productos comprados pulsando sobre ellos para controlar aquellos que todavía no hemos adquirido de nuestra lista. En fin, como veis, una aplicación que nunca está de más llevar instalada en vuestro dispositivo móvil. Si estáis interesados visitar este enlace y descargarla gratuitamente: Mi lista de la compra

Aula Mentor

Aula Mentor

Si eres de ese tipo de seres inquietos que nunca pueden dejar de aprender y que, además, quieren ampliar su currículum profesional, te recomiendo visitar la página de Aula Mentor. Se trata de una iniciativa de formación online perteneciente al Ministerio de Educación, cultura y deporte. Por un precio módico puedes realizar un curso online de una calidad extraordinaria, donde además cuentas con la posibilidad de realizar un examen que te permita obtener un certificado del Ministerio avalando tus estudios. Los exámenes son presenciales, claro, y por ello deberás buscar tu aula mentor más cercana a tu residencia. No te preocupes que hay muchas. Toda la información al respecto de cursos, duración, matrícula y aulas la tenéis en la propia página web. Dado que este blog trata de programación os recomiendo ir al apartado correspondiente en la página web. Os sorprenderéis al encontraros con cursos como el de Symfony2, Java avanzado, Java web o el completísimo sobre aplicaciones Android, entre otros muchos.
Aquí va el enlace: Aula Mentor