Introducción a StaticMaps de Google

Desarrollo de software, Móvil, Software geográfico, Web October 28th, 2008

Introducción

StaticMaps es una herramienta de Google que nos permite integrar en nuestras aplicaciones a imagenes estáticas de su cartografía de una manera muy simple.  Como se puede inferir, para utilizarlos es necesario que la aplicación tenga acceso a Internet y su acceso se realiza a través de un requerimiento HTTP convencional con ciertos parámetros que se verán a continuación y que permiten refinar el contenido de la imagen del mapa producido.

Esta herramienta la he utilizado varias veces en diferentes tipos de proyectos como Mi Primer Moblet (móviles), GeoReferenciación con Java (escritorio) y la demostración de MandarinaSocial (agentes de software).

Para su uso se requiere que el desarrollador registre de manera gratuita el dominio desde donde se va a utilizar el servicio.  El registro se materializa a través de una llave de API particular.  Esta llave se solicita a través del siguiente enlace.

http://code.google.com/apis/maps/signup.html

El servicio se restringe a un máximo de 1000 requerimientos únicos diarios, siendo este límite aplicado por solicitante (ubicación) y no por llave lo que disminuye el impacto de esta restricción, mas aún cuando las solicitudes repetidas de la misma imagen no son tomadas en cuenta para la estadística de la cuota.

Un primer acercamiento a la herramienta consiste en jugar un poco con ella utilizando el Static Map Wizard.

Forma de acceso

Como se mencionó anteriormente, la solicitud se inicia requiriendo un URL con ciertos parámetros a través de GET y el servicio retorna una imagen en un formato compatible con web que puede ser insertada en una página web con una etiqueta <img> o puede ser manipulada por una aplicación desarrollada en cualquier lenguaje de programación como Java o C#.

Los siguientes aspectos del StaticMap pueden ser parametrizados a través de los parámetros del URL.

  • La ubicación del mapa.
  • El tamaño de la imagen generada.
  • El nivel de acercamiento.
  • El tipo de mapa.
  • El lugar de los marcadores.
  • El lugar de las rutas trazadas.
Estructura general del URL

Esta es la estructura básica del URL sobre la cual se estructura el requerimiento del servicio.

http://maps.google.com/staticmap?PARÁMETROS

La lista de PARÁMETROS consiste en varias secciones separadas entre sí por & y que se encuentran construídas con un formato especial y que serán descritas a continuación.

Estos son los parámetros del servicio suceptibles de personalizarse.

  1. center.
  2. zoom.
  3. size.
  4. format.
  5. maptype.
  6. markers.
  7. path.
  8. frame.
  9. key.
Ubicaciones

Las ubicaciones georreferenciadas son especificadas de la forma latitud y longitud como dos valores reales con 6 dígitos decimales de precisión y separados por una coma: 5.07,-75.521.

Los valores válidos de una latitud varían desde -90 hasta 90 grados mientras que los valores válidos para una longitud varía desde -180 hasta 180 grados.

Parámetro Key

Es obligatorio y se utiliza para especificar la llave del API que se obtuvo inicialmente.  Sin esto, es imposible acceder al servicio.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=5&size=500x300&key=ABQIAAAAAa_xc3cplYGMwVbx_zW2chTWZSld1Wm-gV17JxrvtQa7WXWbRRTOL98qj5hk-yEw1n5LrYmEoAwzOg

Parámetro Center

Es obligatorio pero se convierte en opcional bajo ciertas circunstancias.  Determina la ubicación al rededor de la cual se centrará el mapa generado.

http://maps.google.com/staticmap?center=5.07,-75.521

El mapa anterior se encuentra centrado al rededor de las coordenadas de Manizales, Caldas.

Parámetro Zoom

Es obligatorio pero se convierte en opcional bajo ciertas circunstancias.  Determina el nivel de acercamiento al mapa.

Es definido por un número entero que varía entre 0 (menor) hasta 19 (máxima).  Debe tenerse en cuenta que no todos los niveles de acercamiento están disponibles para todos los tipos de mapas.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11

El mapa anterior determina un nivel 11 de acercamiento sobre Manizales.

Parámetro Size.

Es obligatorio.  Especifica el tamaño de la imagen generada.

Su valor se especifica por un ancho y un alto separados por la letra 'x' y su unidad es en pixels: 500x300.  El valor máximo de estas dimensiones es 640x480.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11&size=500x300

La imagen generada a partir del requerimiento anterior tiene un ancho de 500px y un alto de 300px.

Parámetro Format.

Es opcional y determina el tipo de formato de la imagen generada.  Su selección depende de la relación tamaño/calidad deseada.  Si se omite, su valor por defecto es GIF.

Los posibles valores para este parámetro son los siguientes.

  • gif (por defecto).
  • jpg
  • jpg-baseline (no progresivo)
  • png8 (8 bits)
  • png32 (32 bits)

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11&size=500x300&format=png8

El ejemplo anterior genera una imagen con formato PNG de 8 bits.

Parámetro MapType.

Es opcional y determina el tipo de cartografía a utilizarse para la generación de la imagen.  Si se omite, su valor por defecto es roadmap.

Los posibles valores para este parámetro son los siguientes.

  • roadmap (por defecto).
  • mobile.  Presenta mejoras gráficas para la visualización en dispositivos móviles.
  • satellite. Muestra las imagenes de satélite.
  • terrain. Muesta el mapa del relieve y la vegetación.
  • hybrid. Mezcla el contenido de los tipos roadmap y satellite.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11&size=500x300&format=png8&maptype=hybrid

El ejemplo anterior modifica el tipo de mapa visto hasta ahora (roadmap) y presenta un mapa estilo híbrido de la misma ubicación.

Parámetro Markers.

Es opcional y permite especificar y personalizar los marcadores que referenciarán ubicaciones importantes en el mapa.  Es posible especificar hasta 50 marcadores diferentes por mapa.

Cuando se especifica el parámetro markers no es necesario especificar a los parámetros center y zoom ya que estos se pueden calcular automáticamente.

La información de los marcadores se especifica con una cadena separada por '|' (%7C) de la siguiente manera.

markers=infoMarcador1|infoMarcador2|infoMarcador3|...

La información de los marcadores incluye datos tanto de su ubicación como de su presentación.  Cada marcador se crea con la siguiente estructura.

{latitud},{longitud},{tamaño}{color}{identificador}

El siginificado de cada uno de estos campos se describe a continuación.

  • latitud (requerido).  Latitud de la ubicación del marcador.
  • longitud (requerido).  Longitud de la ubicación del marcador.
  • tamaño (opcional).  Tamaño de la imagen del marcador.  Puede tomar uno de los siguientes valores.
    • tiny
    • mid (por defecto)
    • small
  • color (opcional).  Determina el color de la imagen del marcador.  Puede tomar una de las siguientes constantes.
    • black
    • brown
    • green
    • purple
    • yellow
    • blue
    • gray
    • orange
    • red (por defecto)
    • white
  • identificador (opcional).  Permite especificar un carácter alfanumérico y en minúsculas para identificar al marcador.  Debe tenerse en cuenta que este identificador sólo aplica para marcadores tamaño mid.  Su valor por defecto es el punto.

http://maps.google.com/staticmap?size=500x300&format=png8&maptype=hybrid&markers=5.07,-75.521,midyellowm|4.813,-75.696,midbluep|4.534,-75.681,midreda

El ejemplo anterior muestra el mapa del eje cafetero colombiano resaltando sus ciudades con marcadores de la siguiente manera: Manizales (amarillo), Pereira (azul) y Armenia (rojo).

Parámetro Path.

Es opcional y permite especificar y personalizar rutas sobre el mapa que conectan a dos o mas puntos georreferenciados.  El límite es el de máximo 100 puntos por ruta.

El parámetro se define de manera similar a markers siguiendo el siguiente formato.

path=tipoColor:#color,weight:pesoRuta|punto1|punto2|punto3|...

El siginificado de cada uno de estos campos se describe a continuación.

  • tipoColor.  Especifica el tipo de formato del color.  Puede tomar uno de los siguientes valores.
    • rgb.  Esquema RGB estándar con valores de 24 bits de la forma 0xffffff.  Su nivel de opacidad por defecto es de 50%.
    • rgba.  Utiliza valores de 32 bits de la forma 0xffffffff.  El nivel de opacidad está dado por el cuarto byte (últimos dos carácteres) que conforman el canal alfa de transparencia.
  • weight.  Especifica el grosor de la ruta en pixels.

http://maps.google.com/staticmap?size=500x300&format=png8&maptype=hybrid&markers=5.07,-75.521,midyellowm|4.813,-75.696,midbluep|4.534,-75.681,midreda&path=rgb:0x0000ff,weight:5|5.07,-75.521|4.813,-75.696|4.534,-75.681

En este ejemplo se agrega una ruta azul entre Armenia - Pereira - Manizales sobre el ejemplo inmediatamente anterior.

Parámetro Frame.

Es opcional y especifica si la imagen resultante se debe o no mostrar con un borde azul de 5px y con 55% de opacidad a su alrededor.  Por defecto no se muestra.

http://maps.google.com/staticmap?size=500x300&format=png8&maptype=hybrid&markers=5.07,-75.521,midyellowm|4.813,-75.696,midbluep|4.534,-75.681,midreda&path=rgb:0x0000ff,weight:5|5.07,-75.521|4.813,-75.696|4.534,-75.681&frame=true

Enlaces:

Tags: , ,

Ejecutar después de un efecto con Scriptaculous

Desarrollo de software, Web October 28th, 2008

Algunas veces es necesario ejecutar cierta acción exactamente después de que se ejecute un efecto sobre la interfaz de usuario, por ejemplo, resaltar la fila que se va a remover y solamente después de terminado el efecto, se remueve efectivamente la fila.

Con Scriptaculous se debe utilizar el callback afterFinish ya que de lo contrario las instrucciones se ejecutarán de manera serial interfiriéndose mutuamente provocando que la fila sea removida casi de inmediato y el efecto no pueda ser apreciado.

A continuación se muestra un pequeño fragmento de código que ejemplifica la implementación descrita anteriormente.

var op = $('fila_a_remover');
 
op.puff({
    afterFinish: function()
    {
        op.remove();
    }
});

Enlace: Effect.Puff API.

Tags: ,

Autocompletador con Prototype/Scriptaculous - Parte II

Desarrollo de software, Web October 18th, 2008

Como complemento a la primera parte, en este artículo se ampliará el concepto del Autocompleter de Prototype/Scriptaculous a su versión mas flexible que hace uso del envío de mensajes asíncronos mejor conocidos como AJAX.

Para su implementación se requieren de dos partes las cuales se analizarán en el orden expuesto a continuación.

  • Un formulario HTML con el campo que incluye la autocompletación.
  • Una aplicación PHP que recibe y procesa la solicitud de información y genera los resultados de manera dinámica.

El formulario es igual al anterior, incluye el text donde el usuario escribirá el criterio que se autocompletará cuyo identificador es t_criterio y un espacio, cuyo identificador es resultado, donde se desplegarán las posibles sugerencias arrojadas por la aplicación PHP basada en el criterio antes especificado.

<div id='contenedor'>
    <div id='criterio'>
        Criterio
        <input type='text' id='t_criterio' size='50' maxlength='200' />
    </div>
    <div id='resultado'>
        No hay resultados que mostrar.
    </div>
</div>
Ejemplo de Ajax.Autocompleter

Ejemplo de Ajax.Autocompleter

Para activar el autocompletado del campo t_criterio se ejecuta el método estático Ajax.Autocompleter tan pronto como el árbol DOM de la página ha sido cargado de la siguiente manera.

new Ajax.Autocompleter('t_criterio',
                       'resultado',
                       'fuente.php',
                       {
                           paramName: 'criterio',
                           method: 'post',
                           parameters: 'estatico1=valor1&estatico2=valor2',
                           callback: function(editor, paramText) {
                               return paramText + '&time=' + new Date().getTime();
                           },
                           select: 'm_nombre',
                           afterUpdateElement: function (inputField, suggestion) {
                               inputField.value = suggestion.down('span.m_nombre').innerHTML + " / " + suggestion.down('span.m_departamento').innerHTML;
                           }
                       });

Los parámetros que recibe el método se describen a continuación, de los cuales sólo los tres primeros son obligatorios.

  • Id del text con el criterio de búsqueda para la autocompletación.
  • Id del área donde se van a mostrar las opciones sugeridas.
  • URL donde se ubica a la aplicación dinámica que va a procesar la búsqueda de sugerencias a través de AJAX.
  • Hash con opciones adicionales.
    • paramName: nombre del parámetro que se enviará a la aplicación dinámica con el contenido del texto especificado por el usuario.  Si no se especifica este parámetro, se utilizará el atributo name del campo de texto del formulario.
    • method: método a través del cual se enviará la información a la aplicación web: post o get.
    • parameters: parámetros estáticos para ser enviados adicionalmente.
    • callback: función ejecutada antes de ser invocada la aplicación PHP y que permite manipular de manera dinámica los parámetros enviados.
    • select: campo de la sugerencia elegida que es mostrado en el campo de texto cuando la sugerencia es seleccionada.  El valor de este campo se relaciona con el selector CSS donde se encuentra ubicada la información.
    • afterUpdateElement: función invocada justo después de que el usuario ha seleccionado a una de las opciones presentadas.  Permite componer de manera dinámica un valor para ser mostrado como la selección del usuario.  Es mas elaborado y sobreescribe lo especificado en el parámetro select.

Adicionalmente las opciones adicionales minChars y frequency se encuentran también disponibles y operan de igual manera que en el autocompletador local.

La aplicación dinámica (fuente.php) por su parte, desarrollada en PHP para este ejemplo, realiza las siguientes acciones.

Obtiene el valor del criterio de búsqueda especificado por el usuario.  La forma de recuperarlo depende del método (method) utilizado por el formulario.

$criterio = $_POST['criterio'];

Se realiza una consulta a la base de datos y/o un procesamiento de la información lo que constituye el carácter dinámico de la aplicación.  Para este ejemplo, se consulta la base de datos (SQLite utilizando PDO) de la división geopolítica de Colombia y se buscan los municipios cuyos nombres contengan a la subcadena especificada.

$link = new PDO('sqlite:data/database.sqlite');

$sql = "SELECT m.nombre AS nombre, d.nombre AS departamento,
               m.latitud AS latitud, m.longitud AS longitud
        FROM municipios m, departamentos d
        WHERE m.id_departamento = d.id_departamento AND
              m.nombre LIKE '%{$criterio}%'";

$result = $link -> query($sql);

El resultado enviado al formulario está constituído por la salida estándar (echo/print/etc.) de la aplicación PHP.  Su estructura es la de una lista no ordenada: <ul><li>...</li>...</ul>.

Para finalizar, se construye la lista no ordenada con la información obtenida de la base de datos.

$str = "<ul>\n";

foreach ($result as $row)
{
    $str .= "<li>\n";
    $str .= "<div class='titulo'>Título: <span class='m_nombre'>" . utf8_decode($row['nombre']) . "</span></div>";
    $str .= "<div class='titulo'>Departamento: <span class='m_departamento'>" . utf8_decode($row['departamento']) . "</span></div>";
    $str .= "<div class='titulo'>Latitud: <span class='m_latitud'>" . utf8_decode($row['latitud']) . "</span></div>";
    $str .= "<div class='titulo'>Longitud: <span class='m_longitud'>" . utf8_decode($row['longitud']) . "</span></div>";
    $str .= "</li>\n";
}

$str .= "</ul>\n";

echo utf8_encode($str);

La información almacenada e impresa en la variable $str es la que será mostrada en el área de sugerencias: #resultado.

Enlaces:

Tags: , ,

Autocompletador con Prototype/Scriptaculous - Parte I

Desarrollo de software, Web October 15th, 2008

Prototype, al igual que otros frameworks de JavaScript, permite implementar fácilmente comportamientos que que serían dispendiosos de crear a partir del JavaScript básico y convencional.  El hermanito Scriptaculous viene a ayudarnos aún mas con sus efectos y ayudantes.

Un ejemplo de estas posibilidades de rápida implementación es la simulación del autocompletar de un campo de texto.

El objeto Autocompleter acepta dos fuentes de datos diferentes.

  1. Una local como un arreglo de JavaScript.
  2. Una remota y mas dinámica a través de solicitudes AJAX.

En este artículo se va a realizar la demostración del uso de un Autocompleter.local.  Para esto se requieren dos componentes.

  • Un campo de texto donde el usuario escribe el criterio de búsqueda.
  • Una sección de sugerencias donde el Autocompleter despliega las coincidencias basadas en el criterio de búsqueda.
Ejemplo de Autocompleter.local

Ejemplo de Autocompleter.local

Para el ejemplo anterior cuenta con los siguientes elementos.

  • t_criterio: campo de texto para el criterio de búsqueda.
  • resultado: es el div donde se  desplegarán las sugerencias encontradas.
  • departamentos: es un arreglo JavaScript con la información local y estática para las opciones de búsqueda, en este caso el listado de los departamentos de Colombia.

Para activar el autocompletado sobre t_criterio basado en los valores de departamentos, se ejecuta la siguiente instrucción JavaScript.

var ac = new Autocompleter.Local('t_criterio',
                 'resultado',
                 departamentos,
                 {
                     autoSelect     : false,
                     frequency      : 0.4,
                     minChars       : 1,
                     choices        : 10,
                     paritialSearch : false,
                     paritialChars  : 2,
                     fullSearch     : true,
                     ignoreCase     : true
                 });

Los parámetros especificados al método Local son descritos a continuación.

  1. Id del campo de texto con el criterio de búsqueda.
  2. Id del contenedor de los resultados obtenidos.
  3. Arreglo con la información disponible.
  4. Hash con las opciones de configuración del autocompletador.  Todos estos valores son opcionales y los mostrados corresponden con los valores por defecto.

A continuación se describen las opciones de configuración disponibles.

  • autoSelect: Acepta automáticamente la primera sugerencia cuando sólo hay una.
  • frecuency: Tiempo en segundos entre dos intentos de autocompletar.
  • minChars: Cantidad mínima de carácteres necesarios para que se active el autocompletar.
  • choices: Cantidad máxima de opciones sugeridas a mostrarse.
  • paritialSearch: Tomar en cuenta para la búsqueda el comienzo de cada palabra o sólo el comienzo del texto.
  • paritialChars: Cantidad mínima de carácteres necesarios para que se active la búsqueda parcial.
  • fullSearch: Tomar en cuenta cualquier subcadena de las opciones o sólo los comienzos (palabra o línea).
  • ignoreCase: Tomar o no en cuenta la diferencia entre mayúsculas/minúsculas.

Enlaces:

Tags: , ,

Modelos en PHP: cosas buenas/malas del lenguaje

Desarrollo de software, Web October 15th, 2008

PHP es un lenguaje muy fácil de aprender si se tienen conocimientos en C/C++/Java/C# o similares.  Es muy fácil de utilizar y es muy fácil de desarrollar aplicaciones pequeñas-medianas con él.

También, como todo en la vida, tiene sus desventajas.  Lo interesante es que a mi parecer, las ventajas del lenguaje son también desventajas y viceversa según como se miren, es decir, según lo que se necesite.

En este momento me interesa mencionar dos de ellas:

  • Fuera de la caja de se obtiene lo básico, un lenguaje para empezar a escribir código, a diferencia de otros lenguajes que incluyen por si mismos todo un framework o ambiente de desarrollo.
  • Es un lenguaje señoritero, la falta de tipos y de la mucha rigurosidad de los demás lenguajes hace que hasta la gente que no sabe desarrollar software crea que si lo hace.

Estas son verdades: el lenguaje es deficiente para muchas cosas aunque les duelan a algunos que les gusta desgastarse simulando fanatismos hasta por un lenguaje de programación.  Pero como mencioné anteriormente, son cosas buenas/malas según como se les mire.

  • La independencia de tanta infraestructura que tal vez excede lo que necesitamos evita que las soluciones pequeñas y puntuales se conviertan en todo un circo de capas y niveles que consumen tiempo, recursos y paciencia.  Sería como utilizar JSF+Hibernate+Spring para hacer un HolaMundo.  Las soluciones son de la forma y el tamaño como el desarrollador las quiera: el problema es saber que querer y como lograrlo.De todos modos hay muchos frameworks para PHP allá afuera, desde los diminutos, los medianos y los grandes: MoonPHP, Picora, CodeIgniter, KohanaPHP, CakePHP, Prado, Symfony y Zend para nombrar a solo unos pocos del montón que existen en esta Internet que es tan larga como ancha.
  • Esta falta de rigurosidad bien utilizada, nos permite aprovecharla para hacer cosas cosas interesantes.  Todo es un arma peligrosa o una herramienta útil según quien la esté sosteniendo.

Y es con la flexibilidad que confiere la falta de rigurosidad la que permite o facilita la implementación -rápida- de códigos útiles.  MyModel 0.1 es solamente una demostración de las cosas que se pueden hacer con PHP y estoy seguro casi nadie conoce.

Los modelos son la representación de las clases de la lógica del negocio en una aplicación.  Algunos dicen que coinciden 1:1 con las entidades de persistencia: tablas de la base de datos.

Para los modelos, clases ellos con atributos y métodos, gracias al encapsulamiento acostumbramos a definir sus atributos como private/protected y a implementarles métodos setter/getter (obt/pon) para modificar o consultar su estado.

Este procedimiento trae consigo consecuencias negativas en medio de todo lo útil que es el encapsulamiento.

  • Hay que hacer métodos set/get para todos los atributos (que sea interesantes) de todas las clases de los modelos.
  • La mayoría de las veces hacemos unos métodos setter/getter que daría lo mismo que los atributos fueran public.
  • Es tedioso hacer los métodos, mas aún si como acabo de mencionar no incluyen siempre una ventaja tangible.  Los IDEs amables acostumbran a hacer por nosotros las plantillas básicas de estos métodos.

Este mes estuve pensando como poder hacer algo para solucionar estos problemas con PHP y recordé los métodos __set/ __get incluídos en toda clase PHP y se me ocurrió intentar implementar algo como las propiedades de .NET pero que funcionaran de manera automática.

Rápidamente implementé una primera versión que permite hacer esto.

Persona es una clase con un atributo llamado $nombre.  Si Persona hereda de MyModel estará entonces posibilitada para hacer esto:

$p -> Nombre = "Jorge";
echo $p -> Nombre;

La sobreescritura de los métodos mencionados antes me permiten decirle al modelo que cuando le hablen de la propiedad Nombre haga referencia al atributo nombre.  Mas aún, cuando le hablen de Nombre primero verifique si existen los métodos setNombre y getNombre y haga uso de ellos.

Una segunda mini versión le agregó un poco mas de encapsulamiento.

  • Si el atributo es private, no se puede acceder de ninguna manera.
  • Si el atributo es protected sólo se puede acceder desde el exterior si tiene setter/getter.
  • Si el atributo es public se puede acceder externamente.
  • Si el atributo es public pero tiene setter/getter, estos métodos serán utilizados en lugar del acceso directo.
  • Sólo las propiedades cuyos métodos setter/getter sean public pueden ser accedidas desde el exterior.

Con esto podemos hacer, digo yo, los modelos con atributos public y filtrar con métodos setter/getter los que nos interese restringir su acceso.

Ejemplo:

Téngase en cuenta a la clase User cuya implementación es de la siguiente manera.

class User extends MyModel
{
    private   $id;
    public    $username;
    public    $password;
    protected $name;
 
    public function getPassword()
    {
        return str_repeat("*", strlen($this -> password));
    }
 
    public function setName($value)
    {
        $this -> name = "--- " . $value . " ---";
    }
 
    public function getName()
    {
        return strtoupper($this -> name);
    }
}

Considérese un programa que la utiliza como se muestra a continuación.

$u = new User();
 
// $u -> id = 7;                               // Inválido porque $id es private y no ha métodos set/get.
 
$u -> Username = 'jimezam';                  // Se accede directamente porque $username es público.
echo "username: " . $u -> Username . "";     // Se accede directamente porque $username es público.
 
$u -> Password = 'secreto';                   // Se accede directamente porque $password es público.
echo "password: " . $u -> Password . "";     // Se ejecuta getPassword.
 
$u -> Name = "Jorge Ivan";                   // Se ejecuta setName.
echo "nombre: " . $u -> Name . "";           // Se ejecuta getName.

El resultado es el siguiente por los motivos explicados en los comentarios frente a cada línea del código.

username: jimezam
password: *******
nombre: --- JORGE IVAN ---

Se aceptan sugerencias constructivas para ir complementando a MyModel.

Enlaces:

Tags:

Actualización de portales web basados en Drupal a la versión 5.11

Software, Web October 14th, 2008

En este artículo se resumen los pasos realizados para la actualización de los portales Drupal a la versión 5.11 la cual fue liberada en octubre 8 de 2008 y aparece como crítica para ser actualizada lo mas pronto posible.

1. Realizar la copia de seguridad de la base de datos del portal.

2. Actualizar los módulos disponibles según update-status.

3. Realizar la actualización de los archivos.

$ wget http://ftp.drupal.org/files/projects/drupal-5.11.tar.gz
$ mv site site.old
$ tar zxvf drupal-5.11.tar.gz
$ mv drupal-5.11/ site
$ cp -rf site.old/files site
$ cp -rf site.old/sites site
$ cp -rf site.old/themes/MITEMA site/themes/
$ cp -rf site.old/sites/default/modules site/sites/default
(web) $URL/apps/site/update.php
(web) $URL/?q=admin/logs/updates
(web) $URL/apps/site/update.php
$ rm drupal-5.11.tar.gz

Con esta actualización se introducen dos modificaciones al esquema de actualizaciones de Drupal bastante estable que he estado siguiendo hasta la fecha.

  • Actualizar los módulos primero antes de realizar la actualización de Drupal para evitar posibles conflictos aún peores con la nueva versión.
  • Guardar los módulos de terceros bajo sites/default/modules en lugar de bajo modules.  Esto permite separar los módulos de la distribución de Drupal de los instalados del repositorio confiriendo mayor claridad y facilidad en la administración y actualización.

Tags:

La típica distribución de una página web

Desarrollo de software, Web October 13th, 2008

Distribución típica de una página web

Distribución típica de una página web

Esta es la distribución típica de una página web.  Esta compuesta por los siguientes elementos.

  • Cabecera.
  • Columna izquierda.
  • Contenido central.
  • Columna derecha.
  • Pies.

De acuerdo con los estándares actuales, es preferible utilizar divs en lugar de tables (donde sea humanamente posible) ya que el documento HTML debería encargarse de definir el contenido mientras que a través de la definición de estilos (CSS) se debería establecer la presentación, es decir, como se ordena y distribuye el contenido a lo largo y ancho de la página web.

Como lo he mencionado en otras ocasiones para mi CSS es todavía una ciencia oculta, hay muchas cosas que frecuentemente se me enrredan cuando utilizo CSS.  Sin embargo ultimamente lo he estado utilizando un poco mas y he adquirido mas práctica y cada vez me siento mas a gusto con utilizándolo.

Ahora implementar este diseño es algo sencillo para mi ... bueno, casi.

Parto de la siguiente estructura de contenido.

        <div id='pagina'>
            <div id='cabecera'>
                Cabecera <br />
            </div>

            <div id='colizq'>
                Columna Izquierda <br />
            </div>

            <div id='contenido'>
                Contenido <br />
            </div>

            <div id='colder'>
                Columna Derecha <br />
            </div>

            <div id='pies'>
                Pies
            </div>
        </div>

El resultado inicial es claramente inaceptable.

Resultado #1

Resultado #1

Agregamos un poco de estilo para enrriquecer a la presentación.

    #pagina
    {
        width: 1024px;
        margin: auto;
        background-color: pink;
    }

Con esto le damos un ancho suficiente para visualizar correctamente el contenido del sitio y lo centramos para que se vea bonito en monitores mas anchos.

    #cabecera
    {
        padding: 5px;
        background-color: orange;
    }

    #colizq
    {
        padding: 5px;
        background-color: yellow;
        width: 300px;
    }

    #contenido
    {
        padding: 5px;
        background-color: blue;
        width: 394px;
    }

    #colder
    {
        padding: 5px;
        background-color: red;
        width: 300px;
    }

    #pies
    {
        padding: 5px;
        background-color: green;
    }

Les damos colores diferentes a cada una de las partes para diferenciarlas, un padding para separar un poco el borde del contenido de cada uno de los divs y en el caso de la parte central, el ancho específico que se requiera.

Resultado #2

Resultado #2

Ya tiene cara de algo, pero no necesariamente lo que estamos buscando.  Es necesario ordenar las columnas izquirda, centro y derecha para que se ubiquen de la forma como sus mismos nombres lo indican.

En CSS esto equivale a decirle a los divs que floten (float) en la dirección que queramos.

    #colizq
    {
        float: left;
        padding: 5px;
        background-color: yellow;
        width: 300px;
    }

    #contenido
    {
        float: left;
        padding: 5px;
        background-color: blue;
        width: 394px;
    }

    #colder
    {
        float: left;
        padding: 5px;
        background-color: red;
        width: 300px;
    }

El atributo adicionado les indica a los divs que vayan flotando y arreglándose a la izquierda cada vez que son agregados a la presentación.

Resultado #3

Resultado #3

En algunos casos, cuando continúan mas divs y necesitamos que se alineen en una la siguiente fila, es necesario indicarle a un div específico que no permita que otros divs floten a uno/ninguno de sus lados.  Para esto se utiliza el atributo clear (left, right, none, both).

Para el caso de la sección de los pies se complementaría de la siguiente manera.

    #pies
    {
        padding: 5px;
        background-color: green;
        clear: left;
    }

Hasta ahí todo es muy fácil: un pequeño paso para el lector, pero hace un año fue un gran paso para mi.  Pero aún me queda una duda por solucionar.

Qué pasa cuando las columnas -patriotas- tienen altos de diferente longitud ?

Resultado #4.

Resultado #4.

Se nota ese sobrante rosado bajo las columnas izquierda y derecha ?

Si revisamos las clases CSS, la rosada es la #pagina, esto significa que #colizq y #colder no están ocupando el mismo espacio vertical que #contenido hasta #pies y está dejando ver la capa inmediatamente inferior.

Para los "diseños" que comúnmente utilizo esto no es un problema ya que me gustan los diseños minimalistas y el blanco es mi fondo preferido.  Pero que va a pasar el día en que necesite que una columna sea de un fondo diferente del resto ?

Mi pregunta es: cómo hago para que las columnas ocupen la totalidad del espacio vertical disponible entre #cabecera y #pies ?  La duda persiste.

Enlace: código de demostración.

Tags: ,

Editor de operaciones con Prototype

Desarrollo de software, Web October 11th, 2008

Uno de los proyectos que estoy desarrollando para la Fundación consiste en parte en la definición de fórmulas que están formadas a su vez por una o mas operaciones.

Lo primero que se me vino a la mente fue representarlas con un documento XML que simulara al árbol de precedencia de expresiones de la operción con etiquetas anidadas.  El primer problema que apareció cuando lo discutimos es como hacer el usuario final, no ingeniero de sistemas, pudiera posteriormente y con éxito, implementar sus propias fórmulas.  El XML era una buena solución para la persistencia pero no para la interacción con el humano.

Pensando un poco y revisando los muy pocos antecedentes que encontré en el mercado, realicé un diseño para el editor de fórmulas donde cada fila sería una operación que tendría un nombre como identificador y que podría ser utilizado como atributo o parámetro de cualquier otra operación.  Se establecieron las siguientes operaciones.

  1. Operaciones aritméticas (suma, resta, multiplicación y división).
  2. Valor constante.
  3. Valor definido por el usuario.
  4. Sumatoria.
  5. Función externa.

Quería que la interfaz del editor fuera lo mas dinámica posible y elegí para su implementación el uso de Prototype y Scriptaculous.

La primera versión la implementé a principio de este año y era en realidad, mi primera aproximación a estas librerías de JavaScript por lo que su código no explota todas las ventajas de estas librerías.

Versión 0.1.

Versión 0.1.

Como prototipo fue muy interesante y entretenido de desarrollar.  Los colores por supuesto eran para diferenciar rapidamente los diferentes divs de cada operación.

Durante este mes estuve implementando una nueva versión del editor basado en las conclusiones que obtuvimos al mostrarle al cliente nuestro prototipo.  Algunas funcionalidades del prototipo no fueron incluídas en la siguiente versión (al menos en esta iteración) al no aportar grandes beneficios al resultado final.

  • La mayoría de efectos gráficos (muy interesantes).
  • La posibilidad de reordenar a una operación hacia cualquier fila según el índice especificado.
  • El reordenamiento de parámetros de una función.
  • La especificación del tipo de una operación a medida que se determinan sus elementos.

Esta nueva versión incluye varios cambios a nivel conceptual pero en mayor medida incluye muchas mejoras a nivel de código, lo que la hace ahora compatible con IE7.  En especial gracias a las facilidades que traen consigo estas librerías para trabajar manipulando los elementos DOM sobre clases CSS en lugar de los IDs específicos de los elementos.

Versión 0.2.

Versión 0.2.

Esta nueva versión incluye algunas características como las siguientes.

  • Interfaz de usuario mas limpia y clara.
  • Colores para identificar facilmente el tipo de operación.
  • Fácil reordenamiento de operaciones con sólo arrastrar y soltar las mismas.
  • Agregar operaciones (de un tipo definido) y remover las operaciones seleccionadas.
  • Actualización automática de las opciones de atributos y parámetros tan pronto como se desea su modificación y algún nombre de operación se ha modificado o introducido nuevo.
  • Las funciones pueden tener cero o mas parámetros los cuales pueden ser especificados dinámicamente.

El proyecto que estoy desarrollando es muy interesante y aún falta mucho de su implementación, inclusive en mi imaginación tengo muchas ideas para mejorar a este editor: validadores de datos (que tienen un problema interesante de resolver), asistentes WYSIWYG para los diferentes tipos de valores de datos, buscador de funciones (definidas del lado del servidor), ayuda en línea para las funciones, etc.  Desafortunadamente el editor es sólo una pequeña parte de un cuarto del proyecto por lo que tendré que postergar a estas mejoras para lo que espero sea una próxima iteración.

JavaScript, como todo lo que aprendo y disfruto en la vida, entre mas aprendo, mas me doy cuenta que nada se, sin embargo también he notado que estos frameworks de JavaScript facilitan enormemente el trabajo encapsulando la mayor parte sucia, en particular, facilitandome el trabajo con la independencia de navegadores.

Hasta ahora he probado a MooTools y a Prototype/Scriptaculous con amplio éxito.  Hay muchos otros por experimentar: JQuery, ExtJS, Dojo, YUI, etc.  Como siempre, las ganas sobran, el tiempo es el que falta ;-)

Tags: , ,

10 principles of the PHP masters

Desarrollo de software, Web October 5th, 2008

Esta semana volví a toparme con este artículo en nettuts.com, es interesante y vale la pena hacer referencia a él.  Fue escrito por Glen Stansberry quien también ha escrito otros artículos similares como los mencionados a continuación.

En este artículo el autor compila 10 principios o sugerencias para obtener un mayor provecho del desarrollo con PHP incluyendo a su correspondiente explicación desde el punto de vista del autor que los sugiere.

Los puntos tratados hacen referencia a los siguientes temas.

  1. Use PHP Only When You Need it
  2. Use Many Tables With PHP and MYSQL for Scalability
  3. Never, ever trust your users
  4. Invest in PHP Caching
  5. Speed up PHP Development with an IDE, Templates and Snippets
  6. Make Better Use of PHP's Filter Functions
  7. Use a PHP Framework
  8. Don't use a PHP Framework
  9. Use Batch Processing
  10. Turn on Error Reporting Immediately

Enlace: 10 Principles of the PHP Masters.

Tags: ,

Mis primeras estrellitas

Desarrollo de software, Web, Windows September 28th, 2008

Entre viernes y sábado gané mis primeras estrellitas del Desarrollador Cinco Estrellas.  Pude sacar el tiempo para presentar los siguientes exámenes.

Estrella #0:

Fundamentos de la programación.

Estrella #1:

.NET Framework.

C#.

Estrella #2:

Aplicaciones web con ASP.NET.

Aplicaciones Windows con WinForms.

Mi segunda estrellita.

Esta semana va a estar un poco difícil que vuelva a dedicar un tiempo a estas labores astronómicas, sin embargo voy a hacer mi mejor esfuerzo.

Tags: , , ,