<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Los Tiempos Cambian</title>
	<atom:link href="http://www.lostiemposcambian.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lostiemposcambian.com/blog</link>
	<description>tech blog by nitsnets &#124; studios</description>
	<lastBuildDate>Tue, 14 May 2013 08:00:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Animaciones y transiciones con AngularJS</title>
		<link>http://www.lostiemposcambian.com/blog/javascript/animaciones-transiciones-angularjs/</link>
		<comments>http://www.lostiemposcambian.com/blog/javascript/animaciones-transiciones-angularjs/#comments</comments>
		<pubDate>Tue, 14 May 2013 07:59:47 +0000</pubDate>
		<dc:creator>danii</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[webapps]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=6875</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/javascript/animaciones-transiciones-angularjs"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/05/animaciones-transiciones-angularjs.jpg" alt="Animaciones y transciones con Angularjs" title="Animaciones y transciones con Angularjs" width="539" height="344" class="alignnone size-full wp-image-6899 border" /></a>

<p>A partir de la versión <strong>1.1.4 del framework</strong> (<a target="_blank" href="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/angular.min.js">descargar aquí del Google CDN</a>), <strong>AngularJS</strong> viene con soporte nativo para animaciones y transiciones gracias a la nueva directiva <strong>ng-animate</strong>. Os recomendamos encarecidamente echarle un vistazo al <a href="http://www.yearofmoo.com/2013/04/animation-in-angularjs.html">fantástico artículo en el blog yearofmoo</a> que nos explica cómo utilizar esta nueva y genial <em>feature</em> de AngularJS y nos proporciona un buen número de ejemplos.</p>

<p>Puesto que esta directiva es una novedad de esta versión, debemos consultar la <a href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngAnimate">documentación de ngAnimate en los docs de la versión 1.1.4</a> ya que en versiones anteriores no vamos a encontrar referencias a las animaciones.</p>]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/05/animaciones-transiciones-angularjs.jpg" alt="Animaciones y transciones con Angularjs" title="Animaciones y transciones con Angularjs" width="539" height="344" class="alignnone size-full wp-image-6899 border" /></p>
<p>A partir de la versión <strong>1.1.4 del framework</strong> (<a target="_blank" href="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/angular.min.js">descargar aquí del Google CDN</a>), <strong>AngularJS</strong> viene con soporte nativo para animaciones y transiciones gracias a la nueva directiva <strong>ng-animate</strong>. Os recomendamos encarecidamente echarle un vistazo al <a target="_blank" href="http://www.yearofmoo.com/2013/04/animation-in-angularjs.html">fantástico artículo en el blog yearofmoo</a> que nos explica cómo utilizar esta nueva y genial <em>feature</em> de AngularJS y nos proporciona un buen número de ejemplos.</p>
<p>Puesto que esta directiva es una novedad de esta versión, debemos consultar la <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngAnimate">documentación de ngAnimate en los docs de la versión 1.1.4</a> ya que en versiones anteriores no vamos a encontrar referencias a las animaciones.</p>
<h3><span style="color: #008998;">Demo: Creación y edición de Slides con animaciones y transiciones</span></h3>
<p>Para demostrar estas animaciones hemos preparado una pequeña <strong>aplicación de creación y edición de Slides en formato markdown en AngularJS</strong>, con transiciones de entrada y salida que además son dinámicas y dependientes del estado de la aplicación. Es decir, las animaciones de entrada y salida de las slides serán con dirección <em>izquierda-derecha</em> cuando nos movamos a una slide posterior, o <em>derecha->izquierda</em> si nos movemos a una slide posterior <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><a target="_blank" href="http://lostiemposcambian.com/blog/posts/angular-animacion-demo/"><br />
<img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/05/angular-js-animaciones-demo-app.png" alt="Demo app: AngularJS con animaciones" title="Demo app: AngularJS con animaciones" width="539" height="244" class="alignnone size-full wp-image-6899 border" /></a></p>
<p style="background-color: #f5f5f5; text-align: center; padding: 10px 10px 10px 10px;"><a href="http://lostiemposcambian.com/blog/posts/angular-animacion-demo/" target="_blank"><img title="ver demo" src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2012/03/bt_demo.jpg" alt="ver demo" width="262" height="32" /></a> <a href="https://github.com/danii-nebot/angular-animacion-demo/archive/master.zip"><img title="descarga código fuente de Github" src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2010/09/bt_download.jpg" alt="" width="232" height="32" /></a></p>
<h3><span style="color: #008998;"><em>ng directives</em></span></h3>
<p>Las animaciones en AngularJS se declaran mediante la <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngAnimate">directiva ngAnimate</a> y pueden asignarse a uno o varios <strong>eventos de animación</strong>. AngularJs actualmente soporta animaciones asignadas a los siguientes eventos:</p>
<ul>
<li><strong>hide</strong>: cuando un elemento del DOM pasa de visible a hidden,</li>
<li><strong>show</strong>: cuando un elemento del DOM pasa de hidden a visible,</li>
<li><strong>enter</strong>: cuando un elemento nuevo se añade al DOM,</li>
<li><strong>leave</strong>: cuando un elemento es eliminado o deja de estar en el DOMm</li>
<li><strong>move</strong>: cuando un elemento cambia de posición en el DOM.</li>
</ul>
<p>Cada una de las directivas que permite animciones va a poder asignar distintas animaciones a cada uno de estos eventos:</p>
<ul>
<li>La directiva <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngRepeat">ngRepeat</a> soporta los eventos <strong>enter</strong>, <strong>leave</strong> y <strong>move</strong>;</li>
<li><a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngInclude">ngInclude</a>, <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngSwitch">ngSwitch</a> y <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngView">ngView</a> soportan los eventos <strong>enter</strong> y <strong>leave</strong>;</li>
<li>y por último las direcivas <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngShow">ngShow</a> y <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngHide">ngHide</a> soportan los enventos <strong>show</strong> y <strong>hide</strong>, lógicamente.</li>
</ul>
<p>También podemos usar el servicio <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.$animator">$animator</a> para que nuestras directivas <em>custom</em> soporten animaciones asignadas a cualquiera de estos eventos.</p>
<h3><span style="color: #008998;">Transiciones CSS3 vs Animaciones JavaScript</span></h3>
<p>AngularJS nos ofrece la potencia de utilizar animaciones y transiciones definidas en <strong>CSS3</strong>, pero también podemos programarlas mediante <a target="_blank" href="http://jquery.com/">JQuery</a> o cualquier otro <strong>framework de animaciones en JavaScript</strong> que queramos.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/05/animaciones-transiciones-angularjs-css3.jpg" alt="Animaciones y transciones con Angularjs + CSS3" title="Animaciones y transciones con Angularjs + CSS3" width="539" height="317" class="alignnone size-full wp-image-6899 border" /></p>
<p>Las animaciones basadas en transiciones <strong>CSS3</strong> son mucho más sencillas de utilizar ya que simplemente hemos de declararlas en el CSS de nuestra app siguiendo la siguiente nomenclatura: <span class="sourcecode">nombreAnimacion-evento-setup</span> para definir la transition (no olvidarse de los malditos <em>vendor prefixes</em>!) y el estado inicial, y <span class="sourcecode">nombreAnimacion-evento-start</span> para definir el estado final. Por ejemplo en nuestra demo hemos definido la siguiente animación para la transición entre el estado de edición del slide activo, desde <span style="text-decoration:line-through;">alpha</span> <strong>opacidad  0</strong> a <strong>opacidad 1</strong> en 2/3 de segundo:</p>
<pre class="brush: css; title: ; notranslate">
/* ANIMATIONS */
.fade-show-setup {
  -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.66s;
  -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.66s;
  -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.66s;
  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.66s;

  opacity:0;
}
.fade-show-setup.fade-show-start {
  opacity:1;
}
</pre>
<p>Mientras que para animaciones mediante JavaScript utilizaremos una sintaxis más complicada, pero que obviamente nos ofrece mucha más potencia que CSS, ya que podemos recibir parámetros, operar con ellos y también acceder a servicios de Angular. Por ejemplo en nuestra demo hemos definido la siguiente animación de entrada, que tomará dirección <em>izquierda-derecha</em> o <em>derecha->izquierda</em> según un valor precalculado (que dependerá de la slide actual y a la que nos queremos mover):</p>
<pre class="brush: jscript; title: ; notranslate">
// Definimos animación enter
app.animation('animate-enter', ['$rootScope', function($rootScope) {
  return {
    setup : function(element) {

      // margin con respecto al tamaño de la ventana del navegador
      var margin = Math.max(100,($(window).width()-880)/2);

      // utilizamos rootScope para discernir offset a aplicar
      var px = ($rootScope.myAnimation==='fade-right')?'-'+margin+'px':margin+'px';

      jQuery(element).css({ 'opacity': 0, 'margin-left': px });

    },
    start : function(element, done) {
      // lanzar animacion
      jQuery(element).animate({
        'opacity' : 1, 'margin-left': 0
      }, function() {
        // llamar a done() cuando la animación termina
        done();
      });
    }
  };
}]);
</pre>
<h3><span style="color: #008998;">Secuenciación de Animaciones</span></h3>
<p>Uno de los pocos problemas que vemos es que actualmente, AngularJS no proporciona ninguna manera de <strong>secuenciar</strong> animaciones: si un elemento del DOM es sustituido por otro, los eventos <strong>enter</strong> y <strong>leave</strong> se dispararán simultáneamente. Esto puede presentar un problema, ya que nos parece una utilidad muy común el querer, por ejemplo, que la animación de <strong>enter</strong> del nuevo elemento se lance solo cuando el elemento reemplazado ha terminado su animación de <strong>leave</strong>, y no inmediatamente ya puede producirse un solapamiento entre ambas animaciones.</p>
<p>En la demo mostrada hemos <em>solventado</em> esto mediante un uso creativo del servicio <a target="_blank" href="http://code.angularjs.org/1.1.4/docs/api/ng.$timeout">$timeout</a> para simular esta secuenciación. Lo que hacemos es primero <strong>ocultar</strong> el elemento saliente y lanzar la animación asignada a <strong>hide</strong>, y cuando ésta ha terminado (gracias al <span class="sourcecode">$timeout</span>) se ejecutarán los cambios en el DOM que provocan que se disparen los eventos <strong>leave</strong> (que en este caso no tiene asignada ninguna animación ya que el elemento saliente ya está oculto) y <strong>enter</strong>.</p>
<pre class="brush: jscript; title: ; notranslate">
animateSwitchSlide = function (id) {

    // utilizamos rootScope para discernir qué animacion haremos
    $rootScope.myAnimation = (id &gt; $scope.slide.id)?'fade-left':'fade-right';

    $scope.hide=true;

    // transition tras timeout para dar timepo a la animación hide a finalizar
    $timeout( function(){ $location.path('/slides/'+id); }, 550 );
  };
</pre>
<h3><span style="color: #008998;">Conclusión</span></h3>
<p>Nos parece un paso adelante muy importante y un signo de madurez del framework AngularJS el empezar a soportar de forma <strong>nativa, sencilla e intuitiva</strong> una característica como las animaciones, que puede no ser una funcionalidad básica pero nos da mucho juego para <strong>vestir</strong> y enriquecer visualmente nuestra Webapp.</p>
<p>Además gracias al esquema de <em>directivas ng</em> y <em>eventos</em> utilizado, es realmente sencillo <strong>upgradear una aplicación ya terminada</strong> para utilizarlas, ya que simplemente hay que definir las transiciones que queremos y aplicar la directiva <em>ng-animate</em> donde sea necesario, sin necesidad de modificar ni una línea de código. Esto será clave también conforme se consolide el soporte para animaciones con nuevos eventos, funcionalidades y directivas soportadas.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/javascript/animaciones-transiciones-angularjs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mejorando la velocidad de carga de nuestra web con Google PageSpeed Insights</title>
		<link>http://www.lostiemposcambian.com/blog/web-2-0/mejorando-velocidad-carga-web-google-pagespeed-insights/</link>
		<comments>http://www.lostiemposcambian.com/blog/web-2-0/mejorando-velocidad-carga-web-google-pagespeed-insights/#comments</comments>
		<pubDate>Mon, 29 Apr 2013 11:01:04 +0000</pubDate>
		<dc:creator>danii</dc:creator>
				<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[chrome dev tools]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[pagespeed]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=6523</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/web-2-0/mejorando-velocidad-carga-web-google-pagespeed-insights"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/mejorando-velocidad-google-pageSpeed-insights.jpg" alt="Mejorando la velocidad de carga de nuestra página web con Google PageSpeed Insights" title="Mejorando la velocidad de carga de nuestra página web con Google PageSpeed Insights" width="539" height="364" class="alignnone size-full wp-image-6811 border" />
</a>

<p><a target="_blank" href="https://developers.google.com/speed/pagespeed/insights">PageSpeed Insights</a> es una herramienta de Google para analizar y evaluar la velocidad de carga de una páginas web y, lo más importante, además proporcionar una serie de utilísimas <strong>sugerencias</strong> y <strong>herramientas asociadas</strong> para mejorar esta velocidad de carga.</p>

<p>Para evaluar la carga de nuestra página web así como nuestra implementación, Page Insights se basa en  este documento de <a target="_blank" href="https://developers.google.com/speed/docs/best-practices/rules_intro">buenas prácticas</a> que abarca tanto a nivel de front-end (carga de imágenes, archivos JavaScript, CSS, etc) como de configuración de servidor.</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/mejorando-velocidad-google-pageSpeed-insights.jpg" alt="Mejorando la velocidad de carga de nuestra página web con Google PageSpeed Insights" title="Mejorando la velocidad de carga de nuestra página web con Google PageSpeed Insights" width="539" height="364" class="alignnone size-full wp-image-6811 border" /></p>
<p><a target="_blank" href="https://developers.google.com/speed/pagespeed/insights">PageSpeed Insights</a> es una herramienta de Google para analizar y evaluar la velocidad de carga de una páginas web y, lo más importante, además proporcionar una serie de utilísimas <strong>sugerencias</strong> y <strong>herramientas asociadas</strong> para mejorar esta velocidad de carga.</p>
<p>Para evaluar la carga de nuestra página web así como nuestra implementación, Page Insights se basa en  este documento de <a target="_blank" href="https://developers.google.com/speed/docs/best-practices/rules_intro">buenas prácticas</a> que abarca tanto a nivel de front-end (carga de imágenes, archivos JavaScript, CSS, etc) como de configuración de servidor.</p>
<p>A grandes rasgos y sin entrar en muchos detalles podemos resumir los objetivos de estas buenas prácticas en principalmente los tres siguientes:</p>
<ul>
<li>Minimizar el número de peticiones HTTP que se producen,</li>
<li>Reducir el tamaño de las respuestas de estas peticiones HTTP,</li>
<li>y optimizar el renderizado de la página en el navegador.</li>
</ul>
<p>PageSpeed analizará nuestro webiste y nos asignará una <strong>puntuación</strong> o <strong>score</strong> sobre 100 que evalúa cuánto más rápida podría ser la carga de esta web. Un score muy alto y cercano a 100 indica que hay poco que mejorar (es decir, la página ya carga todo lo rápido que puede o cerca) mientras que un score bajo indica que hay bastantes mejoras que podríamos llevar a cabo. Es importante notar que esta puntuación o score es <strong>relativa</strong> a la página sobre la que estamos, es decir no viene en función del tiempo que tarda la página en cargar, si no en función de cuántas de las <strong>buenas prácticas</strong> antes comentadas hemos seguido e implementado.</p>
<p>Podemos utilizar PageInsight como <a target="_blank" href="https://developers.google.com/speed/pagespeed/insights">servicio online</a> introduciendo la URL de la página que queremos evaluar:</p>
<p><a target="_blank" href="https://developers.google.com/speed/pagespeed/insights"><br />
<img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/pagespeed-online.jpg" alt="PageSpeed online" title="PageSpeed online" width="539" height="178" class="alignnone size-full wp-image-6757 border" /><br />
</a></p>
<p>Y además está disponible una extensión open-source para <a target="_blank" href="http://code.google.com/chrome/devtools/docs/overview">Chrome Developer Tools</a> en el navegador Chrome y también para <a target="_blank" href="https://getfirebug.com/downloads/">Firebug</a> para aquellos que sigáis siendo fieles a Firefox. En este artículo nos vamos a basar en la <a target="_blank" href="https://developers.google.com/speed/docs/insights/using_chrome">extensión para <strong>Chrome Developer Tools</strong></a> en Mac, pero el funcionamiento es prácticamente idéntico en todas las versiones.</p>
<h3><span style="color: #008998;">Utilizando la extensión de Chrome Developer Tools</span></h3>
<p>Una vez instalada la extensión, con nuestra página web abierta en Chrome, primero abriremos Chrome Dev Tools:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/abriendo-developer-tools-chrome.jpg" alt="Abriendo Developer Tools Chrome" title="Abriendo Developer Tools Chrome" width="539" height="242" class="alignnone size-full wp-image-6758 border" /><br />
<em>Tools &ndash;> Developer Tools o Ctrl + Shift + I (en Mac: ⌥⌘I)</em></p>
<p>Y una vez abierta la interfaz veremos que aparece una nueva pestaña de PageSpeed dentro de la cual nos encontraremos un <em>call to action</em>:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/pagespeed-tab-chrome-devtools.jpg" alt="Tab de PageSpeed en Chrome Devtools" title="Tab de PageSpeed en Chrome Devtools" width="539" height="231" class="alignnone size-full wp-image-6762 border" /></p>
<p>Al hacer click en cualquiera de los botones rojos <span style="background-color:#DA4E37; color:white; padding:6px 6px; font-size:33%; font-weight:bold;" >ANALYZE</span> o <span style="background-color:#DA4E37; color:white; padding:6px 6px; font-size:33%;font-weight:bold;">START ANALYZING</span> se producirá una recarga de nuestra página y tras un breve lapso de tiempo de análisis se nos mostrarán los resultados del análisis, empezando por una puntuación <strong>PageSpeed Score</strong> que viene a evaluar las medidas que hemos implementado en nuestro sitio para mejorar la velocidad de carga.</p>
<h3><span style="color: #008998;">Puesta en práctica: Mejorando la velocidad de carga de <strong>lostiemposcambian.com</strong></span></h3>
<p>En el caso de la home de <strong>lostiemposcambian.com</strong> incialmente obtuvimos la siguiente evaluación:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/pagespeed-initial-score.jpg" alt="PageSpeed Score inicial de lostiemposcambian.com" title="PageSpeed Score inicial de lostiemposcambian.com" width="539" height="243" class="alignnone size-full wp-image-6781 border" /><br />
<em>PageSpeed Score inicial de <strong>lostiemposcambian.com</strong>: 86 (de un total de100)</em></p>
<p>Una puntuación de <strong>86 puntos de 100</strong> posibles no está nada mal, pero evidentemente tenemos bastantes cosas que mejorar.</p>
<p>Por suerte, en el área izquierda nos aparece una <strong>lista de sugerencias</strong> que el plugin nos ofrece para mejorar la velocidad de carga. Estas sugerencias nos aparecen categorizadas en 3 colores: rojo amarillo y azul según las considere <strong>High Priority</strong>, <strong>Medium Priority</strong> y <strong>Low Priority</strong> respectivamente. Además, en cada sugerencia individual obtenemos detalles de cómo podemos implementarla en el caso particular de nuestra página web.</p>
<p>Obviamente debemos intentar aplicar primero las sugerencias marcadas como <strong>High Priority</strong> en rojo ya que son los que representan un mayor impacto en la velocidad de carga. También aparecen en verde y menos destacados aquellas buenas prácticas que ya tenemos correctamente implementadas.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/overview-issues-pagespeed.jpg" alt="Overview de las sugerencias de PageSpeed" title="Overview de las sugerencias de PageSpeed" width="539" height="288" class="alignnone size-full wp-image-6786 border" /><br />
<em>En el panel izquierdo PageSpeed Insights nos da sugerencias de cómo podemos mejorar la velocidad de carga de nuestra web</em></p>
<p>Vamos a analizar algunas de estas sugerencias y <strong>cómo implementarlas en nuestra página</strong> tomando como ejemplo nuestro caso en <strong>lostiemposcambian.com</strong>, haciendo por supuesto especial hincapié en las de mayor prioridad pero también fijándonos en las más sencillas y que con poco esfuerzo pueden producir mejoras inmediatas en la velocidad de carga de una web.</p>
<h3><span style="color: #008998;">High Priority</span></h3>
<ul>
<li><span style="color: #008998;"><strong>Aprovechar la <em>caché</em> del navegador</strong></span>
<p>Es conveniente evitar que el navegador realice peticiones para recursos estáticos (como por ejemplo imágenes) que ya tiene descargas de visitas anteriores (lo que se conoce como <em>en caché</em>). Es fundamental por tanto añadir valores para los atributos <strong>expiry date</strong> o <strong>maximum age</strong> en la cabecera HTTP de la respuesta para estos elementos a valores con cierta lejanía en el futuro para indicar al navegador que utilice la versión <em>cacheada</em> si la tiene.</p>
</li>
<li><span style="color: #008998;"><strong>Activar Keep-Alive</strong></span>
<p><a target="_blank" href="http://abdussamad.com/archives/169-Apache-optimization:-KeepAlive-On-or-Off.html">Keep-Alive</a> es una fantástica <em>feature</em> de los servidores Apache que permite a servidor y cliente negociar una única petición HTTP para transferir varios recursos, en vez de abrir una nueva petición por recurso. Es fácil ver que esto congenia muy bien con nuestro objetivo de minimizar el número de peticiones HTTP.</p>
<p>Puesto que estas la sugerencia sugerencia anterior y esta son de <strong>configuración de servidor</strong>, en caso de utilizar un <strong>servidor Apache</strong> podemos configurarlas modificando el archivo <span class="sourcecode">.htaccess</span> de nuestra página web. Por ejemplo, estas son las directivas que hemos añadido al <span class="sourcecode">.htaccess</span> de lostiemposcambian.com en el servidor para implementar ambas funcionalidades sugeridas:</p>
<pre class="brush: bash; title: ; notranslate">
&lt;IfModule mod_expires.c&gt;
  ExpiresActive on

# Perhaps better to whitelist expires rules? Perhaps.
  ExpiresDefault                          &quot;access plus 1 month&quot;

# cache.appcache needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
  ExpiresByType text/cache-manifest       &quot;access plus 0 seconds&quot;

# your document html
  ExpiresByType text/html                 &quot;access plus 0 seconds&quot;

# data
  ExpiresByType text/xml                  &quot;access plus 0 seconds&quot;
  ExpiresByType application/xml           &quot;access plus 0 seconds&quot;
  ExpiresByType application/json          &quot;access plus 0 seconds&quot;

# rss feed
  ExpiresByType application/rss+xml       &quot;access plus 1 hour&quot;

# favicon (cannot be renamed)
  ExpiresByType image/x-icon              &quot;access plus 1 month&quot; 

# media: images, video, audio
  ExpiresByType image/gif                 &quot;access plus 3 months&quot;
  ExpiresByType image/png                 &quot;access plus 3 months&quot;
  ExpiresByType image/jpg                 &quot;access plus 3 months&quot;
  ExpiresByType image/jpeg                &quot;access plus 3 months&quot;
  ExpiresByType video/ogg                 &quot;access plus 3 months&quot;
  ExpiresByType audio/ogg                 &quot;access plus 3 months&quot;
  ExpiresByType video/mp4                 &quot;access plus 3 months&quot;
  ExpiresByType video/webm                &quot;access plus 3 months&quot;

# htc files  (css3pie)
  ExpiresByType text/x-component          &quot;access plus 1 month&quot;

# webfonts
  ExpiresByType font/truetype             &quot;access plus 1 month&quot;
  ExpiresByType font/opentype             &quot;access plus 1 month&quot;
  ExpiresByType application/x-font-woff   &quot;access plus 1 month&quot;
  ExpiresByType image/svg+xml             &quot;access plus 1 month&quot;
  ExpiresByType application/vnd.ms-fontobject &quot;access plus 1 month&quot;

# css and javascript
  ExpiresByType text/css                  &quot;access plus 2 months&quot;
  ExpiresByType application/javascript    &quot;access plus 2 months&quot;
  ExpiresByType text/javascript           &quot;access plus 2 months&quot;

  &lt;IfModule mod_headers.c&gt;
    Header append Cache-Control &quot;public&quot;
    Header set Connection keep-alive
  &lt;/IfModule&gt;

&lt;/IfModule&gt;
</pre>
</li>
</ul>
<h3><span style="color: #008998;">Medium Priority</span></h3>
<ul>
<li><span style="color: #008998;"><strong>Combinar imágenes en Sprites CSS</strong></span>
<p>Tambien podemos ahorrar peticiones al servidor si en vez de cargar las imágenes utilizadas en nuestro CSS como <span class="sourcecode">background</span> de una en una las combinamos en una <a target="_blank" href="http://www.w3schools.com/css/css_image_sprites.asp">Image Sprite</a> y posteriormente mostramos la parte correspondiente mediante un reposicionamiento por código CSS. Esta técnica no es aplicable a todas las imágenes y va a depender cómo está montada la estructura del CSS, de si estas imágenes se repiten en horizontal o vertical, si el contenedor de la imagen será siempre del mismo tamaño o dependerá de su contenido, etc.</p>
<p>Por suerte en nuestro caso de <strong>lostiempocambian.com</strong> contábamos con el inestimable apoyo de la gran <a target="_blank" href="https://twitter.com/elisabetpadilla">Eli Padilla</a>, maestra de todas las cosas CSS <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  y conseguimos agrupar cuatro de las pequeñas imágenes background que PageSpeed nos indicaba que se cargaban de forma individual y las encajamos en una Spritesheet así:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/sprite-image-css.png" alt="Sprite Image para usar en CSS" title="Sprite Image para usar en CSS" width="510" height="234" class="alignnone size-full wp-image-6791 border" /><br />
<em>Ejemplo de Spritesheet con fondo transparente y los elementos combinados: estados on y off del botón de buscar y bullet points de los listados en el footer y en el cuerpo de cada post respectivamente.</em></p>
<p>El caso del botón con estado <em>on/off</em> es un ejemplo de libro para esta técnica sin demasiadas complicaciones. Para los bullets de los elementos <span class="sourcecode">&lt;li&gt;</span> de los listados teníamos la complicación de que el contenido podía tener diferentes alturas, de ahí el offset entre una y la otra en el spritesheet.</p>
<p>En cuanto a las modificaciones en el CSS, el código <strong>sin Image Sprite</strong> original era así:</p>
<pre class="brush: css; title: ; notranslate">

#footer-content ul li{background:transparent url('images/bg-footer-content-bullet.png') no-repeat 0px 5px;}

.page #main .entry ul li{background:url(images/ul_li.gif) no-repeat 10px 9px;}

#searchform .input_submit{background:url(images/buscar.gif) no-repeat center center;border:none;cursor:pointer;height:30px;margin:0px 0px 0px 5px;width:60px;}

#searchform .input_submit:hover{background:url(images/buscar_f2.gif) no-repeat center center;}
</pre>
<p>Y el código CSS <strong>con image Sprite</strong> quedaría así:</p>
<pre class="brush: css; title: ; notranslate">

#footer-content ul li{font-size:0.95em;line-height:1.2em;padding:0px 0px 7px 10px;background:transparent url('images/sprites.png') no-repeat 0px -39px;}

.page #main .entry ul li{background:url(images/sprites.png) no-repeat 10px -80px;}

#searchform .input_submit{background: url('images/sprites.png') no-repeat 0 -18px;border:none;cursor:pointer;height:16px;margin:0px 0px 0px 5px;width:60px;}

#searchform .input_submit:hover{background:url('images/sprites.png') no-repeat 0 0;}
</pre>
<p>Y ahora sí la única imagen que se carga en estas reglas CSS es <span class="sourcecode">images/sprites.png</span>, así que hemos reducido cuatro peticiones HTTP a una sola.  </p>
<p>Por supuesto, PageSpeed no tiene en cuenta la estructuración de nuestro CSS ni de nuestro contenido, así que sigue sugiriéndonos la posibilidad de combinar imágenes en un único Sprite aunque no tengamos forma de combinarlas o aunque no tengamos control sobre ellas ya que dependan de sitios externos como <strong>Twitter</strong>, <strong>Facebook</strong>, <strong>WordPress</strong> etc.
</li>
<li><span style="color: #008998;"><strong>Servir recursos desde una URL consistentes</strong></span>
<p>El problema que tenemos aquí es que estamos sirviendo exáctamente el mismo contenido estático, pero lo estamos cargado desde dos URLs distintas. Esto es un gran error, ya que el navegador debe realizar dos peticiones para un mismo recurso, es decir estamos realizando siempre <strong>una petición y una carga de datos de más</strong> y podríamos estar ahorrando nada menos que <strong>68.7KiB</strong>, un peso nada desdeñable.</p>
<p>Por desgracia para nosotros, estudiando las peticiones &ldquo;culpables&rdquo; vemos que son las siguientes:</p>
<ul>
<li><em><strong>http</strong>://platform.twitter.com/&hellip;/follow_button.1363148939.html</em> y:</li>
<li><em><strong>https</strong>://platform.twitter.com/&hellip;/follow_button.1363148939.html</em></li>
</ul>
<p>¡Parece ser que el culpable es el <em>follow button</em> del <strong>widget de Twitter</strong>! Algún programador en Twitter ha utilizado en un sitio <strong>http</strong> y en otro <strong>https</strong> y esta sugerencia va a caer en saco roto en este caso.</p>
</li>
</ul>
<h3><span style="color: #008998;">Low Priority</span></h3>
<p>Todos los puntos que vienen a continuación son menos críticos que los comentados anteriormente, pero muchos de ellos son muy fáciles de solucionar y por tanto merece la pena estudiarlos. ¡Cada granito de arena cuenta!</p>
<ul>
<li><span style="color: #008998;"><strong>Optimizar imágenes</strong></span>
<p>PageSpeed nos analiza si las imágenes que estamos sirviendo están bien optimizadas y nos avisará de cuáles podrían comprimirse para pesar menos, con <a target="_blank" href="http://en.wikipedia.org/wiki/Lossless_compression">lossless compression</a> obviamente para no perder ni un ápice de calidad.
</p>
<p>Una ventaja de utilizar la extensión de <strong>Chrome Dev Tools</strong> en vez del servicio online es que además, en caso de poder optimizarse la imagen nos la comprime el propio PageSpeed y nos la ofrece para descarga (está un poco escondida, la podemos encontrar bajo en link <strong>see optimized content</strong>) . Aunque existen programas y aplicaciones web para esto, PageSpeed es realmente cómodo ya que identifica la imagen <em>infractora</em> y en el mismo momento nos la ofrece ya optimizada sin necesidad de ninguna acción adicional por nuestra parte.</p>
<p>Tras optimizar todas las imágenes del front de lostiemposcambian.com, nos encontramos con que algunas de ellas escapan otra vez a nuestro control ya que dependen de <strong>WordPress</strong> o <strong>Twitter</strong>.</p>
</li>
<li><span style="color: #008998;"><strong>Minimizar archivos CSSs y JavaScript</strong></span>
<p>Deberíamos siempre minimizar nuestros archivos CSSs y JavaScripts en producción para que ocupen lo menos posible. Al igual que hemos visto con las imágenes, en el caso de que nuestros ficheros CSSs y JavaScript puedan minimizarse, PageSpeed nos ofrece para descarga un fichero minimizado para sustituir en producción. Genial! <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</li>
<li><span style="color: #008998;"><strong> Meter <em>inline</em> fragmentos pequeños de  CSS / JavaScript en vez de en archivos externos</strong></span>
<p>Cada fichero adicional representa una petición HTTP más. Para archivos muy pequeños, el coste de hacer esta petición adicional es prohibitivo en relación a su peso y por tanto deberíamos incluirlos <em>inline</em> en otros CSS o JavaScript o tal vez incluso en el mismo archivo HTML. Al igual que las anteriores, no siempre va a depender totalmente de nosotros (<strong>WordPress</strong>, te estoy mirando a ti!)</p>
</li>
<li><span style="color: #008998;"><strong>Evitar bad requests</strong></span>
<p>Por supuesto una petición que acaba en un HTTP Status de la familia <strong>4xx</strong> (error de cliente) es una petición desperdiciada. El más común suele ser el <strong>404 (<em>resource</em> no encontrado)</strong> y si tenemos alguna o varias de éstas es conveniente arreglarlas manualmente, quitándolas o corrigiéndolas.</p>
</li>
<li><span style="color: #008998;"><strong>Especificar las dimensiones de las imágenes en el HTML</strong></span>
<p>Siempre hemos de especificar las dimensiones de las imágenes en la etiqueta <img> mediante los atributos width y height. Esto es debido a que en caso contrario el navegador no conocerá estas dimensiones hasta que la imagen sea cargada, y por tanto hará dos pasadas para renderizar el contenido de la página: una antes de cargar la imagen y otra después, ya que el <em>layout</em> puede cambiar completamente en función de el tamaño de la imagen.</p>
<p>Si en algún caso por omisión o error humano no tenemos estos atributos, PageSpeed se encarga de indicarnos dónde debemos añadirlos y cuáles deben ser sus valores, para mayor comodidad.</p>
</li>
<li><span style="color: #008998;"><strong>Servir las imágenes al tamaño correcto</strong></span>
<p>Relacionado con el punto anterior, es importante servir nuestras imágenes al tamaño correcto, especificado por las dimensiones en el HTML, para no dejar al navegador la tarea de <strong>redimiensionar imágenes</strong>. Hemos de servir imágenes del tamaño al que se van a mostrar, ya que si no obligamos al motor de renderizado del navegador a realizar trabajo extra y además podemos estar cargando bytes de más innecesariamente si mostramos una imagen más pequeña de lo que es realmente.</p>
<p>En el caso de este blog, por <strong>error humano</strong> habíamos especificado algunas dimensiones mal y algunas imágenes estaban siendo redimiensionadas por el browser. Un error muy difícil de detectar sin utilizar PageSpeed ya que las imágenes incorrectas parecían estar bien a simple vista.</p>
</li>
</ul>
<p>
Una vez aplicados todos estos pasos, podemos comprobar que si ejecutamos otra vez el analizador PageSpeed Insights veremos que hemos pasado de un score inicial de 86 sobre 100 nuestro site <strong>lostiemposcambian.com</strong> pasa a un sobresaliente <strong>95 sobre 100</strong> para la home y rondando tambien rondando los 90-95 sobre 100 para los posts individuales. Gracias a la nueva configuración del servidor los visitantes recurrentes serán los más beneficiados, pero los nuevos visitantes también notarán una mejoría gracias a la reducción general del número de <em>HTTP requests</em> y de peso de muchos de los archivos cargados (imágenes optimizadas y archivos CSS y JavaScripts minimizados).
</p>
<p>En resumen, una herramienta magnífica y que recomendamos totalmente para desarrolladores web y también webmasters,  ya que nos puede ayudar a mejorar sensiblemente la velocidad de carga de nuestra página web. Estamos seguros de que los usuarios (en este caso vosotros, queridos lectores) nos agradecerán cada <strong>milisegundo</strong> y <strong>byte</strong> que consigamos arañar de las peticiones HTTP y los tiempos de carga de la página! <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/web-2-0/mejorando-velocidad-carga-web-google-pagespeed-insights/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Snippets de Gist: de la nube a Sublime</title>
		<link>http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-gist-nube-sublime/</link>
		<comments>http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-gist-nube-sublime/#comments</comments>
		<pubDate>Mon, 22 Apr 2013 09:25:41 +0000</pubDate>
		<dc:creator>danii</dc:creator>
				<category><![CDATA[editores de código]]></category>
		<category><![CDATA[gist]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[snippets]]></category>
		<category><![CDATA[sublime]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=6456</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-gist-nube-sublime/"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/snippets-nube-gist-sublime.jpg" alt="Snippets en Gist de la nube a Sublme Text" title="Snippets en Gist de la nube a Sublme Text" width="539" height="400" class="alignnone size-full wp-image-6579 border" /></a>

Una de las mejores características de <strong>Sublime Text 2</strong> es la posibilidad de añadir muy fácilmente funcionalidades gracias a los numerosos plugins creados por la comunidad.  Para recibir un montón de tips de utilización de Sublime y conocer un genial compendio de plugins excelentes para desarrollo web no puedo recomendar suficientemente este <strong>curso gratuito en Tuts+</strong>: <a target="_blank" href="https://tutsplus.com/course/improve-workflow-in-sublime-text-2/">Perfect Workflow in Sublime Text 2</a>. 

Cuidado porque a pesar de estar publicado en la segunda mitad de 2012, ya está un poco <strong>outdated</strong> en algunos puntos y la información de ciertos plugins de Sublime no es del todo exacta o es incompleta debido a que se han producido bastantes cambios y mejoras desde entonces. Éste es el caso con el <a target="_blank" href="https://github.com/condemil/Gist">plugin de Gist</a>, que vamos a comentar en este post y tiene algunas opciones muy interesantes que no existían cuando se grabó este <em>screencast</em>.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/snippets-nube-gist-sublime.jpg" alt="Snippets en Gist de la nube a Sublme Text" title="Snippets en Gist de la nube a Sublme Text" width="539" height="400" class="alignnone size-full wp-image-6579 border" /></p>
<p>Una de las mejores características de <strong>Sublime Text 2</strong> es la posibilidad de añadir muy fácilmente funcionalidades gracias a los numerosos plugins creados por la comunidad.  Para recibir un montón de tips de utilización de Sublime y conocer un genial compendio de plugins excelentes para desarrollo web no puedo recomendar suficientemente este <strong>curso gratuito en Tuts+</strong>: <a target="_blank" href="https://tutsplus.com/course/improve-workflow-in-sublime-text-2/">Perfect Workflow in Sublime Text 2</a>. </p>
<p>Cuidado porque a pesar de estar publicado en la segunda mitad de 2012, ya está un poco <strong>outdated</strong> en algunos puntos y la información de ciertos plugins de Sublime no es del todo exacta o es incompleta debido a que se han producido bastantes cambios y mejoras desde entonces. Éste es el caso con el <a target="_blank" href="https://github.com/condemil/Gist">plugin de Gist</a>, que vamos a comentar en este post y tiene algunas opciones muy interesantes que no existían cuando se grabó este <em>screencast</em>.</p>
<h3><span style="color: #008998;">Snippets de Código en la nube gracias a Gist</span></h3>
<p>Siguiendo con la temática de nuestro post sobre <a href="http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-codigo-sublime-text/">Snippets de código en Sublime</a>, vamos a comentar otra opción muy interesante que es la posibilidad que nos da Sublime de poder insertar Snippets desde <a href="http://gist.github.com/">Gist de Github</a> gracias al genial <a target="_blank" href="https://github.com/condemil/Gist">Plugin de Gist para Sublime</a>. Si tenemos una cuenta de Github automáticamente también tenemos acceso a una cuenta de Gist donde podemos almacenar y compartir Snippets. Al igual que muchos otros plugins y complementos, podemos instalar el plugin de Gist fácilmente en Sublime Text mediante <a target="_blank" href="http://wbond.net/sublime_packages/package_control">Package Control</a>.</p>
<p>Después de instalar el plugin, hemos de asociarlo a <strong>nuestra cuenta de Github</strong> (que es la misma que nos da acceso a <strong>Gist</strong>). Para ello, accedemos a la configuración del plugin (Preferences -> Package Settings -> Gist) y en el archivo de configuración del plugin (en <strong>formato JSON</strong>, al igual que todos los archivos de configuración de Sublime) tenemos la opción de especificar nuestro <strong>username + password</strong> o utilizar nuestro <strong>Github API token</strong>:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/configuracion-gist-sublime.jpg" alt="Configuración Gist en Sublime" title="Configuración Gist en Sublime" width="539" height="195" class="alignnone size-full wp-image-6683 border" /></p>
<p>Una vez el plugin está configurado, tendremos como siempre en Sublime dos maneras para utilizarlo:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/insert-gist-menu-herramientas.png" alt="Insertando Gist desde el menu de Herramientas" title="Insertando Gist desde el menu de Herramientas" width="539" height="148" class="alignnone size-full wp-image-6579 border" /><br />
<em>Abrimos el menú de Herramientas / Tools y la última opción será <strong>Gist</strong>, donde podremos además de insertar Gists de nuestra cuenta crear nuevos o modificar ya existentes.</em></p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/insert-gist-palette.png" alt="Insertando Gist desde la Paleta" title="Insertando Gist desde la Paleta" width="539" height="130" class="alignnone size-full wp-image-6579 border" /><br />
<em>Mediante la Paleta de Sublime no tenemos más que teclear &#8220;gist&#8221; y aparecerán las opciones de este plugin.</em></p>
<p>En ambos casos, al seleccionar <strong>Insert Gist</strong> nos encontraremos con un desplegable que muestra todos los Snippets que tengo guardados en mi <strong>cuenta de Gist</strong>, y al seleccionar uno de ellos se instalará en la posición actual del cursor.</p>
<h3><span style="color: #008998;">Filtrando nuestros Snippets de Gist</span></h3>
<p>Sin embargo, Gist muchas veces lo utilizamos para compartir de forma rápida un fragmento de código a través de internet, o quizás para insertarlo en <a href="http://wordpress.org/extend/plugins/embed-github-gist/">nuestro blog</a>. El caso es que no todos nuestros snippets de Gist los querremos reutilizar de forma regular cuando estemos programando. Por suerte, el plugin nos permite configurar en las preferencias dos opciones para filtrar los Snippets de mi cuenta de Gist que aparecerán en Sublime:</p>
<ul>
<li>Utilizando un prefijo que colocaremos delante de la <strong>descripción</strong> (no el nombre) del Snippet. Esta posibilidad está bien, pero a mí me gusta (tal y como se recomienda en el curso de Tuts+) utilizar prefijos para <strong>denotar el lenguaje de programación</strong> en el que está escrito el Snippet y así encontrar más facilmente el que buscamos a la hora de insertarlo en Sublime.</li>
<li>Mejor aún, podemos filtrar mediante una <strong>etiqueta</strong> o <strong>tag</strong>. El sistema de tags de Gist es tan simple como <strong>intuitivo y efectivo</strong>: cualquier palabra en la descripción que comience por el caracter &#8220;#&#8221; se considerará una etiqueta y podremos utilizarla para filtrar nuestros Snippets.</li>
<li>El plugin también nos da la opción de mostrar sólo aquellos Snippets marcados como &#8220;favoritos&#8221; (<em>starred</em>) opción que vemos menos interesante que las dos anteriores.</li>
</ul>
<p>Así por ejemplo, en mis snippets cualquiera con la etiqueta <strong>#sublime</strong> será el que podré insertar directamente desde el editor gracias al plugin. La genialidad de esto es que así podremos seguir utilizando Gist para <strong>compartir</strong> nuestros snippets de código a traves de Internet como siempre, y tan sólo los que etiquetemos para Sublime aparecerán en la lista dropdown de Sublime para ser insertados. Para esto, accederemos a la configuración del plugin (Preferences -> Package Settings -> Gist) y las últimas tres opciones de configuración serán <span class="sourcecode">&#8220;use_starred&#8221;</span>, <span class="sourcecode">&#8220;gst_prefix</span> y <span class="sourcecode">&#8220;gist_tag&#8221;</span>, como siempre en formato<strong> JSON</strong>.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/configuracion-filtrado-gist-sublime.jpg" alt="Configuración del Filtrado de Gist en Sublime" title="Configuración del Filtrado de Gist en Sublime" width="539" height="140" class="alignnone size-full wp-image-6688 border" /><br />
<em>Configuración del plugin para que filtre por la etiqueta #sublime, sin especificar prefijo</em></p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/gist-descripcion.png" alt="Descripcion Gist" title="Descripcion Gist" width="539" height="250" class="alignnone size-full wp-image-6579 border" /><br />
<em>Ejemplo de un Snippet en Gist con prefijo para denotar el lenguaje (CSS) y etiqueta #sublime para que el filtrado del plugin lo incluya</em></p>
<p>Además de poder acceder a nuestros propios Snippets, no olvidemos <strong>la parte social de Gist</strong>: cualquier Snippet que descubramos en Gist (ya sea por que nos topemos con él por casualidad en otro site, curioseando en la cuenta de algún desarrollador conocido o famosete o en la fantástica sección de <a target="_blank" href="https://gist.github.com/discover">discover Gists</a>) y que nos interese, podemos <em>forkearlo</em> y tan solo editando su descripción y añadiendo el prefijo o la etiqueta filtro, ya lo tendremos listo para ser insertado en Sublime sin necesidad de abrir navegador, ir a Gist, copiar/pegar, etc etc cada vez que queramos utilizarlo <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-gist-nube-sublime/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Snippets de código en Sublime Text 2</title>
		<link>http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-codigo-sublime-text/</link>
		<comments>http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-codigo-sublime-text/#comments</comments>
		<pubDate>Thu, 18 Apr 2013 10:19:36 +0000</pubDate>
		<dc:creator>danii</dc:creator>
				<category><![CDATA[editores de código]]></category>
		<category><![CDATA[snippets]]></category>
		<category><![CDATA[sublime]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=5686</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-codigo-sublime-text">
<img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/snippets-sublime-text.jpg" alt="Snippets en Sublime Text" title="Snippets en Sublime Text" width="539" height="110" class="alignnone size-full wp-image-452 border" /></a>

Vamos a empezar este post <em><strong>evangelizando</strong></em> un poco y <strong>recomendando fervientemente</strong> que si alguien no ha probado todavía <a target="_blank" href="http://www.sublimetext.com/"><strong>Sublime Text 2</strong></a> como editor de código, que se lance ya mismo. Es una auténtica maravilla lo potente, versátil y rápido que puede llegar a ser cuando lo empezamos a dominar, y lo mucho que puede acelerar nuestro <em>workflow</em>.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/snippets-sublime-text.jpg" alt="Snippets en Sublime Text" title="Snippets en Sublime Text" width="539" height="110" class="alignnone size-full wp-image-452 border" /></p>
<p>Vamos a empezar este post <em><strong>evangelizando</strong></em> un poco y <strong>recomendando fervientemente</strong> que si alguien no ha probado todavía <a target="_blank" href="http://www.sublimetext.com/"><strong>Sublime Text 2</strong></a> como editor de código, que se lance ya mismo. Es una auténtica maravilla lo potente, versátil y rápido que puede llegar a ser cuando lo empezamos a dominar, y lo mucho que puede acelerar nuestro <em>workflow</em>.</strong></p>
<p>¿Qué es un Snippet de código? Según la <a target="_blank" href="http://en.wikipedia.org/wiki/Snippet_(programming)">definición de la Wikipedia</a>:</p>
<blockquote><p><span class="bqstart">&#8220;</span>Un Spnippet es un término utilizado en programación para designar una <strong>pequeña región</strong> de código fuente, código máquina o texto plano <strong>reutilizable</strong>. Normalmente, son unidades operativas formalmente definidas que <strong>serán incorporadas</strong> en módulos programables más grandes.<span class="bqend">&#8221;</span></p></blockquote>
<p>Hemos resaltado las que consideramos partes claves de la definición, creemos que se puede resumir en que un Snippet es cualquier <strong>fragmento de código</strong> que reutilizaremos una y otra vez dentro de uno o varios proyectos.</p>
<p>Puesto que a ningún programador le gusta teclear una y otra vez lo mismo, es lógico que una de las <em>features</em> más importantes de un <strong>buen editor de código</strong> sea una buena gestión de Snippets que vaya más allá del típico autocompletar de los nombres de las funciones y palabras reservadas del lenguaje. </p>
<p>Por supuesto, <strong>Sublime Text</strong>, que marca un listón de excelencia para los editores de código, nos permite:</p>
<ul>
<li>Insertar Snippets ya existentes en nuestro código;</li>
<li>Importar Snippets ya creados por otros usuarios de Sublime como si de <em>plugins</em> se tratase;</li>
<li>Definir nuestros propios Snippets personalizados a nuestro gusto</li>
</ul>
<h3><span style="color: #008998;">Insertando Snippets ya existentes</span></h3>
<p>Sublime Text viene con algunos Snippets de uso común preinstalados. Para insertar un Snippet ya existente tenemos dos opciones:</p>
<ul>
<li>Hacer click en Herramientas/Tools y luego en Snippets o  </li>
<li>Sacamos la paleta (<strong>Shift + Command + P</strong> en Mac, en windows supongo que será Shift + Ctrl + P) y escribimos snippet para filtrar las demás opciones </li>
</ul>
<p>En ambos casos nos aparecerán todos los snippets que tenemos asociados al lenguaje de programación en el que estamos trabajando. Si no hemos añadido ninguno importado ni propio (ver siguientes secciones) estos serán los snippets preinstalados de Sublime, que suelen ser bastante útiles&#8230; pero puede no ser suficiente!</p>
<h3><span style="color: #008998;">Importando Snippets mediante Package Control</span></h3>
<p>Por supuesto cualquier persona que trabaje con, por ejemplo, <strong>jQuery</strong> va a necesitar aproximadamente los mismos Snippets. Por eso siempre es conveniente antes de crearnos nuestros propios Snippets para un lenguaje o herramienta el comprobar si ya existe un package de Snippets creado específicamente para esta herramienta. Para esto, podemos utilizar <a target="_blank" href="http://wbond.net/sublime_packages/package_control">Package Control</a> (un plugin de Sublime que es totalmente un <strong>MUST HAVE</strong>)  -> <strong>Instalar Package</strong> y buscarlos por nombre:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/install-snippets-package-control.png" alt="Instalando Snippets desde Package Control" title="Instalando Snippets desde Package Control" width="539" height="200" class="alignnone size-full wp-image-452 border" /><br />
<em>Instalando Snippets creados por otros usuarios desde Package Control</em></p>
<h3><span style="color: #008998;">Creando nuestros snippets</span></h3>
<p>Para crear un nuevo snippet, abrimos el menú de Herramientas/Tools y una de las últimas opción será la de <strong>crear un nuevo snippet</strong>. Un archivo Snippet de Sublime Text es un <strong>XML</strong> con diferentes nodos que son los que necesita Sublime para interpretar qué es lo que queremos hacer con ese snippet exactamente. A la hora de guardarlos tendremos que usar la extensión <strong><em>.sublime-snippet</em></strong> para que después Sublime los reconozca.</p>
<p>Si creamos muchos snippets es importante que los tengamos organizados, así que es interesante meter todos los snippets de un mismo lenguaje de programación en una misma carpeta. Si además a esa carpeta le llamamos con el mismo nombre que utiliza Sublime para identificar ese lenguaje, por ejemplo JavaScript, PHP o HTML, tendremos la ventaja añadida de que sin necesidad de especificar el <strong>scope del snippet</strong> quedará ya <strong>asociado automáticamente a dicho lenguaje.</strong>. Para abrir y editar nuestros snippets posteriormente, por defecto se guardarán en la carpeta <strong>Packages / User</strong>.</p>
<p>Al definir nuestro snippet, el nodo <span class="sourcecode">tabTrigger</span> es la &#8220;palabra de activación&#8221; que escribiremos y al presionar la tecla TAB se expandirá en nuestro snippet. Un detalle adicional: en el menu flotante de añadir snippet, además del tabTrigger se muestra en nombre del archivo donde hemos guardado el snippet, así que es interesante utilizar nombres concisos y sobre todo informativos de qué es lo que este snippet hace exactamente.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/insert-snippet-sublime.jpg" alt="Insertando Snippet desde la paleta de Sublime" title="Insertando Snippet desde la paleta de Sublime" width="539" height="140" class="alignnone size-full wp-image-452 border" /><br />
<em>Insertando Snippet desde la paleta de Sublime se aprecia la importancia del nombre de archivo y el tabTrigger</em></p>
<h3><span style="color: #008998;">Programando snippets</span></h3>
<p>En el nodo <span class="sourcecode">content</span> del XML meteremos el código del snippet en sí, utilizando la <a target="_blank" href="http://manual.macromates.com/en/snippets">sintaxis de textmate</a> para crearlo. Podemos definir <strong>stopPoints</strong> con el símbolo <span class="sourcecode">$</span>:</p>
<p><span class="sourcecode">$1, ${2:valor por defecto}, $3</span></p>
<p>y el orden relativo entre los índices que les asignemos a las stopPoints será el orden en el que el cursor se moverá de una zona a otra al pulsar la tecla tabulador. Lo bueno de los valores por defecto es que cuando nos movemos sobre ese <strong>stopPoint</strong>, se selecciona el valor por defecto entero, de forma que al pulsar cualquier tecla para seguir programando se sustituye automáticamente. Por ejemplo, este es el Snippet que utilizamos para crear una <strong>función Event Listener en ActionScript 3</strong>:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;snippet&gt;
	&lt;content&gt;&lt;![CDATA[
private function on${1:Click}(e:${2:Event}):void
{
  $3
}
]]&gt;&lt;/content&gt;
	&lt;tabTrigger&gt;eventl&lt;/tabTrigger&gt;
&lt;/snippet&gt;
</pre>
<p>Si mientras que estamos programando en AS3 tecleamos &#8220;eventl&#8221; y después pulsamos TAB, el Snippet anterior se insertará en nuestro código. A continuación, el cursor se colocará en el primer stop point, y cada vez que pulse TAB se moverá al siguiente. El código que se insertará será:</p>
<pre class="brush: as3; title: ; notranslate">
  private function onClick(e:Event):void
  {

  }
</pre>
<p>Y el cursor estará inicialmente seleccionando la palabra <span class="sourcecode">Click</span> de manera que si yo tecleo cualquier cosa la sobreescribiré automáticamente, al pulsar la tecla TAB el cursor saltará a <span class="sourcecode">Event</span> otra vez seleccionada para ser sobreescrita, y por último con el siguiente TAB saltará al cuerpo de la función, respetando la indentación.</p>
<p>La clave para mejorar y acelerar nuestro <em>workflow</em> gracias a los snippets es ser persistentes y forzarnos a utilizarlos de forma constante. ¡Esperemos que este post os ayude!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/editores-de-codigo/snippets-codigo-sublime-text/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conferencia AlicantePHP: Proyectos PHP de éxito en nitsnets &#124; studios</title>
		<link>http://www.lostiemposcambian.com/blog/php/conferencia-alicantephp-proyectos-php-de-exito-en-nitsnets-studios/</link>
		<comments>http://www.lostiemposcambian.com/blog/php/conferencia-alicantephp-proyectos-php-de-exito-en-nitsnets-studios/#comments</comments>
		<pubDate>Tue, 16 Apr 2013 10:20:46 +0000</pubDate>
		<dc:creator>elad</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[alicantephp]]></category>
		<category><![CDATA[nitsnets]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=6477</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/php/conferencia-alicantephp-proyectos-php-de-exito-en-nitsnets-studios"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/conferencia-alicantephp-casos-exito-php-nitsnets-studios-elad-rodriguez-transparencia.jpg" alt="Conferencia sobre Proyectos de éxito de PHP en nitsnets &#124; studios" title="Conferencia sobre Proyectos de éxito de PHP en nitsnets &#124; studios" width="539" height="404" class="alignnone size-full wp-image-452 border" /></a>

Ayer <strong>15 de abril</strong> tuvimos el honor de ser invitados a impartir una conferencia / charla entre el <a href="http://alicantephp.es/" target="_blank">nuevo grupo de usuarios de PHP en Alicante</a>. Eran las primeras jornadas que el grupo realizada y se <a href="http://alicantephp.es/primera-reunion-lunes-15-de-abril-a-las-1900/" target="_blank">impartieron dos conferencias</a>. Enhorabuena a <a href="https://twitter.com/raulfraile" target="_blank">Raúl Fraile</a> y <a href="https://twitter.com/manuelljb" target="_blank">Manuel L. Jurado</a> por crear este tipo de eventos <a href="https://twitter.com/search?q=%23alicantePHP&#038;src=hash" target="_blank">#alicantephp</a>.

En este post resumiremos un poco las jornadas y contaremos <strong>las utilidades PHP</strong> que se comentaron así como en qué proyectos fueron utilizadas.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/conferencia-alicantephp-casos-exito-php-nitsnets-studios-elad-rodriguez-transparencia.jpg" alt="Conferencia sobre Proyectos de éxito de PHP en nitsnets | studios" title="Conferencia sobre Proyectos de éxito de PHP en nitsnets | studios" width="539" height="404" class="alignnone size-full wp-image-452 border" /></p>
<p>Ayer <strong>15 de abril</strong> tuvimos el honor de ser invitados a impartir una conferencia / charla entre el <a href="http://alicantephp.es/" target="_blank">nuevo grupo de usuarios de PHP en Alicante</a>. Eran las primeras jornadas que el grupo realizada y se <a href="http://alicantephp.es/primera-reunion-lunes-15-de-abril-a-las-1900/" target="_blank">impartieron dos conferencias</a>. Enhorabuena a <a href="https://twitter.com/raulfraile" target="_blank">Raúl Fraile</a> y <a href="https://twitter.com/manuelljb" target="_blank">Manuel L. Jurado</a> por crear este tipo de eventos <a href="https://twitter.com/search?q=%23alicantePHP&#038;src=hash" target="_blank">#alicantephp</a>.</p>
<p>En este post resumiremos un poco las jornadas y contaremos <strong>las utilidades PHP</strong> que se comentaron así como en qué proyectos fueron utilizadas.</p>
<p>Las conferencias empezaron a las 19:00 en el <a href="http://thegreenbees.es/es" target="_blank">espacio de coworkers The Green Bees</a> con una pequeña introducción por parte de <a href="https://twitter.com/raulfraile" target="_blank">Raúl Fraile</a> al Grupo de usuarios de PHP en Alicante. La verdad es que la asistencia no estuvo mal para ser el primer evento, es más casi rozábamos el aforo completo!!!<br />
Fue una grata sorpresa encontrarme allí a parte de mi equipo (<a href="https://twitter.com/elisabetpadilla" target="_blank">Eli Padilla</a>, <a href="https://twitter.com/websmonerris" target="_blank">Pere Monerris</a> y Ramón Muñiz), a mi amigo <a href="https://twitter.com/perex" target="_blank">José Manuel Pérez</a> experto en PHP y compañero de trabajo en el <a href="http://www.proweb.ua.es" target="_blank">master de la Universidad de Alicante PROWEB</a> y a otra mucha gente conocida que habíamos coincidido en alguna oportunidad.</p>
<h3><span style="color: #008998;">Conferencia: Proyectos de éxito en nitsnets | studios</span></h3>
<p><iframe src="http://prezi.com/embed/0mt5hb42htbg/?bgcolor=ffffff&amp;lock_to_path=0&amp;autoplay=0&amp;autohide_ctrls=0&amp;features=undefined&amp;disabled_features=undefined" width="539" height="392" frameBorder="0"></iframe></p>
<p>Después de la breve presentación fue mi turno de explicar <strong> nuestra experiencia en PHP</strong> y por qué decidimos orientarnos en esta tecnología. En alguna ocasión hemos tenido la oportunidad de hablar de nuestro <a href="http://www.lostiemposcambian.com/blog/nitsnets/ua-nube-buena-tripulacion-aventura-nitsnets-studios/" target="_blank">emprendimiento con nitsnets | studios y cómo llegamos a formar la empresa</a> pero nunca nos habíamos centrado en la importancia del lenguaje de servidor PHP.</p>
<p><a href="http://www.nitsnets.com" target="_blank">nitsnets | studios</a> es una empresa de desarrollo web y nuevas tecnologías que ha desarrollado más de <strong>300 proyectos online</strong> a lo largo de sus <strong>7 años de vida</strong>; desde el inicio y hasta el día de hoy siempre se ha confiado en <a href="http://www.php.net" target=_blank">PHP</a> para todos los desarrollos y proyectos.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/conferencia-alicantephp-casos-exito-php-nitsnets-studios-elad-rodriguez.jpg" alt="Elad Rodriguez impartiendo la conferencia sobre Proyectos de éxito de PHP en nitsnets | studios" title="Elad Rodriguez impartiendo la conferencia sobre Proyectos de éxito de PHP en nitsnets | studios" width="539" height="496" class="alignnone size-full wp-image-452 border" /></p>
<p>Desde el principio pensamos que era importante la reutilización de código y la estructura de trabajo. En 2007 con el arranque de la empresa empezamos como muchas otras con un framework propio: <strong>nts | framework</strong>. Tenía una estructura piramidal con distintos componentes <em>(datagrid, combobox con ajax, tratamiento de imágenes&#8230;)</em> y creamos un ORM lineal para el tratamiento de base de datos mediante el mapeo de entidades del EER a objetos en PHP. Ni siquiera era MVC <em>(Modelo Vista Controlador)</em>. Con este framework se realizaron gran cantidad de proyectos como <a href="http://resources.maxwellrender.com/" target="_blank">resources.maxwellrender.com</a>, <a href="http://www.redshark-fuerteventura.com" target="_blank">www.redshark-fuerteventura.com</a>, <a href="http://www.elenarubio.es" target="_blank">www.elenarubio.es</a>, <a href="http://www.novelda.es" target="_blank">www.novelda.es</a>&#8230;</p>
<p>En poco tiempo nos dimos cuenta que el framework no era lo suficientemente potente, lo suficientemente escalable y reutilizable; pese a que muchos empleados les encantaba <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Hacer un framework al nivel que necesitábamos era un proyecto inmenso en sí y decidimos ¿por qué reinventar la rueda? A finales de 2008 nos metimos de lleno con <a href="http://www.symfony.com" target="_blank"><strong>Symfony 1.1</strong></a> con un proyecto inmenso como fue <a href="http://www.openart.com" target="_blank">Openart, la red social de arte</a>. El proyecto se complicó por su envergadura en sí y además porque la curva de aprendizaje de Symfony fue un poco más lenta de lo normal. Eso sí, el resultado fue un éxito. Actualmente <strong>Symfony 2</strong> es considerado uno de los mejores del mercado.</p>
<p>Un poco más tarde, en 2009, empezamos con proyectos pequeños y gestores de contenido con <a href="http://ellislab.com/codeigniter" target="_blank"><strong>CodeIgniter</strong></a>. La curva de aprendizaje fue tremendamente rápida y todos los empleados (en aquella etapa, siete) aprendieron en apenas una semana; era similar a PHP nativo pero bien organizado.</p>
<p><strong>CodeIgniter</strong> fue gradualmente sustituyendo a <em>nts | framework</em> y a Symfony para proyectos grandes, quedándose como el único framework PHP utilizado en la empresa que cada vez contaba con más códigos, librerías y objetos propios dentro de CodeIgniter. Este cambio de framework en la empresa lo explicamos en un polémico post: <a href="http://www.lostiemposcambian.com/blog/web-2-0/frameworks-php-symfony-vs-codeigniter-casos-de-exito/" target="_blank">Frameworks PHP Symfony vs CodeIgniter en dos casos de éxito</a></p>
<p>A partir de 2009 todos los proyectos fueron desarrollados en este <strong>framework CodeIgniter</strong>: <a href="http://www.nosplay.com" target="_blank">nosplay.com</a> &#8211; red social de videojuegos, <a href="http://www.plazatio.com" target="_blank">plazatio.com &#8211; red social oficial del CTAA de arquitectura</a>, <a href="http://www.portaventura.es" target="_blank">portaventura.es</a>, <a href="http://www.panamajack.es" target="_blank">panamajack.es</a>, <a href="http://www.puralopez.com" target="_blank">puralopez.com</a>, comoquierascolacao.com y muchísimos más&#8230;</p>
<p>Sobre este tema lo tratamos con más detalle en dos artículos, uno sobre <a href="http://www.lostiemposcambian.com/blog/web-2-0/frameworks-php-por-que-usarlos/" target="_blank">frameworks PHP</a> y otro de nuestro proceso de <a href="http://www.lostiemposcambian.com/blog/web-2-0/frameworks-web-2-0/" target="_blank">selección de tecnología y frameworks</a>  </p>
<p>En nuestro afán de seguir mejorando estamos evaluando muy seriamente la migración nuevamente a otro framework PHP: <strong><a href="http://www.laravel.com" target="_blank">Laravel 4</a></strong>. Una muy buena estructuración de objetos y una maravilla que echábamos de menos: los <a href="http://bundles.laravel.com/" target="_blank"><strong>bundles</strong></a>. <em>Paquetes de código </em>con su propia configuración, rutas, migraciones, tareas, etc; pueden ser desde un ORM de base de datos, un sistema de autentificación, etc. La <strong>modularidad</strong> gracias a los bundles puede ser el éxito de este framework, un concepto que aprendimos en Symfony 2 y es algo que buscábamos y añorábamos en CodeIgniter desde hace tiempo.</p>
<p>Además la <strong>migración de CodeIgniter a Laravel </strong>es tan inmediata como fue para nosotros el cambio de PHP nativo (nuestro framework) a CodeIgniter. En nuestro ámbito empresarial esto es vital para seguir facturando desde el primer día. <em>¿Será el 2013 el año de Laravel?</em> Esperamos poder contaros en breve <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3><span style="color: #008998;">Librerías PHP</span></h3>
<p>Después comentamos algunas de las librerías que utilizamos en nitsnets | studios y que os pueden ser de mucha utilidad.</p>
<ul>
<li><a href="http://codeigniter.com/wiki/Wick" target="_blank"><strong>Wick</strong></a> HMVC. Todos nuestros proyectos tienen un sistema de <strong>High MVC</strong> donde partimos de la base que las URLs son únicas y que el controlador principal detecta la URL en cuestión e indica que controlador tiene que aplicar haciendo de <em>dispatcher</em>. Esta utilización la explicamos en otra <a href="http://www.lostiemposcambian.com/blog/web-2-0/industrializacion-en-la-web-conferencia-adwe/" target="_blank">conferencia: La industrialización en la web.</a>
<p>Esto también se puede conseguir con esta <a href="https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc" target="_blank">extensión de CodeIgniter HMVC</a></li>
<li><a href="http://shiftingpixel.com/2008/03/03/smart-image-resizer/" target="_blank"><strong>Smart Image Resizer</strong></a> Tratamiento de imágenes. Un tratamiento que utilizamos en todos los proyectos e incluso lo incluimos en el htacces para poder utilizarlo pero con un SEO de imágenes optimizado. Esto también se vio en la <a href="http://www.lostiemposcambian.com/blog/web-2-0/industrializacion-en-la-web-conferencia-adwe/" target="_blank">conferencia: La industrialización en la web.</a></li>
<li><a href="http://codeigniter.com/wiki/CI_Nusoap_Library" target="_blank"><strong>NuSOAP</strong></a> Web Services Toolkit para PHP.</li>
<li><a href="http://php.net/manual/es/class.soapclient.php" target="_blank"><strong>SoapClient</strong></a> Con esta librería nativa de PHP integramos una pasarela de pago intermedia como es <a href="http://www.paytpv.com" target="_blank">PayTPV</a> una utilidad muy necesaria para la máxima conversión de ventas en los ecommerce internacionales.</li>
<li><a href="http://simplepie.org/wiki/plugins/start#codeigniter" target="_blank"><strong>SimplePie</strong></a> RSS-Atom Feed Parsing. En nuestra plataforma de creación de periódicos y revistas digitales <a href="http://www.gopress.es" target="_blank">Gopress</a> parseamos las RSS e incluíamos noticias de otros medios mediante el feed. También en <a href="http://www.nosplay.com" target="_blank">nosplay.com</a> extraemos las noticias automáticamente de los blogs registrados.</li>
<li><a href="http://sourceforge.net/projects/phpexcelreader" target="_blank"><strong>PHP-ExcelReader</strong></a> Lectura/escritura de ficheros de Excel. Todos nuestros <strong>gestores de contenidos CMS </strong> tienes funciones de exportar datos en formato Excel ya que los departamentos de marketing y de dirección los necesitan.</li>
<li><a href="http://code.google.com/p/dompdf/" target="_blank"><strong>DOMPDF</strong></a> HTML to PDF renderer. Por ejemplo en <a href="http://www.panamajack.es" target="_blank">Panama Jack</a> generamos tarjetas de regalo en PDF.</li>
<li><a href="http://code.google.com/intl/es/apis/youtube/developers_guide_php.html" target="_blank"><strong>Zend_Gdata_YouTube</strong></a> Conexión con los GData de Google como en Youtube.</li>
<li><a href="http://codeigniter.com/wiki/OAuth_for_Twitter" target="_blank"><strong>Twitter Oauth</strong></a> Conexión con la API de Twitter.</li>
<li><a href="http://code.google.com/p/iaml/source/browse/trunk/org.openiaml.model.runtime/src/include/html2text/html2text.php?r=1820" target="_blank"><strong>html_to_text</strong></a> <em>Helper</em> que convierte un documento HTML en texto plano. Muy útil para tener un único cuerpo en la generación de emails automáticos de nuestras aplicaciones.</li>
<li><a href="https://github.com/opentok/OpenTok-CodeIgniter-Plugin" target="_blank"><strong>OpenTok</strong></a> Servicio de videoconferencia OpenTok. Este servicio lo utilizamos en <a href="http://www.reworklution.com" target="_blank">Reworklution.com</a> donde puedes videoformarte con profesionales en directo o la videoformación de las promotoras en la innovadora empresa <a href="http://www.globalfieldmk.com" target="_blank">Global Field Marketing</a></li>
</ul>
<p><strong>Gracias a todo mi equipo de nitsnets </strong>por reunir y agrupar estos conceptos, especialmente a <a href="https://twitter.com/alejandro_such" target="_blank">Alejandro Such</a> que me ha ayudado mucho en esta pequeña charla.</p>
<h3><span style="color: #008998;">Conferencia: Introducción a PHPUnit</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/conferencia-alicantephp-phpunit-manuel-jurado.jpg" alt="Conferencia Introducción a PHPUnit de Manuel Jurado" title="Conferencia Introducción a PHPUnit de Manuel Jurado" width="539" height="400" class="alignnone size-full wp-image-452 border" /></p>
<p><a href="https://twitter.com/manuelljb" target="_blank">Manuel Jurado</a> nos hizo una introducción a la utilización de <a href="https://github.com/sebastianbergmann/phpunit/" target="_blank">PHPUnit</a> y lo importante que son las pruebas en el desarrollo web. Me impactó una frase que decía: <em>&#8220;lo costoso o difícil no es utilizar PHPUnit sino realizar unas buenas pruebas unitarias&#8221;</em>.</p>
<p>Ahora ya no hay excusas para este <em>best practice </em>y hay que realizar test; sobretodo si tienes un proyecto único <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><iframe src="http://www.slideshare.net/slideshow/embed_code/18874722" width="539" height="449" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe></p>
<h3><span style="color: #008998;">Regalitos y cervezas</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/regalos-primera-conferencia-grupo-usuarios-alicante-alicantephp.jpg" alt="Regalos primeras conferencias Grupo de Usuarios PHP" title="Regalos primeras conferencias Grupo de Usuarios PHP" width="539" height="244" class="alignnone size-full wp-image-452 border" /></p>
<p>Al finalizar se realizó el sorteo entre los asistentes de 3 flamantes libros los cuales recomendamos:</p>
<ul>
<li><a href="https://leanpub.com/codehappy" target="_blank">Laravel: Code Happy</a></li>
<li><a href="https://leanpub.com/grumpy-testing" target="_blank">The Grumpy Programmer&#8217;s Guide To Building Testable PHP Applications</a></li>
<li><a href="https://leanpub.com/grumpy-phpunit" target="_blank">The Grumpy Programmer&#8217;s PHPUnit Cookbook</a></li>
</ul>
<p>Este tipo de regalos se pudieron realizar gracias a los patrocinadores del evento de entre los cuales <strong><a href="http://www.nitsnets.com" target="_blank">nitsnets | studios</a></strong> esta orgulloso de poder participar.<br />
Otros patrocinadores son el <a href="http://proweb.ua.es" target="_blank">máster Curso de Especialista Universitario en Programación Web PROWEB de la Universidad de Alicante</a>, <a href="http://thegreenbees.es/es" target="_blank">The Green Bees &#8211; espacio coworking en Alicante</a> y <a href="http://servergrove.es/" target="_blank">Server Grove &#8211; Servidores especialistas en PHP</a>.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/alicantephp-jugando-al-futbolin.jpg" alt="Grupo de Usuarios PHP Alicante jugando al futbolín" title="Grupo de Usuarios PHP Alicante jugando al futbolín" width="539" height="292" class="alignnone size-full wp-image-452 border" /></p>
<p>Por último continuó el <em>networking</em> con unas cervecitas y cocacolas así como unas partidas a un futbolín donde vimos que <em>no somos tan frikis <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/php/conferencia-alicantephp-proyectos-php-de-exito-en-nitsnets-studios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tutorial de Ember: Screencast paso a paso</title>
		<link>http://www.lostiemposcambian.com/blog/javascript/tutorial-de-ember-screencast-paso-a-paso/</link>
		<comments>http://www.lostiemposcambian.com/blog/javascript/tutorial-de-ember-screencast-paso-a-paso/#comments</comments>
		<pubDate>Mon, 15 Apr 2013 08:21:00 +0000</pubDate>
		<dc:creator>danii</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[ember.js]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=6208</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/javascript/tutorial-de-ember-screencast-paso-a-paso">
<img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/ember-video-tutorial.jpg" alt="Ember Video Tutorial" title="Ember Video Tutorial" width="539" height="307" class="alignnone size-full wp-image-452 border" /></a>

<p>Cuando <a target="_blank" href="http://www.lostiemposcambian.com/blog/javascript/intro-framework-ember/">presentamos el framework JavaScript Ember.js</a> ya comentamos que uno de los principales problemas de este framework era la dificultad de hallar buenos recursos de aprendizaje actualizados y por tanto los inicios eran (por decirlo suavemente) un tanto duros. Sin embargo, también advertimos de que los creadores del framework eran conscientes de ello y por tanto podíamos esperar interesantes <strong>mejoras y novedades</strong> al respecto. Pues bien, <a target="_blank" href="http://twitter.com/tomdale">Tom Dale</a>, uno de los autores del framework, se ha puesto manos a la obra y ha grabado un <strong>fantástico screencast</strong> de introducción a la programación de una Web App JavaScript en Ember.</p>]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/ember-video-tutorial.jpg" alt="Ember Video Tutorial" title="Ember Video Tutorial" width="539" height="307" class="alignnone size-full wp-image-452 border" /></p>
<p>Cuando <a target="_blank" href="http://www.lostiemposcambian.com/blog/javascript/intro-framework-ember/">presentamos el framework JavaScript Ember.js</a> ya comentamos que uno de los principales problemas de este framework era la dificultad de hallar buenos recursos de aprendizaje actualizados y por tanto los inicios eran (por decirlo suavemente) un tanto duros. Sin embargo, también advertimos de que los creadores del framework eran conscientes de ello y por tanto podíamos esperar interesantes <strong>mejoras y novedades</strong> al respecto. Pues bien, <a target="_blank" href="http://twitter.com/tomdale">Tom Dale</a>, uno de los autores del framework, se ha puesto manos a la obra y ha grabado un <strong>fantástico screencast</strong> de introducción a la programación de una Web App JavaScript en Ember.</p>
<p>En este <em>screencast</em> se programa &#8220;en directo&#8221; una <strong>mini aplicación de blogging con Ember.js</strong> partiendo prácticamente desde cero. En este post vamos a seguir el <em>screencast</em> paso a paso, comentando el código y las funcionalidades que se van añadiendo. Este tutorial es un ejemplo muy práctico, así que os recomendamos que intentéis seguir el video a la vez que programáis la App y podéis utilizar este post como guía de consulta adicional.</p>
<h3><span style="color: #008998;">Ver Demo Finalizada</span></h3>
<p>Como referencia, os mostramos el que será el resultado final de la aplicación que se construye en el <em>screencast</em>, más un par de adaptaciones y mejoras que hemos decidido añadir nosotros y que comentaremos durante el desarrollo:</p>
<p style="background-color: #f5f5f5; text-align: center; padding: 10px 10px 10px 10px;"><a href="http://lostiemposcambian.com/blog/posts/ember-video-tutorial/" target="_blank"><img title="ver demo" src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2012/03/bt_demo.jpg" alt="ver demo" width="262" height="32" /></a> <a href="https://github.com/danii-nebot/ember_screen_cast_tutorial/archive/master.zip"><img title="descarga código fuente de Github" src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2010/09/bt_download.jpg" alt="" width="232" height="32" /></a></p>
<p>Os recomendamos que no &ldquo;hagáis trampas&rdquo; y echéis mano del código fuente que os proporcionamos y que intentéis seguir el <em>screencast</em> y nuestro <em>step by step</em> programando vosotros cada paso. La idea es aprender Ember siguiendo un ejemplo práctico relativamente sencillo.</p>
<h3><span style="color: #008998;">ScreenCast</span></h3>
<p><iframe width="539" height="303" src="http://www.youtube.com/embed/Ga99hMi7wfY" frameborder="0" allowfullscreen></iframe></p>
<h3><span style="color: #008998;">Archivos iniciales</span></h3>
<p>Hemos preparado <a href="https://github.com/danii-nebot/ember_screen_cast_tutorial/raw/master/ember-video-tutorial-Starting-Point.zip">un zip <strong>Starting Point</strong></a> con los archivos que necesitamos para empezar con este tutorial. Hemos tomado como base el <a target="_blank" href="http://github.com/emberjs/starter-kit/">Starter Kit de Ember.js</a> al que le hemos añadido los siguientes archivos que se van a utilizar para el desarrollo de la aplicación:</p>
<ul>
<li>
<p>El ubicuo <a target="_blank" href="http://twitter.github.io/bootstrap/">twitter bootstrap CSS</a> para tener una base de estilos CSS agradable sin esfuerzo,</p>
</li>
<li>
<p>La genial librería <a target="_blank" href="http://momentjs.com/">moment.js</a> para formatear fácilmente <em>datetimes</em> de JavaScript de forma <em>friendly</em> para personas humanas,</p>
</li>
<li>
<p>La librería <a target="_blank" href="http://github.com/coreyti/showdown">showdown.js</a>, para parsear texto en formato <a target="_blank" href="http://en.wikipedia.org/wiki/Markdown">markdown</a> y convertirlo a HTML, ya que utilizaremos este formato para almacenar nuestros posts en el modelo,</p>
</li>
<li>
<p>Y por último <a target="_blank" href="http://github.com/emberjs/data">Ember data</a> en su última versión <strong>Revision 12</strong>, ya que sorprendentemente no está incluído en el Starter Kit antes mencionado.</p>
</li>
</ul>
<p>Además, hemos eliminado el código inicial de prueba con el que viene la app del Starter Kit y hemos dejado una única línea:</p>
<pre class="brush: jscript; title: ; notranslate">
  App = Ember.Application.create();
</pre>
<p>Y tambien hemos substituido las <em>templates</em> iniciales del <em>Starter Kit</em> por la template inicial estática que se muestra en el video.</p>
<p>Descarga aquí el <a href="https://github.com/danii-nebot/ember_screen_cast_tutorial/raw/master/ember-video-tutorial-Starting-Point.zip">zip <strong>Starting Point</strong></a>, descomprímelo y abre el archivo <strong>index.html</strong> en el navegador (inicialmente no es necesario cargarlo desde un servidor web). Deberías encontrarte el menú de navegación superior y el resto de la pantalla en blanco, pero que todos los archivos necesarios están cargados. Este será nuestro <strong>punto de partida</strong>:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/starting-point.jpg" alt="Starting point en el navegador" title="Starting point en el browser" width="539" height="292" class="alignnone size-full wp-image-452 border" /></p>
<p>En este momento podemos empezar a apreciar la magia de Ember: no hemos programado más quen una línea de código de la aplicación, en la que simplemente la hemos inicializado, y hemos añadido una <em>template</em> sin ningún tipo de vinculación a este objeto JavaScript <strong>App</strong>, y sin embargo el framework Ember.js es lo suficientemente inteligente para saber que esta única plantilla que encuentra es la que tiene que renderizar.</p>
<p>Como se observa en el menú de navegación, nuestar App va a tener dos secciones o páginas principales:</p>
<ul>
<li>
<p><strong>Posts</strong>, que incluirá un listado de posts siguiendo un patrón <a target="_blank" href="http://en.wikipedia.org/wiki/Master%E2%80%93detail_interface">Master-Detail</a>. No es casualidad que nuestra <a target="_blank" href="http://www.lostiemposcambian.com/blog/javascript/intro-framework-ember/">app de intro a Ember</a> y esta estén ambas basadas en <strong>Master-Detail</strong>, ya que el Router de Ember se adapta muy bien a las características de este patrón tan utilizado, como veremos más adelante.</p>
</li>
<li>
<p><strong>About</strong>, una página con información estática donde presentaremos a los autores del blog, que en este caso vamos a personalizar con nuestras biografías <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
</li>
</ul>
<h3><span style="color: #008998;">La Sección About</span></h3>
<p>En este primer paso vamos a centrarnos en la <strong>sección About</strong>. Primero, crearemos un <strong>template de Handlebars</strong> con el contenido estático de la sección (en este caso, una presentación del blog y unas mini biografias nuestras como autores) y la añadimos al HTML:</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;about&quot;&gt;
    &lt;div class=&quot;about&quot;&gt;
      &lt;h3&gt;Sobre el blog&lt;/h3&gt;
      Los tiempos cambian pero no nuestra suerte... o sí! En un mundo como el actual donde todo evoluciona tan rápido (especialmente la tecnología) y las &lt;em&gt;buzzwords&lt;/em&gt; surgen y decaen casi a diario, es cada vez más necesario formarse día a día. Cada día.
      ...
    &lt;/div&gt;

    &lt;div class=&quot;about&quot;&gt;
      &lt;h3&gt;Autores del blog&lt;/h3&gt;
      &lt;strong&gt;Elad Rodriguez&lt;/strong&gt;
      &lt;a href=&quot;http://www.twitter.com/eladnts&quot; target=&quot;_blank&quot;&gt; @eladnts&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;Culé del 1982. Ingeniero Superior en Informática por la Universidad de Alicante (UA). Fundador de la empresa de desarrollo web &lt;a href=&quot;http://www.nitsnets.com&quot; target=&quot;_blank&quot;&gt;nitsnets | studios&lt;/a&gt; Director de proyectos web 2.0 y RIAs.&lt;/li&gt;
        ...
      &lt;/ul&gt;

      &lt;strong&gt;Daniel G. Nebot&lt;/strong&gt;
      &lt;a href=&quot;http://www.twitter.com/daniinebot&quot; target=&quot;_blank&quot;&gt; @daniinebot&lt;/a&gt;

      &lt;ul&gt;
        &lt;li&gt;También nacido en el 1982, aunque sensiblemente antes. Ingeniero Superior en Informática por la Universidad de Alicante (UA).&lt;/li&gt;
        ...
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/script&gt;
</pre>
<p><em>Nota:</em> Aunque en el <em>screencast</em> se utiliza el atributo <span class="sourcecode">id=&#8221;about&#8221;</span> para asociar el template a su ruta, nosotros hemos preferido utilizar el más explícito <span class="sourcecode">data-template-name=&#8221;about&#8221;</span> ya que <a target="_blank" href="http://stackoverflow.com/questions/15882548/what-is-the-correct-way-to-name-templates-in-ember-js">ambos tienen exactamente el mismo funcionamiento</a> y vemos dos ventajas: primero, nos parece más explicativo y además, preferimos evitar un riesgo de colisiones con otros elementos del DOM.</p>
<p>Para que Ember muestre un template, tenemos que tener una ruta asociada a éste, así que vamos a a definir un objeto Route de Ember super simple, con una única ruta que representa esta sección:</p>
<pre class="brush: jscript; title: ; notranslate">
  App.Router.map(function() {
    this.resource('about');
  });
</pre>
<p>Y aquí entra otra vez en juego la <em>magia</em> de Ember: al haber definido una ruta con nombre &lsquo;about&rsquo; y un template con ese mismo nombre &lsquo;about&rsquo;, Ember ya sabe que esta ruta y este template están asociados, sin necesidad de que yo tenga que definir esta relación en escribiendo código.</p>
<p>Para mostrar este template, debemos hacer dos adiciones en nuestro <strong>template principal</strong>:</p>
<ul>
<li>Sustituimos el link estático
<pre class="brush: xml; title: ; notranslate">
  &lt;a href=&quot;#&quot;&gt;About&lt;/a&gt;
</pre>
<p>por un un link a la sección about recien creada en el Router utilizando el helper de <b>Handlebars <span class="sourcecode">{{#linkTo}}</span></b>:</p>
<pre class="brush: jscript; title: ; notranslate">
  {{#linkTo 'about'}}About{{/linkTo}}
</pre>
</li>
<li>y añadimos también el helper <b><span class="sourcecode">{{outlet}}</span></b> que podríamos definir como simplemente un <em>placeholder</em> que indica a Ember en qué punto de la plantilla actual debe renderizar el contenido de la sección.</li>
</ul>
<p>De esta manera, el template principal queda de momento así:</p>
<pre class="brush: xml; title: ; notranslate">
 &lt;script type=&quot;text/x-handlebars&quot;&gt;
    &lt;div class=&quot;navbar&quot;&gt;
      &lt;div class=&quot;navbar-inner&quot;&gt;
        &lt;a class=&quot;brand&quot; href=&quot;#&quot;&gt;Bloggr&lt;/a&gt;
        &lt;ul class=&quot;nav&quot;&gt;
          &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Posts&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;{{#linkTo 'about'}}About{{/linkTo}}&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    {{outlet}}

  &lt;/script&gt;
</pre>
<p>y al entrar en la sección <strong>about</strong> (pinchando en el link del menú de navegación o escribiendo en la barra de dirección del navegador <strong><em>/#/about</em></strong>) veremos esto:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/about-section.jpg" alt="Sección About" title="Sección About" width="539" height="248" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Lista de Posts (Master)</span></h3>
<p>Puesto que esta sección no es estática como la anterior, necesitaremos definir un modelo y un Store de datos:</p>
<pre class="brush: jscript; title: ; notranslate">
  App.Store = DS.Store.extend({
    revision:12,
    adapter: 'DS.FixtureAdapter'
  });
</pre>
<p><span class="sourcecode"><strong>DS.FixtureAdapter</strong></span> nos permite especificar todo nuestro modelo de datos de manera estática como objetos JavaScript. Es perfecto durante fases del desarrollo inicial para trabajar de manera ágil, podríamos decir que son una &ldquo;simulación&rdquo; de carga de datos y que posteriormente podemos susutiurlo sin ningún tipo de fricción por un <a target="_blank" href="http://emberjs.com/guides/models/the-rest-adapter/"><span class="sourcecode">RESTAdapter</span></a> que cargue los datos dinámicos del server mediante un servicio REST.</p>
<p>Definimos el modelo en sí:</p>
<pre class="brush: jscript; title: ; notranslate">
  App.Post = DS.Model.extend({
    title: Ds.attr('string'),
    author: Ds.attr('string'),
    intro: Ds.attr('string'),
    publishedAt: Ds.attr('date')
  });
</pre>
<p><em>Nota:</em> Hemos simplificado un poco el modelo con respecto al que aparece en el <em>screencast</em> agrupando los atributos <span class="sourcecode">extended</span> e <span class="sourcecode">intro</span> en uno al que hemos llamado <span class="sourcecode">fullText</span></p>
<p>Y a continuación añadimos los <b>FIXTURES</b> es decir datos que van a cargar:</p>
<pre class="brush: jscript; title: ; notranslate">
App.Post.FIXTURES = [{
    id:1,
    title: &quot;Mejoras de usabilidad en el ecommerce. Panama Jack&quot;,
    author: &quot;elad&quot;,
    publishedAt: new Date('4-8-2013'),
    fullText: &quot;...&quot;
},
{
    id:2,
    title: &quot;Introducción al framework Ember.js&quot;,
    author: &quot;danii&quot;,
    publishedAt: new Date('4-3-2013'),
    fullText: &quot;...&quot;
}];
</pre>
<p>Para que exista esta sección de posts, añadimos un resource &lsquo;posts&rsquo; en el <strong>Router</strong>, que quedará así:</p>
<pre class="brush: jscript; title: ; notranslate">
  App.Router.map(function() {
    this.resource('about');
    this.resource('posts');
  });
</pre>
<p>Tambien debemos especificar que este modelo de datos que acabamos de crear es el que debemos utilizar para esta ruta, para ello extendemos el objeto <span class="sourcecode">Ember.Route</span> y le indicaremos que cargue el modelo:</p>
<pre class="brush: jscript; title: ; notranslate">
App.PostsRoute = Ember.Route.extend({
    model: function() {
        //return all elements in model
        return App.Post.find();
    }
});
</pre>
<p>Y con esto ya hemos implementado toda la funcionalidad necesaria para esta sección en nuestra App, tan sólo nos queda definir su template y linkarla desde la navegación, para esto una vez más hemos cambiar el link estático del template principal por el helper <span class="sourcecode">{{linkto}}</span>, en este caso a la sección &lsquo;posts&rsquo;.</p>
<p>A continuación tenemos que crear una template con <span class="sourcecode">template-data-name=&#8221;posts&#8221;</span> y puesto que el nombre de la ruta y el nombre del template coinciden Ember ya sabe que ambos van asociados. <strong>Great!</strong></p>
<p>En este template listaremos todos los posts que tenemos, para ello utilizaremos el helper de Handlebars <a target="_blank" href="http://handlebarsjs.com/block_helpers.html"><span class="sourcecode">{{#each}}</span></a> que itera por cada elemento del modelo de datos y renderiza la parte del template que contiene por cada uno, utilizándolo como contexto. El template quedará por tanto así:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;posts&quot;&gt;
    &lt;div class=&quot;container-fluid&quot;&gt;
      &lt;div class=&quot;row-fluid&quot;&gt;
        &lt;div class=&quot;span3&quot;&gt;
          &lt;table class=&quot;table&quot;&gt;
            &lt;thead&gt;
              &lt;tr&gt;&lt;th&gt;Recent Posts&lt;/th&gt;&lt;/tr&gt;
            &lt;/thead&gt;
            {{#each model}}
            &lt;tr&gt;&lt;td&gt;
              &lt;a href=&quot;#&quot;&gt;{{ title }}&lt;/a&gt;&lt;small class=&quot;muted&quot;&gt;por {{ author }}&lt;/small&gt;
            &lt;/td&gt;&lt;/tr&gt;
            {{/each}}
          &lt;/table&gt;
        &lt;/div&gt;
        &lt;div class=&quot;span9&quot;&gt;
          &lt;!-- place holder donde irá la vista detail de cada post --&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/script&gt;
</pre>
<p>Y ya tenemos la vista Master <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/vista-master-posts.jpg" alt="Sección Posts: vista master" title="Sección Posts: vista master" width="539" height="294" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Vista Detail de los Posts</span></h3>
<p>Ahora tan solo nos falta que se cargue la vista <em>Detail</em> de cada post individual al seleccionarlo del listado. Vamos a añadir al Router una ruta anidada (<b>nested route</b>) dentro de la ruta &lsquo;posts&rsquo; que represente a cada post individual:</p>
<pre class="brush: jscript; title: ; notranslate">
App.Router.map(function() {
  this.resource('about');
  this.resource('posts', function() {
    this.resource('post', { path: ':post_id' })
  });
});
</pre>
<p>Y ahora en el HTML creamos una plantilla <span class="sourcecode">template-data-name=&#8221;post&#8221;</span> asociada a esta ruta:</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;post&quot;&gt;
    &lt;h1&gt;{{title}}&lt;/h1&gt;
    &lt;h2&gt;por {{author}} &lt;small class=&quot;muted&quot;&gt;({{publishedAt}})&lt;/small&gt;&lt;/h2&gt;
    &lt;hr&gt;
    &lt;div&gt;
      {{fullText}}
    &lt;/div&gt;
  &lt;/script&gt;
</pre>
<p>A continuación tenemos que linkar desde el listado Master de posts a esta plantilla recién creada, para ello sustitumos la linea donde teníamos los links estáticos con el tag a que habíamos dejado por el helper <span class="sourcecode">{{#linkTo}}</span>, que quedará así:</p>
<pre class="brush: jscript; title: ; notranslate">
  {{#linkTo 'post' this}}{{title}}{{/linkTo}}
</pre>
<p>En este caso hemos de pasar un parámetro <span class="sourcecode"><strong>this</strong></span> al helper, que representa el contexto actual, es decir el modelo de datos que debe mostrar el template. El último paso será añadir el helper <span class="sourcecode">{{outlet}}</span> en el lugar del <em>placehoder</em> que habíamos colocado en la plantilla Master, para que Ember sepa dónde debe renderizar la vista de la ruta anidada.</p>
<p>En este momento debemos poder clickar en cada uno de los posts de nuestra lista y se cargará el contenido asociado a este post:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/post-vista-detail.jpg" alt="Post individual vista Detail" title="Post individual vista Detail" width="539" height="224" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Formato mediante Helpers de Handlebars</span></h3>
<p>Por supuesto, hay un par de problemas obvios de formato actualmente:</p>
<ul>
<li>
<p>La fecha de publicación del post se muestra algo parecido a: <em><span style="color: #999999;">(Mon Apr 08 2013 00:00:00 GMT+0200 (CEST))</span></em> lo cual es un formato de fecha no demasiado legible para el usuario (horrible, vamos);</p>
</li>
<li>
<p>Y el contenido del post sale en formato <strong>Markdown</strong>, obviamente, ya que lo tenemos almacenado así en nuestras Fixtures, cuando lo ideal es que se renderice en el navegador como HTML.</p>
</li>
</ul>
<p>Para dar formato a estos elementos utilizaremos las librerías JavaScript <a target="_blank" href="http://momentjs.com/">moment.js</a> y <a target="_blank" href="http://github.com/coreyti/showdown">showdown.js</a> respectivamente, y lo haremos integrándolos dentro de un par de helpers propios de Handlebars que realizarán estas tareas y que posteriormente incluiremos en el template.</p>
<p>Primero, definimos un <b>BoundHelper</b> de Handlebars mediante <span class="sourcecode">Ember.Handlebars.registerBoundHelper</span>, este tipo de Helper es perfecto para datos dinámicos ya que se comporta como un observer de los datos que muestra y se actualiza automáticamente si estos datos cambiasen. En el <em>screencast</em> podéis ver una demo de este comporamiento.</p>
<p>El primer parámetro de la función <span class="sourcecode">registerBoundHelper</span> será el nombre del helper, y el segundo la función que dará formato a los datos que recibe como parámetro y posteriormente los devolverá ya formateados. Utilizaremos la función <a target="_blank" href="http://momentjs.com/docs/#/displaying/fromnow/"><span class="sourcecode">fromNow()</span></a> de moment.js para mostrar el tiempo que ha pasado desde la fecha de publicación del post. Además, vamos a aprovechar la potencia de <a target="_blank" href="http://momentjs.com/docs/#/i18n/">i18n de moment.js</a> para mostrar <strong>el lapso de tiempo en castellano</strong>, ya que nuestros posts van a estar escritos en la lengua de Cervantes <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<pre class="brush: jscript; title: ; notranslate">
moment.lang('es',
{
  relativeTime: {
    past : 'hace %s',
    s : &quot;unos segundos&quot;,
    m : &quot;un minuto&quot;,
    mm : &quot;%d minutos&quot;,
    h : &quot;una hora&quot;,
    hh : &quot;%d horas&quot;,
    d : &quot;un día&quot;,
    dd : &quot;%d días&quot;,
    M : &quot;un mes&quot;,
    MM : &quot;%d mes&quot;,
    y : &quot;un año&quot;,
    yy : &quot;%d años&quot;
  }
});

Ember.Handlebars.registerBoundHelper('date', function(date) {
  return moment(date).fromNow();
});
</pre>
<p>Y substituimos <span class="sourcecode">{{publishedAt}}</span> por la llamada al helper: <span class="sourcecode">{{date publishedAt}}</span></p>
<p>A continuación, seguimos los mismos pasos para mostrar el texto del post en formato HTML, con la particularidad de que tenemos que utilizar un <span class="sourcecode"><b>Handlebars.SafeString</b></span> ya que por defecto las plantillas en Ember van a <em>escapar</em> todo su contenido por razones obvias de seguridad:</p>
<pre class="brush: jscript; title: ; notranslate">
//creamos objeto converter
//para pasar de markdown a HTML
var showdown = new Showdown.converter();

Ember.Handlebars.registerBoundHelper('markdown', function(input) {
  //devolvemos SafeString para que no escape el contenido HTML
  return new Ember.Handlebars.SafeString(showdown.makeHtml(input));
});
</pre>
<p>E invocamos al helper al mostrar el texto del post, es decir sustituimos <span class="sourcecode">{{text}}</span> por: <span class="sourcecode">{{markdown text}}</span>.</p>
<p>Y finalmente deberíamos ver el post con un formato correcto:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/post-vista-detail-formato.jpg" alt="Post individual Detail con formato" title="Post individual Detail con formato" width="539" height="246" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Añadimos Modo Edición</span></h3>
<p>Hasta este punto nuestra aplicación es <em>Read-only</em>, pero en este momento vamos a añadir un <strong>modo de edición</strong> para poder editar el texto y títlo de los posts <em>on the fly</em> y además mostrando un <strong><em>live-preview</em></strong> de estos cambios en la vista principal del post, ya que vincularemos los datos mediante <strong>Data Binding</strong>. ¡Brutal! <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Lo primero será añadir un botón de edit en el template del post. Para distinguir entre los estados de edición y visualización utilizaremos los helpers de Handlebars <span class="sourcecode">{{#if}}</span> que renderiza una parte del template de forma condicional, y <span class="sourcecode">{{action}}</span> para invocar una función del controlador:</p>
<pre class="brush: xml; title: ; notranslate">
    {{#if isEditing}}
      &lt;h3&gt;Edit mode&lt;/h3&gt;
      &lt;button {{action 'doneEditing'}}&gt;Done&lt;/button&gt;
    {{else}}
      &lt;button {{action 'edit'}}&gt;Edit&lt;/button&gt;
    {{/if}}
</pre>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/post-view-edit-mode.jpg" alt="Post Detail botón edit" title="Post Detail botón edit" width="539" height="223" class="alignnone size-full wp-image-452 border" /></p>
<p>Y a continuación debemos crear esta variable de estado booleana <span class="sourcecode">isEditing</span>, así como las funciones <span class="sourcecode">edit</span> y <span class="sourcecode">doneEditing</span> en el controlador. Fijaros que este controlador que se encarga de la vista Post no lo he tenido que implementar hasta que no he necesitado un comportamiento adicional. Esta es la base de la filosofía de Ember: <strong>implementar sólo los objetos que necesite, del resto ya se encarga el framework</strong>. Al crear un objeto con el nombre PostController, el framework ya sabe que estará asociado a la vista y los datos del Post.</p>
<p>En este caso extenderé a la clase <span class="sourcecode">Ember.ObjectController</span> ya que este controlador tiene como modelo un único post (no un array de posts) e implementaré las funciones que hacen un <strong><em>toggle</em></strong> entre el modo de edición y no edición. Además vamos a hacer un <strong>commit</strong> de todos los cambios que se hagan en el modelo, de manera que cuando estemos listos para guardar los datos y sustituyamos el <span class="sourcecode">FixtureAdapter</span> por un <span class="sourcecode">RESTAdapter</span> se realicen las llamadas al server:</p>
<pre class="brush: jscript; title: ; notranslate">
App.PostController = Ember.ObjectController.extend({
    isEditing: false,
    edit: function()
    {
      this.set('isEditing',true);
    },
    doneEditing: function()
    {
      this.set('isEditing',false);
      //save to server
      this.get('store').commit();
    }

});
</pre>
<p>El siguiente paso será mostrar una UI para editar el post cuando esté en modo edición. Para mantener nuestro template de post sencilla, vamos a hacerlo de manera modular incluyendo un parcial o template externo mediante el helper <span class="sourcecode">{{partial}}</span>. Por convenio, los nombres de template de los parciales empiezan siempre por &ldquo;_&rdquo; para distinguirlos del resto de templates. En este parcial vamos a utilizar los helpers view que se encargan de renderizar una vista, y las vistas predefinidas de Ember<span class="sourcecode">Ember.TextField</span> y <span class="sourcecode">Ember.TextArea</span>, por supuesto vinculadas mediante <strong>Data Binding</strong> al título y al texto del post respectivamente:</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;post/_edit&quot;&gt;
    &lt;p&gt;{{view Ember.TextField valueBinding='title'}}&lt;/p&gt;
    &lt;p&gt;{{view Ember.TextArea valueBinding='text'}}&lt;/p&gt;
  &lt;/script&gt;
</pre>
<p>Y en volvemos al template del post para indicarle que debe incluir este partial cuando esté en modo edición:</p>
<pre class="brush: plain; title: ; notranslate">
  {{#if isEditing}}
    &lt;h3&gt;Edit mode&lt;/h3&gt;
    {{partial 'post/edit'}}
    &lt;button {{action 'doneEditing'}}&gt;Done&lt;/button&gt;
  {{else}}
    ...
</pre>
<p>¡Y ya lo tenemos! Casi sin esfuerzo hemos añadido un modo de edición en el que además, como todos los datos con lo que estamos trabajando están vinculados, el post que estamos mostrando se actualizará <em>on the fly</em> automáticamente.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/post-view-edit-UI.jpg" alt="Vista Post UI Edit" title="Vista Post UI Edit" width="539" height="281" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Una pequeña mejora de Usabilidad</span></h3>
<p>Un pequeño detalle que podemos mejorar es que cuando entramos a la ruta posts, por ejemplo desde el botón de navegación superior, nos vamos a encontrar con una pantalla casi vacía como hemos visto anteriormente:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/vista-master-posts.jpg" alt="Sección Posts: vista master" title="Sección Posts: vista master" width="539" height="294" class="alignnone size-full wp-image-452 border" /></p>
<p>Lo cual no es un para nada un ejemplo de buena usabilidad. Para solucionar este problema, debemos especificar a Ember el contenido que debe mostrar en la ruta por defecto de Posts, es decir cuando no hay ningún post seleccionado. Esta ruta en Ember se llama por convenio <em><strong>/index</strong></em>, así que en este caso por ejemplo debemos llamar a nuestro template <em><strong>posts/index</strong></em>.</p>
<p>Una opción sería crear una plantilla placeholder que indique al usuario lo que debe hacer:</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;posts/index&quot;&gt;
    &lt;p class=&quot;text-warning&quot;&gt;Por favor, seleccione un post&lt;/p&gt;
  &lt;/script&gt;
</pre>
<p>Y quedaría así:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/posts-default-placeholder.jpg" alt="Vista posts placeholder por defecto" title="Vista posts placeholder por defecto" width="539" height="294" class="alignnone size-full wp-image-452 border" /></p>
<p>Lo cual es ciertamente <strong>mucho mejor</strong> y es la opción que se toma en el <em>screencast</em>, pero a nosotros tampoco nos ha convencido.</p>
<p>En nuestra opinión, el comportamiento más adecuado para la usabilidad sería que se cargara automáticamente por defecto el post más reciente. Para ello, lo que vamos a hacer un redirect de esta ruta <em><strong>posts/index</strong></em> a la ruta <em><strong>posts/:post_id</strong></em> con los valores del último post del modelo de datos. Por tanto, puesto que estamos alterando el comportamiento por defecto, tenemos que definir el objeto <strong><span class="sourcecode">PostsIndexRouter</span></strong> y dentro haremos las siguientes operaciones:</p>
<ul>
<li>
<p>Tomaremos el primer elemento del modelo de los posts, que será el último post publicado,</p>
</li>
<li>
<p>A continuación haremos una <a target="_blank" href="http://emberjs.com/api/classes/Ember.Route.html#method_transitionTo"><span class="sourcecode">transitionTo</span></a> a la ruta &#8216;post&#8217; con el modelo que antes hemos seleccionado.</p>
</li>
</ul>
<p>El código quedaría así:</p>
<pre class="brush: jscript; title: ; notranslate">
App.PostsIndexRoute = Ember.Route.extend({
  redirect: function () {
    var posts = this.modelFor('posts');
    var post = posts.get('firstObject');

    this.transitionTo('post', post);
  }
});
</pre>
<p>Pero no está todo bien aún, ya que nos vamos a topar con otro problema: con este código, es posible que el router de Ember intente hacer un redirect <strong>antes</strong> de que el modelo esté completamente cargado, con lo cual saltará un <strong>error en tiempo de ejecución</strong> y el redirect fallará. Para solucionar este problema, hemos tomado la decisión de tener una precarga de datos mediante <strong>bootstrapping</strong> de forma que si el primer post no ha sido cargado a la hora de hacer un redirect, lo tome del bootstrap. Añadiendo esta mejora en el código anterior, quedaría así:</p>
<pre class="brush: jscript; title: ; notranslate">
App.PostsIndexRoute = Ember.Route.extend({
  redirect: function () {
    var posts = this.modelFor('posts');
    var post = posts.get('firstObject');

    if(!post)
    {
        console.log(&quot;LOADING bootstrap'ed DATA&quot;);
        DS.get('defaultStore').load(App.Post, bootstrap);
        post = App.Post.find(1);
    }

    this.transitionTo('post', post);
  }
});
</pre>
<p>Donde <span class="sourcecode">bootstrap</span> es simplemente un objeto JavaScript donde hemos incluido los datos del último post. En producción esta variable será creada con datos dinámicos extraídos del server, claro <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3><span style="color: #008998;">Redireccinamos Index</span></h3>
<p>Relacionado con el paso anterior, al entrar a la index de la aplicación lo ideal sería que nos redireccionara a la lista de posts directamente (y si habéis implementado nuestra mejora, mostrara la vista <em>Detail</em> del primer post). Para esto, simplemente vamos a definir la ruta por defecto de la aplicación para que vaya a la ruta &lsquo;posts&rsquo; similarmente a como hemos hecho el <span class="sourcecode">redirectTo</span> en el paso anterior:</p>
<pre class="brush: jscript; title: ; notranslate">
  App.IndexRoute = Ember.Route.extend({
    redirect: function () {
      this.transitionTo('posts');
    }
  });
</pre>
<h3><span style="color: #008998;">Final: Conectando con server REST</span></h3>
<p>Este último paso no lo vamos a terminar en este ejemplo ya que no tenemos un <strong>servicio REST</strong> implementado en el servidor de este blog, pero podéis observar en el video que simplemente cambiando <span class="sourcecode">&#8216;DS.FixtureAdapter&#8217;</span> por <span class="sourcecode">DS.RESTAdapter</span> y especificando a qué URL tiene que atacar para que el server le pase los datos, ¡ya debería estar funcionando sin tocar ni una línea de código más! El resto de problemas, para el equipo de backend <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3><span style="color: #008998;">Conclusión</span></h3>
<p>Esperamos que este <em>step by step</em> así como el código que os mostramos os resulte útil y os ayude a seguir el <em>screencast</em> y a sumergiros en el mundo de Ember. Como ya comentamos en <a target="_blank" href="http://www.lostiemposcambian.com/blog/javascript/intro-framework-ember/">nuestra anterior intro a este framework</a>, nos parece que Ember tiene un potencial enorme y aunque muchas cosas todavía &#8220;crujen&#8221; al estar el framework en fase de desarrollo, estamos convencidos de que se puede apostar por él ya como una alternativa más que viable para producción de Web Apps JavaScript profesionales.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/javascript/tutorial-de-ember-screencast-paso-a-paso/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backgrid, componente Datagrid para Backbone</title>
		<link>http://www.lostiemposcambian.com/blog/javascript/backgrid-componente-datagrid-para-backbone/</link>
		<comments>http://www.lostiemposcambian.com/blog/javascript/backgrid-componente-datagrid-para-backbone/#comments</comments>
		<pubDate>Wed, 10 Apr 2013 09:00:00 +0000</pubDate>
		<dc:creator>danii</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[backbonejs]]></category>
		<category><![CDATA[datagrid]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=6201</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/javascript/backgrid-componente-datagrid-backbone"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/backgrid-componente-datagrid-backbone-js.jpg" alt="Backgrid componente Datagrid para Backbone" title="backgrid-componente-datagrid-backbone-js" width="539" height="332" class="alignnone size-full wp-image-452 border" /></a>

<p><a target="_blank" href="http://backgridjs.com/">Backgrid</a> es un componente Datagrid para el framework <a target="_blank" href="http://backbonejs.org/">Backbone</a>, pensado para construir <em>widgets datagrid</em> que sean <strong>semánticos y fácilmente adaptables</strong>. Al igual que al trabajar en el framework Backbone, la filosofia de este componente es que las tareas comunes sean fáciles de llevar a cabo, y a su vez posibilitar la realización de tareas difíciles o más especializadas posibilitando una fácil personalización y extensión de sus elementos.</p>]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/backgrid-componente-datagrid-backbone-js.jpg" alt="Backgrid componente Datagrid para Backbone" title="backgrid-componente-datagrid-backbone-js" width="539" height="332" class="alignnone size-full wp-image-452 border" /></p>
<p><a target="_blank" href="http://backgridjs.com/">Backgrid</a> es un componente Datagrid para el framework <a target="_blank" href="http://backbonejs.org/">Backbone</a>, pensado para construir <em>widgets datagrid</em> que sean <strong>semánticos y fácilmente adaptables</strong>. Al igual que al trabajar en el framework Backbone, la filosofia de este componente es que las tareas comunes sean fáciles de llevar a cabo, y a su vez posibilitar la realización de tareas difíciles o más especializadas posibilitando una fácil personalización y extensión de sus elementos.</p>
<p>Las principales ventajas de Backgrid son las siguientes:</p>
<ul>
<li>
<p><strong>Poca o nula curva de aprendizaje</strong>, ya que trabaja con simples modelos, colecciones y vistas de Backbone así que si ya estamos familiarizados con este framework no nos costará nada hacernos con el componente.</p>
</li>
<li>
<p><strong>Vista fácilmente personalizable</strong>. Al ser el <em>template</em> una tabla HTML es muy fácil de customizar los estilos via CSS, ya sea a nivel de cabecera (th) o fila (tr).</p>
</li>
<li>
<p><strong>Totalmente modular</strong>. Por supuesto, al igual que <strong>Backbone</strong>, es super liviano (<em>lightweight</em>) pero fácilmente extensible.</p>
</li>
</ul>
<h3><span style="color: #008998;">Demo: Datagrid con listado de Libros</span></h3>
<p>Vamos a ver un mini ejemplo muy reducido con tan solo <strong>seis filas</strong> pero esperamos que sea ilustrativo para ver cómo funciona el componente. El valor de cada celda se puede editar haciendo click sobre ella, y al hacerlo sobre la cabecera podemos ordenar los datos en función de los valores, excepto en el caso de la columna <strong>Imagen</strong>, que para esta demo hemos pensado que no tenía mucho sentido esta funcionalidad. <strong>Demo en funcionamiento:</strong></p>
<p><iframe src="http://lostiemposcambian.com/blog/posts/backgrid-backbone/datagrid.html" width="539" height="436" style="border:#CCCCCC 1px solid"></iframe></p>
<p style="background-color: #f5f5f5; text-align: center; padding: 10px 10px 10px 10px;">
<a href="http://lostiemposcambian.com/blog/posts/backgrid-backbone/backgrid-backbone-src.zip" target="_blank"><img title="download código fuente" src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2010/09/bt_download.jpg" alt="" width="232" height="32" /></a></p>
<h3><span style="color: #008998;">El Modelo</span></h3>
<p>El modelo que hemos utilizado para este ejemplo va a ser el mismo que usamos en las otras demos de los frameworks JavaScript. El <strong>objeto JSON</strong> con los datos que vamos a cargar del server será:</p>
<pre class="brush: jscript; title: ; notranslate">
[
   {
     'id': 1,
     'titulo': 'El Juego de Ender',
     'autor': 'Orson Scott Card',
     'editorial': 'Ediciones B / Zeta',
     'img': 'img/img1.jpg'
    },
    {
     'id': 2,
     'titulo': 'Juego de tronos',
     'autor': 'George R. R. Martin',
     'editorial': 'Gigamesh',
     'img': 'img/img2.jpg'
    },
    {
     'id': 3,
     'titulo': 'I robot',
     'autor': 'Isaac Asimov',
     'editorial': 'Edhasa',
     'img': 'img/img3.jpg'
    },
       ...
]
</pre>
<p>Para cargar el modelo, tan solo tenemos que definir la <strong>URL</strong> desde donde fetchearemos del server. El código es exactamente igual que al cargar un modelo de <strong>Backbone.js</strong> (que, de hecho, es lo que estamos haciendo!):</p>
<pre class="brush: jscript; title: ; notranslate">
  var Libro = Backbone.Model.extend({});

  var Libros = Backbone.Collection.extend({
    model: Libro,
    url: &amp;amp;quot;data/libros.json&amp;amp;quot;
  });

  var libros = new Libros();
  //cargamos modelo
  libros.fetch();

  //Inicializamos Datagrid
  var datagrid = new Backgrid.Grid({
    columns: columns,
    collection: libros
});
</pre>
<p>Una vez hemos definido el modelo y las columnas que vamos a visualizar, podemos inicializar el objeto Backgrid, que se comportará como una <em>Backbone.View</em>. De esta manera, posteriormente el modelo se cargará de <strong>forma totalmente asíncrona</strong> desde el server y nuestro objeto datagrid se actualizará con los datos.</p>
<h3><span style="color: #008998;">Las Celdas</span></h3>
<p>Backgrid viene por defecto con 10 tipos de celda predefinidos, con comportamientos y formatos asociados según el tipo de datos que pueden contener. Las celdas son editables por defecto al clickarlas, y la mayoría contienen algún tipo de lógica para presentar sus datos de manera legible y <em>friendly</em> para personas humanas. Para información más exhaustiva, os recomendamos por supuesto echarle un ojo a <a target="_blank" href="http://backgridjs.com/#api-cell">la API de las celdas</a>.</p>
<p>Por supuesto, podemos customizar extensivamente estos elementos, por ejemplo un <em>NumberCell</em> adaptado al formato <em>locale</em> hispano de números (que sería el contrario que el anglosajón, es decir <strong>coma</strong> para separar decimales y <strong>punto</strong> para separar los miles, millones etc) puede definirse así:</p>
<pre class="brush: jscript; title: ; notranslate">
  //Extendemos NumberCell para adaptarla
  //al formato locale hispano
  cell: Backgrid.NumberCell.extend({
    orderSeparator: '.',
    decimalSeparator: ','
  })
</pre>
<p>Es además muy sencillo utilizar objetos <em>formatters</em> para definir y adaptar estos tipos de celda añadiendo comportamientos adicionales que necesitemos. Por poner un ejemplo, en nuestra demo hemos decidido que vamos a mostrar en el front los títulos de los libros <strong>en mayúsculas</strong>, independientemente de cómo nos vengan en en modelo desde el server. Para ello, hemos definido un objeto <em>formatter</em> que simplemente debe implementar un método <em>fromRaw</em> para formatear los datos que nos vienen en el modelo, y otro <em>toRaw</em> para quitar el formato que hemos añadido y que no se guarde en el server.</p>
<pre class="brush: jscript; title: ; notranslate">
    //Extendemos StringCell para asginarle un obj formatter custom
    cell:  Backgrid.StringCell.extend({
      formatter:
        {
          toRaw: function(formattedValue) {
            return formattedValue.toLowerCase();
          },
          fromRaw: function(rawValue) {
            return rawValue.toUpperCase();
          }
        }
    })
</pre>
<p>Por supuesto las celdas al fin y al cabo extienden de la clase <a target="_blank" href="http://backbonejs.org/#View">Backbone.View</a>, así que podemos modificar totalmente cómo se renderizan definiendo <strong>templates</strong> para la clase e implementando el método <strong>render</strong>, como haríamos con cualquier <em>View</em> de Backbone.</p>
<p>En nuestro caso hemos utilizado este sistema para conseguir que aparezcan en el DataGrid las imágenes thumbnail de los libros, para lo que nos hemos definido una mini-plantilla de <a target="_blank" href="http://underscorejs.org/">Underscore</a>.</p>
<pre class="brush: jscript; title: ; notranslate">

  //Extendemos StringCell para asignar una template custom
  //en este caso, img tag
  cell: Backgrid.StringCell.extend({
      template: _.template('&amp;amp;lt;img width=&amp;amp;quot;32&amp;amp;quot; height=&amp;amp;quot;50&amp;amp;quot; src=&amp;amp;quot;&amp;amp;lt;%= img %&amp;amp;gt;&amp;amp;quot; /&amp;amp;gt;'),

      render: function() {
        this.$el.html(this.template(this.model.attributes));
        return this;
      }
  })
</pre>
<p>Como podéis observar, un sistema realmente potente que nos permitirá en todos los casos encontrar una celda que se adapte a nuestras necesidades, o customizarla de manera simple y efectiva si lo necesitamos.</p>
<h3><span style="color: #008998;">Demo: Datagrid con extensión Paginator</span></h3>
<p>¿Qué sería de un componente datagrid si no soportara <strong>paginación</strong> de los datos? Por supuesto Backgrid tiene una extensión pensada para esta tarea. Para utilizarla, debemos definir nuestra colección de datos como <a target="_blank" href="http://github.com/wyuenho/backbone-pageable/">Backbone.PageableCollection</a> que es una genial extensión de <em>Backbone.Collection</em> con funcionalidad adicional de paginación realizada por el mismo autor de <strong>Backgrid</strong>.</p>
<p><iframe src="http://lostiemposcambian.com/blog/posts/backgrid-backbone/datagrid-pag.html" width="539" height="233" style="border:#CCCCCC 1px solid"></iframe></p>
<p style="background-color: #f5f5f5; text-align: center; padding: 10px 10px 10px 10px;">
<a href="http://lostiemposcambian.com/blog/posts/backgrid-backbone/backgrid-backbone-src.zip" target="_blank"><img title="download código fuente" src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2010/09/bt_download.jpg" alt="" width="232" height="32" /></a></p>
<p>En este componente es el modelo el que debe que proveer, además de los datos, la información necesaria para las funciones de paginación, es decir la <strong>página actual</strong>, el <strong>número de items por página</strong> a mostrar y el <strong>número total de items</strong>, pero podemos personalizar el comportamiento para que la paginación se produzca en el <strong>cliente</strong> (es decir el server nos mandará un json con <strong>todos</strong> los datos) o en el <strong>server</strong> (y tendré que recuperar los datos de las diferentes páginas en <strong>sucesivas peticiones</strong> al server). El objeto JSON que recibimos del server quedaría por tanto así:</p>
<pre class="brush: jscript; title: ; notranslate">
[
    { 'per_page': 2, 'total_entries': 6,
      'total_pages': 3, 'page': 1
    },
    [
       {
         'id': 1,
         'titulo': 'El Juego de Ender',
         'autor': 'Orson Scott Card',
         'editorial': 'Ediciones B / Zeta',
         'img': 'img/img1.jpg'
        },
        {
         'id': 2,
         'titulo': 'Juego de tronos',
         'autor': 'George R. R. Martin',
         'editorial': 'Gigamesh',
         'img': 'img/img2.jpg'
        },
        ...
    ]
]
</pre>
<p>El resto del código del modelo quedaría igual, excepto el detalle antes mencionado de que en este caso nuestra <strong>colección de datos</strong> deberá extender de  <em>Backbone.PageableCollection</em></p>
<pre class="brush: jscript; title: ; notranslate">
//Inicializamos Datagrid, con paginación
//en el elemento footer
var datagrid = new Backgrid.Grid({
  columns: columns,
  collection: libros,
  footer: Backgrid.Extension.Paginator
});
</pre>
<p>Y por último la inicialización del objeto Backgrid en la que añadimos un elemento <em>footer</em> que contendrá la <strong>extensión paginator</strong> con las funciones esperadas de paginación. Great! <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3><span style="color: #008998;">Conclusión</span></h3>
<p>Esperamos que este componenete os haya parecido interesante, nos parece que se le puede sacar mucho jugo por la potencia que tiene y su facilidad de customización, ya sea mediante la adaptación de los elementos existentes o creando nuevas funcionalidades mediante extensiones. En resumen, una <strong>pequeña joya</strong> para nuestras aplicaciones JavaScript.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/javascript/backgrid-componente-datagrid-para-backbone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mejoras de usabilidad en el ecommerce. Panama Jack</title>
		<link>http://www.lostiemposcambian.com/blog/usabilidad/mejoras-de-usabilidad-en-el-ecommerce-panama-jack/</link>
		<comments>http://www.lostiemposcambian.com/blog/usabilidad/mejoras-de-usabilidad-en-el-ecommerce-panama-jack/#comments</comments>
		<pubDate>Mon, 08 Apr 2013 08:09:24 +0000</pubDate>
		<dc:creator>elad</dc:creator>
				<category><![CDATA[usabilidad]]></category>
		<category><![CDATA[ecommerce]]></category>
		<category><![CDATA[nitsnets]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=5859</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/usabilidad/mejoras-de-usabilidad-en-el-ecommerce-panama-jack"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/panamajack-usabilidad-ecommerce.jpg" alt="Mejoras de usabilidad en el ecommerce. Panama Jack" title="Mejoras de usabilidad en el ecommerce. Panama Jack" width="539" height="356" class="alignnone size-full wp-image-452 border" /></a>

Hace <strong>unos pocos días</strong> publicamos la nueva versión de uno de nuestros grandes clientes <a href="http://www.panamajack.es" target="_blank">Panama Jack</a>. Entre las nuevas mejoras de esta nueva versión se encuentra un nuevo diseño (realizado internamente por el departamento creativo de Panama Jack) y <strong>mejoras de usabilidad</strong>.

Durante este artículo reflexionaremos de <strong>algunas de estas mejoras de usabilidad</strong> a partir del <em>antes y después</em> del ecommerce. Esperemos que os sirvan para conocer más sobre nuestro punto de vista de la usabilidad en las tiendas online.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/panamajack-usabilidad-ecommerce.jpg" alt="Mejoras de usabilidad en el ecommerce. Panama Jack" title="Mejoras de usabilidad en el ecommerce. Panama Jack" width="539" height="356" class="alignnone size-full wp-image-452 border" /></p>
<p>Hace <strong>unos pocos días</strong> publicamos la nueva versión de uno de nuestros grandes clientes <a href="http://www.panamajack.es" target="_blank">Panama Jack</a>. Entre las nuevas mejoras de esta nueva versión se encuentra un nuevo diseño (realizado internamente por el departamento creativo de Panama Jack) y <strong>mejoras de usabilidad</strong>.</p>
<p>Durante este artículo reflexionaremos de <strong>algunas de estas mejoras de usabilidad</strong> a partir del <em>antes y después</em> del ecommerce. Esperemos que os sirvan para conocer más sobre nuestro punto de vista de la usabilidad en las tiendas online.</p>
<h3><span style="color: #008998;">Antes y después</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-home-2012-2013.jpg" alt="Panama Jack 2013. Antes y después" title="Panama Jack 2013. Antes y después" width="539" height="352" class="alignnone size-full wp-image-452 border" /></p>
<p>En principio se puede ver el restyling que se hizo de la home. Podemos observar la web nueva online directamente <a href="http://www.panamajack.es" target="_blank">www.panamajack.es</a> (también en esta captura: <a href="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-home-2013.png" target="_blank">Panama Jack home 2013</a>) y podemos observar la <a href="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-home-2012.jpg" target="_blank">home de la web anterior de Panama Jack</a>.</p>
<p>Las modificaciones han sido considerables en todos los aspectos pero nos queremos <strong>centrar en algunos elementos de usabilidad</strong>.</p>
<h3><span style="color: #008998;">Nueva cabecera. Menú desplegable <em>on-click</em></span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-cabecera-2012-2013.jpg" alt="Cabecera Panama Jack ecommerce 2012-2013" title="Cabecera Panama Jack ecommerce 2012-2013" width="539" height="252" class="alignnone size-full wp-image-452 border" /></p>
<p>La cabecera además de aplicarse un restyling (como en toda la web) se propuso una <strong>reducción considerable del alto</strong> para poder ver el producto lo más arriba posible.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-menu-desplegable-2013.png" alt="Menú desplegable Panama Jack ecommerce" title="Menú desplegable Panama Jack ecommerce" width="539" height="372" class="alignnone size-full wp-image-452 border" /></p>
<p>Por otro lado se han incluido las subcategorias de hombre y mujer como <strong>menús desplegables</strong>; consiguiendo así una <strong>reducción de clicks</strong>, evitando tener que hacer dos clicks en favor de uno sólo.</p>
<p>Se han <strong>cuidado otros muchos detallitos</strong> como por ejemplo el cambio de mercado / idioma  al ser una opción que se <em>autodetecta</em> y no se suele utilizar tiene menos presencia en la web y se puede cambiar las dos opciones de golpe desde un popup interior (antes eran dos desplegables)</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-seleccion-mercado-idioma-2012-2013.jpg" alt="Selección de mercado e idioma Panama Jack ecommerce 2013" title="Selección de mercado e idioma Panama Jack ecommerce 2013" width="539" height="234" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Listado de productos. 2 líneas de producto</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-listado-productos-2-lineas-usabilidad-2013.jpg" alt="Listado de productos. 2 líneas de producto. Panama Jack ecommerce 2013" title="Listado de productos. 2 líneas de producto. Panama Jack ecommerce 2013" width="539" height="362" class="alignnone size-full wp-image-452 border" /></p>
<p>Mediante la <strong>reducción de la cabecera</strong> y cuidando el alto (height) del resto de elementos conseguimos el objetivo de <strong>ver 2 líneas de producto </strong> en el primer impacto visual del listado en la resolución mínima de 1024&#215;768. Hay que tener en cuenta que la resolución del iPAD es de 1024&#215;768 y en el mercado de productos de calidad como es Panama Jack muchas ventas vienen habilitadas desde las tablets de Apple.</p>
<p>El objetivo era ver <em>ocho productos de una tacada</em> para llamar más la atención del comprador consiguiendo que en un primer golpe de vista pudiera interesarse y comprar más productos; eso sí sin dar la sensación de bazar ni bajar en exceso la correcta visualización del calzado, es decir intentando respetar las dimensiones de los zapatos que tan buenos resultados habían funcionado.</p>
<p>Si vemos las <a href="http://www.lostiemposcambian.com/blog/usabilidad/estadisticas-resolucion-de-pantallas-mas-utilizadas-en-la-web" target="_blank">estadísticas de resoluciones de pantalla en el desarrollo web</a> con una altura de 580px (altura útil) abarcamos aproximadamente a un 40%, otro 48% incluso vería más productos ya que tendría 700px de alto o más, tan sólo el 2% tiene una resolución inferior al 768px de alto con lo que no apreciarían esta mejora.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-carga-productos-listado-2013.jpg" alt="Carga de productos automática en listado Panama Jack ecommerce 2013" title="Carga de productos automática en listado Panama Jack ecommerce 2013" width="539" height="496" class="alignnone size-full wp-image-452 border" /></p>
<p>Por otro lado <strong>se eliminaron los paginadores</strong> al más <em>estilo Facebook</em> y con la detección del scroll sigue cargando productos. Sin necesidad de hacer click seguimos viendo productos hasta finalizar la visualización de todos <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3><span style="color: #008998;">Filtro de talla/color por AJAX</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-filtro-ajax-2013.jpg" alt="Filtro por AJAX ecommerce" title="Filtro por AJAX ecommerce" width="539" height="279" class="alignnone size-full wp-image-452 border" /></p>
<p>El filtro de tallas y colores del listado de productos se ha mejorado considerablemente.  El filtro se realiza por AJAX <strong>sin refresco de página ni botón aceptar</strong>, simplemente al clickear se refresca el listado. El usuario espera menos y ve su filtro mucho más rápido. También el ordenar cambia su forma de desplegable a un texto enlace plano con flechitas de arriba/abajo, más sutil y menos intrusivo.</p>
<p>Cuando se aplica un filtro se añade una franja informativa con la actual búsqueda para no perder al usuario, si se le da a la <strong>(x) se limpia el filtro</strong> y se vuelven a ver todos los productos de la categoría que se esta visualizando. Esta franja se redujo también a una sola línea (anteriormente eran varias).</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-resultado-filtro-2013-mark.jpg" alt="Filtro por AJAX. Franja informativa" title="Filtro por AJAX. Franja informativa" width="539" height="237" class="alignnone size-full wp-image-452 border" /></p>
<p>Eso sí, se quería mantener la posibilidad de copiar URLs (para enviarlas a un amigo, etc) incluso con los filtros aplicados. El objetivo era tener una funcionalidad para <strong>compartir el listado de productos con filtros</strong>. Se ha utilizado la técnica de <em>deeplinking</em> con <strong>#/</strong> para no perder esta importante funcionalidad pasando parámetros por la URL y rescatándolos posteriormente. Así se consigue una increíble funcionalidad que ni una de las mejores tiendas online del mundo como es <em>zara.com</em> la tiene mimada a este nivel <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-filtro-ajax-url-2013.jpg" alt="Filtro por AJAX. URL" title="Filtro por AJAX. URL" width="539" height="25" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Roll-over en los productos con fotografía en uso</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-rollover-productos-2013.jpg" alt="Roll-over en los productos con fotografía en uso Panama Jack ecommerce 2013" title="Roll-over en los productos con fotografía en uso Panama Jack ecommerce 2013" width="539" height="300" class="alignnone size-full wp-image-452 border" /></p>
<p>Esta mejora ya se aplicó en una versión anterior al restyling pero nos ha parecido muy interesante mencionarla. Al pasar por encima de un producto en el listado se realiza una sustitución de imagen con animación para ver otra vista del calzado o una <strong>visualización del calzado puesto en una persona</strong>. Con esta segunda opción de la vista de <em>cómo quedaría puesto</em> esta demostrado que el usuario <strong>se siente más atraído y compra más. </strong></p>
<h3><span style="color: #008998;">Ficha de producto</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-ficha-galeria-2012-2013.jpg" alt="Ficha de producto Panama Jack antes / después" title="Ficha de producto Panama Jack antes / después" width="539" height="351" class="alignnone size-full wp-image-452 border" /></p>
<p>La ficha de producto se ha modificado también considerablemente (<a href="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-ficha-2013.png" target="_blank">versión nueva ficha de producto</a> vs <a href="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-ficha-2012-big.jpg" target="_blank">versión antigua ficha de producto</a>). El objetivo volver a ver todo lo importante del producto en el caso extremo de 1024&#215;768 (con visibilidad de alto útil de 580px). Se tenía que ver <strong>todas las fotografías, el producto entero a la perfección y por supuesto el botón de comprar.</strong></p>
<p>La distribución de las <strong>miniaturas imágenes secundarias</strong> del producto cambia de estar debajo de la fotografía (que a ese golpe de vista no se apreciaba) a la parte de la <strong>izquierda</strong>. Sustituyendo al menú de categorías que ya no es necesario en esta ficha de producto ya que las encontramos en el menú desplegable.</p>
<p>El <strong>carrusel de imágenes se desplaza al pinchar sobre la elección de una imagen</strong>, de este modo se carga la nueva imagen y sin tener que desplazar el ratón puedes ir pinchando y viendo todas las vistas o imágenes del producto. Una funcionalidad muy cómoda que mejora la anterior web que tenías que pasar por encima de la miniatura (no hacías click pero obligaba a mover el ratón)</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-carrusel-ficha-producto-2013.jpg" alt="Carrusel ficha de producto Panama Jack ecommerce 2013" title="Carrusel ficha de producto Panama Jack ecommerce 2013" width="539" height="373" class="alignnone size-full wp-image-452 border" /></p>
<p>De igual modo en la resolución mínima de 1024&#215;768 la imagen se tenía que ver perfecta y centrada con la vertical. En algunos productos de la anterior web para ver bien el producto había que acabar haciendo scroll sobre la ficha de producto lo cual no genera el mismo impacto.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-ficha-producto-1024x768-20131.jpg" alt="Ficha producto con resolución 1024x768 Panama Jack ecommerce 2013" title="Ficha producto con resolución 1024x768 Panama Jack ecommerce 2013" width="539" height="379" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Carrito de la compra</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-carrito-2012-2013.jpg" alt="Carrito cesta de la compra Panama Jack ecommerce 2012-2013" title="Carrito cesta de la compra Panama Jack ecommerce 2012-2013" width="539" height="289" class="alignnone size-full wp-image-452 border" /></p>
<p>La cesta de la compra se ha diseñado con el concepto de la bolsa de campaña de Panama Jack con lo que se ha conseguido una <strong>cesta más corporativa y más visual.</strong><br />
Su utilidad de todas formas es inferior porque se ha realizado un proceso para evitar tener que pasar por la cesta de la compra para realizar tu pedido mediante <em>one-click</em>. </p>
<h3><span style="color: #008998;">Botón comprar. En un sólo click al proceso de compra</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/panamajack-seleccion-talla-2012-2013.jpg" alt="Botón comprar. En un sólo click al proceso de compra" title="Botón comprar. En un sólo click al proceso de compra" width="539" height="291" class="alignnone size-full wp-image-452 border" /></p>
<p>Normalmente en un proceso de compra en la ficha del producto indicas la cantidad de unidades que quieres del mismo. Pero después de meses analizando nuestro mercado nos dimos cuenta que Panama Jack es un producto de calidad que en la mayoría de los casos se compra un único par. Por eso se decidió <strong>eliminar el desplegable de cantidad y así quitar un click al usuario.</strong></p>
<p>En el anterior ecommerce una vez añadido el producto a la cesta; aparecía la cesta en el extremo superior derecha con un botón de comprar, al pinchar sobre el se iniciaba el proceso de compra y <em>checkout</em>. Con el nuevo diseño directamente al pinchar sobre comprar de la ficha de producto iniciamos este proceso de <em>checkout</em> evitando así dos clicks (el de selección de unidades y el de confirmar que quieres comprar). Hemos pasado de <strong>4 clicks a 2 clicks</strong> (elección de talla y comprar). De este modo reducimos el tiempo de un usuario en la finalización de la compra y se prevén más conversiones de venta.</p>
<h3><span style="color: #008998;">Conclusión</span></h3>
<p>Estas han sido algunas de las mejoras que hemos visto interesante contaros y que os pueden servir de utilidad.</p>
<p>En <a href="http://www.nitsnets.com" target="_blank">nitsnets | studios</a> cuidamos mucho los detalles de usabilidad dándole vueltas una y otra vez a procesos que pueden ser mejorados; unos procesos que dependen del producto que se vende, el mercado, sus usuarios, etc.</p>
<p>Las mejoras de usabilidad van a repercutir directamente en la utilización del site y producir más ventas con lo cual conseguimos mayor satisfacción del cliente. Esperamos seguir observando y estudiando los procesos para mejorar día a  día nuestros ecommerce.</p>
<p>En breve conoceremos si estas modificaciones en <a href="http://www.panamajack.es" target="_blank">www.panamajack.es</a> suponen un <strong>nuevo incremento en ventas</strong> y en la utilización del site del cual estamos convencidos de ello <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/usabilidad/mejoras-de-usabilidad-en-el-ecommerce-panama-jack/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Cuatro factores para el éxito de JavaScript</title>
		<link>http://www.lostiemposcambian.com/blog/javascript/cuatro-factores-para-el-exito-de-javascript/</link>
		<comments>http://www.lostiemposcambian.com/blog/javascript/cuatro-factores-para-el-exito-de-javascript/#comments</comments>
		<pubDate>Wed, 03 Apr 2013 10:29:22 +0000</pubDate>
		<dc:creator>danii</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[webapps]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=5907</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/cuatro-factores-para-exito-javascript"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/factores-exito-javascript.jpg" alt="Cuatro factores para el exito de JavaScript" title="Cuatro factores para el éxito de JavaScript" width="539" height="300" class="alignnone size-full wp-image-452 border" /></a>

<p>No vamos a esconder nuestra admiración por <a target="_blank" href="http://twitter.com/codinghorror">Jeff Atwood</a>, afamado autor del blog <a target="_blank" href="http://www.codinghorror.com/blog/">Coding Horror</a> y cofundador de <a target="_blank" href="http://stackoverflow.com">Stackoverflow</a> y ahora <a target="_blank" href="http://discourse.org">Discourse</a>, una aplicacion JavaScript open source para foros de discusión desarrollada en <a target="_blank" href="http://www.lostiemposcambian.com/blog/javascript/intro-framework-ember/">Ember.js</a>. Precisamente fue en el evento <a target="_blank" href="http://www.embercamp.com/">EmberCamp 2013</a>, durante la charla de clausura que Atwood hizo algunas reflexiones muy interesantes sobre el pasado y el futuro de <strong>JavaScript</strong> y las <strong>aplicaciones</strong> y el <strong>desarrollo web</strong> en general.</p>

<p>No olvidemos que fue allá por 2007, con la <strong>web 2.0</strong> aún prácticamente en pañales, cuando Atwood publicó en su blog la (narcisísticamente nombrada) <a target="_blank" href="http://www.codinghorror.com/blog/2007/07/the-principle-of-least-power.html">Atwood&#8217;s Law</a>:</p>

<blockquote><span class="bqstart">&#8220;</span>Any aplication that <em>can</em> be written in JavaScript, <em>will</em> eventually be  be written in JavaScript<span class="bqend">&#8221;</span></blockquote>

<p>¡No se puede ser más profético!</p>

<p>Entre otras cosas, Atwood destaca <strong>cuatro factores</strong> (ya sean características de JavaScript o circunstanciales) que han contribuido al auge de este lenguaje y su actual popularidad entre los desarrolladores.</p>]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/factores-exito-javascript.jpg" alt="Cuatro factores para el exito de JavaScript" title="Cuatro factores para el éxito de JavaScript" width="539" height="300" class="alignnone size-full wp-image-452 border" /></p>
<p>No vamos a esconder nuestra admiración en este blog por <a target="_blank" href="http://twitter.com/codinghorror">Jeff Atwood</a>, afamado autor del blog <a target="_blank" href="http://www.codinghorror.com/blog/">Coding Horror</a> y cofundador de <a target="_blank" href="http://stackoverflow.com">Stackoverflow</a> y ahora <a target="_blank" href="http://discourse.org">Discourse</a>, una aplicacion JavaScript open source para foros de discusión desarrollada en <a target="_blank" href="http://www.lostiemposcambian.com/blog/javascript/intro-framework-ember/">Ember.js</a>. Precisamente fue en el evento <a target="_blank" href="http://www.embercamp.com/">EmberCamp 2013</a>, durante la charla de clausura que Atwood hizo algunas reflexiones muy interesantes sobre el pasado y el futuro de <strong>JavaScript</strong> y las <strong>aplicaciones</strong> y el <strong>desarrollo web</strong> en general.</p>
<p>No olvidemos que fue allá por 2007, con la <strong>web 2.0</strong> aún prácticamente en pañales, cuando Atwood publicó en su blog la (narcisísticamente nombrada) <a target="_blank" href="http://www.codinghorror.com/blog/2007/07/the-principle-of-least-power.html">Atwood&rsquo;s Law</a>:</p>
<blockquote><p><span class="bqstart">&#8220;</span>Any aplication that <em>can</em> be written in JavaScript, <em>will</em> eventually be  be written in JavaScript<span class="bqend">&#8221;</span></p></blockquote>
<p>¡No se puede ser más profético!</p>
<p>Entre otras cosas, Atwood destaca <strong>cuatro factores</strong> (ya sean características de JavaScript o circunstanciales) que han contribuido al auge de este lenguaje y su actual popularidad entre los desarrolladores.</p>
<ul>
<li>
<h3><span style="color: #008998;">Ubicuidad</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/javascript-everywhere.jpg" alt="JavaScript es ubicuo: se encuentra en todas partes" title="javascript-everywhere" width="510" height="383" class="alignnone size-full wp-image-452 border" /></p>
<p>Javascript ciertamente es un lenguaje de programación anticuado,  simple, limitado y no particularmente rápido, pero <strong>gana por defecto</strong>: todo el mundo tiene o quiere acceder a internet, por consiguiente navega en internet a traves de un navegador, y todos los navegadores ejecutan JavaScript.</p>
<blockquote><p><span class="bqstart">&#8220;</span><em>JavaScript is the world&rsquo;s most ubiquitous computing runtime</em> &#8211; Jeff Atwood, 2013<span class="bqend">&#8221;</span></p></blockquote>
<p>Podemos decir sin duda que JavaScript ha triunfado donde <strong>Java</strong> fracasó totalmente, ya que la inmensa mayoría de dispositivos lo ejecutan sin problemas, lo cual nos lleva al siguiente punto:</p>
</li>
<li>
<h3><span style="color: #008998;">Increíbles mejoras en rendimiento</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/sunspider-benchmark-results-js.jpg" alt="Mejoras en rendimiento de JavaScript" title="sunspider-benchmark-results-js" width="510" height="274" class="alignnone size-full wp-image-452 border" /><br />
<em>Slide con los datos tomada de la presentación de Jeff Atwood</em></p>
<p>El benchmark de JavaScript Sunspider que en 2007 se ejecutaba en entre 5 y 20 segundos dependiendo del navegador, apenas alcanza hoy en día un tiempo de ejecución de <strong>poco más de 100 ms</strong> en navegadores modernos. Actualmente, los <a target="_blank" href="http://www.lostiemposcambian.com/blog/web-2-0/claves-rendimiento-navegadores-web-layout-javascript-engine/#js">motores de ejecución de JavaScript</a> siguen mejorando, y aunque el ritmo explosivo de incremento de velocidad de ejecución se ha enfriado un poco, lo cierto es que actualmente JavaScript puede ejecutar <em>CASI</em> cualquier tipo de aplicación en un navegador moderno.</p>
<p>Incluso los dispositivos móbiles, sospechosos habituales, están duplicando su potencia de ejecución en menos de un año actualmente (son los únicos computadores que siguen cumpliendo la <a target="_blank" href="http://en.wikipedia.org/wiki/Moore's_law">ley de Moore</a>) y no tienen problemas en ejecutar código JavaScript cada vez más complejo.</p>
</li>
<li>
<h3><span style="color: #008998;">Open Source</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/04/js-open-source.jpg" alt="JavaScript es Open Source :)" title="js-open-source" width="510" height="158" class="alignnone size-full wp-image-452 border" /></p>
<p>El código JavaScript es es abierto por defecto, podemos acceder a él simplemente utilizando <em>&ndash;>View Page Source</em> en el navegador, o cualquier herramienta de inspección o desarrollo web. Esto lo convierte en totalmente <strong>Open Source</strong>, ya que aunque es cierto que el código puede ofucscarse, no hay forma de evitar que sea examinado.</p>
<p>Hace unos años era impensable que una industria software funcionase totalmente basada en código abierto, pero JavaScript y las aplicaciones web están demostrando que no solo es viable sino también muy beneficioso para la <strong>comunidad de desarrolladores</strong>, al fomentar una dispersión del conocimiento, know-how, buenas prácticas etc.</p>
</li>
<li>
<h3><span style="color: #008998;">Web User Experience</span></h3>
<p><a target="_blank" href="http://xkcd.com/1174/"><br />
<img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/xkcd-download-our-app.jpg" alt="XKCD download our app!" title="xkcd-download-our-app" width="510" height="256" class="alignnone size-full wp-image-452 border" /><br />
</a><em>El genial <a target="_blank" href="http://xkcd.com/1174/">http://xkcd.com/1174/</a> </em></p>
<p>Es cierto que a pesar de las mejoras en rendimiento a las que nos hemos referido anteriormente, una <strong>aplicación software nativa</strong> (ya sea de escritorio o mobile) siempre se va a ejecutar mucho más eficientemente que una aplicación JavaScript en un navegador. Sin embargo, por el hecho de estar ejecutando nuestra aplicación dentro de un navegador tenemos muchas otras ventajas intrínsecas, principalmente a nivel de <strong>experiencia de usuario</strong> donde el navegador implementa por defecto funcionalidades que el usuario da por supuestas como <strong>copy&amp;paste</strong>, <strong>bookmarking</strong> y <strong>compartir</strong> fácilmente estados a través de URLs o <strong>zoom in &amp; zoom out</strong>, omisiones en ocasiones realmente molestas en el caso de <strong>aplicaciones mobile</strong>.</p>
<p>La conclusión es que la tendencia por tanto será el alejarse de las páginas webs tradicionales basadas en contenido estático presentado mediante HTML y con formato CSS y entrar en el mundo de las <strong>aplicaciones JavaScript</strong>. El sitio web será cada vez más una <em>aplicación</em> con funcionalidades y menos una <em>página</em> de información estática.</p>
</li>
<p>Os dejamos por último con el video completo de la charla (en inglés claro):</p>
<p><iframe width="539" height="303" src="http://www.youtube.com/embed/ncrwsg33TtI" frameborder="0" allowfullscreen></iframe></p>
<p>Durante la charla y la ronda de preguntas y respuestas posterior se habla también de otros tópicos muy interesantes relacionados con el desarrollo web y el mundo de la web en general tales como <strong>Progressive Enhancement</strong> y si tiene sentido en el contexto de la web actual, <strong>Ruby vs PHP</strong> (y que nadie se sorprenda de los palos que recibe PHP), qué le falta al entorno <strong><a target="_blank" href="http://nodejs.org/">Node.js</a></strong> para terminar de despegar y las comunidades alrededor de un producto que se crean gracias al <strong>código Open Source</strong> y beneficios asociados, y más. Totalmente recomendable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/javascript/cuatro-factores-para-el-exito-de-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Estadísticas resolución de pantallas más utilizadas en la web</title>
		<link>http://www.lostiemposcambian.com/blog/usabilidad/estadisticas-resolucion-de-pantallas-mas-utilizadas-en-la-web/</link>
		<comments>http://www.lostiemposcambian.com/blog/usabilidad/estadisticas-resolucion-de-pantallas-mas-utilizadas-en-la-web/#comments</comments>
		<pubDate>Mon, 01 Apr 2013 10:46:19 +0000</pubDate>
		<dc:creator>elad</dc:creator>
				<category><![CDATA[usabilidad]]></category>
		<category><![CDATA[estadísticas]]></category>

		<guid isPermaLink="false">http://www.lostiemposcambian.com/blog/?p=5315</guid>
		<description><![CDATA[<a href="http://www.lostiemposcambian.com/blog/usabilidad/estadisticas-resolucion-de-pantallas-mas-utilizadas-en-la-web"><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/estadisticas-resolucion-de-pantallas-mas-utilizadas-en-la-web-enero-2013.jpg" alt="Estadísticas resolución de pantallas más utilizadas en la web" title="Estadísticas resolución de pantallas más utilizadas en la web" width="539" height="303" class="alignnone size-full wp-image-452 border" /></a>

Hace un tiempo que queríamos escribir un artículo sobre las estadísticas de resolución de pantallas más usadas en la web. Estas estadísticas son datos muy importantes para conocer cuales son las dimensiones de pantalla de los usuarios, a qué público vamos dirigidos, etc... y así poder tenerlo en cuenta en la <strong>usabilidad</strong> de nuestro website.

Con la aparición de los <strong>tablets</strong> y los <strong>smartphones</strong> el abanico de tamaños de pantalla se ha expandido considerablemente, apareciendo muchísimas dimensiones diferentes y rebajando incluso los porcentajes de los formatos más estándares.

Desde hace ya unos años en el desarrollo web se ha sustituido en cierta medida el <strong>problema de la compatibilidad de navegadores</strong> (gracias a que poco a poco todas las compañías se están ciñendo a los estándares con HTML5/CSS3 y otras se basan directamente en web-kit) por el <strong>problema de las resoluciones de los dispositivos</strong>.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/estadisticas-resolucion-de-pantallas-mas-utilizadas-en-la-web-enero-2013.jpg" alt="Estadísticas resolución de pantallas más utilizadas en la web. Enero 2013" title="Estadísticas resolución de pantallas más utilizadas en la web. Enero 2013" width="539" height="303" class="alignnone size-full wp-image-452 border" /><br />
<span style="font-size:10pt; "><em>Imagen original propiedad del artículo de <a href="http://punchcut.com/perspectives/expanding-universe-toolset-managing-screen-resolutions" target="_blank">Punchcut</a> (modificada para añadir <strong>1366&#215;768</strong>)</em></span></p>
<p>Hace un tiempo que queríamos escribir un artículo sobre las estadísticas de resolución de pantallas más usadas en la web. Estas estadísticas son datos muy importantes para conocer cuales son las dimensiones de pantalla de los usuarios, a qué público vamos dirigidos, etc&#8230; y así poder tenerlo en cuenta en la <strong>usabilidad</strong> de nuestro website.</p>
<p>Con la aparición de los <strong>tablets</strong> y los <strong>smartphones</strong> el abanico de tamaños de pantalla se ha expandido considerablemente, apareciendo muchísimas dimensiones diferentes y rebajando incluso los porcentajes de los formatos más estándares.</p>
<p>Desde hace ya unos años en el desarrollo web se ha sustituido en cierta medida el <strong>problema de la compatibilidad de navegadores</strong> (gracias a que poco a poco todas las compañías se están ciñendo a los estándares con HTML5/CSS3 y otras se basan directamente en web-kit) por el <strong>problema de las resoluciones de los dispositivos</strong>.</p>
<h3><span style="color: #008998;">Fuentes de datos. Enero 2013</span></h3>
<p>Las fuentes de datos estadísticos analizadas en este artículo recopilan datos actualizados en <strong>Enero de 2013</strong>:</p>
<ul>
<li><a href="http://gs.statcounter.com/#resolution-ww-monthly-201202-201302" target="_blank"><strong>Statcounter.com</strong></a>. Basadas en 15 mil millones de páginas vistas al mes (3 millones de sites)</li>
<li><a href="http://www.w3counter.com/globalstats.php" target="_blank"><strong>W3schools</strong></a>. Se realizan a partir de las visitas obtenidas durante los últimos 10 años a <a href="http://www.w3schools.com" target="_blank">www.w3schools.com</a>. Hay que tener en cuenta que la web de W3schools es para usuarios interesados en tecnologías web por lo que estos números podrían no ser 100% fiables en un usuario de internet medio, aún así nos permite servirnos de referencia. <a href="http://www.w3schools.com/browsers/browsers_display.asp" target="_blank">Estadísticas de resolución de pantalla en la web</a> y <a href="http://www.w3schools.com/browsers/browsers_resolution_higher.asp" target="_blank">Estadísticas de Altas resoluciones de pantalla de los navegadores web</a></li>
<li><a href="http://www.w3counter.com/globalstats.php" target="_blank"><strong>W3Counter</strong></a> Realtime Web Analytics for Websites and Blogs</li>
<li><a href="http://http://www.screenresolution.org/" target="_blank"><strong>Screenresolution.org</strong></a></li>
<li><a href="http://www.netmarketshare.com/report.aspx?qprid=17" target="_blank"><strong>Netmarketshare.com</strong></a></li>
</ul>
<h3><span style="color: #008998;">Resolución de pantalla de los navegadores web</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/estadisticas-resolucion-pantalla-web-statcounter-enero2013.jpg" alt="estadísticas resolución de pantalla web Statcounter.com Enero 2013" title="estadísticas resolución de pantalla web Statcounter.com Enero 2013" width="539" height="348" class="alignnone size-full wp-image-452 border" /></p>
<p>Durante muchos años el desarrollo web se ha basado en la resolución estándar de <strong>1024&#215;768</strong> <em>(hace apenas 3 años aproximadamente el 40% de los usuarios tenía esta resolución)</em>. En la <strong>actualidad</strong> ya no es la resolución más utilizada, actualmente <strong>es 1366&#215;768 es la resolución más usada en internet</strong> que es la resolución estándar de Windows 8.</p>
<p>Estadísticas de las resoluciones de pantalla más usadas en Internet (las fuentes de datos coinciden en su tendencia):</p>
<p><style>
table {
border: 1px solid black;
border-spacing: 0px;
}
td {</p>
<p>border-style: inset;
padding: 2px;
}
</style>
<table>
<tr style="background-color: #CCCCCC;">
<td width="300">
resolución
</td>
<td width="239">
% utilización Enero 2013
</td>
</tr>
<tr>
<td>
1366&#215;768
</td>
<td>
20-25%
</td>
</tr>
<tr style="background-color: #F5F5F5;">
<td>
<strong>1024&#215;768</strong>
</td>
<td>
<strong>10-15%</strong>
</td>
</tr>
<tr>
<td>
1280&#215;1024
</td>
<td>
8-10%
</td>
</tr>
<tr>
<td>
1280&#215;800
</td>
<td>
8-10%
</td>
</tr>
<tr>
<td>
1920&#215;1080
</td>
<td>
6-10%
</td>
</tr>
<tr>
<td>
1920&#215;1080
</td>
<td>
6-10%
</td>
</tr>
<tr>
<td>
800&#215;600
</td>
<td>
2%
</td>
</tr>
</table>
<p style="padding-top:20px">
La solución técnica que se le ha dado en el desarrollo web al problema de esta diversidad de resoluciones web se llama <a href="http://es.wikipedia.org/wiki/Dise%C3%B1o_web_adaptativo" target="_blank">Responsive Web Design</a> que nos permite hacer interfaces adaptadas al entorno del usuario mediante estructuras e imágenes fluidas gracias a <em>media-queries de CSS</em>.<br />
Podemos ver algunos increíbles ejemplos en <a hef="http://thenextweb.com/dd/2013/01/13/30-new-inspiring-responsive-design-websites/1/" target="_blank">The Next Web: 29 new inspiring responsive designs on the web</a> con ejemplos como la <em>BBC, Disney, Time</em>&#8230;</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/bbc-responsive-web-design.jpg" alt="BBC Responsive Web Design" title="BBC Responsive Web Design" width="539" height="317" class="alignnone size-full wp-image-452 border" /></p>
<p>En muchas ocasiones se toma un tamaño mínimo como base para el diseño inicial y a pesar de que ya no es el estándar <strong>se sigue desarrollando como base el formato mínimo 1024&#215;768</strong>, ya que no se puede despreciar a un <strong>10-15%</strong> <em>(no sucede lo mismo con 800&#215;600)</em>.</p>
<p>Es fundamental tener en cuenta este tamaño mínimo de 1024&#215;768 para la usabilidad y el primer impacto del usuario. Cómo las barras de navegación y scrolls tienen un tamaño, el <strong>área visible y útil</strong> de esta resolución sería <strong>990&#215;580</strong> aproximadamente<em> (muy utilizado en la antigüedad con Flash <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</em>. Es en esta área donde se mostrará el primer mensaje, lo imprescindible de tu producto, el botón de compra, etc.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/resolucion-pantalla-web-1024x768.jpg" alt="resolución de pantalla web 1024x768" title="resolución de pantalla web 1024x768" width="539" height="435" class="alignnone size-full wp-image-452 border" /></p>
<p>De todas formas en nuestra opinión, quizás un tanto polémica, es que el <em>Responsive Web Design</em> es la mejor solución desde pantallas de iMac de 27&#8243; hasta los ipads mini de 7&#8243; o incluso un poco menos; pero cuando se trata de desarrollar para smartphones los procesos deben ser distintos ya que su caso de uso es distinto y por tanto deberíamos crear una versión o vista específica para este tipo de dispositivos, sobretodo si hablamos de e-commerce o software (no tanto en páginas meramente informativas). Así lo hicimos en <a href="http://www.actiu.com" target="_blank">actiu.com</a></p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/actiu-website-iphone.jpg" alt="Actiu versión website y mobile" title="Actiu versión website y mobile" width="539" height="393" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">La mejor fuente de datos: nuestra propia web</span></h3>
<p>De todas formas, aunque todas estas estadísticas son muy interesantes es muy importante estudiar nuestra propia web y nuestros propios usuarios; al final pese a que mundialmente existan unos datos lo mejor es ver quién es nuestro público concreto. Mediante <a href="https://www.google.com/analytics/" target="_blank">Googe Analytics</a> vamos a poder hacer este estudio viendo las tendencias de nuestros visitantes.</p>
<p>Deberíamos fijarnos también de los usuarios que abandonan la web rápidamente, sus resoluciones y navegadores; quizás su salida del site sea por una mala o no correcta visualización de la web y no tanto porque el contenido no le interesaba. Debemos ser muy sensibles con esto <img src='http://www.lostiemposcambian.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>En nuestro caso en concreto de <strong>lostiemposcambian.com</strong> los datos de los últimos 30 días son similares a los explicados en el artículo:</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/estadisticas-lostiemposcambian-resolucion-marzo2013.jpg" alt="estadísticas resolución de pantallas lostiemposcambian.com marzo 2013" title="estadísticas resolución de pantallas lostiemposcambian.com marzo 2013" width="539" height="257" class="alignnone size-full wp-image-452 border" /></p>
<h3><span style="color: #008998;">Browserstack.com la mejor solución para test en navegadores, dispositivos y resoluciones de pantalla</span></h3>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/browserstack-mejor-solucion-test-navegadores-web-resoluciones.jpg" alt="Browserstack.com la mejor solución para test en navegadores, dispositivos y resoluciones de pantalla" title="Browserstack.com la mejor solución para test en navegadores, dispositivos y resoluciones de pantalla" width="539" height="338" class="alignnone size-full wp-image-452 border" /></p>
<p>La solución en la nube de <a href="http://www.browserstack.com/" target="_blank">www.browserstack.com</a> a nitsnets | studios nos ha cambiado la vida. Pese a no ser una solución muy rápida es una herramienta que nos está ayudando mucho desde el primer día y 100% recomendable; gracias a mi amigo <a href="http://www.twitter.com/joseleperez" target="_blank">Josele</a> que nos la descubrió.</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/browserstack-opciones-dispositivos-navegadores-resolucion.jpg" alt="Browserstack.com opciones navegadores, dispositivos y resoluciones de pantalla" title="Browserstack.com opciones navegadores, dispositivos y resoluciones de pantalla" width="539" height="600" class="alignnone size-full wp-image-452 border" /></p>
<p>Consiste en una solución cloud donde probar nuestro desarrollo web en cualquier navegador web así como en cualquier dispositivo en real (hay muchos). Se acabó tener máquinas virtuales para probar los Internet Explorer antiguos, simuladores de tablets y smartphones, comprar varios dispositivos para pruebas, máquinas virtuales en la oficina, etc&#8230;</p>
<p><img src="http://www.lostiemposcambian.com/blog/wp-content/uploads/2013/03/browserstack-lostiemposcambian-ie7-1024x768.jpg" alt="Browserstack.com con www.lostiemposcambian.com ie7 1024x768" title="Browserstack.com con www.lostiemposcambian.com ie7 1024x768" width="539" height="334" class="alignnone size-full wp-image-452 border" /></p>
<p>Aquí podemos ver como se vería lostiemposcambian.com en <em>Windows XP con Internet Explorer 7 a una resolución de 1024&#215;768</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lostiemposcambian.com/blog/usabilidad/estadisticas-resolucion-de-pantallas-mas-utilizadas-en-la-web/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
