[Win8] JavaScript – Llamadas a servicio de datos externos “Cross-Domain”

Con la llegada del nuevo sistema operativo de Microsoft, se nos abre un inmenso abanico de posibilidades a los desarrolladores web que no podemos desaprovechar. Ya que podemos crear estas nuevas aplicaciones con HTML 5 y JavaScript para que corran de forma nativa en la nueva interfaz. De esta manera podremos reutilizar todos nuestros conocimientos y nuestra experiencia en realizar aplicaciones que podrán ser consumidas directamente por millones de usuarios potenciales gracias a la nueva tienda de Windows.

Lo primero que tenemos que tener claro es que las aplicaciones web pueden ejecutarse en dos contextos diferentes.

  1. El usuario puede abrir la aplicación web desde el navegador que más le guste como se ha realizado siempre. Y la aplicación se ejecutara en un entorno limitado donde no se podrá acceder a las nuevas Apis que ofrece el sistema “WinRT, WinJS”.

  2. El usuario ejecutara una aplicación de la App Store realizada con HTML y javascript, en este caso la aplicación se ejecutará de forma nativa y en un contexto local. Tenemos acceso a las Apis del sistema para disfrutar de todas las ventajas que nos ofrece Windows 8 accesible directamente desde nuestro código JavaScript.

Si ya tenemos claro estos dos escenarios, tendremos que adaptar un poco nuestras aplicaciones web para que funcionen correctamente como aplicación nativa en Windows8.

Por ejemplo si queremos consumir un servicio externo de datos “cross-domain” sin problemas, podemos utilizar la librería WinJS para hacer una llamada XmlHttpRequest de forma asíncrona y recuperar estos datos de una forma muy sencilla.

 WinJS.xhr({ url: "http://localhost:32999/api/values" }).then(
               function (response) {
                   var json = JSON.parse(response.responseText);
                   json.forEach(function (item) {
                       items.push(item);
            }
        );
 } );

Este ejemplo accede a un servicio WebApi que retorna una lista de datos en formato JSon, hay que destacar que está utilizando el patrón Promise para realizar la llamada de forma asíncrona como casi siempre que interactuemos con las Apis de Windows 8.

Los parámetros que acepta esta función son:

  • type: (opcional). Especifica el Verbo HTTP a utilizar GET, POST, HEAD “petición sin cuerpo de mensaje”. Por defecto la llamada es GET.
  • url: URL del servicio de Datos.
  • user: (opcional). String con el nombre de usuario para la autentificación.
  • password: (opcional). String con la contraseña para la autentificación.
  • headers: (opcional). Objeto cuyas propiedades se usan como nombres de encabezado y los valores de las propiedades se utilizan como valores de estas propiedades del encabezado.
  • data: (opcional). El objeto que se pasa como datos en la llamada.
  • customRequestInitializer: (opcional). Función para utilizar antes de lanzar la llamada XmlHttpRequest.

Un ejemplo de una llamada estableciendo un parámetro en la cabecera, para asegurarse que la respuesta no está cacheada.

WinJS.xhr({
    url: " http://localhost:1489/api/demo ",
    headers: {
        "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT"
    }
})
    .done(function complete(result) {
        ...
    });

Para más información sobre las propiedades que acepta la cabecera visitar HTTP Response Headers:

Y para finalizar veremos un ejemplo completo de una llamada a un servicio de datos enlazado a un ListView:

  1.  
    1. El origen de los datos que consulta al servicio: Un fichero Datos.js donde se especifica un espacio de nombres “Data” que utilizaremos más adelante para enlazar los datos con el control.

(function () {
    var items = new WinJS.Binding.List();

    WinJS.xhr({ url: "http://localhost:1489/api/demo" }).then(
               function (response) {
                   var json = JSON.parse(response.responseText);
                   json.forEach(function (item) {
                       items.push(item);
                   }
               );
               }
             );

    var publicMembers = { Modelos: items };

    WinJS.Namespace.define("Data", publicMembers);
})();

     2. Enlazamos los datos al control de lista de forma declarativa:

  <div id="lista"  data-win-control="WinJS.UI.ListView"  
             data-win-options="  {
                itemDataSource : Data.Modelos.dataSource,
                layout:{type: WinJS.UI.GridLayout}
         }" >
   </div>

xi1bz

Con este sencillo ejemplo podemos comprobar que sencillo es recuperar los datos de un origen externo sin tenernos que preocupar por el cross-posting ya que se ejecuta la llamada en el contexto local y además se enlaza los datos de forma declarativa con nuestro control HTML.

 

Cross-Posting: http://mrubino.net

JavaScript Visual Studio and TDD

La idea de esta entrada es demostrar lo fácil que puede ser trabajar usando TDD con JavaScript desde nuestro Visual Studio como cualquier otro proyecto de test que tengamos en nuestra solución.

Para este ejemplo utilizaré una aplicación ASP.NET MVC con QUnit el framework de test unitarios que utiliza JQuery y para lanzar los test utilizo directamente Resharper como cuando utilizo otros frameworks como NUnit, MSTest, etc. Debo aclarar que para Visual Studio hay un test runner que lo podéis descargar desde Chutzpah si no tenéis la oportunidad de utilizar Resharper que personalmente me encanta.

Tanto para instalar QUnit como Chutzpah podemos utilizar Nuget desde nuestro proyecto.

TDD

La idea es que necesitamos un Objeto cliente que le podamos especificar diferentes propiedades como puede ser el Nombre, dirección y además añadir sus pedidos.

Test 1

Siguiendo el desarrollo guiado por pruebas, lo primero que tenemos que hacer es una prueba donde intentaremos definir el nombre del cliente.

Lo primero que necesito es poder crear un variable cliente para las pruebas y poderlo utilizar en todas las pruebas y comprobar que cumple con los requisitos. Para eso creo un contexto donde se agruparan todos los test y compartirán la variable cliente. Para esto utilizaré la función module de la librería QUnit.

 

01 ///<reference path="../qunit.js" />
02 module("Client TDD", {
03 setup: function () {
04 this.Client = new Client();
05 this.Client.Name = "Marc";
06 },
07 teardown: function () {
08 this.testData = null;
09 }
10 });

 

Esta función necesita primero el nombre del contexto y luego el objeto usado como el entorno del test. El objeto testEnvironment tiene una función setup que se lanza antes de cada test y podemos utilizar para crear las propiedades que necesitemos utilizar a lo largo de los múltiples test que utilicemos y un teardown que se ejecuta después de cada test que podemos utilizar para limpiar los datos.

Ahora si que podemos crear nuestro primer test.

 

1 test("Test Set Client Name", function () {
2 equal("Marc", this.Client.Name, "el nombre es Marc");
3 });

 

Esta primer test comprueba si el cliente contiene una Propiedad Nombre y si su valor es “Marc” para eso utilizaremos una comprobación de igualdad “equal”.

Yo como he comentado antes utilizaré Resharper para lanzar mis Test. El resultado del primer test tiene que ser negativo como no podía ser de otra manera utilizando TDD.

Resharper nos abrirá un el navegador con el QUnit Test Suite, además de mostrarnos el resultado en nuestro Visual Studio.

Los Errores son clarísimos no tenemos creado el objeto Cliente:

  1. Setup failed on Test Set Client Name: ‘Client’ no está definido.
  2. Died on test #2: No se puede obtener valor de la propiedad ‘Name’: el objeto es nulo o está sin definir.

Pues ahora nos toca implementar el objeto que la prueba necesita para ser pasada con éxito.

Utilizaré un nuevo fichero javascript donde tendré el código que utilizaré en la aplicación y crearé un objeto cliente utilizando el patrón module, con una parte privada y otra pública.

 

1 var Client = function () {
2 var _private = {};
3 var _public = {};
4 _public.Name = "";
5 return _public;
6 };

 

Tenemos que añadir la referencia al script del código en el fichero donde se encuentran los test y ya podemos relanzar la prueba.

 

1 ///<reference path="../qunit.js" />
2 ///<reference path="../Demo/Client.js" />
3 module("Client TDD", { . . .

 

Todo Verde !!! El objeto Cliente ya está cogiendo forma y todo guiados inicialmente por una prueba de lo que esperábamos que fuera.

Test 2

Siguiendo con la definición de nuestro objeto ahora queremos poder definir una propiedad dirección que será objeto un poco más complicado.

 

01 module("Client TDD", {
02 setup: function () {
03 this.Client = new Client();
04 this.Client.Name = 'Marc';
05 this.Client.Address = {
06 street: 'Gran Via',
07 state: 'Barcelona',
08 PostalCode: '08001' };
09 },
10 . . .

 

1 test("Test Set Address", function () {
2 equal({ street: "Gran Via", state: "Barcelona", PostalCode: "08001" },
3 this.Client.Address,
4 'The address is { street: "Gran Via", state: "Barcelona", PostalCode: "08001" }');
5 });

 

Como antes hasta que no añadamos esta propiedad al objeto cliente no pasará la prueba correctamente,

 

1 var _public = {};
2 _public.Name = "";
3 _public.Address = { street: "", state: "", PostalCode: "" };
4 return _public;

 

Pero el test vuelve a fallar !!!

El test falla porque estamos comparando dos objetos que aunque tengan todas las propiedades con el valor igual, son dos objetos diferentes. Par este caso no nos sirve un simple equal y tendremos que hacer una comparación más profunda que nos servirá para objetos y arrays con deeEqual.

 

1 test('Test Set Address', function () {
2 deepEqual({ street: 'Gran Via', state: 'Barcelona', PostalCode: '08001' },
3 this.Client.Address,
4 'The address is { street: "Gran Via", state: "Barcelona", PostalCode: "08001" }');
5 });

 

Test 3

Ahora nuestra intención es hacer un Get-Set y un Count de los pedidos del cliente.

 

01 test('Test Set.Get Orders', function () {
02 this.Client.Set_Order({ Id: "12345", Name: "Rent Car", Total: 237.45 });
03 expect(2);
04 deepEqual(
05 { Id: "12345", Name: "Rent Car", Total: 237.45 },
06 this.Client.Get_Order(1),
07 'The order is { Id: "12345", Name: "Rent Car", Total: 237.45 }');
08 strictEqual(2, this.Client.Orders(), 'The client have 2 orders');
09
10 });

 

Como siempre en TDD la primera prueba falla porque falta definir las funciones en el objeto cliente.

Ampliamos el objeto y pasamos la prueba:

 

1 _public.Set_Order = function (order) {
2 _private.Orders.push(order);
3 };
4 _public.Get_Order = function (index) { return _private.Orders[index]; };
5 _public.Orders = function () { return _private.Orders.length; };

 


Lo que hay que destacar de este test es que hemos definido dos pruebas en el mismo test con expect(2) y hemos hecho una comprobación estricta con resultado y tipo en el count con strictEqual.

Ya tenemos nuestro objeto completo y podríamos seguir con TDD por ejemplo haciendo alguna prueba asíncrona con asyncTest , pero si necesitáis más información sobre QUnit podéis consultar su documentación en http://docs.jquery.com/QUnit

Conclusión

Ya no tenemos excusa para no tener nuestro código JavaScript cubierto con pruebas unitarias garantizando la calidad y un código más mantenible. Con TDD podemos crear nuestros objetos javascript desde nuestros requerimientos y tener directamente garantizado su correcto funcionamiento a partir de nuetros requisitos y necesidades establecidas.

Cross-Posting: http://mrubino.net 

 

 

MVC Exportar Datos a .XLS “Excel Files”

Este truco es uno de los top10 en los foros de MSDN y sigue siendo una de aquellas cosas que no es fácil encontrar una documentación clara y adecuada.

Si hablamos desde la perspectiva de ASP.NET MVC esta tarea se nos simplifica muchísimo porque desde nuestro controlador podemos devolver directamente el contenido de un fichero como cualquier otro ActionResult que tengamos configurado. Para eso tenemos el método File que nos proporciona esa funcionalidad y no tenemos que utilizar directamente el objeto Response como nos pasaba con el clásico ASP.NET WebForms.

 

1 FileContentResult File(byte[] fileContents, string contentType)
2 FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName)
3 FileStreamResult File(Stream fileStream, string contentType)
4 FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName)
5 FilePathResult File(string fileName, string contentType)
6 FilePathResult File(string fileName, string contentType, string fileDownloadName)

 

Para este ejemplo utilizaré la sobrecarga que retorna un FileStreamResult porque lo que queremos hacer es:

Un servicio que recupere los datos de nuestro repositorio, serialice nuestra entidad del dominio en un XML directamente en memoria. Devuelva su contenido especificando que es un fichero Excel y el nombre del fichero que se utilizará para guardar.

Todo esto lo generará dinámicamente en memoria sin tener que tener el fichero Excel físicamente en nuestro servidor.

 

01 public ActionResult ObtenerMisEnviosXmlExcel()
02 {
03 _productosServices = new ProductosServices();
04 var stream = new MemoryStream();
05 var serialicer = new XmlSerializer(typeof(List));
06
07 //Cargo los datos
08 List datos = _productosServices.GetProductos();
09
10 //Lo transformo en un XML y lo guardo en memoria
11 serialicer.Serialize(stream, datos);
12 stream.Position = 0;
13
14 //devuelvo el XML de la memoria como un fichero .xls
15 return File(stream, "application/vnd.ms-excel", "Pedidos.xls");
16 }

 

Para poder serializar nuestra entidad del dominio utilizaremos la clase XmlSerializer que se encuentra en el namespace System.Xml.Serialization.

Cada vez que realicemos esta llamada nos devolverá el fichero Excel creado al vuelo con los datos recuperados de nuestro repositorio.

Una cosa que hay que tener en cuenta al realizar la serialización en XML, es que no es el formato estándar de Excel y tiene que abrir el fichero como datos XML. Eso implica que al abrir el fichero lance un par de avisos que son un poco incómodos más que otra cosa.

He estado probando diferentes librerías para crear ficheros Excel, pero todos te permiten montando el documento por programación, pero no montarlo automáticamente dependiendo de los datos cargados como es el caso del ejemplo anterior.

Si alguien conoce alguna librería que sea capaz de hacerlo directamente o tiene alguna experiencia parecida le invito a que la comparta para poder ampliar esta información y que nos sea de utilidad a todos.

Os recuerdo que también tenéis una entrada relacionada para generar un PDF al vuelo directamente desde una de nuestras vistas recuperando su HTML.

Cross-Posting: http://mrubino.net 

 

Webcat May en BCN !!!

Este miércoles 23 de Mayo se celebra en Barcelona el encuentro mensual que organiza el grupo WebCat «Barcelona web professionals». En estas reuniones se realizan micro sesiones de diferentes tipos y niveles pero con el punto en común que nos une a todos los que trabajamos en entornos orientados a la web.

Micro Sesiones:

Lugar 23 mayo de 7pm a 9pm en Providència, 88, Barcelona. Para más informaciñon http://lanyrd.com/2012/webcat-may
Nos Vemos 😉

How to: Insect Invaders

 Desde que asistí al Hack-a-thon de Fuengirola sobre Windows Phone, mi intención ha sido aprovechar la cuenta de suscriptor y publicar algún tipo de aplicación.

Le estuve dando muchas vueltas a que tipo de aplicación podría realizar, mi primera intención era hacer una brújula que apuntara a la Meca para que los musulmanes lo tuvieran más fácil a la hora de orientarse, pero mi sorpresa fue mayúscula cuando me di cuenta que ya habían un par de aplicaciones de este tipo y además una era de pago. A partir de ese momento entendí que cualquier idea que pudiera tener seguro que ya estaba publicado en el MarketPlace.

Pero no desistí en el intento y se me ocurrió hacer un juego en XNA, si tengo que empezar de cero a programar para Windows Phone que mejor que hacer un juego en XNA que no una aplicación con Silverligth que no me gusta nada.

Bueno ya tenía la base y ahora pensar en el juego. Ummm mi primer juego y sin tener ni idea de XNA no puede ser muy complicada de desarrollar. Que mejor que empezar con un clásico que no tiene muchas pantallas y que seguro no puede ser muy difícil de programar como es el Space Invaders.

Cuando tomas una decisión como la mía es ir a la página de Microsoft donde puedes encontrar los ejemplos de todo lo que necesitas para desarrollar tu aplicación.

La Base para el Juego:

  • Pantallas de la aplicación
    • Inicial
    • Juego Principal
    • Menú Pausa
    • Fin de Partida
  • Un fondo que no se tiene que animar
  • Una entidad Nave para el jugador principal
    • Movimiento de derecha a izquierda
    • Disparo “sonido de disparo”
    • Explosión para cuando es alcanzado y Sonido explosión
  • Una entidad Enemigo para crear todos los enemigos con esta base.
    • Movimiento de izquierda a derecha “pero en bloque”
    • Diferentes puntuaciones por tipo de enemigo
    • Disparo
    • Explosión al ser alcanzado y sonido
  • Diferentes niveles para hacer durar un poco el juego
  • Recursos para mostrar las vidas, puntuación y record

¿ Como una persona que nunca ha creado un juego, ni a programado en XNA puede salir exitoso de esta experiencia ?

Yo por ejemplo para mi primer contacto con el tema, miré el curso de un juego con XNA llamado Shootter.

 

Existe una página web sobre desarrollo en Windows Phone indispensable para todo aquel que quiera introducirse en este mundo con gran cantidad de ejemplos que podremos utilizar en nuestros desarrollo.

Pero tener cuidado no tengáis la tentación de publicar directamente el ejemplo de Microsoft como si fuera vuestro que ya no seríais los primeros XD.

Después de esta experiencia que realmente he aprendido mucho he decidido pasar el juego a HTML5 y JavaScript para poderlo utilizar en diferentes plataformas, ya os informaré como me va y si la experiencia es igualmente positiva “seguro que si”.

No os olvidéis de descargar y probar mi juego 😉

http://www.windowsphone.com/es-ES/apps/c2b100ff-45d8-4972-9d33-8bcbc2f148ba

[Evento] We ♥ JavaScript 2!

El sábado que viene día 28 de Abril, se celebra en Barcelona un encuentro de los profesionales en desarrollo web que apreciamos lo que significa javascript, lo hemos sufrido como todo el mundo, pero también sabemos valorar todo lo que nos aporta. Este evento es organizado por Agile-Barcelona, Runroom y Softonic, un evento de mañana y tarde .

Agenda

10:00 – 11:00 APRETURA – RECEPCIÓN
11:00 – 11:30 Charla sobre CoffeeScript
12:00 – 12:30 Networking
12:30 – 13:30 Charla sobre Game Development
13:30 – 15:00 COMIDA (cortesía de Softonic)
15:00 – 18:00 Workshop Backbone.js
15:00 – 18:00 Workshop PhoneGap.js

* Importante: Los workshops son en paralelo, de modo que te rogamos que únicamente saques ticket en uno de los dos.

Si tenéis pensado asistir daros prisa que solo quedan pocas plazas, yo ya me he registrado 😉

http://welovejs.es

 

Microsoft MVP ASP.NET/IIS 2012

Segundo año consecutivo que he recibido la grata noticia desde Microsoft que he sido nombrado nuevamente Microsoft MVP en ASP.NET / IIS para este 2012.

Enhorabuena. Nos complace presentarle el programa de nombramiento MVP de Microsoft® de 2012. Este nombramiento se concede a los líderes excepcionales de la comunidad técnica que comparten de forma activa su experiencia de alta calidad y de la vida real con otras personas. Le agradecemos especialmente la contribución que ha realizado en las comunidades técnicas en el área de ASP.NET/IIS a lo largo del pasado año.

La verdad que es una experiencia inolvidable poder participar en esta comunidad y que se te valore por ello, pero lo más importante y con lo que realmente me quedo es con las personas que he conocido durante todos estos años y que me han ayudado siempre que lo he necesitado y nunca me ha faltado su apoyo. Si los tuviera que nombrar a todos seguramente me dejaría a alguno, pero desde aquí si que me gustaría nombrar a dos personas muy activas en la comunidad que este año se han quedado sin reconocimiento por parte de Microsoft, pero estoy seguro y conociendolos muy bien, sé que ellos seguirán aportando y ayudando a todo el mundo que lo necesite y seran nuevamente nombrados MVP. Un saludo muy fuerte para Toni Recio y José Miguel Torres.

Espero poder seguir aportando mi granito de arena y agradecer a Microsoft este reconocimiento.

 

Cross-Posting: http://mrubino.net/ 

 

 

Exprime la potencia asíncrona en IIS

Una aplicación ASP.NET sobre IIS escala muy bien y tiene muy buen resultado cuando hablamos de peticiones por segundo, pero la cosa puede mejorar cuando hablamos de conexiones concurrentes.

Teniendo en cuenta que cada vez más nuestras aplicaciones son asíncronas, está aumentando la cantidad de peticiones que nuestra aplicación tiene que soportar .

Por defecto ASP.NET 4.o acepta 5.000 peticiones concurrentes por CPU

Peticiones concurrentes por CPU:

Una aplicación ASP.NET en modo integrado bajo IIS7 nos permite configurar cómo administrar los subprocesos y como poner en cola las solicitudes cuando la aplicación está hospedada en un grupo de aplicaciones de IIS.

Los valores applicationPool se aplican a todos los grupos de aplicaciones que se ejecutan en una versión determinada de .NET Framework. La configuración está contenida en un archivo aspnet.config. Hay una versión de este archivo para las versiones 2.0 y 4 de .NET Framework. (Las versiones 3.0 y 3.5 de .NET Framework comparten el archivo aspnet.config con la versión 2.0.)

  • maxConcurrentRequestPerCPU: Especifica cuántas solicitudes simultáneas permite ASP.NET por CPU.
  • maxConcurrentThreadsPerCPU: Especifica cuántos subprocesos simultáneos se pueden estar ejecutando para un grupo de aplicaciones para cada CPU. Esto proporciona una manera alternativa de controlar la simultaneidad de ASP.NET, ya que puede limitar el número de subprocesos administrados que se pueden usar por CPU para atender las solicitudes. De forma predeterminada este valor es 0, lo que significa que ASP.NET no limita el número de subprocesos que se pueden crear por CPU, aunque el grupo de subprocesos de CLR también limita el número de subprocesos que se pueden crear.
  • requestQueueLimit: Especifica el número máximo de solicitudes que se pueden poner en cola para ASP.NET en un único proceso. Cuando dos o más aplicaciones ASP.NET se ejecutan en un único grupo de aplicaciones, el conjunto acumulativo de solicitudes que se realizan a cualquier aplicación del grupo de aplicaciones está sujeto a este valor.

Para configurar nuestra aplicación que trabaja con el framework 4.0 x64

  1. fichero de configuración :
    • %windir%Microsoft.NETFrameworkv4.0.30319aspnet.config
  2. Modificar el fichero 
1 <configuration>
2 <system.web>
3 <applicationPool maxConcurrentRequestsPerCPU="5000"
4 maxConcurrentThreadsPerCPU="0" requestQueueLimit="5000" />
5 </system.web>
6 </configuration>

 

Peticiones concurrentes por Aplicación:

Si lo que queremos es controlar la peticiones concurrentes por aplicación nos tendremos que ir a la configuración serverRuntime de nuestro servidor IIS.

  • appConcurrentRequestLimit: Especifica el número máximo de solicitudes que pueden poner en cola para una aplicación. El valor predeterminado es 5.000.

Modificamos la configuración del servidor:

  1. Abrimos el fichero de configuración:
    • %windir%System32inetsrvconfigapplicationHost.config
  2. Buscar el elemento serverRuntime
  3. Modificar la propiedad appConcurrentRequestLimitque por defecto son 5.000

 

1 <serverRuntime appConcurrentRequestLimit="250000" />

 

Además se puede controlar el tamaño de las cola que utiliza ASP.NET cuando se supera la cantidad de solicitudes por CPU estableciendo requestQueueLimit de processModel.

 

1 <processModel autoConfig="false" requestQueueLimit="250000" />

 

Con todas estas modificaciones podemos controlar mucho mejor el rendimiento de nuestra aplicación y potenciar la gran cantidad de peticiones que se verán incrementadas con el uso de peticiones asíncronas.

Cross-Posting: http://mrubino.net 

 

 

MVP Summit 2012

Por primera vez he podido asistir al evento anual que organiza Microsoft dedicado a los MVP de todo el mundo llamado MVP Summit 2012.

Miles de personas reunidas con un mismo objetivo y con la posibilidad de ver las instalaciones que tiene Microsoft en Redmond.

Mi experiencia a este aspecto es totalmente positiva, poder estar una semana con mis colegas y conocer a gente de todo el mundo y especialmente al grupo de Españoles + Andorra, con los que pasé muy buenos momentos. Poder conocer a los integrantes del equipo de producto es otra oportunidad que no se puede explicar.

Nos hablaron de las novedades que se han lanzados durante estos días sin realmente darnos ninguna noticia bomba y pudimos jugar con las nuevas betas a la vez que el resto del mundo.

Está claro que si Microsoft me vuelve a reconocer con el nombramiento MVP nuevamente, no dejaré de asistir a esta convocatoria porque realmente vale la pena.

Y como una imagen vale más que mil palabras…

Optimización Web Sprites CSS

La ventaja de utilizar sprites para nuestros efectos con imágenes, es que no tenemos que esperar a que las imágenes se carguen individualmente, ya que solo tendremos una imagen principal para obtener el mismo efecto.

Piensa la cantidad de descargas que tiene que efectuar el navegador para cada una de las pequeñas imágenes que normalmente utilizamos en nuestras webs. Si todas estas pequeñas descargas la disminuimos en una principal reduciremos el tiempo de descarga de la página de una manera considerable.

El ejemplo más utilizado sería los tres estados de un ratón “normal, al pasar por encima con el ratón y al presionar”. Si utilizas tres imágenes independientes el usuario l pasar el ratón por encima del botón puede experimentar un retardo al mostrar la nueva imagen porque el navegador la tiene que descargar. Pero si utilizamos sprite con CSS este efecto indeseado desaparece a la vez que optimizamos la descarga.

Ejemplo 1: Imágenes por separado.

Imagen 1

Imagen 2

Imagen 3

El CSS para dar efecto al botón.

 

01 .btnSinSprite
02 {
03 width: 211px;
04 height: 64px;
05 background: url(../../Content/btn1.png);
06 border: black solid 0px;
07 cursor: pointer;
08 }
09 .btnSinSprite:hover
10 {
11 background: url(../../Content/btn2.png);
12 }
13 .btnSinSprite:active
14 {
15 background: url(../../Content/btn3.png);
16 }

 

Ejemplo 2: Imagen en Sprite.

Imagen

El CSS para dar efecto al botón.

 

01 .btnConSprite
02 {
03 width: 211px;
04 height: 64px;
05 background: url(../../Content/btnS.png)0 0;
06 border: black solid 0px;
07 cursor: pointer;
08 }
09 .btnConSprite:hover
10 {
11 background: url(../../Content/btnS.png)0 135px;
12 }
13 .btnConSprite:active
14 {
15 background: url(../../Content/btnS.png)0 70px;
16 }

 

Lo importante de utilizar una sola imagen es poder posicionar el fondo mediante la posición x-y, y jugar con el tamaño . De esta manera se muestra la porción de la imagen que necesitamos en cada momento.

Como se puede observar con las imágenes individuales tenemos tres descargas de 3,3KB que han tardado 48ms y con una imagen tipo sprite tenemos solo una descarga de 8,19KB que se ha descargado en 15ms. Una buena mejora con un simple botón imaginaros si optimizamos todas nuestras imágenes de la página.

Ejemplo 1

Ejemplo 2

Con esto ya tenemos un pasito más para poder tener nuestra web un poco más optimizada y para que veáis que esto es una buena práctica os pongo la colección de iconos que utilizan los controles JQuery UI en sus temas.

Cross-Posting: http://mrubino.net