<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Fernando Espinosa - Ferdev</title>
    <link>http://www.ferdev.com</link>
    <language>es</language>
    <webMaster>fer@ferdev.com (Fernando Espinosa Jiménez)</webMaster>
    <pubDate>2011-03-05T23:57:47+01:00</pubDate>
    <copyright>Copyright 2009-2010</copyright>
    <ttl>60</ttl>
    <description>Freelance Ruby on Rails developer</description>
    
    <item>
      <title>Cambiar el idioma a selenium</title>
      <link>http://www.ferdev.com/2010/08/14/cambiar-idioma-selenium.blog.html</link>
      <pubDate>Sat Aug 14 00:00:00 +0200 2010</pubDate>
      <guid>http://www.ferdev.com/2010/08/14/cambiar-idioma-selenium.blog.html</guid>
      <description>&lt;p&gt;Ayer me encontré con un problema haciendo tests para un pet-project que estoy haciendo con Rails3 3.0.0.rc. Parece ser que a partir de la versión 1.0.0.beta.9 de &lt;a href='http://github.com/carlhuda/bundler' title='Bundler'&gt;bundler&lt;/a&gt;, culerity lanza un error a la hora de crear el browser con celerity. Mientras investigo el problema, no quería dejar el desarrollo parado, así que decidí cambiar el driver de &lt;a href='http://github.com/jnicklas/capybara' title='Capybara'&gt;capybara&lt;/a&gt; a selenium. Pero el firefox que trae el driver de selenium integrado se me ejecutaba en castellano, y yo tengo los tests escritos en inglés, por lo que fallaban. Tras twittear buscando ayuda, &lt;a href='http://twitter.com/pacoguzman/status/21053477686' title='@pacoguzman tweet'&gt;@pacoguzman me pasó un link&lt;/a&gt;(gracias!) de la gente de &lt;a href='http://teambox.com/' title='Teambox'&gt;Teambox&lt;/a&gt; que tenía la clave para solucionarlo.&lt;/p&gt;

&lt;p&gt;Lo solución consiste en extraer el profile del driver de selenium, pasarle la nueva clave del idioma, y volver a asignar el profile al driver de selenium. La clave que había que pasar era &amp;#8216;intl.accept_languages&amp;#8217; (sacado de hacer un about:config en mi Firefox y buscar un poco) junto con el lenguaje que quieras usarlo, en mi caso &amp;#8216;en&amp;#8217;. Como yo estoy usando &lt;a href='http://github.com/cavalle/steak' title='Steak'&gt;Steak&lt;/a&gt; para mis test de aceptación, incorporé el código en el archivo de configuración &amp;#8216;spec/acceptance/acceptance_helper.rb&amp;#8217;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='no'&gt;Capybara&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Driver&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Selenium&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;class_eval&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;driver&lt;/span&gt;
      &lt;span class='vi'&gt;@driver&lt;/span&gt; &lt;span class='o'&gt;||=&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt;
        &lt;span class='n'&gt;profile&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Selenium&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;WebDriver&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Firefox&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Profile&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; 
        &lt;span class='n'&gt;profile&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;intl.accept_languages&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
        &lt;span class='n'&gt;driver&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Selenium&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;WebDriver&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;for&lt;/span&gt; &lt;span class='ss'&gt;:firefox&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:profile&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;profile&lt;/span&gt;
        &lt;span class='nb'&gt;at_exit&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;driver&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;quit&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
        &lt;span class='n'&gt;driver&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Y listo, selenium en inglés y todos los tests pasando!&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/rails"></category>
      
      <category domain="http://www.ferdev.com/tag/testing"></category>
      
      <category domain="http://www.ferdev.com/tag/capybara"></category>
      
      <category domain="http://www.ferdev.com/tag/selenium"></category>
      
    </item>
    
    <item>
      <title>Blog migrado a Jekyll</title>
      <link>http://www.ferdev.com/2010/07/05/blog-migrado-a-jekyll.html</link>
      <pubDate>Mon Jul 05 00:00:00 +0200 2010</pubDate>
      <guid>http://www.ferdev.com/2010/07/05/blog-migrado-a-jekyll.html</guid>
      <description>&lt;p&gt;La semana pasada me lié la manta a la cabeza y me puse a migrar todo el blog de Wordpress a &lt;a href='http://jekyllrb.com/' title='transform your texto into a monster'&gt;Jekyll&lt;/a&gt;. Los motivos que me han llevado a moverlo a Jekyll son dos: velocidad y sencillez. Jekyll es un generador de sitios web estáticos programado en ruby. Jekyll genera a partir de plantillas y ficheros &lt;a href='http://daringfireball.net/projects/markdown/' title='Markdown'&gt;markdown&lt;/a&gt; o &lt;a href='http://textile.thresholdstate.com/' title='Textile'&gt;textile&lt;/a&gt;, ficheros html y xml (entre otras cosas). Al ser contenido estático, pierdes algunas cosas como el sistema de comentarios. Pero con &lt;a href='http://disqus.com/' title='Disqus'&gt;Disqus&lt;/a&gt; o &lt;a href='http://intensedebate.com/' title='Intense Debate'&gt;IntenseDebate&lt;/a&gt; queda solucionado el problema.&lt;/p&gt;

&lt;p&gt;De paso he aprovechado para hacer un pequeño rediseño, y ahora tengo todo el contenido de la web en el mismo html, y mediante un pequeño javascript se realiza el scroll entre las diferentes secciones. Simplemente obtiene el atributo &amp;#8216;href&amp;#8217; del enlace, obtiene el elemento al que referencia y su offset vertical, y anima el desplazamiento del cursor principal hasta esa posición. Además degrada bien si el usuario no tiene el javascript activado.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#menu li a&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;live&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;evt&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
  &lt;span class='nx'&gt;evt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;preventDefault&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
  &lt;span class='kd'&gt;var&lt;/span&gt; 
    &lt;span class='nx'&gt;destination_id&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;attr&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;href&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
    &lt;span class='nx'&gt;scrollTo&lt;/span&gt;       &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;destination_id&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;offset&lt;/span&gt;&lt;span class='p'&gt;().&lt;/span&gt;&lt;span class='nx'&gt;top&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;html,body&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;animate&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='nx'&gt;scrollTop&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;scrollTo&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='mi'&gt;2000&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;easeInOutExpo&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;He publicado el código fuente del blog por si queréis echarle un vistazo (aunque no tiene gran cosa que ver). Todavía no está terminado, faltan algunas cosas como la paginación de posts y algunos retoques más, pero como ya es funcional me he decidido a publicarlo.&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/blog"></category>
      
      <category domain="http://www.ferdev.com/tag/jekyll"></category>
      
    </item>
    
    <item>
      <title>RightJS, un framework javascript muy interesante</title>
      <link>http://www.ferdev.com/2010/05/10/rightjs-un-framework-javascript-muy-interesante.html</link>
      <pubDate>Mon May 10 00:00:00 +0200 2010</pubDate>
      <guid>http://www.ferdev.com/2010/05/10/rightjs-un-framework-javascript-muy-interesante.html</guid>
      <description>&lt;p&gt;Llevaba tiempo queriendo escribir acerca de este framework javascript, uno de los más interesantes del momento. Quizá no sea tan conocido como jQuery o MooTools, pero en mi opinión merece estar tan arriba como ellos. Además, ciertos elementos de su sintaxis resultarán familiares a los rubistas. Más adelante explicaré cuales.&lt;/p&gt;

&lt;p&gt;La mejor manera de hablar de &lt;a href='http://rightjs.org' title='The Right JavaScript Framework'&gt;RightJS&lt;/a&gt; es comentar sus características principales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sintaxis sencilla y curva de aprendizaje baja. Si ya conoces otro framework como jQuery o Prototype, te costará muy poco aprender RightJS.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Posiblemente&lt;/strong&gt;, el más rápido de todos los frameworks JavaScript. Difícil de demostrar, pero &lt;a href='http://rightjs.org/benchmarks'&gt;diversos tests&lt;/a&gt; parecen corroborarlo. No sé si el más rápido, pero desde luego es rapidísimo.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Llamadas a funciones por nombre. Muchas veces tenemos el típico callback para acceder a un método del propio objeto. Con RightJS no necesitaremos dicho callback, símplemente pasaremos el nombre de la función como string.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// Modo habitual&lt;/span&gt;
&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;element&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;onClick&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;hide&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;

&lt;span class='c1'&gt;// Usando llamadas por nombre&lt;/span&gt;
&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;element&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;onClick&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;hide&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Soporte en navegadores más antiguos de la última especificación JavaScript/ECMAScript. Por ejemplo:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href='http://rightjs.org/docs/array#filter'&gt;&lt;strong&gt;Array#filter&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;strings&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anny&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;manny&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;banny&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='nx'&gt;strings&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;filter&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;string&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;string&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;length&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='c1'&gt;// -&amp;gt; [&amp;#39;anny&amp;#39;, &amp;#39;manny&amp;#39;, &amp;#39;banny&amp;#39;];&lt;/span&gt;

&lt;span class='nx'&gt;strings&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;filter&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;match&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='sr'&gt;/[a-z]ann/&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='c1'&gt;// -&amp;gt; [&amp;#39;manny&amp;#39;, &amp;#39;banny&amp;#39;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href='http://rightjs.org/docs/array#map'&gt;&lt;strong&gt;Array#map&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;strings&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anny&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;banny&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;manny&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='nx'&gt;strings&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;string&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;. &amp;#39;&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='nx'&gt;string&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;

&lt;span class='c1'&gt;// -&amp;gt; [&amp;#39;1. anny&amp;#39;, &amp;#39;2. banny&amp;#39;, &amp;#39;3. manny&amp;#39;];&lt;/span&gt;

&lt;span class='nx'&gt;strings&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;capitalize&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='c1'&gt;// -&amp;gt; [&amp;#39;Anny&amp;#39;, &amp;#39;Banny&amp;#39;, &amp;#39;Manny&amp;#39;];&lt;/span&gt;

&lt;span class='nx'&gt;strings&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;replace&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;nn&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='c1'&gt;// -&amp;gt; [&amp;#39;aby&amp;#39;, &amp;#39;baby&amp;#39;, &amp;#39;maby&amp;#39;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href='http://rightjs.org/docs/string#trim'&gt;&lt;strong&gt;String#trim&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='s1'&gt;&amp;#39; asdf &amp;#39;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;trim&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// -&amp;gt; &amp;#39;asdf&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Extensión del core de JavaScript con algunos métodos que sonarán a muchos rubistas:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href='http://rightjs.org/docs/array#compact'&gt;&lt;strong&gt;Array#compact&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;undefined&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='p'&gt;].&lt;/span&gt;&lt;span class='nx'&gt;compact&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

&lt;span class='c1'&gt;// -&amp;gt; [0, 1, 2, 3];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href='http://rightjs.org/docs/string#endsWith'&gt;&lt;strong&gt;String#endsWith&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='s1'&gt;&amp;#39;image.gif&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;endsWith&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;.gif&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;       &lt;span class='c1'&gt;// -&amp;gt; true&lt;/span&gt;

&lt;span class='s1'&gt;&amp;#39;image.gif&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;endsWith&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;.GIF&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;       &lt;span class='c1'&gt;// -&amp;gt; false&lt;/span&gt;
&lt;span class='s1'&gt;&amp;#39;image.gif&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;endsWith&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;.GIF&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt; &lt;span class='c1'&gt;// -&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Manejo de números simplificado.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// Conversión de string a number&lt;/span&gt;
&lt;span class='s1'&gt;&amp;#39;123&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;toInt&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;   &lt;span class='c1'&gt;// -&amp;gt; 123&lt;/span&gt;
&lt;span class='s1'&gt;&amp;#39;1.3&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;toFloat&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// -&amp;gt; 1.3&lt;/span&gt;

&lt;span class='c1'&gt;// Manejo de números&lt;/span&gt;
&lt;span class='mf'&gt;1.4&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;floor&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// -&amp;gt; 1&lt;/span&gt;
&lt;span class='mf'&gt;1.4&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;ceil&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;  &lt;span class='c1'&gt;// -&amp;gt; 2&lt;/span&gt;
&lt;span class='mf'&gt;1.4&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;round&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// -&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Aunque JavaScript ya es un lenguaje orientado a objetos, la clase &lt;code&gt;Class&lt;/code&gt; hace más sencilla la herencia, implementación de interfaces, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;Klass&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;Class&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;AnotherClass&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;Module1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nx'&gt;extend&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;  &lt;span class='nx'&gt;Module2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;

  &lt;span class='nx'&gt;initialize&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='c1'&gt;//....&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Y también: &lt;a href='http://rightjs.org/docs/form#send' title='Form#send'&gt;envío&lt;/a&gt; simplificado de formularios, uso de spinners automáticos en peticiones AJAX, manejo unificado de &lt;a href='http://rightjs.org/tutorials/uniformed-events-handling'&gt;eventos&lt;/a&gt; y &lt;a href='http://rightjs.org/tutorials/uniformed-options-handling'&gt;opciones&lt;/a&gt; de métodos, arquitectura abierta, soporte para &lt;a href='http://rightjs.org/plugins'&gt;plugins&lt;/a&gt;, y una &lt;a href='http://github.com/MadRabbit/right-rails'&gt;gema&lt;/a&gt; para facilitar la integración con Rails (soporta Rails3).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como véis, es un framework al que merece la pena echarle un vistazo. Sobre todo si eres un desarrollador de back que no te sientes muy cómodo con la parte front (está orientado principalmente a desarrolladores Rails, como se puede ver). Creo que bien merece uno de vuestros PetProjects ;-)&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/javascript"></category>
      
      <category domain="http://www.ferdev.com/tag/rightjs"></category>
      
      <category domain="http://www.ferdev.com/tag/frameworks"></category>
      
    </item>
    
    <item>
      <title>Rediseño del blog y freelanceo</title>
      <link>http://www.ferdev.com/2010/03/23/rediseno-del-blog-y-freelanceo.html</link>
      <pubDate>Tue Mar 23 00:00:00 +0100 2010</pubDate>
      <guid>http://www.ferdev.com/2010/03/23/rediseno-del-blog-y-freelanceo.html</guid>
      <description>&lt;p&gt;La semana pasada he estado dándole un pequeño rediseño al blog. El diseño que había era el resultante de haber hecho unas cuantas pruebas, y al final por falta de tiempo no había podido cambiarlo. Quería algo minimalista, con buena legibilidad, y con el menor número de imágenes posible.&lt;/p&gt;

&lt;p&gt;De hecho, la única imagen es el nuevo logo (a excepción de los iconos de social media, que son de &lt;a href='http://www.komodomedia.com/' title='Komodo Media'&gt;Komodo Media&lt;/a&gt;). Y he creado un logo porque me embarco en la aventura del desarrollo freelance, y éste será mi nueva identidad visual. Últimamente estoy viendo mucha gente que se dedica a ello y me he decidido a dar el salto. Así que si alguien necesita un desarrollador Ruby on Rails, javascript, php, java o .NET, aquí me tenéis!&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/redesign"></category>
      
      <category domain="http://www.ferdev.com/tag/freelance"></category>
      
    </item>
    
    <item>
      <title>Testing AjaxUpload con Capybara + Culerity</title>
      <link>http://www.ferdev.com/2010/03/10/testing-ajaxupload-con-capybara-culerity.html</link>
      <pubDate>Wed Mar 10 00:00:00 +0100 2010</pubDate>
      <guid>http://www.ferdev.com/2010/03/10/testing-ajaxupload-con-capybara-culerity.html</guid>
      <description>&lt;p&gt;Llevo unos días probando &lt;a href='http://github.com/jnicklas/capybara'&gt;Capybara&lt;/a&gt; después de los comentarios tan buenos que había escuchado de él en &lt;a href='http://twitter.com/albertoperdomo/status/9643469318'&gt;twitter&lt;/a&gt; últimamente, especialmente de su integración con &lt;a href='http://github.com/langalex/culerity'&gt;Culerity&lt;/a&gt;. Los hados además trataban de decirme algo porque la última &lt;a href='http://github.com/porras/madrid-rb-feb-2010'&gt;charla&lt;/a&gt; de &lt;a href='http://twitter.com/madridrb'&gt;madridrb&lt;/a&gt; que dio &lt;a href='http://twitter.com/porras'&gt;@porras&lt;/a&gt; versaba sobre esto mismo (y &lt;a href='http://github.com/cavalle/steak'&gt;Steak&lt;/a&gt;, que también estoy probando y me está gustando mucho). Por cierto que debería haber ido a la charla (pero no pude :-() porque seguro que me hubiese ahorrado muchos de los problemas que me encontré.&lt;/p&gt;

&lt;p&gt;Los primeros vinieron con la instalación. Culerity es un recubrimiento (que poco me gusta esta palabra) de &lt;a href='http://github.com/jarib/celerity'&gt;Celerity&lt;/a&gt;, que a su vez es otro recubrimiento de &lt;a href='http://htmlunit.sourceforge.net/'&gt;HtmlUnit&lt;/a&gt;, un navegador web sin interfaz gráfico programado en Java. Y debido a esto, necesitas Jruby para instalar la gema de Celerity. Pues bien, rvm y todo este tinglado no se llevan demasiado bien. Y aunque hay un &lt;a href='http://rvm.beginrescueend.com/integration/culerty/'&gt;hack&lt;/a&gt; para salir al paso, a mi no me valía del todo (a parte que no me gustaba mucho que digamos) porque yo no estaba usando Cucumber sino Steak (requisito para que funcione el Hack). Al final conseguí hacerlo funcionar instalando Jruby mediante Macports. No sé si me dará problemas en el futuro, pero hasta que Culerity y rvm se lleven mejor, me gusta más esta solución que andar cambiando variables de entorno en cada test.&lt;/p&gt;

&lt;p&gt;La aplicación con la que estaba haciendo las pruebas tiene una carga de javascript muy alta, y los primeros problemas que me dieron los tests lo achacaba a esto. &amp;#8220;Demasiado javascript&amp;#8221;, pensaba para mis adentros cuando al testear una petición ajax me daba un error con la respuesta en formato JSON. Dándole vueltas y más vueltas, a punto de desinstalarlo todo porque no conseguía solucionarlo, di con la solución no recuerdo muy bien dónde: la última versión de Celerity (0.7.9) usaba una versión de HtmlUnit con algunos bugs, y recomendaban instalar la versión &lt;strong&gt;0.7.4&lt;/strong&gt;. Pues mano de santo oiga :-)&lt;/p&gt;

&lt;p&gt;Y llegamos al quid de la cuestión: probar &lt;a href='http://valums.com/ajax-upload/'&gt;AjaxUpload&lt;/a&gt; con Capybara + Culerity. Me ha costado un par de días hacerlo funcionar, y en realidad ha sido una tontería. No hacía falta más que detenerse un poco a pensar como funciona AjaxUpload por dentro.&lt;/p&gt;

&lt;p&gt;AjaxUpload es un hack para simular una subida asíncrona de un archivo al servidor de nuestra página web. Para ello, se vale de los siguientes pasos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Se asocia al elemento de la página web que tú hayas definido (un enlace o un botón, por ejemplo).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Cuando se dispara el evento &amp;#8220;mouseover&amp;#8221; sobre ese elemento, crea un div transparente de las mismas dimensiones que el elemento y lo sitúa por encima de él. Cuando el usuario intente pulsar el elemento, será este div en realidad el que se vea pulsado.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Cuando el usuario hace click en el div, se genera el elemento input file y se abre el diálogo de selección de archivo.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;En cuanto el usuario selecciona el fichero, AjaxUpload crea un formulario, le agrega el input file del paso anterior, y crea un iframe. Este iframe, será el &amp;#8220;target&amp;#8221; del formulario recien creado.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;AjaxUpload envía el formulario (que hará la subida del fichero a través del iframe) y fin del proceso.&lt;/p&gt;

&lt;p&gt;Mi problema venía con el diálogo de selección. No veía cómo conseguir seleccionar el archivo y pulsar el botón &amp;#8220;Aceptar&amp;#8221; del diálogo de selección. Sabía que la clase &lt;em&gt;Celerity::FileField&lt;/em&gt; contaba con el método &lt;em&gt;Set&lt;/em&gt;, con el que podía pasarle la ruta de un archivo&amp;#8230; Pero no sé por qué me dio por pensar que si el diálogo estaba abierto, no funcionaría. Hasta que lo probé, y me di cuenta que Celerity establece la ruta del archivo y cierra la ventana de diálogo él solito. Así que, problema resuelto.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aquí va un pequeño trozo de código de como quedaría montado. He sacado los selectores principales a variables para que se entienda mejor. Ah! También decir que yo tengo configurado Capybara para que por defecto use selectores css :-)&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;# selector del botón asociado a AjaxUpload&lt;/span&gt;
&lt;span class='n'&gt;button_selector&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;button#upload&amp;#39;&lt;/span&gt;
&lt;span class='c1'&gt;# selector del div que contendrá al input file. Se posicionará justo encima de button_selector&lt;/span&gt;
&lt;span class='n'&gt;div_selector&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;div.ajaxupload_container&amp;#39;&lt;/span&gt;
&lt;span class='c1'&gt;# selector del input file&lt;/span&gt;
&lt;span class='n'&gt;input_selector&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;div.ajaxupload_container input.ajaxupload&amp;#39;&lt;/span&gt;
&lt;span class='c1'&gt;# ruta al archivo a subir&lt;/span&gt;
&lt;span class='n'&gt;file_path&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;image.jpg&amp;#39;&lt;/span&gt;

&lt;span class='c1'&gt;# Simulamos el evento &amp;#39;mouseover&amp;#39; sobre el botón original asociado a AjaxUpload&lt;/span&gt;
&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;button_selector&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;trigger&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:mouseover&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='c1'&gt;# Comprobamos que se haya creado el div de AjaxUpload&lt;/span&gt;
&lt;span class='n'&gt;page&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;have_css&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;div_selector&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='c1'&gt;# Hacemos click en el div para disparar la creación del input file&lt;/span&gt;
&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;div_selector&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;click&lt;/span&gt;

&lt;span class='c1'&gt;# El input file debería haberse creado&lt;/span&gt;
&lt;span class='n'&gt;page&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;have_css&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;input_selector&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='c1'&gt;# Le pasamos la ruta de archivo al input file&lt;/span&gt;
&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;input_selector&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;set&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;file_path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Y ya está! Una aclaración: he modificado AjaxUpload para que asigne una clase al div y al input file que crea y sea más sencillo seleccionarlos, ya que por defecto no les asigna identificador ni clases de ningún tipo.&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/rails"></category>
      
      <category domain="http://www.ferdev.com/tag/ruby"></category>
      
      <category domain="http://www.ferdev.com/tag/capybara"></category>
      
      <category domain="http://www.ferdev.com/tag/culerity"></category>
      
      <category domain="http://www.ferdev.com/tag/testing"></category>
      
      <category domain="http://www.ferdev.com/tag/ajaxupload"></category>
      
    </item>
    
    <item>
      <title>Plugin jQuery para obtener dimensiones de un objeto</title>
      <link>http://www.ferdev.com/2009/10/31/plugin-jquery-para-obtener-dimensiones-de-un-objeto.html</link>
      <pubDate>Sat Oct 31 00:00:00 +0100 2009</pubDate>
      <guid>http://www.ferdev.com/2009/10/31/plugin-jquery-para-obtener-dimensiones-de-un-objeto.html</guid>
      <description>&lt;p&gt;Hola!&lt;/p&gt;

&lt;p&gt;Hace mucho que no escribo por aquí, no dispongo de demasiado tiempo&amp;#8230; Como podéis ver, cuando saco unos minutos voy haciendo pruebas de diseño con el blog. Tengo intención de pasarlo a HTML5, usar CSS3 al máximo e intentar usar el menor número de imágenes posibles, a ver si lo consigo :D Bueno, al grano.&lt;/p&gt;

&lt;p&gt;Trabajando en un proyecto me surgió la necesidad una vez de conocer las dimensiones (alto y ancho) de unos objetos ocultos que luego estaba agregando a otros elementos del DOM de mi página. El problema es que por diversas razones, necesitaba conocer su tamaño antes de agregarlos al objeto DOM, y jQuery, aunque cuenta con unos maravillosos métodos para obtener el tamaño de cualquier objeto (tanto tamaño exterior, contando el ancho de los bordes y demás, como el tamaño interior del objeto, sin bordes ni nada). El problema, es que si el objeto está oculto (display: none), jQuery no puede calcular el tamaño y te devolverá cero.&lt;/p&gt;

&lt;p&gt;Hay una solución muy sencilla para esto. Agregas el objeto con el tamaño a calcular a una capa que tendremos posicionada en modo &amp;#8220;absolute&amp;#8221; y fuera de la vista del usuario (fuera del viewport del navegador), dándole una posición &amp;#8220;left: -1000px&amp;#8221; (por ejemplo). Así, el objeto no es necesario que esté oculto, jQuery podrá calcular sus dimensiones y no lo tendrás dentro del flujo de la página, por lo que no te descolocará nada.&lt;/p&gt;

&lt;p&gt;Aquí os dejo el código del plugin, tal y como lo vengo usando en mi proyecto. Espero que os sea útil!&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='p'&gt;;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;fn&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;objectSize&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(){&lt;/span&gt;

    &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;calculateSize&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;domNode&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
        &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;divSizer&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;createElement&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;div&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;attr&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;sizer&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;css&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;           
            &lt;span class='nx'&gt;width&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;100%&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
            &lt;span class='nx'&gt;height&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;100%&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
            &lt;span class='nx'&gt;position&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;absolute&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
            &lt;span class='nx'&gt;left&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;-10000px&amp;#39;&lt;/span&gt; 
        &lt;span class='p'&gt;}).&lt;/span&gt;&lt;span class='nx'&gt;appendTo&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;body&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
        &lt;span class='nx'&gt;size&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nx'&gt;width&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;height&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
    
        &lt;span class='nx'&gt;divSizer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;domNode&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='nx'&gt;size&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;width&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;parseInt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;domNode&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;outerWidth&lt;/span&gt;&lt;span class='p'&gt;());&lt;/span&gt;
        &lt;span class='nx'&gt;size&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;height&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;parseInt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;domNode&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;outerHeight&lt;/span&gt;&lt;span class='p'&gt;());&lt;/span&gt;
        &lt;span class='nx'&gt;divSizer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;remove&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
        &lt;span class='k'&gt;delete&lt;/span&gt; &lt;span class='nx'&gt;divSizer&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;size&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;calculateSize&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;]));&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;
&lt;span class='p'&gt;})(&lt;/span&gt;&lt;span class='nx'&gt;jQuery&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/javascript"></category>
      
      <category domain="http://www.ferdev.com/tag/jquery"></category>
      
      <category domain="http://www.ferdev.com/tag/plugins"></category>
      
    </item>
    
    <item>
      <title>SWFUpload, Rails y los 406</title>
      <link>http://www.ferdev.com/2009/10/06/swfupload-rails-y-los-406.html</link>
      <pubDate>Tue Oct 06 00:00:00 +0200 2009</pubDate>
      <guid>http://www.ferdev.com/2009/10/06/swfupload-rails-y-los-406.html</guid>
      <description>&lt;p&gt;En una aplicación que tenía funcionando en Snow Leopard con SWFUpload para subir imágenes al servidor, y RoR en el lado del servidor, me estaba dando problemas al realizar los uploads desde Internet Explorer 8. En concreto, el servidor me devolvía un error 406 tras haber guardado la imagen y justo antes de realizar la respuesta al navegador(en formato json). El error 406 se produce cuando desde el servidor se está respondiendo a una solicitud con un tipo MIME que no está soportado dentro de la cabecera ACCEPT que envió el navegador. El servidor no sabe qué hacer con la solicitud, y lanza ese error.&lt;/p&gt;

&lt;p&gt;Bien, pues se produce en concreto con IE8 en Windows XP porque SWFUpload envía como único tipo MIME en su cabecera ACCEPT el tipo &amp;#8220;text/&lt;em&gt;&amp;#8221;. Imagino que es un problema con el plugin de Flash de Windows (Flash 10 estaba usando), y que si lo pruebo con otro navegador en Windows sucederá lo mismo, no lo he probado.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para solucionarlo, en primer lugar deberemos añadir un nuevo tipo MIME al environment.rb de nuestro proyecto:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='no'&gt;Mime&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Type&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;register&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;text/*&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:all_text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Luego, en la acción en la que estemos guardando la imagen, tenemos que añadir un nuevo manejador de este tipo de peticiones:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;respond_to&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
	&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all_text&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:text&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;text_to_render&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Y eso es todo, con esto Internet Explorer 8 debería estar recibiendo el resultado de la subida de una imagen con SWFUpload.&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/rails"></category>
      
      <category domain="http://www.ferdev.com/tag/ruby"></category>
      
      <category domain="http://www.ferdev.com/tag/flash"></category>
      
      <category domain="http://www.ferdev.com/tag/swfupload"></category>
      
    </item>
    
    <item>
      <title>Registro progresivo en paginas web</title>
      <link>http://www.ferdev.com/2009/05/26/registro-progresivo-en-paginas-web.html</link>
      <pubDate>Tue May 26 00:00:00 +0200 2009</pubDate>
      <guid>http://www.ferdev.com/2009/05/26/registro-progresivo-en-paginas-web.html</guid>
      <description>&lt;p&gt;Como no he tenido mucho tiempo últimamente de cambiar el diseño del blog, pero sí lo tengo para escribir algunos artículos, cambio el tema de wordpress por uno más vistoso hasta que pueda modificar el genérico.&lt;/p&gt;

&lt;p&gt;Comienzo hablando de un tema que en mi opinión es muy interesante (y útil), y que no he visto implementado en ningún sitio aún. De hecho aunque los habrá, yo no he visto ninguno. Se trata del registro progresivo de datos en formularios.&lt;/p&gt;

&lt;p&gt;¿En qué consiste? Es un patrón de desarrollo, por tanto es aplicable a cualquier tipo de tecnología web, no está atado a ningún framework o lenguaje. Va muy de la mano de la gestión de las cookies, y de un modelo de datos organizado y pensado desde un principio para soportar esta técnica. El objetivo principal de este patrón de desarrollo es evitar una de las barreras de entrada más colosales de cualquier sitio web: el registro de usuarios en un sistema para permitir la interacción del éstos con el mismo. ¿Cuantas veces hemos reculado al entrar a un sitio y ver que tenemos que registrarnos para realizar la acción más sencilla, como comprar en una tienda on-line? Estoy seguro que los sitios con esta barrera de entrada tienen una gran pérdida de usuarios (igual a dinero) por este motivo. Voy a tratar de describir en líneas generales el proceso a seguir para implementarlo y sus desventajas (que las tiene, claro).&lt;/p&gt;

&lt;p&gt;Básicamente, el proceso consiste en registrar en algún motor de persistencia (una base de datos en el mayor de los casos) los datos que un usuario no registrado va introduciendo en el mismo a lo largo del tiempo y sus sucesivas visitas. Es decir, un día un usuario entra a la web, introduce su dirección para una cosa, otro día vuelve a entrar e introduce su fecha de nacimiento, y así sucesivamente. La clave del patrón está en registrar esa información y tenerla disponible para el usuario para que, en caso de que algún día se decida a formalizar su registro en la web, ofrecerle toda esa información que el usuario ha ido acumulando en su interacción con el sitio. De este modo, el usuario llegado a ese punto, sólo tiene que introducir los datos obligatorios para realizar el registro (por ejemplo, email y contraseña) y automáticamente su perfil queda creado junto con los datos que el usuario fue introduciendo. Es una ventaja para la página web, porque cuenta con un conjunto de datos de los usuarios no registrados que de otra forma no tendría, y una ventaja para el usuario porque facilita enormemente su interacción con el sitio.&lt;/p&gt;

&lt;p&gt;Pero, todo hay que decirlo, esta técnica tiene sus inconvenientes, y parte de algunas premisas que no se pueden dar en todos los sistemas. En primer lugar, para poder hacer uso de esta técnica, el navegador del usuario que se conecta debe tener las cookies habilitadas. Sin esta primera condición es imposible montarlo. O mejor dicho, yo no sabría cómo hacerlo. Se podría hacer registrando la dirección IP del usuario que se conecta, pero teniendo en cuenta que en España la gran mayoría de los usuarios utilizan ADSL&amp;#8217;s con ip dinámica, no veo esta opción factible.  Por otro lado, el uso de cookies es la principal debilidad de esta técnica. Las cookies tienen una fecha de caducidad. E incluso antes de que se consuma esta fecha, el usuario puede perfectamente hacer una limpieza de sus cookies, con lo que perdemos el enlace del usuario con los datos que ha ido almacenando en el sitio. Y este problema nos lleva al siguiente: cuando un usuario borra o pierde su cookie del sitio web, y se nos quedan todos sus datos huérfanos, están ocupando un espacio valiosísimo en el motor de persistencia, que habrá que borrar de alguna manera.&lt;/p&gt;

&lt;p&gt;A pesar de los problemas, me parece una técnica muy interesante como para dejarla de lado. ¿Qué porcentaje de usuarios tiene las cookies desactivadas en su navegador? No sé cual es la estadística, pero estoy seguro que no es muy elevada. Además, ¿qué problema hay si el usuario no las tiene? Símplemente no podrá usar esta funcionalidad, y por otro lado tendríamos una gran cantidad de usuarios (los que sí tienen las cookies activadas) haciendo uso de ella. Se le podría aconsejar que las active llegados a ese punto si así lo creyesen necesario los desarrolladores. Y respecto al borrado de los datos huérfanos&amp;#8230; Tampoco es problema llevar un registro de las cookies que llevan más tiempo sin usarse y hacer una limpieza de datos cada X tiempo. Cuestión de sopesar los pros y los contras.&lt;/p&gt;

&lt;p&gt;Entrando más en detalle de susodicha técnica, creo que lo mejor es poner un ejemplo que es como mejor se entienden las cosas. Pongamos como ídem una tienda de comercio electrónico, con su carrito de la compra y su formulario de registro final. Sin emplear este patrón, el proceso de compra para el usuario sería:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;El usuario agrega un producto al carrito, y pulsa en &amp;#8220;formalizar compra&amp;#8221; para proceder a su pago.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;El sitio web necesita saber a quién y a dónde enviar el producto, por lo que le muestra dos formularios (generalmente) según el caso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Formulario sin registro: el usuario introduce sus datos y su dirección ya que no está registrado, y así el sistema obtiene sus datos.&lt;/li&gt;

&lt;li&gt;Formulario con registro: el usuario ya está registrado en el sitio, introduce su usuario y password, y el sistema ya tiene sus datos para realizar la compra.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Ya con los datos del usuario, la web muestra el formulario de pago y la compra finaliza (el usuario a pesar de la crisis tiene mucha pasta, y finaliza la compra sin problemas:D).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ahora, empleando el nuevo patron:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Un usuario entra al sitio web. Se busca una cookie en la cual hemos guardado su identificador de usuario.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Si no encontramos la cookie, creamos un usuario nuevo en la base de datos, vacío, pero con una clave primaria única. Con esta clave primaria única, creamos una nueva cookie y guardaremos este identificador en ella.&lt;/li&gt;

&lt;li&gt;Si encontramos la cookie, buscamos en la base de datos el identificador de usuario almacenado en la misma. De este modo hemos recuperado los datos de un usuario de la base de datos.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;El usuario navega por la tienda, y decide añadir un producto al carrito. Luego le da a &amp;#8220;formalizar compra&amp;#8221; porque no quiere nada más, que está la vida muy cara.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Le presentamos el formulario de contacto al usuario, y aquí es donde entran en juego las bondades de esta técnica.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;El usuario es asiduo comprador de nuestra tienda, ha realizado otras compras y tenemos todos los datos que ha introducido anteriormente en la base de datos. Como hemos recuperado la instancia del usuario en el primer paso, se los mostramos por si quiere validarlos o corregir algo. Al usuario símplemente le queda introducir sus datos de pago si es necesario, y el proceso ha finalizado.&lt;/li&gt;

&lt;li&gt;El usuario no había comprado nunca, por lo que rellena los datos del formulario necesarios para poder realizar el pedido. Estos datos, se guardan en la base de datos contra el usuario que hemos recuperado en el paso uno. Si el usuario vuelve a entrar alguna vez a la tienda y su cookie sigue existiendo (lo más probable, en mi humilde opinión), podremos recuperar su identificador de usuario y mostrarle sus datos.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;El usuario sin registrar vuelve al cabo de los dias, hace otra compra y decide registrarse en la tienda (para beneficiarse de unos vales de descuento disponibles sólo para usuarios registrados, por ejemplo). Nada más tendrá que introducir su email y contraseña (o los datos que sean necesarios para el registro) y quedará registrado.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Quizá se pueda poner un ejemplo más correcto del uso de esta técnica, pero creo que la idea se capta. En mi opinión es para tenerla en consideración, y si además la complementamos con algún sistema de identificación como OAuth o Facebook Connect, creo que puede llegar a ser una herramienta muy poderosa.&lt;/p&gt;

&lt;p&gt;Más adelante escribiré un post sobre su implementación en una web desarrollada con Ruby on Rails.&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/patterns"></category>
      
    </item>
    
    <item>
      <title>Paso 1: wordpress instalado</title>
      <link>http://www.ferdev.com/2009/05/08/paso-1-wordpress-instalado.html</link>
      <pubDate>Fri May 08 00:00:00 +0200 2009</pubDate>
      <guid>http://www.ferdev.com/2009/05/08/paso-1-wordpress-instalado.html</guid>
      <description>&lt;p&gt;Empiezo las andanzas en el mundo &amp;#8220;blogueril&amp;#8221; personal. Me llamo Fer, y en este blog intentaré transmitir lo mejor que pueda los conocimientos que he ido adquiriendo a lo largo de mi vida en el mundo del desarrollo de software (y un poquito de diseño también, pero poco, que no es lo mío).&lt;/p&gt;

&lt;p&gt;Como primer paso he conseguido un dominio, un servidor y la última versión de &lt;a href='http://wordpress.org/' title='wordpress'&gt;wordpress 2.7.1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Poco a poco, iré implementando mi propio tema de wordpress. Para ello, parto de la base del tema &lt;a href='http://carringtontheme.com/' title='Carrington Jam'&gt;Carrington Jam&lt;/a&gt;, tema especialmente pensado para modificarlo a gusto del consumidor. Para realizar este tema, principalmente utilizaré el framework javascript &lt;a href='http://www.jquery.com/' title='jQuery 1.3.2.'&gt;jQuery 1.3.2&lt;/a&gt;, mi favorito de entre todos los actuales.&lt;/p&gt;

&lt;p&gt;Falta algún plugin, publicidad para sobrellevar la crisis, añadir mi cuenta de twitter&amp;#8230; Poco a poco iré actualizando.&lt;/p&gt;

&lt;p&gt;Bienvenidos :-)&lt;/p&gt;</description>
      
      <category domain="http://www.ferdev.com/tag/wordpress"></category>
      
      <category domain="http://www.ferdev.com/tag/carrington"></category>
      
      <category domain="http://www.ferdev.com/tag/jquery"></category>
      
    </item>
    
  </channel>
</rss>
