Author Archives: admin

Qué son los REST Services

[Fuente: http://www.dosideas.com/noticias/java/314-introduccion-a-los-servicios-web-restful.html]

La Transferencia de Estado Representacional (REST – Representational State Transfer) fue ganando amplia adopción en toda la web como una alternativa más simple a SOAP y a los servicios web basados en el Lenguage de Descripción de Servicios Web (Web Services Descripcion Language – WSDL). Ya varios grandes proveedores de Web 2.0 están migrando a esta técnología, incluyendo a Yahoo, Google y Facebook, quienes marcaron como obsoletos a sus servicios SOAP y WSDL y pasaron a usar un modelo más facil de usar, orientado a los recursos.

Veamos los principios de REST para entender más esta tecnología.

Presentando REST

REST define un set de principios arquitectónicos por los cuales se diseñan servicios web haciendo foco en los recursos del sistema, incluyendo cómo se accede al estado de dichos recursos y cómo se transfieren por HTTP hacia clientes escritos en diversos lenguajes. REST emergió en los últimos años como el modelo predominante para el diseño de servicios. De hecho, REST logró un impacto tan grande en la web que prácticamente logró desplazar a SOAP y las interfaces basadas en WSDL por tener un estilo bastante más simple de usar.

REST no tuvo mucha atención cuando Roy Fielding lo presentó por primera vez en el año 2000 en la Universidad de California, durante la charla academica “Estilos de Arquitectura y el Diseño de Arquitecturas de Software basadas en Redes”, la cual analizaba un conjunto de principios arquitectónicos de software para usar a la Web como una plataforma de Procesamiento Distribuido. Ahora, años después de su presentación, comienzan a aparecer varios frameworks REST y se convertirá en una parte integral de Java 6 a través de JSR-311.

Los 4 principios de REST

Una implementación concreta de un servicio web REST sigue cuatro principios de diseño fundamentales:

  • utiliza los métodos HTTP de manera explícita
  • no mantiene estado
  • expone URIs con forma de directorios
  • transfiere XML, JavaScript Object Notation (JSON), o ambos

A continuación vamos a ver en detalle estos cuatro principios, y explicaremos porqué son importantes a la hora de diseñar un servicio web REST.

REST utiliza los métodos HTTP de manera explícita

Una de las caraterísticas claves de los servicios web REST es el uso explícito de los métodos HTTP, siguiendo el protocolo definido por RFC 2616. Por ejemplo, HTTP GET se define como un método productor de datos, cuyo uso está pensado para que las aplicaciones cliente obtengan recursos, busquen datos de un servidor web, o ejecuten una consulta esperando que el servidor web la realice y devuelva un conjunto de recursos.

REST hace que los desarrolladores usen los métodos HTTP explícitamente de manera que resulte consistente con la definición del protocolo. Este principio de diseño básico establece una asociación uno-a-uno entre las operaciones de crear, leer, actualizar y borrar y los métodos HTTP. De acuerdo a esta asociación:

  • se usa POST para crear un recurso en el servidor
  • se usa GET para obtener un recurso
  • se usa PUT para cambiar el estado de un recurso o actualizarlo
  • se usa DELETE para eliminar un recurso

Una falla de diseño poco afortunada que tienen muchas APIs web es el uso de métodos HTTP para otros propósitos. Por ejemplo, la petición del URI en un pedido HTTP GET, en general identifica a un recurso específico. O el string de consulta en el URI incluye un conjunto de parámetros que definen el criterio de búsqueda que usará el servidor para encontrar un conjunto de recursos. Al menos, así como el RFC HTTP/1.1 describe al GET.

Pero hay muchos casos de APIs web poco elegantes que usan el método HTTP GET para ejecutar algo transaccional en el servidor; por ejemplo, agregar registros a una base de datos. En estos casos, no se utiliza adecuadamente el URI de la petición HTTP, o al menos no se usa “a la manera REST”. Si el API web utiliza GET para invocar un procedimiento remoto, seguramente se verá algo como esto:

GET /agregarusuario?nombre=Zim HTTP/1.1

Este no es un diseño muy atractivo porque el método aquí arriba expone una operación que cambia estado sobre un método HTTP GET. Dicho de otra manera, la petición HTTP GET de aquí arriba tiene efectos secundarios. Si se procesa con éxito, el resultado de la petcición es agregar un usuario nuevo (en el ejemplo, Zim) a la base de datos. El problema es básicamente semántico. Los servidores web están diseñados para responder a las peticiones HTTP GET con la búsqueda de recursos que concuerden con la ruta (o el criterio de búsqueda) en el URI de la petición, y devolver estos resultados o una representación de los mismos en la respuesta, y no añadir un registro a la base de datos. Desde el punto de vista del protocolo, y desde el punto de vista de servidor web compatible con HTTP/1.1, este uso del GET es inconsistente.

Más allá de la semántica, el otro problema con el GET es que al ejecutar eliminaciones, modificaciones o creación de registros en la base de datos, o al cambiar el estado de los recursos de cualquier manera, provova que las herramientas de caché web y los motores de búsqueda (crawlers) puedan realizar cambios no intencionales en el servidor. Una forma simple de evitar este problema es mover los nombres y valores de los parámetros en la petición del URI a tags XML. Los tags resultantes, una representación en XML de la entidad a crear, pueden ser enviados en el cuerpo de un HTTP POST cuyo URI de petición es el padre de la entidad.

Antes:

GET /agregarusuario?nombre=Zim HTTP/1.1

Después:

POST /usuarios HTTP/1.1
Host: miservidor
Content-type: application/xml

<usuario>
    <nombre>Zim</nombre>
</usuario>

El método acá arriba es un ejemplo de una petición REST: hay un uso correcto de HTTP POST y la inclusión de los datos en el cuerpo de la petición. Al recibir esta petición, la misma puede ser procesada de manera de agregar el recurso contenido en el cuerpo como un subordinado del recurso identificado en el URI de la petición; en este caso el nuevo recurso debería agregarse como hijo de /usuarios. Esta relación de contención entre la nueva entidad y su padre, como se indica en la petición del POST, es análoga a la forma en la que está subordinado un archivo a su directorio. El cliente indica esta relación entre la entidad y su padre y define el nuevo URI de la entidad en la petición del POST.

Luego, una aplicación cliente puede obtener una representación del recurso usando la nueva URI, sabiendo que al menos lógicamente el recurso se ubica bajo /usuarios

GET /usuarios/Zim HTTP/1.1
Host: miservidor
Accept: application/xml

Es explícito el uso del GET de esta manera, ya que el GET se usa sólamente para recuperar datos. GET es una operación que no debe tener efectos secundarios, una propiedad también conocida como idempotencia.

Se debe hacer un refactor similar de un método web que realice actualizaciones a través del método HTTP GET. El siguiente método GET intenta cambiar la propipedad “nombre” de un recurso. Si bien se puede usar el string de consulta para esta operación, evidentemente no es el uso apropiado y tiende a ser problemático en operaciones más complejas. Ya que nuestro objetivo es hacer uso explícito de los métodos HTTP, un enfoque REST sería enviar un HTTP PUT para actualizar el recurso, en vez de usar HTTP GET.

Antes:

GET /actualizarusuario?nombre=Zim&nuevoNombre=Dib HTTP/1.1

Después:

PUT /usuarios/Zim HTTP/1.1
Host: miservidor
Content'Type: application/xml

<usuario>
    <nombre>Dib</nombre>
</usuario>

Al usar el método PUT para reemplazar al recurso original se logra una interfaz más limpia que es consistente con los principios de REST y con la definición de los métodos HTTP. La petición PUT que se muestra arriba es explícita en el sentido que apunta al recurso a ser actualiza identificándolo en el URI de la petición, y también transfiere una nueva representación del recurso del cliente hacia el servidor en el cuerpo de la petición PUT, en vez de transferir los atributos del recurso como un conjunto suelo de parámetros (nombre = valor) en el mismo URI de la petición.

El PUT arriba mostrado también tiene el efecto de renombrar al recurso Zim a Dib, y al hacerlo cambia el URI a /usuarios/Dib. En un servicio web REST, las peticiones siguientes al recurso que apunten a la URI anterior van a generar un error estándard “404 Not Found”.

Como un principio de diseño general, ayuda seguir las reglas de REST que aconsejan usar sustantivos en vez de verbos en las URIs. En los servicios web REST, los verbos están claramente definidos por el mismo protocolo: POST, GET, PUT y DELETE. Idealmente, para mantener una interfaz general y para que los clientes puedan ser explícitos en las operaciones que invocan, los servicios web no deberían definir más verbos o procedimientos remotos, como ser /agregarusuario y/actualizarusuario. Este principio de diseño también aplica para el cuerpo de la petición HTTP, el cual debe usarse para transferir el estado de un recurso, y no para llevar el nombre de un método remoto a ser invocado.

REST no mantiene estado

Los servicios web REST necesitan escalar para poder satisfacer una demanda en constante crecimiento. Se usan clusters de servidores con balanceadores de carga y alta disponibilidad, proxies, y gateways de manera de conformar una topología serviciable, que permita transferir peticiones de un equipo a otro para disminuir el tiempo total de respuesta de una invocación al servicio web. El uso de servidores intermedios para mejorar la escalabilidad hace necesario que los clientes de servicios web REST envien peticiones completas e independientes; es decir, se deben enviar peticiones que incluyan todos los datos necesarios para cumplir el pedido, de manera que los componentes en los servidores intermedios puedan redireccionar y gestionar la carga sin mantener el estado localmente entre las peticiones.

Una petición completa e independiente hace que el servidor no tenga que recuperar ninguna información de contexto o estado al procesar la petición. Una aplicación o cliente de servicio web REST debe incluir dentro del encabezado y del cuerpo HTTP de la petición todos los parámetros, contexto y datos que necesita el servidor para generar la respuesta. De esta manera, el no mantener estado mejora el rendimiento de los servicios web y simplifica el diseño e implementación de los componentes del servidor, ya que la ausencia de estado en el servidor elimina la necesidad de sincronizar los datos de la sesión con una aplicación externa.

Servicios con estado vs. sin estado

La siguiente ilustración nos muestra un servicio con estado, del cual una aplicación realiza peticiones para la página siguiente en un conjunto de resultados múlti-página, asumiendo que el servicio mantiene información sobre la última página que pidió el cliente. En un diseño con estado, el servicio incrementa y almacena en algún lugar una variable paginaAnteriorpara poder responder a las peticiones siguientes.

servicio web stateful

Los servicios con estado tienden a volverse complicados. En la plataforma Java Enterprise Edition (Java EE), un entorno de servicios con estado necesita bastante análisis y diseño desde el inicio para poder almacenar los datos eficientemente y poder sincronizar la sesión del cliente dentro de un cluster de servidores. En este tipo de ambientes, ocurre un problema que le resulta familiar a los desarrolladores de servlets/JSP y EJB, quienes a menudo tienen que revolver buscando la causa de una java.io.NotSerializableException cuando ocurre la replicación de una sesión. Puede ocurrir tanto sea en el contenedor de Servlets al intentar replicar la HttpSession o por el contenedor de EJB al replicar un EJB con estado; en todos los casos, es un problema que puede costar mucho esfuerzo resolver, buscando el objeto que no implementa Serializable dentro de un grafo complejo de objetos que constituyen el estado del servidor. Además, la sincronización de sesiones es costosa en procesamiento, lo que impacta negativamente en el rendimiento general del servidor.

Por otro lado, los servicios sin estado son mucho más simples de diseñar, escribir y distribuir a través de múltiples servidores. Un servicio sin estado no sólo funciona mejor, sino que además mueve la responsabilidad de mantener el estado al cliente de la aplicación. En un servicio web REST, el servidor es responsable de generar las respuestas y proveer una interfaz que le permita al cliente mantener el estado de la aplicación por su cuenta. Por ejemplo, en el mismo ejemplo de una petición de datos en múltiples páginas, el cliente debería incluir el número de página a recuperar en vez de pedir “la siguiente”, tal como se muestra en la siguiente figura:

servicio web stateless

Un servicio web sin estado genera una respuesta que se enlaza a la siguiente página del conjunto y le permite al cliente hacer todo lo que necesita para almacenar la página actual. Este aspecto del diseño de un servicio web REST puede descomponerse en dos conjuntos de responsabilidades, como una separación de alto nivel que clarifica cómo puede mantenerse un servicio sin estado.

Responsabilidad del servidor

  • Genera respuestas que incluyen enlaces a otros recursos para permitirle a la aplicación navegar entre los recursos relacionados. Este tipo de respuestas tiene enlaces embebidos. De la misma manera, si la petición es hacia un padre o un recurso contenedor, entonces una respuestsa REST típica debería también incluir enlaces hacia los hijos del padre o los recursos subordinados, de manera que se mantengan conectados.
  • Genera respuestas que indican si son susceptibles de caché o no, para mejorar el rendimiento al reducir la cantidad de peticiones para recursos duplicados, y para lograr eliminar algunas peticiones completamente. El servidor utiliza los atributos Cache-Control y Last-Modified de la cabecera en la respuesta HTTP para indicarlo.

Responsabilidades del cliente de la aplicación

  • Utiliza el atributo Cache-Control del encabezado de la respuesta para determinar si debe cachear el recurso (es decir, hacer una copia local del mismo) o no. El cliente también lee el atributo Last-Modified y envia la fecha en el atributo If-Modified-Since del encabezado para preguntarle al servidor si el recurso cambió desde entonces. Esto se conoce comoGET Condicional, y ambos encabezados van de la mano con la respuesta del servidor 304 (No Modificado) y se omite al recurso que se había solicitado si no hubo cambios desde esa fecha. Una respuesta HTTP 304 significa que el cliente puede seguir usando la copia local de manera segura, evitando así realizar las peticiones GET hasta tanto el recurso no cambie.
  • Envia peticiones completas que pueden ser serviciadas en forma independiente a otras peticiones. Esto implica que el cliente hace uso completo de los encabezados HTTP tal como está especificado por la interfaz del servicio web, y envia las representaciones del recurso en el cuerpo de la petición. El cliente envia peticiones que hacen muy pocas presunciones sobre las peticiones anteriores, la existencia de una sesión en el servidor, la capacidad del servidor para agregarle contexto a una petición, o sobre el estado de la aplicación que se mantiene entre las peticiones.

Esta colaboración entre el cliente y el servicio es esencial para crear un servicio web REST sin estado. Mejora el rendimiento, ya que ahorro ancho de banda y minimiza el estado de la aplicación en el servidor.

REST expone URIs con forma de directorios

Desde el punto de vista del cliente de la aplicación que accede a un recurso, la URI determina qué tan intuitivo va a ser el web service REST, y si el servicio va a ser utilizado tal como fue pensado al momento de diseñarlo. La tercera característica de los servicios web REST es justamente sobre las URIs.

Las URI de los servicios web REST deben ser intuitivas, hasta el punto de que sea facil adivinarlas. Pensemos en las URI como una interfaz auto-documentada que necesita de muy poca o ninguna explicación o referencia para que un desarrollador pueda comprender a lo que apunta, y a los recursos derivados relacionados.

Una forma de lograr este nivel de usabilidad es definir URIs con una estructura al estilo de los directorios. Este tipo de URIs es jerárquica, con una única ruta raiz, y va abriendo ramas a través de las subrutas para exponer las áreas principales del servicio. De acuerdo a esta definición, una URI no es sólamente una cadena de caracteres delimitada por barras, sino más bien un árbol con subordinados y padres organizados como nodos. Por ejemplo, en un servicio de hilos de discusiones que tiene temas varios, se podría definir una estructura de URIs como esta:

http://www.miservicio.org/discusion/temas/{tema}

La raiz, /discusion, tiene un nodo /temas como hijo. Bajo este nodo hay un conjunto de nombres de temas (como ser tecnologia, actualidad, y más), cada uno de los cuales apunta a un hilo de discusión. Dentro de esta estructura, resulta facil recuperar hilos de discusión al tipear algo después de /temas/.

En algunos casos, la ruta a un recurso encacja muy bien dentro de la idea de “esctructura de directorios”. Por ejemplo, tomemos algunos recursos organizados por fecha, que son muy prácticos de organizar usando una sintáxis jerárquica.

El siguiente ejemplo es intuitivo porque está basado en reglas:

http://www.miservicio.org/discusion/2008/12/23/{tema}

El primer fragmento de la ruta es un año de cuatro dígitos, el segundo fragmento es el mes de dos dígitos, y el tercer fragmento es el día de dos dígitos. Puede resultar un poco tonto explicarlo de esta manera, pero es justamente el nivel de simpleza que buscamos. Tanto humanos como máquinas pueden generar estas estructuras de URI porque están basadas en reglas. Como vemos, es facil llenar las partes de esta URI, ya que existe un patrón para crearlas:

http://www.miservicio.org/discusion/{año}/{mes}/{dia}/{tema}

Podemos también enumerar algunas guías generales más al momento de crear URIs para un servicio web REST:

  • ocultar la tecnología usada en el servidor que aparecería como extensión de archivos (.jsp, .php, .asp), de manera de poder portar la solución a otra tecnología sin cambiar las URI.
  • mantener todo en minúsculas.
  • sustituir los espacios con guiones o guiones bajos (uno u otro).
  • evitar el uso de strings de consulta.
  • en vez de usar un 404 Not Found si la petición es una URI parcial, devolver una página o un recurso predeterminado como respuesta.

Las URI deberían ser estáticas de manera que cuando cambie el recurso o cambie la implementación del servicio, el enlace se mantenga igual. Esto permite que el cliente pueda generar “favoritos” o bookmarks. También es importante que la relación entre los recursos que está explícita en las URI se mantenga independiente de las relaciones que existen en el medio de almacenamiento del recurso.

REST transfiere XML, JSON, o ambos

La representación de un recurso en general refleja el estado actual del mismo y sus atributos al momento en que el cliente de la aplicación realiza la petición. La representación del recurso son simples “fotos” en el tiempo. Esto podría ser una representación de un registro de la base de datos que consiste en la asociación entre columnas y tags XML, donde los valores de los elementos en el XML contienen los valores de las filas. O, si el sistema tiene un modelo de datos, la representación de un recurso es una fotografía de los atributos de una de las cosas en el modelo de datos del sistema. Estas son las cosas que serviciamos con servicios web REST.

La última restricción al momento de diseñar un servicio web REST tiene que ver con el formato de los datos que la aplicación y el servicio intercambian en las peticiones/respuestas. Acá es donde realmente vale la pena mantener las cosas simples, legibles por humanos, y conectadas.

Los objetos del modelo de datos generalmente se relacionan de alguna manera, y las relaciones entre los objetos del modelo de datos (los recursos) deben reflejarse en la forma en la que se representan al momento de transferir los datos al cliente. En el servicio de hilos de discusión anterior, un ejemplo de una representación de un recurso conectado podría ser un tema de discusión raiz con todos sus atributos, y links embebidos a las respuetas al tema.

<discusion fecha="{fecha}" tema="{tema}">
    <comentario>{comentario}</comentario>
    <respuestas>
          <respuesta de="
 gaz@mail.com" href="/discusion/temas/{tema}/gaz"/>
          <respuesta de="
 gir@mail.com" href="/discusion/temas/{tema}/gir"/>
    </respuestas>
</discusion>

Por último, es bueno construir los servicios de manera que usen el atributo HTTP Accept del encabezado, en donde el valor de este campo es un tipo MIME. De esta manera, los clientes pueden pedir por un contenido en particular que mejor pueden analizar. Algunos de los tipos MIME más usados para los servicios web REST son:

MIME-Type Content-Type
JSON application/json
XML application/xml
XHTML application/xhtml+xml

Esto permite que el servicio sea utilizado por distintos clientes escritos en diferentes lenguajes, corriendo en diversas plataformas y dispositivos. El uso de los tipos MIME y del encabezado HTTP Accepto es un mecanismo conocido como negociación de contenido, el cual le permite a los clientes elegir qué formato de datos puedan leer, y minimiza el acoplamiento de datos entre el servicio y las aplicaciones que lo consumen.

Conclusión

No simpre REST es la mejor opción. Está surgiendo como una alternativa para diseñar servicios web con menos dependencia en middleware propietario (por ejemplo, un servidor de aplicaciones), que su contraparte SOAP y los servicios basados en WSDL. De algún modo, REST es la vuelta a la Web antes de la aparición de los grandes servidores de aplicaciones, ya que hace énfasis en los primeros estándares de Internet, URI y HTTP. Como examinamos en este artículo, XML sobre HTTP es una interfaz muy poderosa que permite que aplicaciones internas, como interfaces basadas en JavaScript Asincrónico + XML (AJAX) puedan conectarse, ubicar y consumir recursos. De hecho, es justamente esta gran combinación con AJAX que generó esta gran atención que tiene REST hoy en día.

Resulta muy flexible el poder exponer los recursos del sistema con un API REST, de manera de brindar datos a distintas aplicaciones, formateados en distintas maneras. REST ayuda a cumplir con los requerimientos de integración que son críticos para construir sistemas en donde los datos tienen que poder combinarse facilmente (mashups) y extenderse. Desde este punto de vista, los servicios REST se convierten en algo mucho más grande.

Este artículo es tan sólo una breve introducción a los servicios web REST, y espera ser el puntapié inicial para que puedan continuar explorando esta forma de exponer servicios.

Javascript : arrays asociativos

[Fuente: http://www.hunlock.com/blogs/Mastering_Javascript_Arrays#quickIDX9]

Javascript no implementa Arrays asociativos

Un array asociativo es un array que utiliza una string en vez de un número como índice para acceder a un elemento concreto del array.

var normalArray    = [];
    normalArray[1] = 'This is an enumerated array';

    alert(normalArray[1]);   // outputs: This is an enumerated array

var associativeArray           = [];
    associativeArray['person'] = 'John Smith';

    alert(associativeArray['person']); // outputs: John Smith

Javascript no tiene, y no soporta Arrays Asociativos. Sin embargo… Todos los arrays en Javascript son objetos y la sintáxis básica de objetos en Javascript simula un array asociativo. Es por ello que el ejemplo anterior funciona. Pero ten en cuenta que aunque lo parezca no es un array propiamente dicho. Es decir el campo ‘person’ pasa a ser una propiedad del objeto ‘associativeArray’ pero los métodos .length(), .sort() y demás métodos de array que implementa javascript no funcionarán.

Podemos hacer un bucle de todas las propiedades del objeto asi:

var associativeArray = [];
associativeArray["one"] = "First";
associativeArray["two"] = "Second";
associativeArray["three"] = "Third";
for (i in associativeArray) {
   document.writeln(i+':'+associativeArray[i]+', ');
   // outputs: one:First, two:Second, three:Third
};

En el ejemplo de arriba,  associativeArray.length es cero porque de hecho no pones nada dentro del array, realmente lo añadimos como atributos del objeto associativeArray. Por tanto “associativeArray[0]” sale undefined.

Como un ejemplo final, el código anterior funcionará independientemente de si defines associativeArray como un Array ([]) , un objeto ({}) , una expresion regular (//), una String (“”) , o cualquier otro objeto Javascript.

En resumen — intenta no utilizar arrays asociativos, sino que prográmalos como lo que son — propiedades de los objetos , no Arrays.

Crear un plugin de jQuery

[Fuente: http://docs.jquery.com/Plugins/Authoring]

Extender jQuery con plugins y métodos es muy potente y puede ahorrarte mucho tiempo de desarrollo por medio de abstraer las funciones complejas dentro de plugins. Explicaremos aqui lo básico, las mejores prácticas y los fallos más comunes

Primeros pasos

Para escribir un plugin de jQuery , empieza añadiendo una nueva propiedad de función al objeto jQuery.fn donde el nombre de la propiedad es el nombre de tu plugin:

jQuery.fn.myPlugin = function() {

  // Do your awesome plugin stuff here

};

Cuidao!  Dónde está el símbolo del dolar que tanto queremos? Está aún ahí , pero para asegurarnos que tu plugin no colisiona con otras librerias que utilicen el símbolo del dolar, la mejor práctica es pasar jQuery a un IIFE (Immediately Invoked Function Expression) que lo mapea al símbolo del dolar de forma que no puede ser sobreescrito por otra librería en ese ámbito.

(function( $ ) {
  $.fn.myPlugin = function() {

    // Do your awesome plugin stuff here

  };
})( jQuery );

Así mejor. De esta forma , dentro de esa función IIFE podemos utilizar el dolar con total tranquilidad.

Contexto

Ahora que tenemos nuestra interfaz lista podemos empezar a escribir el código del plugin. Pero antes de eso, comentamos algo importante sobre el contexto. En el ámbito inmediato de la función del plugin, la palabra clave this se refiere al objeto jQuery sobre el que se invocó el método del plugin. Es un error muy común confundirlo con los casos donde jQuery accepta una función de callback, y aqui el this se refiere al elemento DOM nativo. Esto hace que muchas veces los programadores de forma innecesaria hagan un wrapping de la palabra clave this en la función jQuery.

(function( $ ){

  $.fn.myPlugin = function() {

    // there's no need to do $(this) because
    // "this" is already a jquery object

    // $(this) would be the same as $($('#element'));

    this.fadeIn('normal', function(){

      // the this keyword is a DOM element

    });

  };
})( jQuery );

$('#element').myPlugin();

Lo básico

Ahora que entendemos el contexto de los plugins de jQuery , escribamos un plugin que haga algo:

(function( $ ){

  $.fn.maxHeight = function() {

    var max = 0;

    this.each(function() {
      max = Math.max( max, $(this).height() );
    });

    return max;
  };
})( jQuery );

var tallest = $('div').maxHeight(); // Returns the height of the tallest div

Este plugin simplemente el div que tenga la altura máxima dentro de la página.

 

Manteniendo la capacidad de encadenamiento

The previous example returns an integer value of the tallest div on the page, but often times the intent of a plugin is simply modify the collection of elements in some way, and pass them along to the next method in the chain. This is the beauty of jQuery’s design and is one of the reasons jQuery is so popular. So to maintain chainability in a plugin, you must make sure your plugin returns thethis keyword.

(function( $ ){

  $.fn.lockDimensions = function( type ) {  

    return this.each(function() {

      var $this = $(this);

      if ( !type || type == 'width' ) {
        $this.width( $this.width() );
      }

      if ( !type || type == 'height' ) {
        $this.height( $this.height() );
      }

    });

  };
})( jQuery );

$('div').lockDimensions('width').css('color', 'red');

Because the plugin returns the this keyword in its immediate scope, it maintains chainability and the jQuery collection can continue to be manipulated by jQuery methods, such as .css. So if your plugin doesn’t return an intrinsic value, you should always return the this keyword in the immediate scope of the plugin function. Also, as you might assume, arguments you pass in your plugin invocation get passed to the immediate scope of the plugin function. So in the previous example, the string ‘width’ becomes the type argument for the plugin function.

Defaults and Options

For more complex and customizable plugins that provide many options, it’s a best practice to have default settings that can get extended (using $.extend) when the plugin is invoked. So instead of calling a plugin with a large number of arguments, you can call it with one argument which is an object literal of the settings you would like to override. Here’s how you do it.

(function( $ ){

  $.fn.tooltip = function( options ) {  

    // Create some defaults, extending them with any options that were provided
    var settings = $.extend( {
      'location'         : 'top',
      'background-color' : 'blue'
    }, options);

    return this.each(function() {        

      // Tooltip plugin code here

    });

  };
})( jQuery );

$('div').tooltip({
  'location' : 'left'
});

In this example, after calling the tooltip plugin with the given options, the default location setting gets overridden to become 'left', while the background-color setting remains the default'blue'. So the final settings object ends up looking like this:

{
  'location'         : 'left',
  'background-color' : 'blue'
}

This is a great way to offer a highly configurable plugin without requiring the developer to define all available options.

Namespacing

Properly namespacing your plugin is a very important part of plugin development. Namespacing correctly assures that your plugin will have a very low chance of being overwritten by other plugins or code living on the same page. Namespacing also makes your life easier as a plugin developer because it helps you keep better track of your methods, events and data.

Plugin Methods

Under no circumstance should a single plugin ever claim more than one namespace in thejQuery.fn object.

(function( $ ){

  $.fn.tooltip = function( options ) {
    // THIS
  };
  $.fn.tooltipShow = function( ) {
    // IS
  };
  $.fn.tooltipHide = function( ) {
    // BAD
  };
  $.fn.tooltipUpdate = function( content ) {
    // !!!
  };

})( jQuery );

This is a discouraged because it clutters up the $.fn namespace. To remedy this, you should collect all of your plugin’s methods in an object literal and call them by passing the string name of the method to the plugin.

(function( $ ){

  var methods = {
    init : function( options ) {
      // THIS
    },
    show : function( ) {
      // IS
    },
    hide : function( ) {
      // GOOD
    },
    update : function( content ) {
      // !!!
    }
  };

  $.fn.tooltip = function( method ) {

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

// calls the init method
$('div').tooltip(); 

// calls the init method
$('div').tooltip({
  foo : 'bar'
});

// calls the hide method
$('div').tooltip('hide'); 

// calls the update method
$('div').tooltip('update', 'This is the new tooltip content!');

This type of plugin architecture allows you to encapsulate all of your methods in the plugin’s parent closure, and call them by first passing the string name of the method, and then passing any additional parameters you might need for that method. This type of method encapsulation and architecture is a standard in the jQuery plugin community and it used by countless plugins, including the plugins and widgets in jQueryUI .

Events

A lesser known feature of the bind method is that is allows for namespacing of bound events. If your plugin binds an event, its a good practice to namespace it. This way, if you need to unbind it later, you can do so without interfering with other events that might have been bound to the same type of event. You can namespace your events by appending “.<namespace>” to the type of event you’re binding.

(function( $ ){

  var methods = {
     init : function( options ) {

       return this.each(function(){
         $(window).bind('resize.tooltip', methods.reposition);
       });

     },
     destroy : function( ) {

       return this.each(function(){
         $(window).unbind('.tooltip');
       })

     },
     reposition : function( ) {
       // ...
     },
     show : function( ) {
       // ...
     },
     hide : function( ) {
       // ...
     },
     update : function( content ) {
       // ...
     }
  };

  $.fn.tooltip = function( method ) {

    if ( methods[method] ) {
      return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

$('#fun').tooltip();
// Some time later...
$('#fun').tooltip('destroy');

In this example, when the tooltip is initialized with the init method, it binds the reposition method to the resize event of the window under the namespace ‘tooltip’. Later, if the developer needs to destroy the tooltip, we can unbind the events bound by the plugin by passing its namespace, in this case ‘tooltip’, to the unbind method. This allows us to safely unbind plugin events without accidentally unbinding events that may have been bound outside of the plugin.

Data

Often times in plugin development, you may need to maintain state or check if your plugin has already been initialized on a given element. Using jQuery’s data method is a great way to keep track of variables on a per element basis. However, rather than keeping track of a bunch of separate data calls with different names, it’s best to use a single object literal to house all of your variables, and access that object by a single data namespace.

(function( $ ){

  var methods = {
     init : function( options ) {

       return this.each(function(){

         var $this = $(this),
             data = $this.data('tooltip'),
             tooltip = $('<div />', {
               text : $this.attr('title')
             });

         // If the plugin hasn't been initialized yet
         if ( ! data ) {

           /*
             Do more setup stuff here
           */

           $(this).data('tooltip', {
               target : $this,
               tooltip : tooltip
           });

         }
       });
     },
     destroy : function( ) {

       return this.each(function(){

         var $this = $(this),
             data = $this.data('tooltip');

         // Namespacing FTW
         $(window).unbind('.tooltip');
         data.tooltip.remove();
         $this.removeData('tooltip');

       })

     },
     reposition : function( ) { // ... },
     show : function( ) { // ... },
     hide : function( ) { // ... },
     update : function( content ) { // ...}
  };

  $.fn.tooltip = function( method ) {

    if ( methods[method] ) {
      return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

Using data helps you keep track of variables and state across method calls from your plugin. Namespacing your data into one object literal makes it easy to access all of your plugin’s properties from one central location, as well as reducing the data namespace which allows for easy removal if need be.

Summary and Best Practices

Writing jQuery plugins allows you to make the most out of the library and abstract your most clever and useful functions out into reusable code that can save you time and make your development even more efficient. Here’s a brief summary of the post and what to keep in mind when developing your next jQuery plugin:

  • Always wrap your plugin in a closure: (function( $ ){ /* plugin goes here */ })( jQuery );
  • Don’t redundantly wrap the this keyword in the immediate scope of your plugin’s function
  • Unless you’re returning an intrinsic value from your plugin, always have your plugin’s function return the this keyword to maintain chainability.
  • Rather than requiring a lengthy amount of arguments, pass your plugin settings in an object literal that can be extended over the plugin’s defaults.
  • Don’t clutter the jQuery.fn object with more than one namespace per plugin.
  • Always namespace your methods, events and data.

10 Razones por las que fallan los proyectos web

[Fuente: http://speckyboy.com/2012/08/24/10-reasons-why-website-projects-fail/]

A menudo me pregunto porqué hay tantos clientes que vienen a nosotros después de que sus proyectos Web hayan fallado. Alrededor del 75% de nuestro negocio viene de proyectos donde alguien no ha podido terminar su trabajo. La situación más común es lo que yo llamo el “Money Pit”. Ahí es donde el programador sigue diciendo al cliente que está casi hecho pero nunca lo acaba.

Hoy todos los proyectos utilizan algún tipo de Gestor de Contenidos. En vez de pintar un lienzo como en los viejos tiempos del HTML, estamos haciendo aplicaciones que necesitan seguir aproximaciones al desarrollo más tradicionales. Si el proyecto es codificado de forma impropia, entonces muy a menudo tienes que tirarlo todo a la basura y empezar de nuevo. El coste de arreglar todos estos problemas puede ser significativo.

Pienso que debería compartir las razones más comunes que hemos visto alrededor de todos estos años que hacen que los proyectos fallen.

1. El “Sindrome Freelance”: programadores no cualificados; utilizando tu marca , amigo / vecino , contratando en tu nombre o yendo más alla de lo que deberían.

Quieres hacer un web increible que automatizará las gestiones de tu negocio y se beneficiará de las maravillosas oportunidades que Internet proporciona. Todos te dicen que pueden hacerlo para ti y todos te suenan a lo mismo. El problema es que la mayoría de la gente con la que estás hablando no están cualificados para realizar el trabajo. La mayoría de las agencias de marketing son increibles a la hora de construir tu marca, pero tienen gente en su empresa apropiada para desarrollar tu aplicación web?

Asegurate que ellos no están subcontratando tu proyecto a freelances o incluso peor, lo están encargando a grupos de trabajo en paises lejanos. Visita o habla con la gente que está desarrollando tu website y mira su trabajo. Habla para pedirles referencias. Mira que no te den gato por liebre. Han hecho ellos proyectos de complejidad similar? Hacer negocios con amigos / vecinos no tiene sentido. Contratar programadores para tu empresa  puede convertirte en aprendiz de todo maestro de nada. Hace falta varios perfiles con diferentes especializaciones para construir los websites de hoy. Los recursos de la casa se ajustan mejor a una fase del proyecto en la que el proyecto ya ha sido comenzado. Es en ese momento en el que el programador de tu empresa puede servir de soporte de recursos según sean necesarios a los programadores de tu website ahorrandote dinero.

2. Saltarse lo fundamental: Carencia de una clara definición del ámbito y los requerimientos

Todo el mundo está siempre ansioso para empezar y estamos seguros de conocer lo que tienen que hacer. Pero no pensamos  sobre cómo va a funcionar y qué sucede bajo distintos escenarios. Estos es especialment cierto cuando una compañia pone su negocio online. Cómo afectará este nuevo proceso a su negocio? La mayor parte de los clientes creen que saben lo que ellos quieren, pero el diablo está en los detalles. No puedo decirte cuántos clientes conocemos que cuando les presionamos a detallar su funcionalidad, ellos habian pasado por alto algunas ramificaciones. Asegurate que pasas por un ejercicio de planificación detallado antes de empezar a programar. asegurate de programar algo que tus clientes quieren y necesitan, no solo lo que ellos quieren. Saca input de tus clientes.

3. Perdida de liderato. Falta de interés en comprar y falta de participación

La gestión quiere una nueva web para alcanzar objetivos corporativos e incrementar el ROI. La gestión no tiene tiempo de estar en la toma de las decisiones estratégicas que deben ser hechas. Aparecen grandes problemas cuando la gestión prueba la versión Beta y encuentra que no es lo que originalmente ellos querian. Algunos de los mejores proyectos en los que hemos trabajado son aquellos en los cuales la gestión ejecutiva estuvo más activamente involucrada desde el comienzo. Los cambios pueden ser muy caros en tiempo y dinero si tienen que hacerse al final del proyecto en vez de al comienzo.

4. El “Sindrome Facebook” abarca más de lo que puede abarcar

Hay que ser cuidados de no querer abarcar más de lo que se puede. Roma no fue construida en un día. Si tienes entre manos un proyecto realmente complejo, hazlo en fases. No tienes que sacarlo todo en la primera versión de una vez. No hay nada malo con reemplzar la web antigua después de que se hayan completado tres o cuatro fases.

5. Anteponiendo el diseño como lo primero: Diseñar sin proposito ni función

Hemos visto diseños muy bonitos para nuevos proyectos que directamente no pueden ser programados o son muy caros de construir. Es mejor diseñar toda la funcionalidad teniendo en cuenta la plataforma donde el diseño va a ser integrado. Entonces debes hacer trabajar a tu equipo de programadores junto con el diseñador, asi juntos deben llegar a algo que es bonito y funcional a la vez. De otra forma llegarás a tener un Frankestein que no hay por donde cojerlo.

6. Código descontrolado: No utilizar un Control de Versiones

Hoy en día es insondable programar una web sin algún tipo de sistema de control de versiones de código. Nosotros utilizamos GITSVN. Cuando los programadores crean , soportan y actualizan archivos de código fuente para una aplicación grande, la coordinación puede ser compleja. Los sistemas de control de código fuente graban todos los cambios de los archivos, con comentarios , en un proyecto. Necesitas tener la posibilidad de poder recuperar la funcionalidad, fundir distintas ramas de desarrollo y trabajar off line. Un apropiado control de versiones es vital para cualquier proyecto.

 

7. Programadores descontrolados: Carencia de buena gestión del Proyecto

The Project Manager (PM) is the Quarterback of your football team. The PM is responsible for the successful planning, execution, monitoring, control and closure of a project. The PM needs to understand the client’s needs and provide communication to and from the developers. Without a proficient PM, the project will get off track and become a run away train that ends up in disaster. A good PM will publish weekly progress reports keeping everything on track.

8. Intentar reinventar la rueda: hackeando el core o el código fuente

Hacking is changing the source code structure. We always believe in K.I.S.S, Keep it short and simple. When an unqualified developer doesn’t know how to do something, they tend to hack the code to make it do it. This causes a number of problems and greatly affects quality. If your developer fixes one problem and another arises, it may be the result of a lot of hacks.

Doing so will make it near impossible for site updates due to Security and bug fixes. It also makes it difficult for those that come in after to maintain the site and could possibly leave your site vulnerable to exploits. We have a tool we run that uncovers all of the Hacks for our customers who come to us in trouble. Then we show them the results and why their website doesn’t work.

9. Getting Off Track: Scope Creep

Esto sucede mucho. La tarea principal de un buen PM es mantener las cosas en el buen camino. Es natural según avanzas en el proyecto de desarrollo, que se te ocurran nuevas ideas y cosas que quieres. Pero necesitas darte cuenta que cada vez que haces un cambio, esto suma tiempo y coste en tu proyecto.

This happens a lot. A good PM’s main job is to keep things on track. It’s natural as you go through the development, to come up with new ideas and things you want. You need to realize that every time you make a change, it adds to the time and cost of your project. Changes late within the process have large affects. If a website is built and tested, you will have to retest after the change. Some changes are beneficial, especially if they make the website better for your users. But lots of indecision and changing can derail a project. Scope Creep happens when decision makers aren’t involved early on or the project didn’t go through proper planning.

10. Inexistencia de Testing de funcionalidad: carencia de pruebas de Calidad sólidas

Es importante hacer pruebas unitarias de cada pieza de funcionalidad y entonces hacer test de regresiones en el producto final. Todos los proyectos tienen bugs (fallos), asi que es mejor hacer que los programadores encuentren los problemas a los usuarios. Nosotros generalmente reservamos de un 20 a un 25% del tiempo de desarrollo a tareas de QA

It’s important to unit test each piece of functionality and then do regression testing on the final product. All projects have bugs, so it’s better to have the developers find the problems instead of your users. We usually set aside 20% to 25% of the development time to perform proper QA. Make sure there is a comprehensive QA Plan, otherwise you could get a website that has a lot of issues. Developers need to be thinking about quality from day one and be responsible to fix their problems. Otherwise it could get very sloppy.

Conclusion

Building a successful website requires all ten of these areas to be properly addressed. Failure to perform any of these tasks could derail a project which ends up being completely wasted money in the budget. When you select a developer make sure they can address all of these before you start. Properly done projects can be a tremendous asset to the wellbeing of your company.

Hacia una web para Retina

[Fuente: http://coding.smashingmagazine.com/2012/08/20/towards-retina-web/]

Con el reciente anuncio y versión del Retina Macbook Pro, Apple ha introducido las pantallas de doble densidad a todas las categorias de productos en sus lineas de ventas, allanando el camino a la nueva generación de estandares de pantalla. Mientras el iPhone de cuarta generación nos ofreció lo que era Web en modo “no-Retina” en 2010, hemos tenido que esperar a la tercera generación de iPad para darnos cuenta de lo anticuados que están nuestros gráficos e imágenes de contenido.

En los confines del jardin de Apple, las apps nativas son actualizadas con los gráficos Retina de una forma eficaz, con la ayuda de un sólido SDK y de un proceso de transición bien documentado. Por contraste, la Web al tener una naturaleza tan abierta hace que la transición a displays de alta densidad sea lento y doloroso. En la ausencia de estandares ampliamente aceptados por la industria para hacer eficaz este proceso, cada diseñador/programador Web se le deja la responsabilidad de que sus usuarios tengan la mejor experiencia de usuario, independientemente del tipo de pantalla que estén utilizando.

Antes de entrar en materia, veamos brevemente algunas nociones básicas que son claves para entender los retos y restricciones de diseñar para múltiples densidades de pantalla.

Los píxeles de los dispositivos

Device Pixels

Un pixel de dispositivo (o pixel físico) es la unidad más pequeña en una pantalla. Cada pixel configura su propio color y brillo como le va diciendo el sistema operativo. La impreceptible distancia entre puntos minusculos hace el efecto optico de percibir la imagen de forma completa y contínua.

La densidad de la pantalla se refiere al número de píxeles de dispositivo en un superficie física. Es a menudo medido en pixeles por pulgada (PPI). Apple ha acuñado el término “Retina” para sus pantallas de doble densidad, haciendo que el ojo humano no pueda ni de lejos distinguir píxeles individuales en la pantalla desde una distancia de visionado “normal”.

Los píxeles CSS

CSS Pixels

Un pixel CSS es un unidad abstracta utilizada por los navegadores para dibujar contenido de forma precisa y consistente en las páginas Web. Genericamente, los píxeles CSS se refieren a píxeles independientes del dispositivo (DIPs). En pantallas de densidad estandar, 1 pixel CSS se corresponde con el pixel de dispositivo.

<div height="200" width="300"></div>

Esto utilizaría una caja de 200×300 de píxeles de dispositivo para ser dibujado en la pantalla. En la pantalla Retina, el mismo div utiliza 400×600 para que salga del mismo tamaño, resultando en cuatro veces más píxeles, como mostramos en la siguiente figura:

Device Pixels In Retina Displays

En un pantalla Retina , para cubrir la misma superficie física se utiliza 4 veces más de píxeles de dispositivo

La proporción entre los pixeles de dispositivo y los pixeles de CSS puede obtenerse utilizando el siguiente media query y sus equivalentes especificos del vendedor:

	 device-pixel-ratio,
	 -o-device-pixel-ratio,
	 -moz-device-pixel-ratio,
	-Webkit-device-pixel-ratio {
	…
	}

O puedes utilizar sus primos hermanos que vendrán en un futuro:

device-pixel-ratio,
	 -o-min-device-pixel-ratio,
	 min--moz-device-pixel-ratio,
	-Webkit-min-device-pixel-ratio {
	…
}

En Javascript ,  window.devicePixelRatio puede ser utilizado para obtener el mismo ratio, aunque no todos los navegadores lo soportan. Ambas técnicas serán discutidas en más profundidad en este artículo.

Así por ejemplo podemos decirle a una pagina web que utilice una hoja de estilos diferente en caso de pantallas de alta densidad:

<!-- High pixel density displays -->
<link rel='stylesheet' href='highRes.css' media='only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2)' />

o dentro de una hoja de estilos:

/* iPhone 4 ----------- */
@media
only screen and (-webkit-min-device-pixel-ratio : 1.5),
only screen and (min-device-pixel-ratio : 1.5) {
/* Styles */
}

 

Los pixeles Bitmap

Bitmap Pixels

Un pixel de bitmap es la unidad más pequeña de datos de una imagen raster (PNG. GIF, JPG, etc). Cada pixel contien información sobre cómo debe ser mostrado, incluyendo su posición en el sistema de coordenadas de la imagen y su color. Algunos formatos de imágenes pueden almacenar datos adicionales por pixel, tales como la opacidad (lo que se llama el canal alpha).

Además de la resolución raster, una imagen de la web tiene un tamaño abstracto,  definido en pixeles CSS. El browser ensancha o estrecha la imagen basándose en el height y el width CSS mientras está dibujando la imagen.

Cuando una imagen raster se muestra a tamaño completo en una pantalla de densidad estandar, 1 pixel de bitmap se correspondecon 1 pixel de dispositivo, resultando en una representación completamente fiel. Como el pixel de un bitmap no puede ser dividido, es multiplicado por 4 en las pantallas Retina para preservar el mismo tamaño físico de la imagen, perdiendo detalle en el camino.

Bitmap Pixels On Retina Displays

Each bitmap pixel gets multiplied by four to fill the same physical surface on a Retina display.

La herramienta Pecho (Tool Chest)

Incluso aunque estamos en el camino de un cambio, hay varias aproximaciones para optimizar los gráficos para pantallas Retina , y más que estarán saliendo en el mismo momento que se lee esto. Cada método hace algún grado de compromiso entre al rendimiento, facilidad de implementación y soporte multinavegador (corss-browser). Por tanto , elegir la herramienta debe ser analizado caso por caso, teniendo en cuenta tanto los factores cuantitativos como los cualitativos.

 

El tamaño en HTML y CSS

La forma más directa de servir gráficos web preparados para Retina es reducir a la mitad el tamaño de tus imagenes raster utilizando CSS o HTML,  o manualmente o programaticamente. Por ejemplo. para servir una imagen de 200×300 pixeles (recuerda pixeles CSS), deberiamos subir una imagen con una resolución de bitmap de 400×600 al servidor, entonces reducirla al 50% utilizando CSS o atributos HTML. En una pantalla estandar , el resultado seria una imagen renderizada con cuatro veces menos pixeles que el tamño completo del bitmap – un proceso que es conocido como “downsampling

How downsampling works

A CSS-sized image gets its dimensions halved during the rendering process.

Debido a que la misma imagen en una pantalla Retina utiliza 4 veces más pixeles , cada pixel físico termina coincidiendo exactamente con un pixel del bitmap , permitiendo que la imagen se dibuje completamente fiel.

How HTML sizing works

CSS-sized images regain their full-detail glory on Retina displays.

Hay varias formas de conseguir esto:

USING HTML

The easiest way to apply CSS sizing would be by using the width and height attributes of the img tag:

1 <img src="example@2x.png" width="200" height="300" />

Please note that, even though specifying height is optional, it allows the browser to reserve the space required for the image before loading it. This prevents the page layout from changing as the image loads.

What to use it for? Single-page websites with few content images.

USING JAVASCRIPT

The same result can also be obtained using Javascript by targeting all Retina-ready content images in the document and halving their sizes. With the help of jQuery, this would look like this:

1 $(window).load(function() {
2 var images = $('img');
3 images.each(function(i) {
4 $(this).width($(this).width() / 2);
5 });
6 });

What to use it for? Websites with few content images.

USING CSS (SCSS)

If you want to keep all of the presentation code in your CSS files, then the most common technique involves setting the image as the background of another HTML element, usually a div, then specifying its background-size property. You could either set explicit width and height values for the background image or use the contain value if the dimensions of the HTML element are already specified. It is worth noting that the background-size property is not supported in IE 7 or 8.

1 .image {
2 background-image: url(example@2x.png);
3 background-size: 200px 300px;
4 /* Alternatively background-size: contain; */
5 height: 300px;
6 width: 200px;
7 }

You could also target a :before or :after pseudo-element instead:

1 .image-container:before {
2 background-image: url(example@2x.png);
3 background-size: 200px 300px;
4 content:'';
5 display: block;
6 height: 300px;
7 width: 200px;
8 }

This technique works just as well with CSS sprites, as long as the background-position is specified relatively to the CSS size (200 × 300 pixels in this case):

01 .icon {
02 background-image: url(example@2x.png);
03 background-size: 200px 300px;
04 height: 25px;
05 width: 25px;
06
07 &.trash {
08 background-position: 25px 0;
09 }
10
11 &.edit {
12 background-position: 25px 25px;
13 }
14 }

When using image sprites, consider any OS-specific limitations.

What to use it for? Websites that make limited use of the background-image property, such as those that rely on a single-image sprite.

HTML AND CSS SIZING: PROS

  • Easy to implement
  • Cross-browser compatible

HTML AND CSS SIZING: CONS

  • Non-Retina devices have to download larger assets.
  • Downsampled images might lose some of their sharpness on standard-density screens, depending on the algorithm used.
  • The background-size property is not supported in IE 7 or 8.

Querying Pixel Density

Querying Pixel Density

Perhaps the most popular way to serve Retina-ready graphics on the Web is by querying the device for its pixel density and then serving assets accordingly. This can be done using either CSS or JavaScript.

USING CSS MEDIA QUERIES

As of this writing, almost every major browser vendor has implemented a prefixed variant of device-pixel-ratio and its two siblings, min-device-pixel-ratio and max-device-pixel-ratio. These media queries can be used in conjunction with the background-imageproperty to serve Retina-ready assets to high-density devices:

01 .icon {
02 background-image: url(example.png);
03 background-size: 200px 300px;
04 height: 300px;
05 width: 200px;
06 }
07
08 @media only screen and (-Webkit-min-device-pixel-ratio: 1.5),
09 only screen and (-moz-min-device-pixel-ratio: 1.5),
10 only screen and (-o-min-device-pixel-ratio: 3/2),
11 only screen and (min-device-pixel-ratio: 1.5) {
12 .icon {
13 background-image: url(example@2x.png);
14 }
15 }

By using a ratio of 1.5 instead of 2, you can target other non-Apple devices with the same query.

What to use it for? Any website or app that uses the background-image property for graphic assets. Not suitable for content images.

CSS QUERYING: PROS

  • Devices download only those assets that target them.
  • Cross-browser compatible
  • Pixel-precise control

CSS QUERYING: CONS

  • Tedious to implement, especially on large websites.
  • Displaying content images as backgrounds of other HTML elements is semantically incorrect.

USING JAVASCRIPT

The pixel density of the screen can be queried in Javascript usingwindow.devicePixelRatio, which reports the same value as its CSS counterpart. Once a higher-density screen is identified, you can replace every inline image with its Retina counterpart:

01 $(document).ready(function(){
02 if (window.devicePixelRatio > 1) {
03 var lowresImages = $('img');
04
05 images.each(function(i) {
06 var lowres = $(this).attr('src');
07 var highres = lowres.replace(".", "@2x.");
08 $(this).attr('src', highres);
09 });
10 }
11 });

Retina.js is a Javascript plugin that implements roughly the same technique as described above, with some additional features, such as skipping external images and skipping internal images with no @2x counterparts.

Lastly, it is worth noting that devicePixelRatio is not entirely cross-browser compatible.

What to use it for? Any website with content images, such as landing pages and blogs.

JAVASCRIPT QUERYING: PROS

  • Easy to implement
  • Non-Retina devices do not download large assets.
  • Pixel-precise control

JAVASCRIPT QUERYING: CONS

  • Retina devices have to download both standard- and high-resolution images.
  • The image-swapping effect is visible on Retina devices.
  • Does not work on some popular browsers (such as IE and Firefox).

Scalable Vector Graphics

Scalable Vector Graphics

Regardless of the method used, raster images remain inherently constrained by their bitmap resolution; they were never meant to be infinitely scalable. This is where vector graphics have the advantage, being a future-proof way to “Retinize” your Web graphics.

As of this writing, the vector XML-based SVG format has cross-browser support of more than 70% and can be used in several ways on the Web. SVG images can be easily created in and exported from a number of vector-graphic editors, such as Adobe Illustrator and free alternatives such as Inkscape.

As far as Web design goes, the most straightforward way to use SVG assets is with the HTML img tag or with the CSS background-image and content:url() properties.

1 <img src="example.svg" width="200" height="300" />

In the example above, a single SVG image can be used as a universal asset, scaling infinitely up or down as required. This not only saves precious bandwidth (most SVG files tend to be smaller in size than standard-resolution PNGs), but also makes your graphic assets much easier to maintain. The same would apply if used in CSS:

01 /* Using background-image */
02
03 .image {
04 background-image: url(example.svg);
05 background-size: 200px 300px;
06 height: 200px;
07 width: 300px;
08 }
09
10 /* Using content:url() */
11
12 .image-container:before {
13 content: url(example.svg);
14 /* width and height do not work with content:url() */
15 }

If you have to support IE 7 or 8 or Android 2.x, then you will need a fallback solution that swaps SVG images with their PNG counterparts. This can be easily done with Modernizr:

01 .image {
02 background-image: url(example.png);
03 background-size: 200px 300px;
04 }
05
06 .svg {
07 .image {
08 background-image: url(example.svg);
09 }
10 }

For best cross-browser results and to avoid some rasterization headaches in Firefox and Opera, make each SVG image at least the size of its parent HTML element.

In HTML, you can implement a similar fallback solution by adding a custom data attribute to your img tag:

1 <img src="example.svg" data-png-fallback="example.png" />

Then, handle the rest with jQuery and Modernizr:

1 $(document).ready(function(){
2 if(!Modernizr.svg) {
3 var images = $('img[data-png-fallback]');
4 images.each(function(i) {
5 $(this).attr('src', $(this).data('png-fallback'));
6 });
7 }
8 });

This HTML and JavaScript route, however, would not prevent browsers with no SVG support from downloading the SVG assets.

What to use it for? Any website or app. Suitable for icons, logos and simple vector illustrations.

SVG: PROS

  • One universal asset for all devices
  • Easy to maintain
  • Future-proof: infinitely scalable vector graphics

SVG: CONS

  • No pixel precision due to anti-aliasing
  • Unsuitable for complex graphics due to large file sizes
  • No native support in IE 7 and 8 or early Android versions

Icon Fonts

Icon Fonts

Popularized by Twitter’s Bootstrap, the technique of using @font-face with icon-based fonts has garnered a following of its own as a resolution-independent alternative to bitmap icons. The technique consists of using a custom Web font that replaces the alphabet with monochrome glyphs, which can be styled using CSS, just like any other text on the website.

There is no shortage of comprehensive, good-quality icon fonts that would cover most of your needs. That being said, importing a large font in half a dozen formats only to use a small subset of the icons is a bad idea. Consider building your own custom font with free tools such as FontelloFont Builder or even Inkscape.

The most common way to use icon fonts on websites is by assigning an .icon or .glyphclass to a particular HTML element — most often a <span> or an <i> — and then using the letter corresponding to the desired icon as its content:

1 <span class="icon">a</span>

After having imported your custom font using @font-face, you would declare it:

1 .icon {
2 font-family: 'My Icon Font';
3 }

Another technique consists of using the :before pseudo-element and the contentproperty, with a unique class for each icon:

1 <span class="glyph-heart"></span>
1 [class^="glyph-"]:before {
2 font-family: 'My Icon Font';
3 }
4
5 .glyph-heart:before {
6 content: 'h';
7 }

What to use it for? Websites or apps with a high number of icons, and for rapid prototyping.

ICON FONTS: PROS

  • Future-proof: infinitely scalable glyphs
  • Cross-browser compatible
  • More flexible than graphic assets: can be used in placeholder text and other form elements, etc.

ICON FONTS: CONS

  • No pixel precision due to subpixel anti-aliasing
  • Hard to maintain: changing a single icon requires regenerating the whole font.
  • Relies on semantically incorrect markup (unless used with :before or :afterpseudo-elements).

Favicons

Favicons are getting their fair share of attention, being increasingly used outside of browser chrome as an iconic representation of our websites and apps. To make your favicons Retina-ready, export an .ico file in both 16- and 32-pixel versions. If you are using a Mac, you can create your own .ico files with Apple’s Icon Composer (included in theGraphic Tools in Xcode) or with Icon Slate, a paid third-party application.

A Glimpse Of The Future

Besides the techniques covered above, several other efforts are being made independently by organizations and individuals alike, not the least of which is Apple’s own-Webkit-image-setintroduced last spring. This proposal allows for multiple variants of the same image to be provided in one CSS declaration:

1 .image {
2 background-image: -Webkit-image-set(url(example.png) 1x, url(example@2x.png) 2x);
3 background-size: 200px 300px;
4 }

This technique does not, however, cover images inside img tags, and it is Webkit-only as of this writing.

Another notable effort is Scott Jehl’s Picturefill, an HTML and Javascript solution that makes heavy use of data attributes and media queries to serve different images in different media contexts.

1 <div data-picture>
2 <div data-src="example.png"></div>
3 <div data-src="example@2x.png" data-media="(min-device-pixel-ratio: 1.5)"></div>
4
5 <!-- Fallback content for non-JS browsers -->
6 <noscript>
7 <img src="example.png" >
8 </noscript>
9 </div>

Even if the markup puts you off, it is a good cross-browser solution to consider if you are dealing with few content images.

Last but not least, the ambitious picture element proposal aims to bring responsive images to the Web using a markup-only approach for multiple image sources, coupled with media queries that route each device to the right asset.

CLOSING WORDS

Like other major shifts the Web is currently undergoing, attaining resolution independence will be a long journey. As Web designers and developers, either we can sit down and wait passively for a convention to be standardized, or we can immediately start offering a pleasurable viewing experience to our users. Let’s get to work.

(al)

CSS: 10 sencillos pasos para aprender posicionamiento CSS

[Fuente: http://www.nosolocodigo.com/10-sencillos-pasos-para-aprender-posicionamiento-css]

El posicionamiento CSS es la técnica utilizada para maquetar diseños usando únicamente XHTML y las propiedades CSS. Es el estándar hoy en día y todo sitio web bien maquetado debería usar esta técnica. Las ventajas son muchas, pero entre ellas destaca una mejor separación entre la apariencia y la estructura de la página, un código más semántico y entendible por buscadores, es decir, mejor para SEO, y un tamaño de página resultante inferior, por lo tanto mayor velocidad de carga de la página.

El otro día, vía Twitter me os hablé de un pequeño tutorial donde se enseñaban las bases del posicionamiento CSS en 10 lecciones prácticas. El tutorial me pareció muy bueno y creo que es básico para cualquier persona que quiera aprender a maquetar sitios web con CSS.  Los pasos son realmente sencillos de seguir.
Para todo el tutorial se va a utilizar siempre la misma estructura XHTML, que se muestra a continuación.

	<div id="example">

		<div id="div-before">
			<p>id = div-before</p>
		</div>

		<div id="div-1">
			<div id="div-1-padding">

				<p>id = div-1</p>

			        <div id="div-1a">
				        <p>id = div-1a</p>
				        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer pretium dui sit amet felis. Integer sit amet diam. Phasellus ultrices viverra velit.</p>
			        </div>

			        <div id="div-1b">
				        <p>id = div-1b</p>
				        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer pretium dui sit amet felis. Integer sit amet diam. Phasellus ultrices viverra velit. Nam mattis, arcu ut bibendum commodo, magna nisi tincidunt tortor, quis accumsan augue ipsum id lorem.</p>
			        </div>

			        <div id="div-1c">
				        <p>id = div-1c</p>
			        </div>

			</div>
		</div>

		<div id="div-after">
			<p>id = div-after</p>
		</div>

	</div>

POSITION STATIC

El posicionamiento normal de todos los elementos es static, que significa que cada elemento se posiciona donde le corresponde según el flujo normal de la página. Si no se indica nada, este es el valor que toman todos los elementos.

#div-1 {
    position:static;
}

El resultado que se muestra es el mismo que si no se hubiese aplicado ninguna regla CSS.

Posicionamiento CSS estático. Propiedad static.

POSITION RELATIVE

Si se especifica la posición relativa para un elemento, puedes posicionar este elemento usando las propiedades top, bottom, left y right, y el elemento se posicionará a la distancia indicada respecto de donde debería estar según el flujo normal de la página.

#div-1 {
    position:relative;
    top:20px;
    left:-40px;
}

Posicionamiento relativo en CSS.

POSITION ABSOLUTE

Si se especifica position absolute, el elemento se muestra exactamente donde se indica en las propiedades top, bottom, left o right.

#div-1a {
    position:absolute;
    top:0;
    right:0;
    width:200px;
}

Posicionamiento CSS absoluto

POSITION RELATIVE + POSITION ABSOLUTE

Si especificas la posición de div-1 de forma relativa, todos los elementos contenidos dentro de div-1 se posicionaran relativamente a div-1, por lo tanto si le establecemos la posición absoluta a div-1a, este se posicionará en la esquina superior derecha del contendor div-1.

#div-1 {
     position:relative;
}
#div-1a {
     position:absolute;
     top:0;
     right:0;
     width:200px;
}

Posicionamiento CSS relativo + absoluto

2 COLUMNAS POSICIONADAS DE FORMA ABSOLUTA

Utilizando posicionamiento relativo en el contenedor y absoluto para las columnas se pueden posicionar las columnas, una en cada lado.
Una ventaja de usar este posicionamiento es que se puede colocar el HTML de las columnas en cualquier orden, ya que el posicionamiento se realiza de forma absoluta.

#div-1 {
      position:relative;
}
#div-1a {
      position:absolute;
      top:0;
      right:0;
      width:200px;
}
#div-1b {
     position:absolute;
     top:0;
     left:0;
     width:200px;
}

Posicionamiento CSS de columnas de forma absoluta
Si te fijas, los demás elementos han sido tapados por las dos columnas que están posicionadas de forma absoluta. Vamos a ver cómo solucionar esto.

COLUMNAS POSICIONADAS DE FORMA ABSOLUTA CON ALTO DEFINIDO

Para poder visualizar el contenido tapado por las dos columnas, habría que darle un alto definido al elemento contenedor, de esta forma ya se visualizarían.

#div-1 {
    position:relative;
    height:250px;
}
#div-1a {
    position:absolute;
    top:0;
    right:0;
    width:200px;
}
#div-1b {
    position:absolute;
    top:0;
    left:0;
    width:200px;
}

posicionamiento CSS de columnas con alto fijo
Pero esta no es una solución válida para la mayoría de los diseños, porque lo normal es que no se sepa cual va a ser la longitud del texto introducido en las columnas. ¿Cómo se puede solucionar esto? Sigue leyendo…

POSICIONAMIENTO FLOTANTE

Para columnas de altura variable, el posicionamiento absoluto no sirve, en este caso hay que utilizar el posicionamiento flotante. Con la propiedad float se puede posicionar un elemento lo más a la derecha posible o lo más a la izquierda posible, dejando que el resto de elementos fluya alrededor suyo. El div div-1a está flotado a la izquierda, y el texto del resto de divs fluye alrededor el div-1a, pero el resto de divs (div-1b y div-1c) siguen ocupando la misma posición que antes, es decir todo el contendor, porque son elementos de bloque. Esto significa que el texto no se solapará con div-1, pero si le asignas una imagen de fondo con CSS, esta imagen sí que se solapará con div-1.

#div-1a {
    float:left;
    width:200px;
}

Posicionamiento CSS flotante

COLUMNAS FLOTANTES

Para que no se solapen unos elementos con otros hay que flotar todas las columnas. Para que se muestren una al lado de otra, entre todas las columnas han de sumar un ancho no superior al ancho del contenedor. Si te fijas, tanto div-after, como div-1 (que hace de contenedor) se solapan con las columnas creadas, vamos a ver como solucionar esto.

#div-1a {
    float:left;
    width:150px;
}
#div-1b {
    float:left;
    width:150px;
}

Posicionamiento CSS con columnas flotantes

COLUMNAS FLOTANTES CON CLEAR

Luego, en el último div (div-1c), en este caso el que hace de pie, se le puede añadir la propiedad clear, para que deje de tener efecto el flotado de las columnas de arriba y el resto del contenido se posicione debajo.

#div-1a {
    float:left;
    width:190px;
}
#div-1b {
    float:left;
    width:190px;
}
#div-1c {
     clear:both;
}

paso9

FIN

Con estos pasos se ha aprendido lo básico del posicionamiento CSS. Se han dejado bastantes cosas por ver, como la compatibilidad entre navegadores, etc… Pero creo que es una buena introducción para aprender a colocar cada elemento de la página donde le corresponde sin usar tablas o técnicas desaconsejadas.

¿Qué es Google Apps Engine?

Google App Engine te permite ejecutar aplicaciones web en la infraestructura de Google. Las aplicaciones del App Engine son fáciles de programar , fáciles de mantener, y fáciles de escalar a tu tráfico y el almacenamiento que se necesite. Con App Engine, no hay servidores que mantener: tu solamente subes tu app, y está lista para ser servida a tus usuarios.

Puedes servir tu app desde tu propio dominio (como por ejemplo http://www.example.com) utilizando Google Apps. O, pùedes servir tu app utilizando el nombre que quieras en el dominio appspot.com . Puedes compartir tu app con el mundo, o limitar el acceso a los miembros de tu organización.

Google App Engine soporta apps escritas en diferentes lenguajes de programación. Con el entorno Java del App Engine , puedes desarrollar tu app utilizando la tecnologia Java estandar, incluyendo la JVM, Java Servlets, y el lenguage de programación Java – o cualquier otro lenguaje utilizando una JVM o compilador , como puede ser Javascript o Ruby. App Engine además te ofrece dos entornos de ejecución dedicados de Python, cada uno de los cuales incluye el intérprete de Python y la librería estandar de Python. Finalmente, App Engine proporciona un Go runtime environment que se ejecuta nativamente en código Go. Estos entornos de ejecución son construidos para asegurar que tu aplicación se ejecuta rápidamente, de forma segura, y sin interferencia de otras apps del sistema.

Con App Engine, tú solo pagas por lo que tú usas. No hay costes de configuración y no hay cuotas recurrentes a pagar. Los recursos que tu aplicación utiliza, tales como almacenamiento y ancho de banda, son medidos por los gigabytes utilizados y facturados en tarifas competitivas. Tu controlas la máxima cantidad de recursos que tu app puede consumir, asi siempre estás dentro del presupuesto.

El App Engine no cuesta nada para empezar con él. Todas las aplicaciones pueden utilizar hasta 1GB de almacenamiento y suficiente CPU y ancho de banda para soportar un servicio de app de alrededor de 5 millones de páginas vistas al mes, absolutamente gratis. Cuando activas que se facture por tu app, entonces se te cobrará por lo que te pases de esos límites.

 

El entorno de Aplicación

Google App Engine te hace fácil construir una aplicación que se ejecuta de forma fiable, incluso bajo condiciones de estres y con grandes volumenes de datos. App Engine incluye las siguientes características:

  • Servicio de páginas web dinámicas, con soporte completo para utilizar las tecnologías web más comunes.
  • Almacenamiento persistente con queries, ordenación y transacciones.
  • Escalado automático y balance de carga
  • APIs para autenticar usuarios y enviar email utilizando Google Accounts
  • Un entorno de desarrollo local completo que simula el Google App Engine en tu ordenador.
  • Colas de tareas para realizar trabajo del ámbito de la petición web.
  • Tareas planificadas para ser disparadas por eventos en momentos concretos o a frecuencias determinadas.

Tu aplicación puede ejecutar en uno de los tres siguientes entornos de ejecución:

  • El entorno Go
  • El entorno Java
  • El entorno Python (a elegir entre Python 2.5 o Python 2.7)ç

Cada uno de estos entornos de programación proporciona protocolos y tecnologías estandars para desarrollo de aplicaciones web.

 

El cajón de arena (Sandbox)

Applications run in a secure environment that provides limited access to the underlying operating system. These limitations allow App Engine to distribute web requests for the application across multiple servers, and start and stop servers to meet traffic demands. The sandbox isolates your application in its own secure, reliable environment that is independent of the hardware, operating system and physical location of the web server.

Examples of the limitations of the secure sandbox environment include:

  • An application can only access other computers on the Internet through the provided URL fetch and email services. Other computers can only connect to the application by making HTTP (or HTTPS) requests on the standard ports.
  • Applications cannot write to the file system in any of the runtime environments. An application can read files, but only files uploaded with the application code. The app must use the App Engine datastore, memcache or other services for all data that persists between requests. The Python 2.7 environment allows bytecode to be read, written, and modified.
  • Application code only runs in response to a web request, a queued task, or a scheduled task, and must return response data within 60 seconds in any case. A request handler cannot spawn a sub-process or execute code after the response has been sent.

The Go Runtime Environment

App Engine’s Go runtime environment provides a convenient way to implement and deploy web applications written in the Go Programming Language.

The Go runtime environment uses Go release r60.3. The SDK includes the Go compiler and standard library, so it has no additional dependencies. As with the Java and Python environments, not all the standard library’s functionality is available inside the sandbox. For example, attempts to open a socket or write to a file will return an os.EINVAL error.

The SDK includes an automated build service to compile your app, so you’ll never need to invoke the compiler yourself. And—as with the Python SDK—your app will be automatically re-built whenever you change the source. This keeps you productive by making the edit-compile-run cycle refreshingly short.

The Go environment provides idiomatic Go APIs for most of the App Engine services.

You can upload other third-party libraries with your application, as long as they are implmented in pure Go.

For more information about the Go runtime environment, see The Go Runtime Environment.

The Java Runtime Environment

You can develop your application for the Java runtime environment using common Java web development tools and API standards. Your app interacts with the environment using the Java Servlet standard, and can use common web application technologies such as JavaServer Pages (JSPs).

The Java runtime environment uses Java 6. The App Engine Java SDK supports developing apps using either Java 5 or 6.

The environment includes the Java SE Runtime Environment (JRE) 6 platform and libraries. The restrictions of the sandbox environment are implemented in the JVM. An app can use any JVM bytecode or library feature, as long as it does not exceed the sandbox restrictions. For instance, bytecode that attempts to open a socket or write to a file will throw a runtime exception.

Your app accesses most App Engine services using Java standard APIs. For the App Engine datastore, the Java SDK includes implementations of the Java Data Objects (JDO) andJava Persistence API (JPA) interfaces. Your app can use the JavaMail API to send email messages with the App Engine Mail service. The java.net HTTP APIs access the App Engine URL fetch service. App Engine also includes low-level APIs for its services to implement additional adapters, or to use directly from the application. See the documentation for the datastorememcacheURL fetchmailimages and Google Accounts APIs.

Typically, Java developers use the Java programming language and APIs to implement web applications for the JVM. With the use of JVM-compatible compilers or interpreters, you can also use other languages to develop web applications, such as JavaScript, Ruby, or Scala.

For more information about the Java runtime environment, see The Java Runtime Environment.

The Python Runtime Environment

With App Engine’s Python runtime environment, you can implement your app using the Python programming language, and run it on an optimized Python interpreter. App Engine includes rich APIs and tools for Python web application development, including a feature rich data modeling API, an easy-to-use web application framework, and tools for managing and accessing your app’s data. You can also take advantage of a wide variety of mature libraries and frameworks for Python web application development, such as Django.

The Python runtime environment uses Python version 2.5.2 by default. You can also choose the Python 2.7.2 runtime.

The Python environment includes the Python standard library. Of course, not all of the library’s features can run in the sandbox environment. For instance, a call to a method that attempts to open a socket or write to a file will raise an exception. For convenience, several modules in the standard library whose core features are not supported by the runtime environment have been disabled, and code that imports them will raise an error.

Application code written for the Python environment must be written exclusively in Python. Extensions written in the C language are not supported.

The Python environment provides rich Python APIs for the datastoreGoogle AccountsURL fetch, and email services. App Engine also provides a simple Python web application framework called webapp to make it easy to start building applications.

You can upload other third-party libraries with your application, as long as they are implemented in pure Python and do not require any unsupported standard library modules.

For more information about the Python runtime environment, see The Python Runtime Environment.

Storing Your Data

The App Engine environment provides a range of options for storing your data:

  • App Engine Datastore provides a NoSQL schemaless object datastore, with a query engine and atomic transactions.
  • Google Cloud SQL provides a relational SQL database service for your App Engine application, based on the familiar MySQL RDBMS.
  • Google Cloud Storage provides a storage service for objects and files up to terabytes in size, accessible from Python and Java applications.

The Datastore

App Engine provides a distributed NoSQL data storage service that features a query engine and transactions. Just as the distributed web server grows with your traffic, the distributed datastore grows with your data. You have the choice between two different data storage options differentiated by their availability and consistency guarantees.

The App Engine datastore is not like a traditional relational database. Data objects, or “entities,” have a kind and a set of properties. Queries can retrieve entities of a given kind filtered and sorted by the values of the properties. Property values can be of any of the supported property value types.

Datastore entities are “schemaless.” The structure of data entities is provided by and enforced by your application code. The Java JDO/JPA interfaces and the Python datastore interface include features for applying and enforcing structure within your app. Your app can also access the datastore directly to apply as much or as little structure as it needs.

The datastore provides ACID transactions using optimistic concurrency control. An update of a entity occurs in a transaction that is retried a fixed number of times if other processes are trying to update the same entity simultaneously. Your application can execute multiple datastore operations in a single transaction which either all succeed or all fail, ensuring the integrity of your data.

The datastore implements transactions across its distributed network using “entity groups.” A transaction manipulates entities within a single group. Entities of the same group are stored together for efficient execution of transactions. Your application can assign entities to groups when the entities are created.

Google Accounts

App Engine supports integrating an app with Google Accounts for user authentication. Your application can allow a user to sign in with a Google account, and access the email address and displayable name associated with the account. Using Google Accounts lets the user start using your application faster, because the user may not need to create a new account. It also saves you the effort of implementing a user account system just for your application.

If your application is running under Google Apps, it can use the same features with members of your organization and Google Apps accounts.

The Users API can also tell the application whether the current user is a registered administrator for the application. This makes it easy to implement admin-only areas of your site.

For more information about integrating with Google Accounts, see the Users API reference.

App Engine Services

App Engine provides a variety of services that enable you to perform common operations when managing your application. The following APIs are provided to access these services:

URL Fetch

Applications can access resources on the Internet, such as web services or other data, using App Engine’s URL fetch service. The URL fetch service retrieves web resources using the same high-speed Google infrastructure that retrieves web pages for many other Google products.

Mail

Applications can send email messages using App Engine’s mail service. The mail service uses Google infrastructure to send email messages.

Memcache

The Memcache service provides your application with a high performance in-memory key-value cache that is accessible by multiple instances of your application. Memcache is useful for data that does not need the persistence and transactional features of the datastore, such as temporary data or data copied from the datastore to the cache for high speed access.

Image Manipulation

The Image service lets your application manipulate images. With this API, you can resize, crop, rotate and flip images in JPEG and PNG formats.

Scheduled Tasks and Task Queues

An application can perform tasks outside of responding to web requests. Your application can perform these tasks on a schedule that you configure, such as on a daily or hourly basis. Or, the application can perform tasks added to a queue by the application itself, such as a background task created while handling a request.

Scheduled tasks are also known as “cron jobs,” handled by the Cron service. For more information on using the Cron service, see the Python or Java cron documentation.

Task queues keep track of tasks to handle in the background. The Python, Java, and Go runtime environments can use task queues. For information about the task queue service, see the Python API documentationthe Java API documentation or the the Go API documentation.

Development Workflow

The App Engine software development kits (SDKs) for Java, Python, and Go each include a web server application that emulates all of the App Engine services on your local computer. Each SDK includes all of the APIs and libraries available on App Engine. The web server also simulates the secure sandbox environment, including checks for attempts to access system resources disallowed in the App Engine runtime environment.

Each SDK also includes a tool to upload your application to App Engine. Once you have created your application’s code, static files and configuration files, you run the tool to upload the data. The tool prompts you for your Google account email address and password.

When you build a new major release of an application that is already running on App Engine, you can upload the new release as a new version. The old version will continue to serve users until you switch to the new version. You can test the new version on App Engine while the old version is still running.

The Java SDK runs on any platform with Java 5 or Java 6. The SDK is available as a Zip file. If you use the Eclipse development environment, you can use the Google Plugin for Eclipse to create, test and upload App Engine applications. The SDK also includes command-line tools for running the development server and uploading your app.

The Python SDK is implemented in pure Python, and runs on any platform with Python 2.5, including Windows, Mac OS X and Linux. The SDK is available as a Zip file, and installers are available for Windows and Mac OS X.

The Go SDK features an idiomatic, native Go API for using the App Engine services, and uses the same tools as the Python SDK (with some additional machinery for automatically compiling your Go apps). The Go SDK is stand-alone—you do not need to install Go separately—and is available as a Zip file for both Mac OS X and Linux (a Windows version will be available soon).

The Administration Console is the web-based interface for managing your applications running on App Engine. You can use it to create new applications, configure domain names, change which version of your application is live, examine access and error logs, and browse an application’s datastore.

Quotas and Limits

Not only is creating an App Engine application easy, it’s free! You can create an account and publish an application that people can use right away at no charge, and with no obligation. An application on a free account can use up to 1 GB of storage and up to 5 million page views a month. When you are ready for more, you can enable billing, set a maximum daily budget, and allocate your budget for each resource according to your needs.

You can register up to 10 applications per developer account.

Each app is allocated resources within limits, or “quotas.” A quota determines how much of a given resource an app can use during a calendar day. In the near future, you will be able to adjust some of these quotas by purchasing additional resources.

Some features impose limits unrelated to quotas to protect the stability of the system. For example, when an application is called to serve a web request, it must issue a response within 60 seconds. If the application takes too long, the process is terminated and the server returns an error code to the user. The request timeout is dynamic, and may be shortened if a request handler reaches its timeout frequently to conserve resources.

Attempts to subvert or abuse quotas, such as by operating applications on multiple accounts that work in tandem, are a violation of the Terms of Service, and could result in apps being disabled or accounts being closed.

For a list of quotas and an explanation of the quota system, including which quotas can be increased by enabling billing, see Quotas.

For More Information…

For more information about Google App Engine:

jQuery Mobile: Toolbars

[Fuente: http://jquerymobile.com/test/docs/toolbars/docs-bars.html]

Tipos de Toolbar

En jQuery Mobile, hay dos tipos de standars de toolbars: Cabeceras (Headers) y Pies (Footers).

  • La Header bar sirve como el título de la página, es generalemente el primer elemento dentro de cada página de una web de movilidad, y tipicamente contiene el título de la página y hasta dos botones.
  • El Footer bar es generalmente el ultimo elemento dentro de cada pagina de una web de movilidad, y tiende a estar más abierta en términos de contenidos y funcionalidad, pero tipicamente contiene una combinación de textos y botones.

Es muy común tener una barra de navegación horizontal o tab bar dentro del header o del footer; jQuery Mobile inclute el navbar widget que convierte un lista no-ordenada de links en una botonera horizontal, que funcione bien en estos casos.

Ver el  data- attribute reference para ver todas los posibles atributos que se pueden poner con las toolbars.

Opciones de posicionamiento de las Toolbar

Las headerss y los footers pueden ser posicionados en las páginas de varias formas distintas. Por defecto, las toolbars utilizan el modo de posicionamiento “inline”. En este modo, las headers y el footer se colocan en el flujo de documento natural (el comportamiento HTML por defecto), lo cual te asegura que van a ser visibles en todos los dispositivos, independientemente del código Js o CSS de posicionamiento que tenga.

El modo de posicionamiento “fixed” positioning mode fija las toolbars arriba o al fondo del viewport de los navegadores que soportan CSS fixed positioning (la mayoria de los browsers los incluyen). Las browsers que no lo soportan , las toolbars tendrán la posición static e inline de la página.

Cuando el tap-toggling esta activo, tapping la pantalla cambiará la visibilidad de las toolbars fixed. Tapping the page cuando las toolbars no están visibles las muestra de nuevo. Tapping otra vez las esconde. Esto le da a los usuarios la opción de esconder las toolbars hasta que las necesiten y maximizar los contenidos centrales de la pagina. Un inconveniente de las fixed toolbars es que nunca realmente se esconden, porque cambian entre modo de posicionamiento fixed y static. Esto quiere decir que si estas arriba de la pagina, no puedes esconder el header toolbar haciendo tap-toogle, porque lo que hace en su vez es cambiar a su punto en el documento en el top de la página. Lo mismo pasa con los fixed footers si estamos al fondo de la página.

Para obtener este comportamiento del header y el footer , añade el atributo  data-position="fixed" al elemento header o footer.

Un modo de posicionamiento “fullscreen” “fullscreen” position mode funciona como el modo fixed excepto que las toolbars solapan el contenido de la página, más que ocupar un espacio en el documento cuando no están en modo fixed. Esto es útil para apps de inmersión como son visores de fotos o videos donde quieres que el contenido rellene toda la pantalla y la toolbars puedan ser escondidas o invocadas a aparecer haciendo un toque (tapping) de la pantalla. Recuerda que las toolbars en este modo se pondrán sobre el contenido de la página asi que es mejor que sea utilizada en situaciones especificas.

Opencart: cómo esta estructurado, cómo añadir contenido al site

Introducción

OpenCart utiliza una arquitectura pseudo MVC. Puedes aprender más sobre MVC en Google, pero en OpenCart esta montado de la forma siguiente:

Hay dos “caras” del sistema OpenCart: “admin” & “catalog”. Está muy claro lo que hace cada una. Pero lo mejor sobr eesto, es que ambas tienen la misma estructura y funcionalidad. Hay también un conjunto de ficheros comunes que llamamos “library”. Los ficheros dentro del library son utilizados para crear las estructuras y variables globales necesarias para el resto del carrito de la compra, asi como funcionalidades básicas.

Para simplificar, en el siguiente ejemplo, trabajaremos del lado “catalog”.

Componentes MVC

Hay 3 partes principales en cada pantalla que se muestra:

1. Controlador

Este es el fichero core donde tienen lugar todos los calculos, queries de DB y magia diversa. Aqui es también son configuradas las variables para valores e idiomas que son pasadas a la variables de vista para que se muestren. Los ficheros del Controller están localizados en el directorio “controller” tanto en catalog como en admin, dependiendo de qué estes modificando.

2. Idioma

Aqui es donde los idiomas son configurados. Los ficheros de idioma utilizan una configuración del tipo ‘constant=value’. El nombre de la constante se utiliza en el código, y nunca cambia. Solo cambia el valor según el idioma. Por ejemplo:

ENGLISH: $_['text_review'] = 'Product Review';
SPANISH: $_['text_review'] = 'De Revisión de Producto';
GERMAN:  $_['text_review'] = 'Produkt Bewertung';

Observese que el lado izquierdo (constante) no cambia.

Los ficheros de idioma están alojados en el directorio “language”

3. Vista

Esto se refiere al template o ficheros tpl. Todas las variables que son pasadas desde el controlador a la vista pueden ser utilizadas para mostrar la salida de los cálculos o funcionalidad. Por ejemplo, si quieres mostrar el total del carrito de la compra, primero necesitas definirlo en el controlador y pasarlo como variable de vista. Algunos ejemplos:

$view = $this->locator->create('template');
set('entry_page', $language->get('entry_page'));
set('text_review_by', $language->get('text_review_by')); 

/* Sets a variable called "text_review_by" to the value pulled
from the language file for the constant matching that variable name */

Los fichero de vista están localizados en el directorio “template”.

Poniéndolo todo junto

La mayoría de los controladores tienen un nombre intuitivo para explicar lo que ellos representan:

product.php = the product page
cart.php = the cart page
home.php = the home page

Ellos también tienen nombres similares para sus ficheros de vista e idiomas correspondientes.

Ejemplo

Digamos que queremos añadir un nuevo mensaje a la página principal que diga “Jander CLander”

1.- Editamos el fichero controller:

EDIT: catalog/controller/home.php

Localizasmos una variable existente para utilizar la como guía (no inventemos la rueda).

FIND:

$view->set('text_latest', $language->get('text_latest'));

AFTER, ADD:

$view->set('text_jander', $language->get('text_jander'));

2.-Ahora insertamos el nuevo valor a nuestro fichero de idioma:

EDIT: catalog/language/english/controller/home.php

Nos servimos de guia de una existente:

$_['text_latest']   = 'Latest Products';

Añadimos

$_['text_jander']   = 'Happy Holidays to your family from www.MySite.com!';

3.- Finalmente , lo insertamos en el fichero de template:

EDIT: catalog/template/default/content/home.tpl

FIND:

<?php echo $text_greeting; ?>

AFTER, ADD:

<?php echo $text_jander; ?>

DONE!

Ya debes poder ver el nuevo mensaje en la home

Monedas sociales.Cooperativas integrales

Cooperativas Integrales

Propuesta de transición para construir un modelo de sociedad basado en la autogestión en todos los ámbitos de vida como forma de cubrir las necesidades básicas materiales e inmateriales de todas las personas.

Qué es la Cooperativa Integral

  • Es un espacio que nos permite construir un entramado de relaciones económicas autogestionadas fomentando las relaciones sociales solidarias, las ideas de colectividad y de autogestión
  • Es Integral porque junta todos los elementos básicos de una economía como son la producción, el consumo, la financiación y la moneda propia y, al mismo tiempo, porque quiere integrar todos los sectores de la actividad necesarios para vivir
  • Proyectos productivos autónomos y servicios públicos de interés común (espacios comunes, centrales de compras, etc.) manteniendo una relación de reciprocidad y solidaria.

Qué objetivos tiene

  • Crear un entramado de relaciones económicas cooperativas y solidarias entre personas y organizaciones sociales que salga de las reglas del mercado y que no sea controlado por el estado.
  • Desarrollar productos ecológicos y locales, servicios necesarios para nuestro día a día y nuevos proyectos vinculados a las necesidades reales.

Rechazamos el Euro como medio de intercambio

  • Es parcial y escaso: lo crean instituciones financieras privadas con fines lucrativos.
  • Se fundamenta sobre la deuda: se crea cuando los bancos otorgan créditos
  • Promueve la falta de honestidad y la corrupción
  • Se esfuma hacia los centros financieros y de poder
  • Destruye las economías locales y la comunidad, provocando una degeneración social y cultural
  • Fomenta la competitividad debido a su insuficiencia
  • La usura: el dinero para pagar los intereses del dinero deuda nunca se crea

Sistema económico integral

La economía como herramienta para generar redes de autosuficiencia

  • Desarrollar herramientas que faciliten las interrelaciones económicas.
  • Claves para construir un sistema económico integral de transición.

Economía financiera (euro)

  • Entendido como parte de este modelo en transición, utilizamos el euro para interactuar con el sistema económico capitalista
  • En los proyectos en transición necesitaremos inyecciones de euros para ponerlos en marcha.
  • Con estos objetivos surge dentro de la red de Cooperativa integral, una cooperativa de autofinanciamiento social en red (CASX), 1º estructura bancaria en forma de cooperativa de servicios financieros en España

Euros virtuales

El euro virtual trading es una aplicación del C.E.S para poder mover euros entre cuentas del C.E.S, este sistema permite mover % en euros sin tener que hacerse transacciones entre cuentas corrientes reales, con sus comisiones y con su funcionamiento privativo.

Moneda social (Trueque multirecíproco)

  • Las monedas libres, sociales o locales, sirven para asignar un valor a los bienes y servicios.
  • Restan hegemonía al capitalismo y podría sustituir progresivamente al euro
  • Comparten unos criterios éticos, ecológicos y sociales que permiten que todas las personas puedan interaccionar
  • Se entiende como una herramienta de transición, que inevitablemente convive con la economía capitalista
  • La moneda social en las cooperativas integrales suelen ser virtuales a través del C.E.S o en papel.

El trueque

  • Acción no-monetaria de intercambio de bienes, servicios y conocimientos.
  • Un acuerdo verbal directo entre ofertante y demandante que satisface las pretensiones de ambas partes en relación a la equidad del intercambio

Economía comunitaria (compartir y donaciones)

Puesta en común de los recursos para el disfrute colectivo de personas que interaccionan, funcionando bajo relaciones de afinidad y apoyo mutuo.

Conclusión

  • Es necesario asumir la relación con la economía capitalista como una relación en transición
  • Forma parte de un camino a recorrer para llegar a generar a largo plazo otra economía fuera de lo establecido
  • La profundización en la economía comunitaria, el trueque, las monedas sociales y movimiento de euros hacia proyectos autogestionados, tienen que entenderse como ejes complementarios de una misma estrategia de transición.