Convirtiendo la documentación de FuelPHP a un único documento

Introducción.

FuelPHP es un framework para el desarrollo de aplicaciones que a pesar de su muy reciente aparición es muy interesante y prometedor para el entorno del desarrollo de aplicaciones web con software libre.  Este framework es similar a Codeigniter o Kohana en términos de su simplicidad, sin embargo no se basa directamente en ninguno de ellos sino que por el contario, toma los conceptos e ideas de diseño exitosas de los principales frameworks y los integra en una única base para la implementación de aplicaciones web.

Teniendo una relativa corta edad, su desarrollo ha sido veloz y su versión 1.0 se encuentra muy próxima a publicarse.  La documentación también ha evolucionado rápidamente y se encuentra en contínua actualización.  Esta se presenta por secciones que se pueden revisar directamente siendo esto muy apropiado para las consultas rápidas de la misma sin embargo -en mi opinión personal- no es tan útil cuando se está aprendiendo del framework por primera vez ya que no es posible realizar una revisión o búsqueda líneal de los temas ni mucho menos imprimirlos.

Dado lo prometedor del framework decidí tomarme un par de minutos para desarrollar una solución que me permitiera consolidar fácilmente la documentación en un único documento para poder imprimirlo y estudiar de él.  Terminé con una pequeña herramienta basada en Javascript con jQuery que realizar esta tarea.  Debido a las limitaciones de seguridad impuestas por los navegadores es necesario que se descargue en un servidor web local la documentación para que pueda ser procesada por esta herramienta.

Debe tenerse en cuenta que los documentos generados o impresos no recibirán las contínuas actualizaciones que si recibe la versión en línea, por este motivo prefiero no distribuír el documento completo con la versión del día sino compartir el método para que pueda ser creado frecuentemente.

Instalación.

Crear una carpeta en el árbol de directorios (DOCUMENT_ROOT) públicos del servidor de páginas.

Descomprimir la distribución de la herramienta en el directorio web.

Descargar la distribución actual de FuelPHP y descomprimirla en el directorio web al mismo nivel de la herramienta. 

Los archivos contenidos en la carpeta de mas alto nivel serán similares a los mostrados a continuación en la cual se utilizó la versión 1.0-RC3 del framework.

Contenidos de la carpeta web
Contenidos de la carpeta web

 

Configuración.

El único paso necesario para configurar la herramienta consiste en editar el archivo FuelPHPOneDoc/FuelPHPOneDoc.js y modificar apropiadamente el valor de la variable baseUrl la cual deberá contener la dirección absoluta en la cual se publicó localmente la documentación de FuelPHP.  De esta manera en el ejemplo anterior, si la carpeta pública web corresponde con la dirección http://localhost/onedoc/ entonces el valor de baseUrl será http://localhost/onedoc/v1.0-rc3/docs/.

Ejecución.

Acceder al URL de la herramienta utilizando un navegador web.  En el caso del ejemplo anterior sería a la dirección http://localhost/onedoc/FuelPHPOneDoc/FuelPHPOneDoc.html.

Documentación de FuelPHP en un unico documento
Documentación de FuelPHP en un unico documento

 

Requerimiento: servidor de páginas web.

Por la razón que se mencionó anteriormente, es necesario contar con un servidor de páginas web para publicar tanto el contenido de la documentación original de FuelPHP como la herramienta para modificar su presentación.

En caso de no contarse con un servidor de páginas instalado, este podrá obtenerse de diferentes maneras: Apache (todas las plataformas), Internet Information Service (sólo Windows), XAMPP (todas las plataformas) y nginx (todas las plataformas) entre muchos otros.

Si no se cuenta con ninguno de estos servidores de páginas web pero se cuenta con soporte para el lenguaje Python, es posible utilizar temporalmente el servidor web de desarrollo que incluye este lenguaje.  Para utilizarlo será necesario abrir una terminal y ubicarse en el directorio que se convertirá en público a través de web e invocar la aplicación.

$ cd /home/jimezam/tmp/FuelPHP

Si cuenta con soporte para Python 2.x:

$ python -m SimpleHTTPServer

En cambio, si se cuenta con soporte para Python 3.x, la instrucción a ejecutar será la siguiente.

$ python -m http.server 8000

En ambos casos el puerto que se utilizará para lanzar el nuevo servidor web será el 8000 así que este tendrá que ser tenido en cuenta durante la determinación del respectivo URL.  En este caso, el URL que deberá ser consultado será http://localhost:8000/FuelPHPOneDoc/FuelPHPOneDoc.html.

Arrastrar y soltar con HTML5

Introducción.

En este artículo se revisarán los pasos necesarios para implementar la facilidad de arrastrar y soltar (drag and drop) en una página web aprovechando las funcionalidades provistas por HTML5.  Para este desarrollo se utilizará jQuery para facilitar la implementación, sin embargo esto no es estrictamente necesario.

Establecer los elementos “arrastrables”.

El primer paso consiste en establecer cuales elementos podrán ser arrastrados, para hacer esto se les deberá agregar el atributo draggable=’true’.  En el caso del ejemplo, los elementos arrastrables son imágenes de la siguiente manera.

<img id="tool0" draggable="true" title="tool" src="img/tool0.png" alt="tool" />
<img id="tool1" draggable="true" title="tool" src="img/tool1.png" alt="tool" />
<img id="tool2" draggable="true" title="tool" src="img/tool2.png" alt="tool" />

Definir el comportamiento de los elementos “arrastrables”.

El siguiente paso es establecer que se debe hacer cuando los objetos arrastrables son manipulados, es decir, manejar sus eventos.  Estos eventos corresponden con los siguientes y su implementación se debe definir cuando la estructura de la página se encuentra completamente cargada.

 dragstart  El elemento se empieza a arrastrar.
 drag  El elemento está siendo arrastrado.
 dragend  El elemento ha dejado de ser arrastado.

Durante el manejo del evento dragstart se realizan las siguientes tareas.

  1. Almacenar la información del elemento arrastrable (su id en este caso) necesaria para ser procesado en caso de ser soltado exitosamente.
  2. Agregar una nueva clase CSS (itemSelected) para modificar su apariencia mientras es arrastrado.
  3. Modificar la imagen del elemento arrastrado la cual por defecto es la del mismo elemento.
$('.page #main #items .item').bind('dragstart', function(event) {

    // Store information about the item dragged.

    event.originalEvent.dataTransfer.setData("text/plain", event.target.getAttribute('id'));

    // Add a CSS class to highlight the dragged item.

    $(event.target).addClass('itemSelected');

    // Set an image as drag icon.  The image was preloaded.

    var dragIcon = document.createElement('img');
    dragIcon.src = 'img/hand.png';

    event.originalEvent.dataTransfer.setDragImage(dragIcon, 139, 43);
});

Durante el manejo del evento drag no se realizan tareas especiales en este caso.

$('.page #main #items .item').bind('drag', function(event) {
    // The item is being dragged!
});

Durante el manejo del evento dragend se realiza una única tarea y corresponde con retirar la clase CSS añadida durante dragstart para indicar que el elemento ya no está siendo arrastrado actualmente.

$('.page #main #items .item').bind('dragend', function(event) {

    // Remove the CSS class that highlights it while beign dragged.

    $(event.target).removeClass('itemSelected');
});

Definir el comportamiento de las “zonas de descarga”.

El paso final consiste en establecer que se debe hacer cuando los objetos arrastrables interactúan con las zonas de descarga (drop zones), es decir, manejar sus eventos.  Estos eventos corresponden con los siguientes y su implementación también se debe definir cuando la estructura de la página se encuentra completamente cargada.

 dragenter  El elemento arrastrable ha entrado a una zona de descarga.
 dragleave  El elemento arrastrable ha salido de una zona de descarga.
 dragover  El elemento arrastrable está siendo arrastrado sobre una zona de descarga.
 drop  El elemento arrastrable ha sido soltado sobre una zona de descarga.

Durante el manejo del evento dragenter se agrega una nueva clase CSS (itemOnDropArea) para modificar la apariencia de la zona de descarga mientras un elemento es arrastrado sobre ella.

$('.page #main #boxes .box').bind('dragenter', function(event) {

    // Add a CSS class to highlight the drop zone used.

    $(event.target).addClass('itemOnDropArea');

    // Prevents the default event that denies the DnD
    // behaviour.  Acts as "event.preventDefault()" in
    // vanilla Javascript.

    return false;
});

Durante el manejo del evento dragleave se realiza la tarea contraria, se remueve la clase CSS agregada durante el suceso del evento anterior para mostrar que ningún elemento es arrastrado ahora sobre la zona de descarga.

$('.page #main #boxes .box').bind('dragleave', function(event) {

    // Remove the CSS class that highlights the used drop zone.

    $(event.target).removeClass('itemOnDropArea');

    // Prevents the default event that denies the DnD
    // behaviour.  Acts as "event.preventDefault()" in
    // vanilla Javascript.

    return false;
});

Durante el manejo del evento dragover no se realiza en este caso ninguna tarea interesante además de indicarle al navegador que evite su comportamiento por defecto el cual es impedir que se realice.

$('.page #main #boxes .box').bind('dragover', function(event) {

    // Prevents the default event that denies the DnD
    // behaviour.  Acts as "event.preventDefault()" in
    // vanilla Javascript.

    return false;
});

Durante el manejo del evento drop, que sucede cuando el elemento arrastrable se suelta sobre la zona de descarga, se realizan las siguientes tareas en la aplicación de demostración.

  1. Obtener la información almacenada en el objeto dataTransfer definida durante el manejo del evento dragstart.
  2. Obtener la información del objeto arrastrable.
  3. Obtener la información de la zona de descarga.
  4. Determinar si la descarga del objeto es válida o no en la zona de descarga específica.
  5. Realizar una acción según se determine en la tarea anterior: remover el elemento o mostrar un mensaje de error.
  6. Evitar que se efectúe el comportamiento por defecto relacionado con el evento.
$('.page #main #boxes .box').bind('drop', function(event) {

	// Get the stored information about the draggable item,
	// the element ID in this case.

	var itemId = event.originalEvent.dataTransfer.getData("text/plain");

	// Get the type of the draggable item, stored in the
	// ALT attribute in this case.

	var itemType = $("#" + itemId).attr('alt');

	// Get the drop zone's ID to difference the type of it.

	var dropboxType = $(event.target).attr('id');

	// Check if the draggable item can be or not dropped
	// into the current drop zone.

	if(dropboxType == 'toolbox')
	{
		if(itemType == 'tool')
			$("#" + itemId).remove();
		else
			alert("That is a FRUIT, put it on the Fruit's Basket!");
	}

	if(dropboxType == 'fruitbasket')
	{
		if(itemType == 'fruit')
			$("#" + itemId).remove();
		else
			alert("That is a TOOL, put it on the Toolbox!");
	}

	// Remove the CSS class that highlights the used drop zone.

	$(event.target).removeClass('itemOnDropArea');

	// Prevents the default event that denies the DnD
	// behaviour.  Acts as "event.preventDefault()" in
	// vanilla Javascript.

	return false;
});

El prototipo.

En este prototipo se utilizan los fragmentos de código mostrados en este artículo, en él se muestran en la parte inferior dos series de objetos arrastrables (herramientas y frutas) y en la parte superior dos zonas de descarga (una caja de herramientas y una canasta de frutas).  La página web permitirá que el usuario arrastre los elementos a cualquiera de de las zonas de descarga, sin embargo sólo aceptará que se almacenen en la zona correcta.  En caso de intentarse hacer lo contrario se obtendrá un mensaje de error.

Prototipo de demostración de arrastrar y soltar con HTML5
Prototipo de demostración de arrastrar y soltar con HTML5

Enlaces.

Experimentando con jQuery Mobile: The Simple List 0.1

Introducción.

Después de experimentar con jQTouch durante la implementación de un prototipo de aplicación para el 6CCC, me ha tomado unas cuantas horas para elaborar un nuevo prototipo de aplicación web móvil, esta vez utilizando jQuery Mobile como framework para el nivel de presentación.

Su uso es muy similar al visto anteriormente, sin embargo considero que este proyecto cuenta con mejor documentación que el primero.  Ambos se basan en la mejora progresiva (Progresive Enhancement) y en la degradación aceptable (Graceful degradation) lo que los hace fáciles de entender por parte de los desarrolladores que estén habituados al uso de HTML/CSS/Javascript.

El prototipo.

Esta aplicación permite administrar una lista simple de elementos al estilo de las cosas por hacer.  La idea con este prototipo es el experimentar el uso del framework jQuery Mobile.

Para la persistencia se utiliza la facilidad del LocalStorage provisto por HTML5 y que es soportado por los navegadores web modernos incluyendo los incorporados en los sistemas operativos de los dispositivos móviles.

Estas son a grandes razgos las funcionalidades y flujos de información del prototipo.

The Simple List 0.1
The Simple List 0.1

 

Estas son algunas de las pantallas (page) de la aplicación web.

El prototipo puede probarse en línea a través de la web (ver sección de enlaces) y ya que su código fuente se encuentra completamente documentado, servirá también como ejemplo práctico para quienes estén interesados en aprender a desarrollar utilizando este framework web.

Enlaces.

Aplicación para el 6CCC: cómo llego ? Version web móvil

Introducción.

Otro prototipo que estuve preparando para el sexto Congreso Colombiano de Computación fue una aplicación web móvil basada en jQTouch para facilitarle a los visitantes consultar fácilmente la agenda de las conferencias y obtener la ruta que se deberá recorrer para llegar a los lugares del evento o demás sitios de interés de la ciudad.

El prototipo.

  • Como se mencionó, se desarrolló utilizando jQTouch el cual es un plugin de jQuery por ende, la mayor parte de la aplicación se encuentra desarrollada en Javascript.
  • La estructura de la información se encuentra implementada en HTML5 (sin validar aún).
  • Se utilizó el servicio de mapas y rutas de Bing Maps ya que según los requerimientos de esta aplicación Bing cuenta con mejor información de Colombia que los demás proveedores.
  • La aplicación realiza la geocodificación de la ubicación del usuario, intentando identificar la dirección en que se encuentra.
  • También permite realizar la geocodificación inversa (de dirección a posición geográfica) según solicitud del usuario.  En este caso parece que la calidad del servicio de Bing es inferior a la de Google y valdría la pena cambiar al proveedor de este servicio específico.
  • Por restricciones de seguridad de los navegadores web modernos, es necesario que el usuario autorice el acceso al GPS por parte de la aplicación web.  Si esto no se realiza, la aplicación no podrá contar con la posición del usuario en la ciudad.
  • Para la demostración se manipuló el código de la aplicación para que en el momento de trazar una ruta siempre se tome una ubicación en Manizales (Caldas) como posición del usuario y permitir así experimentar con esta funcionalidad del prototipo.

Conclusiones.

  • Por falta de tiempo no pudo hacerse pública la aplicación web móvil ya que no fue posible realizar suficientes pruebas con dispositivos móviles reales.
  • Es necesario investigar mas acerca de jQTouch para utilizarlo en aplicaciones reales en producción.  Hasta el momento me parece una opción muy interesante para el desarrollo fácil de aplicaciones web móviles sin embargo hasta el momento no he encontrado buena documentación al respecto.
  • La mayor parte del prototipo se encuentra lista, espero en un futuro cercano realizar mayores pruebas y ajustes para publicarlo como una versión final.

Enlaces.

Ejemplo de AJAX rápido y simple con PHP y jQuery

Introducción.

Muy probablemente usted esté aquí, leyendo este artículo porque desea aprender a utilizar AJAX con PHP de una manera muy simple y rápida.  Yo estoy aquí porque hoy no tengo sueño y que mejor manera de esperarlo que escribir un pequeño tutorial acerca del acceso asíncrono de contenidos web utilizando el framework de jQuery.

Para no tener que dividir el artículo en varias entregas vamos a desarrollar un ejemplo muy sencillo y clásico: la calculadora, sólo que a diferencia de la habitual esta realizará sus cálculos del lado del servidor y presentará sus resultados a través de llamados con AJAX.  La implementación Javascript asociada con el objeto AJAX (el objeto XMLHTTPRequest) no la realizaremos directamente sino que utilizaremos el framework de jQuery el cual simplifica y facilita enormemente el desarrollo en Javascript.  El lado del servidor, los cálculos de nuestra calculadora, se implementarán en el viejo y conocido PHP.  Por supuesto para implementar el nivel de presentación (página web) que recibe el cliente tendremos que hablar un poco de HTML y CSS.

Qué es AJAX ?

AJAX es el acrónimo de Asynchronous JavaScript and XML, un conjunto de tecnologías web que permiten que las aplicaciones web desde sus clientes se comuniquen y soliciten información al servidor de manera asíncrona sin interferir con el contenido y comportamientos de la página actual, es decir, sin refrescar (postback) la página web por completo.

Su implementación se basa en el objeto XMLHttpRequest o XHR el cual fue originalmente desarrollado por Microsoft y apareció por primera vez en 1999 como un control ActiveX de Internet Explorer 5, posteriormente los demás navegadores lo acogieron desarrollando sus propias implementaciones.

En términos generales el uso de AJAX mejora la usabilidad de las páginas permitiendo a los desarrolladores crear aplicaciones que se comportan de manera similar a las aplicaciones de escritorio.  Un ejemplo de esto son los clientes de correo web de última generación (como GMail) y las aplicaciones geográficas (como Google Maps).  También tiene sus desventajas como presentar una mayor dificultad para su depuración, control de favoritos e historial y que los buscadores web comúnmente no pueden acceder a sus contenidos para indexarlos.

Consulte mas información acerca de AJAX en Wikipedia.

Procedimiento.

Estos son los pasos generales que realizaremos para implementar nuestra pequeña aplicación.

  1. Crear la estructura básica de la página web.
  2. Implementar el formulario de la calculadora.
  3. Mejorar la presentación del formulario.
  4. Implementar la lógica del negocio de la calculadora.
  5. Incluír una referencia a la librería de jQuery en la página web.
  6. Implementar los llamados asíncronos a la lógica del negocio de la calculadora.

La estructura básica de la página.

El primer paso es crear la estructura básica de la página web que recibirá el usuario.  Esta se puede crear con cualquier editor de texto desde el bloc de notas hasta otro mas elaborado como Dreamweaver o Eclipse PDT.  Lo importante es que sea un editor de archivos planos.  En mi caso estoy probando gPHPEdit para Linux el cual se ve hasta ahora simple y conciso.  Para el caso de Windows un editor simple como el Notepad++ servirá.

Creamos entonces el archivo calculadora.html con el siguiente contenido.

<!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>
       <!-- Documento HTML con carácteres UTF8 -->
       <meta http-equiv="Content-type" content="text/html; charset=utf-8" />

       <title>Calculadora AJAX</title>

       <!-- Clases CSS internas -->

       <!-- Referencias a Javascripts externos -->

       <!-- Código Javascript interno -->
    </head>
    <body>
        <!-- Contenido del documento -->
    </body>
</html>

He incluído algunos <!– comentarios –> que nos servirán mas adelante para ubicar donde en el documento se deberán agregar segmentos de código adicionales.  Como se puede apreciar, esperamos ceñirnos al XHTML 1.1 transitional.

El formulario de la calculadora.

Este deberá contar con las siguientes partes básicas.

  1. Una sección para los mensajes de error (mensaje) de la aplicación.
  2. Un form (formulario) que representa al formulario en HTML.
  3. Un campo de texto (operando1) para 4 dígitos para que el usuario ingrese al primer operando.
  4. Un campo de selección (operador) para que el usuario elija la operación a efectuarse: suma, resta, multiplicación o división.
  5. Un campo de texto (operando2) para 4 dígitos para que el usuario ingrese al segundo operando.
  6. Un botón (igual) para invocar la operación de los datos.
  7. Una sección (resultado) para mostrar el resultado de la operación.

La siguiente es la implementación de esta sección y debe insertarse como el Contenido del documento en la plantilla de la estructura básica de la página web.

<div id='pagina'>
    <div id='mensaje'>&nbsp;</div>

    <form id='formulario' action='#' method='post'>
        <input type='text' id='operando1' name='operando1' value='' size='4' maxlength='4' />

        <select id='operador' name='operador'>
            <option value='SU'>+</option>
            <option value='RE'>-</option>
            <option value='MU'>*</option>
            <option value='DI'>/</option>
        </select>

        <input type='text' id='operando2' name='operando2' value='' size='4' maxlength='4' />

        <input type='button' id='igual' value='=' />

        <span id='resultado'>&nbsp;</span>
    </form>
 </div>
Nota.  El atributo del nombre (name) es requerido en los campos del formulario que se van a transmitir a través de la invocación asíncrona cuando el formulario es enviado completo como lo vamos a hacer en esta práctica.

Mejorar la presentación del formulario.

Este es el producto final de la actualización de la presentación de la página web, es necesario modificar los atributos visuales de cada una de las partes del formulario recién creado.

Interfaz de usuario de la calculadora
Interfaz de usuario de la calculadora

Las nuevas características se especifican utilizando hojas de estilo (CSS) y se referencian a través de sus identificadores, etiquetas o clases.

El siguiente código CSS realiza las modificaciones propuestas al formulario.  Estas se deben insertar en la sección de Clases CSS Internas.

<style type="text/css">

 #pagina                                       /* Envoltura general */
 {
       margin: auto;                           /* Margenes (centrado) */
       width: 600px;                           /* Ancho */
       text-align: center;                     /* Textos internos centrados */
       font-family: "arial, sans-serif";       /* Fuente del texto */
 }

 #mensaje                                      /* Mensaje de error */
 {
       width: 100%;                            /* Ancho */
       margin-top: 20px;                       /* Margen superior */
       margin-bottom: 30px;                    /* Margen inferior */
       color: #ff0e0e;                         /* Color del texto (foreground) */
       font-size: 12px;                        /* Tamaño de la fuente */
 }

 #operando1, #operando2                        /* Campos de texto de los operandos */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
       border-style: groove;                   /* Estilo del borde */
 }

 #operador                                     /* Selector del operador */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
 }

 #igual                                        /* Botón para realizar la operación */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
 }

 #resultado                                    /* Campo de texto donde se despliega el resultado */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
       font-style: italic;                     /* Atributo de fuente itálica o cursiva */
 }

 </style>

La lógica del negocio de la calculadora.

El hecho de calcular el valor resultante de la operación elegida a partir de los operandos especificados es lo que llamamos la lógica del negocio.  Esta lógica, como se dijo inicialmente, la vamos a implementar en PHP en el archivo calcular.php.

Los pasos generales que deben realizarse para llevar a cabo exitosamente el cálculo del valor resultante son los siguientes.

  1. Obtener la información provista por el usuario: operandos y operador.
  2. Verificar que la información proporcionada por el usuario sea válida.
  3. Realizar la operación indicada con los valores suministrados.
  4. Mostrar el resultado.

Como veremos a continuación la implementación de estos pasos es ligeramente mas interesante que su simple mención.

Para iniciar el código PHP, le indicamos al navaegador que la respuesta del script será un texto.  Este paso específico es opcional ya que para PHP este es el tipo de respuesta por defecto.

<?php

/* Indicar el tipo de contenido que tendrá la respuesta */

header('Content-type: text/html');

La implementación de las siguientes acciones la vamos a recubrir en un bloque try/catch ya que es suceptible de generar errores y consecuentemente, lanzar excepciones.

El siguiente paso es el obtener, intentar sanear y verificar los operandos proporcionados por el usuario desde el formulario HTML.  Los parámetros fueron transmitidos a través del método post y los elementos se diferencian por su identificador.

try
{
    /* Obtener y sanear los valores de los operadores */

    $operando1 = filter_var($_POST['operando1'], FILTER_SANITIZE_NUMBER_FLOAT);
    $operando2 = filter_var($_POST['operando2'], FILTER_SANITIZE_NUMBER_FLOAT);

    /* Verificar que los valores de los operadores correspondan
       con los tipos esperados */

    if(!filter_var($operando1, FILTER_VALIDATE_FLOAT) ||
       !filter_var($operando1, FILTER_VALIDATE_FLOAT))
           throw new Exception("Operandos inválidos: [{$operando1}] y [{$operando2}]");

Realizamos una tarea similar con el operador, obtenemos su valor y verificamos que sea válido.

    /* Obtener el valor del operador */

    $operador = $_POST['operador'];

    /* Verificar que el operador suministrado sea válido */

    if(!in_array($operador, array('SU', 'RE', 'MU', 'DI')))
        throw new Exception ("Operador inválido: [{$operador}]");

Definimos una variable para almacenar el resultado de la operación solicitada.

    /* Almacenar resultado, inicialmente desconocido */

    $resultado = 0;

Realizamos la operacion correspondiente al operador recibido.  Se deben tener en cuenta dos posibles contingencias que pueden suceder: en el caso de la division, el denominador, es decir, el segundo operador no puede ser cero.  El segundo caso que debe tenerse en cuenta es que el operador recibido no corresponda con ninguna de las operaciones conocidas, esto habria sido validado inicialmente al verificar el operador suministrado despues de su recuperacion.

    /* Realizar la operación solicitada */

    switch($operador)
    {
        case 'SU':    $resultado = $operando1 + $operando2;
        break;

        case 'RE':    $resultado = $operando1 - $operando2;
        break;

        case 'MU':    $resultado = $operando1 * $operando2;
        break;

        case 'DI':    /* Verificar si el denominador es cero,
                         en ese caso, la división no puede realizarse */

                      if ($operando2 == 0)
                          throw new Exception ('División por cero');

                      $resultado = $operando1 / $operando2;
        break;

        default:      /* Si ninguna operación se ejecutó significa
                         que el operador era inválido (segunda verificación) */

                      throw new Exception('Operador desconocido');
        break;
    }
}

Para terminar la lógica de la calculadora debemos lidiar con los dos posibles resultados.  Si el procesamiento tuvo algún error (se lanzó una excepción durante el proceso) o si su terminación fue exitosa.

En caso de haber sucedido un error este se indica al usuario mediante un mensaje descriptivo y al navegador al enviarle un código 400.

catch(Exception $e)            /* La operación produjo un error */
{
    /* Indica al navegador la condición de error */

    header("Status: 400 Bad Request", true, 400);

    /* Despliega el mensaje de error para el usuario */

    echo $e -> getMessage();

    exit(1);
}

En caso de terminar la operación exitosamente, se deberá mostrar al usuario el resultado de la misma e informarle al navegador con un código 200.

/* La operación se realizó exitosamente */

/* Indica al navegador la condición de éxito */

header("Status: 200 OK", true, 200);

/* Despliega el resultado de la operación para el usuario */

echo number_format($resultado, 4);

exit(0);

?>

Incluír la referencia a jQuery.

En este paso lo que hacemos en incluír a la librería jQuery en nuestro proyecto web para poder utilizarla en nuestros fragmentos de código Javascript.

Para hacer esto se debe agregar la siguiente línea en la sección Referencias de Javascript externos.

<script src="http://www.google.com/jsapi"></script>
<script>google.load("jquery", "1");</script>

Este fragmento utiliza Google AJAX Libraries que nos permite incluír los principales frameworks de Javascript en nuestros sitios web sin preocuparnos por su almacenamiento o implementación, en este caso, incluír la distribución estable mas reciente de la rama 1.x.  Obviamente este método requiere que el cliente tenga acceso a Internet además de la aplicación web.

Una forma mas tradicional de hacer lo mismo es el descargar por nuestra propia cuenta la distribución de jQuery desde su sitio web, almacenar el archivo en nuestro servidor y hacer una referencia desde la página web como se muestra a continuación.

<script src='http://www.servidor.com/ruta/jquery.js' type='text/javascript'></script>

Implementar las invocaciones asíncronas.

La implementación de la invocación asíncrona se realiza directamente en Javascript utilizando a la librería jQuery recién referenciada.  Su código se agrega bajo la sección Código Javascript interno.

El primer paso que se debe realizar para su implementación es relacionar el evento de presionar el botón igual con la invocación del llamado asíncrono.  Para hacer esto vamos a utilizar un método no invasivo, es decir, no vamos a contaminar el HTML con el atributo onClick para el elemento INPUT sino que lo haremos desde el código Javascript favoreciendo la separación entre presentación/lógica del negocio y maximizando la flexibilidad de esta última.

Para hacer esto, tan pronto como se carga la página se asocia el evento de clic sobre el botón de igual para que se invoque la función procesar.

<script type='text/javascript'>

/* Código a ejecutarse tan pronto como la
   página ha sido cargada por el navegador */

$(document).ready(function ()
{
	/* Asociar el evento de clic del botón 'igual'
	   con la lógica del negocio de la aplicación */

	$('#igual').click(function()
	{
		procesar();
	});
});

El siguiente paso es la implementación de la función procesar.  En ella se realiza el llamado asíncrono a través de AJAX a la aplicación web en PHP desarrollada anteriormente para realizar el cálculo solicitado.

Una invocación asíncrona típica incluye la siguiente información básica.

  1. El URL de la aplicación web a invocarse.
  2. El tipo del requerimiento a realizarse (GET o POST normalmente).
  3. Los datos a enviarse como parámetros desde el formulario web (en formato QueryString).
  4. Definir la implementación de que hacer si la invocación es exitosa.
  5. Definir la implementación de que hacer si la invocación es fallida.

En el siguiente fragmento de código se especifican los primeros tres elementos de la lista.  El llamado asíncrono accederá a la aplicación web calcular.php mediante el método post y se le enviarán como parámetros los campos del formulario formulario.

function procesar()
{
	$.ajax ({
		url: 	'calcular.php',                   /* URL a invocar asíncronamente */
		type:   'post',                           /* Método utilizado para el requerimiento */
		data: 	$('#formulario').serialize(),     /* Información local a enviarse con el requerimiento */

En caso de ser exitoso se deberá mostrará un mensaje verde informándolo y se desplegará el resultado obtenido de la operación en la ubicación definida para este fin.

		/* Que hacer en caso de ser exitoso el requerimiento */

		success: 	function(request, settings)
		{
			/* Cambiar el color del texto a verde */

			$('#mensaje').css('color', '#0ab53a');

			/* Mostrar un mensaje informando el éxito sucedido */

			$('#mensaje').html("Operación realizada exitosamente");

			/* Mostrar el resultado obtenido del cálculo solicitado */

			$('#resultado').html(request);
		},

En caso de que la invocación sea fallida se deberá mostrar un mensaje rojo informando el error sucedido y se removerá cualquier resultado previo que pueda haber para no confundir al usuario con información anterior.

		/* Que hacer en caso de que sea fallido el requerimiento */

		error: 	function(request, settings)
		{
			/* Cambiar el color del texto a rojo */

			$('#mensaje').css('color', '#ff0e0e');

			/* Mostrar el mensaje de error */

			$('#mensaje').html('Error: ' + request.responseText);

			/* Limpiar cualquier resultado anterior */

			$('#resultado').html('Error');
		}
	});  // Fin de la invocación al método ajax
}  // Fin de la función procesar

</script>

Enlaces.

id='operador'

Hacer algo cuando inicia o termina el evento AJAX con jQuery

Introducción.

Este pequeño fragmento de código es muy útil, permite manipular un objeto del DOM cuando suceden los eventos de inicio o terminación del AJAX.  Muy útil para mostrar de manera fácil y automatizada un indicador de AJAX para informar al usuario que hay una transacción asíncrona en curso.

Procedimiento.

$('#loader').ajaxStart(function () {
    $(this).fadeIn();
});

$('#loader').ajaxStop(function () {
    $(this).fadeOut();
});

Adicionalmente hay otros eventos que pueden manejarse de igual manera ajaxComplete, ajaxError, ajaxSend y ajaxSuccess, además de los ya mencionados ajaxStart y ajaxStop.

Enlaces.

Presentación de Sismos recientes en Colombia

Sismos recientes en Colombia
Sismos recientes en Colombia

Sismos recientes en Colombia es una aplicación de agregación de contenido que permite visualizar de manera gráfica en la geografía Colombiana la ubicación de los sismos que han sucedido en el territorio nacional, tanto los [últimos diez] destacados por su intensidad como la actividad sísmica completa de la semana anterior.  Esta información se actualiza casi en tiempo real, con una diferencia de al rededor de 3o minutos después del suceso, gracias a los servicios de la Red Sismológica Nacional del Instituto Colombiano de Geología y Minería.

La base del proyecto fue desarrollado en una semana de descanso utilizando casi por completo Software Libre.  Se construyó utilizando PHP, HTML/CSS/Javascript/AJAX, jQuery, CodeIgniter, SwiftMailer, SQLiteEclipse PDT y Google Maps.  La aplicación aún se encuentra en progreso, alias beta, así que aún tengo pensando hacerle varias mejoras y complementos.

Actualmente el sitio web permite consultar la información de los sismos destacados y de los sismos diarios de la semana en curso, la información georreferenciada se despliega en el mapa gráficamente desde donde se puede acceder a la información disponible del sismo.  El último sismo destacado sucedido cuenta con un enlace a la RSNC donde se amplía su información.  Las fechas y horas hacen referencia al territorio colombiano, es decir, GMT-5.  Adicionalmente la aplicación cuenta con un sistema de caché que permite agilizar la presentación de información cuando esta se encuentra fresca en el sistema y de refrescarla en ciertos intervalos, disminuyendo la consulta a las fuentes de datos y el tiempo de generación del contenido.

He planeado realizar las siguientes mejoras a la aplicación sin ningún orden necesario.

  • Mejorar los colores de la presentación.  Los actuales son de prueba, estoy buscando a alguien que si sepa del tema para que me asesore.
  • Establecer tooltips informativos para facilitar la utilización del sitio.
  • Verificar la viabilidad de crear un mapa del sitio (sitemap) que facilite las búsquedas de contenido en el sitio.
  • Establecer un procedimiento cron que actualice la inforamción aún sin la consulta de visitantes.
  • Establecer la comunicación con otras aplicaciones como Twitter.
  • Establecer valores finales para la duración de los cachés de información.
  • Implementar un módulo de Contáctenos.
  • Crear una versión móvil que muestre la información resumida.
  • Implementar un indicador que le muestre al usuario en que sección del sistema se encuentra.
  • Verificar el cumplimiento [en lo posible] de XHTML.
  • Establecer la viabilidad de incluír información de sismos de otros lugares del mundo como valor agregado al sitio.

La aplicación, [con optimismo] al igual que las cosas buenas del mundo, se encuentra licenciado bajo CC NC-SA así que su código será liberado tan pronto como termine de implementar las principales mejoras y lo documente para dejarlo apto para el consumo humano.

Si alguien tiene alguna sugerencia acerca de como mejorar esta aplicación me gustaría mucho que lo compartiera conmigo.

Enlaces.

Resaltando la sintáxis de códigos en WordPress

Hasta ahora no he encontrado una solución para resaltar la sintáxis de segmentos de código en WordPress.  Hasta la fecha he utilizado varios plugins con resultados parcialmente exitosos.

El primero que probé fue CodeHighlighterPlugin de IdeaThinking.com.  Es simple, resalta la sintáxis de múltiples lenguajes y opcionalmente permite mostrar un número de línea.  Para señalar el código a resaltar se debe encerrar entre etiquetas <pre lang=”XXXX” lineno=”1″>…</pre>.

Después encontré a varios blogs que resaltaban el código de manera mas elegante, con segmentos que coloreaban las líneas y permitían cambiar entre vista enrriquecida y vista plana así como copiar al portapapeles.  Encontré entonces al Google Syntax Highlighter for WordPress de Peter Ryan.  Soporta menos lenguajes (no incluye a bash por ejemplo) sin embargo es mi favorito hasta el momento.  Para segmentar el código a resaltar se debe encerrar entre etiquetas <pre name=”code” class=”XXXX”>…</pre>.

El problema hasta ahora es que TinyMCE, el editor WYSIWYG de WordPress, es felíz borrándome los atributos de los pre convirtiéndo mis fragmentos de código en invisibles para el resaltador haciendo que cada vez que edite o cree un artículo con códigos tenga que editar los textos de manera visual y después tenga que corregir las etiquetas de manera HTML.  Es infame!

Buscando una mejor opción ante este problema encontré el plugin SyntaxHighlighter2 de S H Mohanjith el cual hábilmente utiliza una sintaxis BBCode para segmentar el código a resaltar:  [source language=’XXXX’]…[/source].

Sin embargo le encontré un problema colateral al plugin: al no utilizar etiquetas pre, el editor/navegador no respetan los espacios en blanco que contenga el código a su izquierda, es decir, se ignora la identación.  El autor muy amablemente me sugirió copiar y pegar los códigos desde el modo HTML sin embargo esto es lo que precisamente quiero evitar.

Anoche, ante la imposibilidad de encontrar una mejor solución y mi testarudez, tuve una idea: utilizar el plugin de Peter Ryan el cual no funciona como quisiera porque el editor le remueve el atributo name y agregárselo de manera dinámica cuando cuando la página se ha desplegado en el cliente.

Hoy me dí manos a la obra y encontré que WordPress utiliza jQuery así que investigué como manipular el evento onLoad, obtener todas las etiquetas pre y como agregarles el atributo name=’code’ faltante.  El siguiente fue el resultado.

<script type='text/javascript'>
jQuery(document).ready(function() {
    jQuery('pre').each(function () {
         jQuery(this).attr('name', 'code');
    });
});
</script>

Por razones aún desconocidas no pude hacer funcionar el plugin en el onLoad también para que se encolaran los códigos y terminaran ejecutándose secuencialemente cuando el árbol DOM estuviera listo.  Como alternativa modifiqué apropiadamente el archivo fuente del plugin que inserta el script en la página del blog.

En wp-content/plugins/google-syntax-highlighter/google_syntax_highlighter.php agregué las siguientes líneas al final del código.

<script class="javascript">
/* sección de código agregada */
jQuery('pre').each(function () {
        jQuery(this).attr('name', 'code');
});

/* código ya existente en el archivo */
dp.SyntaxHighlighter.ClipboardSwf = '<?php echo $current_path; ?>Scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
</script>

Aún tengo que utilizar el módo HTML o utilizar el botón Insert/Edit Attributes de TinyMCE para indicarle a las etiquetas pre cual es el lenguaje de su contenido (class), sin embargo ya no tengo que preocuparme por el atributo name ni porque este sea borrado cada vez que edite al artículo.

Enlaces.