<?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"
	>

<channel>
	<title>Scriptia</title>
	<atom:link href="http://blog.scriptia.net/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.scriptia.net</link>
	<description>Javascript y buenas prácticas en español</description>
	<pubDate>Thu, 01 Jan 2009 11:38:51 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Trabajando con jQuery: timeline arrastrable, del espaguetismo al plugin</title>
		<link>http://blog.scriptia.net/articulos/2008/10/jquery-del-espagueti-al-plugin.html</link>
		<comments>http://blog.scriptia.net/articulos/2008/10/jquery-del-espagueti-al-plugin.html#comments</comments>
		<pubDate>Mon, 20 Oct 2008 18:44:20 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[artículos]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[plugins]]></category>

		<category><![CDATA[tutoriales]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/articulos/2008/10/jquery-del-espagueti-al-plugin.html</guid>
		<description><![CDATA[En el capítulo de hoy veremos cómo reconvertir un código espagueti en un bonito plugin reutilizable.
Objetivo del widget: permitir desplazar horizontalmente mediante arrastre (pincho, arrastro, suelto) un bloque de contenido. Si tienes prisa por ver en qué acaba la cosa, ve directamente a la demo.
Elementos: un contenedor (con overflow: auto) y su contenido. Para nuestro [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/al-margen/2006/09/carrusel.html' rel='bookmark' title='Permanent Link: Carrusel'>Carrusel</a> <small>Continua la lluvia de plugins para jQuery. Esta vez nos...</small></li><li><a href='http://blog.scriptia.net/al-margen/2007/10/un-patron-de-desarrollo-de-plugins-para-jquery.html' rel='bookmark' title='Permanent Link: Un patrón de desarrollo de plugins para jQuery'>Un patrón de desarrollo de plugins para jQuery</a> <small>Mike Alsup, autor de jQuery form plugin y otras delicias,...</small></li><li><a href='http://blog.scriptia.net/articulos/2008/07/eventos-en-jquery-12.html' rel='bookmark' title='Permanent Link: Eventos en jQuery 1.2'>Eventos en jQuery 1.2</a> <small>Días ha que escribí una nota sobre los eventos en...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>En el capítulo de hoy veremos cómo reconvertir un código espagueti en un bonito plugin reutilizable.</p>
<p>Objetivo del widget: permitir desplazar horizontalmente mediante arrastre (pincho, arrastro, suelto) un bloque de contenido. Si tienes prisa por ver en qué acaba la cosa, ve directamente a <a href="http://choangalvez.nom.es/presentaciones/jquery/examples/timeline-jquery.html">la demo</a>.</p>
<p>Elementos: un contenedor (con <code>overflow: auto</code>) y su contenido. Para nuestro ejemplo:</p>
<pre><code class="html">&lt;div id="#timeline"&gt;
  &lt;ul&gt;
    &lt;li&gt;...&lt;/li&gt;
    &lt;li&gt;...&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;</code></pre>
<p>Con unos estilos tal que:</p>
<pre><code class="css">#timeline {
 width: 600px;
 height: 400px;
 overflow: auto;
}

#timeline ul {
 width: 1000px;
 margin: 0;
 padding: 0;
}

#timeline li {
 display: block;
 width: 200px;
 padding: 10px;
 margin: 0;
 float: left;
}</code></pre>
<p>Sobre estas piedras edificaremos nuestra iglesia. Veamos paso a paso el código necesario para hacer que la cosa se mueva. Pondremos en marcha la maquinaria cuando pinchemos sobre el contenedor:</p>
<pre><code class="javascript">$('#timeline')
  .bind('mousedown', function(e) {
    // aquí vendrá nuestro código
  });</code></pre>
<p>A fin de evitar el uso de variables globales, utilizarmos <code>data</code>, un método de jQuery que nos permite mantener relaciones entre valores y elementos DOM. Vamos a mantener los siguientes datos: posición actual del scroll, elemento al que afecta y posición del puntero en el momento del <code>mousedown</code>.</p>
<pre><code class="javascript">$(document)
  .data('timeline', {
    element: this,
    scroll: this.scrollLeft,
    x : e.clientX
  });</code></pre>
<p>Observa que estamos conservando los datos en <code>document</code>. En cada momento existirá un máximo de un elemento en desplazamiento.</p>
<p>Bien, ha empezado la acción&#8230; pero todavía no estamos siguiendo los movimientos del puntero. Asignemos un par de manejadores para los eventos <code>mousemove</code> y <code>mouseup</code> de <code>document</code>.</p>
<p>¿Por qué para <code>document</code> y no para el contenedor con el que estamos tratando? Aunque el puntero salga del contenedor durante el arrastre, queremos seguir desplazando el contenido. Y si saliera y no controláramos <code>mouseup</code> a nivel de documento, nuestro script nunca abandonaría el modo &#8220;estamos arrastrando cositas&#8221;.</p>
<p>Como somos chulos y modernos, aprovecharemos los eventos.con-espacio-de-nombres que jQuery gentilmente pone a nuestra disposición. Para <code>mousemove</code>, recuperamos los datos que hemos almacenado en <code>mousedown</code> y modificamos la propiedad <code>scrollLeft</code> del contenedor sumándole la diferencia entre la posición actual del ratón y la almacenada. En <code>mouseup</code>, limpiamos los datos almacenados y eliminamos los manejadores de eventos del espacio <code>timeline</code> asignados a <code>document</code>.</p>
<pre><code class="javascript">jQuery(document)
  .bind('mousemove.timeline', function(e) {
    var data = jQuery(this).data('timeline');
    data.element.scrollLeft = data.scroll + data.x - e.clientX;
  })
  .bind('mouseup.timeline', function(e) {
    jQuery(this)
      .removeData('timeline')
      .unbind('.timeline');
  });</code></pre>
<p>Para rematar, cancelaremos la acción por defecto de <code>mousedown</code> para no seleccionar texto mientras arrastramos:</p>
<pre><code class="javascript">e.preventDefault();</code></pre>
<p>Poniéndolo todo junto y dentro de una llamada a <code>ready</code>, tenemos la cosita funcionando:</p>
<pre><code class="javascript">jQuery(document).ready(function() {

  jQuery('#timeline')
    .bind('mousedown', function(e) {

      jQuery(document)
        .data('timeline', {
          element: this,
          scroll: this.scrollLeft,
          x : e.clientX
        })
        .bind('mousemove.timeline', function(e) {
          var data = jQuery(this).data('timeline');
          data.element.scrollLeft = data.scroll + data.x - e.clientX;
        })
        .bind('mouseup.timeline', function(e) {
          jQuery(this)
            .removeData('timeline')
            .unbind('.timeline');
        });

      e.preventDefault();

    });
});</code></pre>
<p>¡Genial! Con esto ya tenemos el comportamiento deseado, pero&#8230; no parece muy reutilizable. Pluguinifiquemos.</p>
<h2 id="construyendo_un_plugin">Construyendo un plugin</h2>
<p>Cuando invocamos la función <code>jQuery</code> (o su alias habitual, <code>$</code>), recuperamos un objeto. Dicho objeto tiene un prototipo. Para añadir métodos al objeto devuelto por <code>jQuery</code>, los añadimos a su prototipo. Así que algo tal que:</p>
<pre><code class="javascript">jQuery.prototype.miMetodo = function() {

};</code></pre>
<p>Ya nos serviría para ir tirando. Pero hay un idioma más <em>jotacueriesco</em> para decir lo mismo. De paso añadamos un <code>return this</code> a nuestro método para permitir el encadenamiento de llamadas:</p>
<pre><code class="javascript">jQuery.extend(jQuery.fn, {
  miMetodo : function() {
    return this;
  }
});</code></pre>
<p>Con esto ya podemos darnos el gustazo de escribir:</p>
<pre><code class="javascript">jQuery('#miCosa')
  .miMetodo()
  .etcetera();</code></pre>
<p>Pero escribir <code>jQuery</code> (que es lo que debemos hacer si queremos asegurarnos de que nuestro plugin es compatible con otras bibliotecas) una y otra vez es escribir mucho. Vamos a meter <strong>todo</strong> el código de nuestro plugin dentro de una función anónima que nos permita tener un alias <strong>seguro</strong> para <code>jQuery</code>.</p>
<pre><code class="javascript">(function($) {

})(jQuery);</code></pre>
<p>Y vamos a rellenarlo poquito a poco.</p>
<pre><code class="javascript">(function($) {
  $.extend($.fn, {
    timeline : function() {
      this
        .bind('mousedown', handleMouseDown);
      return this;
    }
  });

  function handleMouseDown(e) {
    // bla bla
  }

})(jQuery);</code></pre>
<p>Fíjate: extraemos el código de manejo del evento <code>mousedown</code>. ¿Por qué? No necesitamos ningún dato <strong>local</strong> y por tanto no necesitamos del cierre funcional para acceder a dicho dato (ni generar la función al vuelo para cada widget). Haremos lo mismo para los manejadores de <code>mousemove</code> y <code>mouseup</code>:</p>
<pre><code class="javascript">(function($) {
  $.extend($.fn, {
    timeline : function() {
      this
        .bind('mousedown', handleMouseDown);
      return this;
    }
  });

  function handleMouseDown(e) {
    $(document)
      .data('timeline', {
        element: this,
        scroll: this.scrollLeft,
        x : e.clientX
      })
      .bind('mousemove.timeline', handleMouseMove)
      .bind('mouseup.timeline', handleMouseUp);
    e.preventDefault();
  }

  function handleMouseMove(e) {
    var data = $(this).data('timeline');
    data.element.scrollLeft = data.scroll + data.x - e.clientX;
  }

  function handleMouseUp(e) {
    $(this)
      .removeData('timeline')
      .unbind('.timeline');
  }

})(jQuery);</code></pre>
<p>Con esto nuestro código espagueti ya parece algo más ordenadito. Pero un plugin sin opciones sabe a poco. Vamos a considerar la posibilidad de configurar la proporción de desplazamiento/arrastre y de decidir si ocultamos o no la barra de scroll nativa. Por partes:</p>
<pre><code class="javascript">$.extend($.fn, {
  timeline : function(opts) {
    var config = $.extend({
      speed: 1.5,
      accesible: true
    }, opts || {});

    this
      .bind('mousedown', config, handleMouseDown);

    if (!config.accesible) {
      this.css('overflow', 'hidden');
    }

    return this;
  }
});</code></pre>
<p>Ahora el método <code>timeline</code> acepta un argumento que corresponde a un objeto de configuración. Utilizamos <code>jQuery.extend</code> para aplicar los valores sobre una configuración por defecto. Y al asignar el manejador para <code>mousedown</code> lo pasamos como argumento. Si esto resulta nuevo para ti, lo que te falta saber es que con una asignación de este tipo, el manejador recibirá estos datos extra en la propiedad <code>data</code> del objeto que representa el evento. Modifiquemos el manejador para transmitir la configuración:</p>
<pre><code class="javascript">function handleMouseDown(e) {
  $(document)
    .data('timeline', {
      element: this,
      scroll: this.scrollLeft,
      x : e.clientX,
      config : e.data
    })
    .bind('mousemove.timeline', handleMouseMove)
    .bind('mouseup.timeline', handleMouseUp);
  e.preventDefault();
}</code></pre>
<p>Utilicemos la configuración en <code>handleMouseMove</code>:</p>
<pre><code class="javascript">function handleMouseMove(e) {
  var data = $(this).data('timeline');
  data.element.scrollLeft = data.scroll + (data.x - e.clientX) * data.config.speed;
}</code></pre>
<p>Y listo. Ya tenemos un plugin bastante decente. Para ponerlo en marcha:</p>
<pre><code class="javascript">jQuery(document)
  .ready(function() {
    $('el.selector-de-dios')
      .timeline({ speed: 2, accesible: false })
  });</code></pre>
<h2>Bola extra 1: configuración por defecto</h2>
<p>Si nuestro usuario siempre va a preferir la opción no accesible del plugin, no por ser idiota (u obedecer órdenes) le vamos a obligar a pasar la configuración una y otra vez. Apañemos:</p>
<pre><code class="javascript">$.extend($.fn, {
  timeline : function(opts) {
    var config = $.extend({}, $.fn.timeline.defaults, opts || {});
    // ...
    return this;
  }
});

$.fn.timeline.defaults = {
  speed: 1.5,
  accesible: true
};</code></pre>
<p>De esta manera permitimos al usuario configurar las opciones de manera global manipulando <code>jQuery.fn.timeline.defaults</code> a su antojo.</p>
<h2>Bola extra 2: mousewheel</h2>
<p>El plugin <a href="http://plugins.jquery.com/project/mousewheel" hreflang="en">mousewheel</a> permite controlar los movimientos de la ruedita del ratón. Aprovechémoslo:</p>
<pre><code class="javascript">$.extend($.fn, {
    timeline : function(opts) {
      // ...
      if ($.fn.mousewheel) {
        this
          .mousewheel(function(e, delta) {
            this.scrollLeft -= delta * config.mousewheelSpeed;
            e.preventDefault();
          });
      }
      return this;
    }
  });</code></pre>
<p>Puedes probar la combinación de todos estos elementos en la <a href="http://choangalvez.nom.es/presentaciones/jquery/examples/timeline-jquery.html">demo correspondiente</a>.</p>
<h2>Coda</h2>
<p>Choan no inventa nada nuevo, lo tratado aquí viene a ser una combinación de mis conocimientos, gustos y experiencia y lo expuesto en estos dos artículos:</p>
<ul>
<li><a href="http://jqueryfordesigners.com/fun-with-overflows/" hreflang="en" xml:lang="en" lang="en">Fun with overflows</a>, de Remy Sharp.</li>
<li><a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern" hreflang="en" xml:lang="en" lang="en">A Plugin Development Pattern</a>, de Mike Alsup.</li>
</ul>
<p>Ten presente que la arquitectura propuesta para este plugin no siempre es la más adecuada —ya hablaremos de ello— y que el plugin de ejemplo no está publicado ni oficial ni extra oficialmente y <strong>nadie</strong> te dará soporte.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/articulos/2008/10/jquery-del-espagueti-al-plugin.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>jShoulda y JsUnitTest, pruebas unitarias en JavaScript al estilo Shoulda</title>
		<link>http://blog.scriptia.net/al-margen/2008/10/jshoulda-y-jsunit-test-unit-testing-javascript.html</link>
		<comments>http://blog.scriptia.net/al-margen/2008/10/jshoulda-y-jsunit-test-unit-testing-javascript.html#comments</comments>
		<pubDate>Sat, 11 Oct 2008 16:57:45 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[al margen]]></category>

		<category><![CDATA[jShoulda]]></category>

		<category><![CDATA[JsUnitTest]]></category>

		<category><![CDATA[newjs]]></category>

		<category><![CDATA[unit-testing]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/al-margen/2008/10/jshoulda-y-jsunit-test-unit-testing-javascript.html</guid>
		<description><![CDATA[Hablábamos el otro día de QUnit, hoy hablaremos de JsUnitTest –otro sistema de testing– y de jShoulda, una capa de abstracción que un servidor ha moldeado con sus propias manos y a imagen y semejanza de Shoulda.
Principiemos hablando de JsUnitTest, un port sin dependencias del sistema de testing desarrollado para probar prototype y script.aculo.us.
¿Qué necesitamos?

jsunittest.js, [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/articulos/2008/07/pruebas-unitarias-con-qunit.html' rel='bookmark' title='Permanent Link: Pruebas unitarias con QUnit'>Pruebas unitarias con QUnit</a> <small>Las pruebas unitarias (unit testing) son necesarias y convenientes, ya...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Hablábamos el otro día de <a href="http://blog.scriptia.net/articulos/2008/07/pruebas-unitarias-con-qunit.html">QUnit</a>, hoy hablaremos de JsUnitTest –otro sistema de testing– y de jShoulda, una capa de abstracción que un servidor ha moldeado con sus propias manos y a imagen y semejanza de <a href="http://www.thoughtbot.com/projects/shoulda" title="thoughtbot: Shoulda testing plugin" hreflang="en">Shoulda</a>.</p>
<p>Principiemos hablando de <a href="http://jsunittest.com/" hreflang="en">JsUnitTest</a>, un <em xml:lang="en" lang="en">port</em> <strong>sin dependencias</strong> del sistema de testing desarrollado para probar <a href="http://www.prototypejs.org/" title="Prototype JavaScript framework: Easy Ajax and DOM manipulation for dynamic web applications" hreflang="en">prototype</a> y <a href="http://script.aculo.us/" title="script.aculo.us - web 2.0 javascript" hreflang="en">script.aculo.us</a>.</p>
<h2>¿Qué necesitamos?</h2>
<ul>
<li><a href="http://jsunittest.com/dist/jsunittest.js">jsunittest.js</a>, la biblioteca de testing;</li>
<li>un documento HTML que la referencie.</li>
</ul>
<p>Algo como esto bastará:</p>
<pre><code class="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
  &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&gt;
  &lt;title&gt;Minimal JsUnitTest&lt;/title&gt;
  &lt;script src="/js/jsunittest.js" type="text/javascript"&gt;&lt;/script&gt;
  &lt;link rel="stylesheet" href="/css/unittest.css" type="text/css" media="screen"/&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;h1&gt;Minimal JsUnitTest&lt;/h1&gt;

  &lt;div id="testlog"&gt;
    Los resultados de las pruebas se muestran, por defecto
    en el elemento con id=testlog
  &lt;/div&gt;

&lt;script type="text/javascript"&gt;
  // aquí irá el código de nuestras pruebas,
  // también podemos hacer referencia a un script externo
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h2>Cómo escribir tests con JsUnitTest</h2>
<p>Para definir y ejecutar las pruebas, creamos una instancia de <code>Test.Unit.Runner</code>:</p>
<pre><code class="javascript">new Test.Unit.Runner({});</code></pre>
<p>En el objeto de configuración que pasamos como argumento, definimos como propiedades las pruebas a realizar:</p>
<pre><code class="javascript">new Test.Unit.Runner({
  testNombreDelTest : function() {
    this.assert(true);
  },
  testOtroTest : function() {
    this.assert(true);
  }
});</code></pre>
<p>Los nombres de las propiedades correspondientes a pruebas deben comenzar por &#8220;test&#8221;. Si deseamos ejecutar funciones de preparación y limpieza antes y después de cada una de las pruebas, utilizamos las propiedades <var>setup</var> y <var>teardown</var> para definirlas:</p>
<pre><code class="javascript">new Test.Unit.Runner({
  setup : function() {
    this.foo = 1;
  },
  testNombreDelTest : function() {
    this.assert(true);
  },
  testFoo : function() {
    this.assertEqual(1, this.foo);
  }
});</code></pre>
<p>Observa: tanto las funciones de preparación como las de prueba se ejecutan en el contexto de una instancia de <code>Test.Unit.Testcase</code>. Las posibles aserciones son métodos de dicha instancia (por eso usamos <code>this</code>). También podemos utilizar <code>this</code> para mantener variables que vayamos a utilizar en nuestras pruebas.</p>
<p>La mayor parte de los métodos asertivos aceptan tres parámetros: el valor esperado, el valor real y (opcionalmente) un mensaje que el sistema nos mostrará en caso de error.</p>
<p>He aquí una lista deliberadamente incompleta de los métodos de aserción:</p>
<ul>
<li>assert</li>
<li>assertEqual</li>
<li>assertNotEqual</li>
<li>assertEnumEqual</li>
<li>assertEnumNotEqual</li>
<li>assertHashEqual</li>
<li>assertHashNotEqual</li>
<li>assertIdentical</li>
<li>assertNotIdentical</li>
<li>assertNull</li>
<li>assertNotNull</li>
<li>assertUndefined</li>
<li>assertNotUndefined</li>
</ul>
<p>Comprueban lo que su nombre parece indicar. Un detalle importante: en JavaScript, dos arrays con el mismo contenido (o dos objetos-usados-como-hashes) no pueden compararse mediante igualdad. Por tanto, si quieres comparar dos arrays necesitarás utilizar <code>assertEnumEqual</code>. Y para comparar dos objetos, <code>assertHashEqual</code>.</p>
<h2>Automatización</h2>
<p><a href="http://drnicwilliams.com/" title="Dr Nic" hreflang="en">drnic</a>, el humano detrás de JsUnitTest, es también padre de <a href="http://newjs.rubyforge.org/" title="JavaScript Project Generator">newjs</a>, un gem (si no sabes qué es un gem, ignora esta sección hasta que lo averigües) pensada para facilitar el desarrollo de bibliotecas JavaScript. Sus virtudes:</p>
<ul>
<li>incluye JsUnitTest;</li>
<li>simplifica la creación de nuevos tests;</li>
<li>automatiza la ejecución de los tests.</li>
</ul>
<p>Sin entrar en detalles. O lo ves, o no lo ves:</p>
<pre><code>$ newjs milib
      create
      create  config
      create  lib
      create  src
      create  script
      create  tasks
      create  test/assets
      create  test/unit
      create  test/functional
      create  test/assets/unittest.css
      create  test/assets/jsunittest.js
      # etcetera
  dependency  install_rubigen_scripts
      exists    script
      create    script/generate
      create    script/destroy
$ cd milib
$ script/generate unit_test basic
      exists  test/unit
      create  test/unit/basic_test.html
$ rake test_units
(in /Users/choan/Current/tirame/milib)

Started tests in Safari
.
Finished in 2 seconds.
1 tests, 1 assertions, 0 failures, 0 errors

Started tests in Firefox
.
Finished in 1 seconds.
1 tests, 1 assertions, 0 failures, 0 errors

Skipping Internet Explorer, not supported on this OS

Skipping Konqueror, not supported on this OS

Started tests in Opera
.
Finished in 3 seconds.
1 tests, 1 assertions, 0 failures, 0 errors</code></pre>
<p>Sí, amigo mío, mediante la ejecución de una tarea <a href="http://rake.rubyforge.org/" title="Rake -- Ruby Make" hreflang="en">rake</a> hemos ejecutado las pruebas en cada uno de los navegadores disponibles en nuestro sistema y hemos recogido los resultados. Algo que Chuck Norris no es capaz de hacer.</p>
<h2>jShoulda</h2>
<p>Pero vayamos con jShoulda, que yo he venido aquí a hablar de mi libro.</p>
<p><a href="http://jshoulda.scriptia.net/" hreflang="en">jShoulda</a> es una capa de abstracción para JsUnitTest que permite escribir nuestros tests al más puro estilo Shoulda. Algo así:</p>
<pre><code class="javascript">context('A context', {},
  should('run a test', function() {
    this.assert('Yay!');
  }),
)();</code></pre>
<p>¿Y qué ventaja tiene esto? Para un test vulgar, ninguna, francamente. Pero si tus pruebas requieren de inicializaciones complejas, la cosa se pone chula.</p>
<pre><code class="javascript">context('A context', {
  setup: function() {
    this.foo = 1;
  }
  },
  should('run its setup function', function() {
    this.assertEqual(1, this.foo);
  }),
  context('which is a "nested" context', {
    setup: function() {
      this.foo +=1;
    }
    },
    should('run both setup functions', function() {
      this.assertEqual(2, this.foo);
    })
  )
)();
</code></pre>
<p>Para utilizar jShoulda necesitas&#8230; <a href="http://jshoulda.scriptia.net/js/jshoulda.js">jshoulda.js</a>. Y un documento HTML como el anterior, al que añadirás la referencia a la biblioteca.</p>
<p>Pero para probarlo no necesitas descargar nada. Pásate por la <a href="http://jshoulda.scriptia.net/">página del proyecto</a>. Los resultados de pruebas que encontrarás en ella (suponiendo que la visites con JavaScript activado) corresponden al test de ejemplo ejecutado <em>en vivo</em>. Si quieres juguetear, doblecliquea en el código, modifícalo a tu gusto y pulsa el botón. Sugerencia: haz fallar las pruebas. Mola.</p>
<p>Si estás interesado en jShoulda y tu inglés no es ni mejor ni peor que el mío, lee el <a href="http://jshoulda.scriptia.net" hreflang="en">tutorial de jShoulda</a>, suscríbete a la <a href="http://groups.google.com/group/jshoulda">lista de correo</a> y, si das con algún bug, <a href="http://github.com/choan/jshoulda/tree/master" title="jShoulda en github">arréglalo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/al-margen/2008/10/jshoulda-y-jsunit-test-unit-testing-javascript.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Pruebas unitarias con QUnit</title>
		<link>http://blog.scriptia.net/articulos/2008/07/pruebas-unitarias-con-qunit.html</link>
		<comments>http://blog.scriptia.net/articulos/2008/07/pruebas-unitarias-con-qunit.html#comments</comments>
		<pubDate>Sat, 26 Jul 2008 19:15:40 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[artículos]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[Qunit]]></category>

		<category><![CDATA[unit-testing]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/articulos/2008/07/pruebas-unitarias-con-qunit.html</guid>
		<description><![CDATA[Las pruebas unitarias (unit testing) son necesarias y convenientes, ya programes en Ruby, en PHP, en JavaScript o en Cuenca. En esta notita veremos cómo utilizar QUnit –la biblioteca creada para el testeo del núcleo de jQuery– para testear nuestros propios proyectos.

El documento base
Comencemos pues, por descargar QUnit y preparar un documento HTML con la [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/al-margen/2006/07/elementos-de-interfaz-para-jquery.html' rel='bookmark' title='Permanent Link: Elementos de interfaz para jQuery'>Elementos de interfaz para jQuery</a> <small>Arrastrar y soltar, ordenar listas, bonitos efectos...Interface elements for jQuery....</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/08/comenzando-con-jquery.html' rel='bookmark' title='Permanent Link: Comenzando con jQuery'>Comenzando con jQuery</a> <small>Si todavía no conoces jQuery esta guía escrita por Jörn...</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/08/jquery-10.html' rel='bookmark' title='Permanent Link: jQuery 1.0'>jQuery 1.0</a> <small>jQuery 1.0 está en la calle....</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Las pruebas unitarias (unit testing) son <strong>necesarias</strong> y <strong>convenientes</strong>, ya programes en Ruby, en PHP, en JavaScript o en Cuenca. En esta notita veremos cómo utilizar <a href="http://docs.jquery.com/QUnit" hreflang="en">QUnit</a> –la biblioteca creada para el testeo del núcleo de <a href="http://jquery.com" hreflang="en">jQuery</a>– para testear nuestros propios proyectos.</p>
<p><span id="more-120"></span></p>
<h2>El documento base</h2>
<p>Comencemos pues, por <a href="http://dev.jquery.com/view/trunk/qunit/" hreflang="en">descargar QUnit</a> y preparar un documento HTML con la siguiente estructura:</p>
<pre><code class="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;My Test Suite&lt;/title&gt;
  &lt;link rel="Stylesheet" media="screen" href="ruta/a/testsuite.css" /&gt;
  &lt;script type="text/javascript" src="ruta/a/jquery.js"&gt;&lt;/script&gt;
  &lt;script type="text/javascript" src="ruta/a/testrunner.js"&gt;&lt;/script&gt;

  &lt;style type="text/css" media="screen"&gt;
  /* &lt;![CDATA[ */
    #main {
      display: none;
    }
  /* ]]&gt; */
  &lt;/style&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;h1&gt;My Test Suite&lt;/h1&gt;
  &lt;h2 id="banner"&gt;&lt;/h2&gt;
  &lt;h2 id="userAgent"&gt;&lt;/h2&gt;

  &lt;div id="main"&gt;
  &lt;/div&gt;

  &lt;ol id="tests"&gt;&lt;/ol&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>El elemento con <code>id="banner"</code> es utilizado por QUnit para mostrar el resultado global de la ejecución de las pruebas. En <code>id="userAgent"</code> se muestra información relativa al navegador utilizado. La lista y el detalle de la ejecución de cada prueba se genera en <code>id="tests"</code>.</p>
<p>En caso de disponer de <a href="http://getfirebug.com/" hreflang="en">Firebug</a>, QUnit volcará abundante y útil información en la consola.</p>
<p>Si necesitamos un fragmento de HTML para la ejecución de las pruebas, lo incluiremos en <code>id="main"</code>. Ojo: antes de la ejecución de cada test se devuelve el contenido de este elemento a su estado inicial, esto es, no se mantienen los eventos asignados ni las modificaciones realizadas sobre el árbol en tests anteriores.</p>
<h2>Nuestro primer test</h2>
<p>Al ajo. La ejecución de una prueba implica una llamada a la función <code>test</code>, pasando como parámetros una cadena identificativa y la referencia a una función en la que se realizan las comprobaciones (aserciones).</p>
<p>La más sencilla de las comprobaciones es <code>ok</code>. Si el parámetro que recibe evalúa a <code>true</code>, el resultado se considera satisfactorio.</p>
<p>Poniendo los dos últimos párrafos en código:</p>
<pre><code class="javascript">test('Prueba minimalista', function(){
  ok(1, 'mi mensajito');
});</code></pre>
<p>Incorpora esas líneas a tu documento de pruebas (dentro de un elemento <em class="element">SCRIPT</em>) y échale un vistazo en el navegador. ¿Todo bien?</p>
<h2>Comprobaciones varias</h2>
<p>Por supuesto disponemos de otros métodos de comprobación de resultados, estos son los fundamentales:</p>
<dl>
<dt><code>equals(unArgumento, otroArgumento, mensaje)</code></dt>
<dd>Comprueba la igualdad de dos argumentos primitivos.</dd>
<dt><code>isSet(unArray, otroArray, mensaje)</code></dt>
<dd>Comprueba que dos arrays tienen el mismo contenido.</dd>
<dt><code>isObject(unObjeto, otroObjeto, mensaje)</code></dt>
<dd>Comprueba que dos objetos tienen los mismos valores asignados a las mismas propiedades.</dd>
</dl>
<h2>Módulos</h2>
<p>Si utilizamos el mismo documento para probar distintas partes de nuestra biblioteca podemos utilizar la función <code>module</code> para dar nombre a las secciones de la suite.</p>
<pre><code class="javascript">module('Widget de votaciones');
test('tras la inicialización'), function() {
  // inicializamos un widget, etc.
  equals($('a.rate', widget).length, 5, 'contiene 5 estrellicas');
});

test('etcetera', function() {
  // otro test por aquí
});</code></pre>
<h2>Expectaciones</h2>
<p>Todo lo que puede fallar, falla (de hecho, si practicas el desarrollo basado en pruebas, lo primero que debería hacer cada test es fallar). Para indicar el total de comprobaciones que se realizarán en una prueba, utilizamos la función <code>expect</code>.</p>
<pre><code class="javascript">module('expectaciones');
test('un test', function() {
  expect(3);
  ok(1, 'una');
  equals(1 + 1, 2, 'dos');
  equals(calculoCasiImposible(), 42, 'y tres');
});</code></pre>
<p>De esta manera, si la ejecución de <code>calculoCasiImposible</code> (la tercera comprobación) falla estrepitosamente, la prueba no se da por buena.</p>
<h2>Asincronía y pausas</h2>
<p>Si realizamos peticiones asíncronas en nuestros tests, necesitaremos detener la ejecución de la serie y reanudarla cuando convenga. Los métodos <code>stop</code> y <code>start</code> hacen lo que su nombre parece indicar.</p>
<pre><code class="javascript">module('asincronía');
test('con pausa', function() {
  expect(2);
  ok(1, 'una');
  function my_callback(response, status) {
    start();
    equals(response, '1', 'el servidor devuelve lo que toca');
  }
  // detenemos la ejecución de las pruebas
  stop();
  // lanzamos una petición Ajax
  $.get(some_url, my_callback);
});
</code></pre>
<p>Si quieres empaparte de pruebas escritas con y para QUnit, lo mejor es que descargues una <a href="http://jqueryjs.googlecode.com/files/jquery-1.2.6-release.zip">una release completa de jQuery</a> y bucees en sus entrañas.</p>
<p>Y esto ha sido todo. La semana que viene más y más sexy (si cabe).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/articulos/2008/07/pruebas-unitarias-con-qunit.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Eventos en jQuery 1.2</title>
		<link>http://blog.scriptia.net/articulos/2008/07/eventos-en-jquery-12.html</link>
		<comments>http://blog.scriptia.net/articulos/2008/07/eventos-en-jquery-12.html#comments</comments>
		<pubDate>Thu, 17 Jul 2008 00:45:58 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[artículos]]></category>

		<category><![CDATA[eventos]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[tutoriales]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/articulos/2008/07/eventos-en-jquery-12.html</guid>
		<description><![CDATA[Días ha que escribí una nota sobre los eventos en jQuery. Y hora es de ampliar dicho artículo con las novedades que la serie 1.2 de jQuery añade al respecto.

Lo de siempre
Recordemos las bases de la asignación y el manejo de eventos en jQuery. La forma básica de asignar un manejador es la siguiente:
$('un.selector')
  [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/articulos/2006/12/eventos-en-jquery.html' rel='bookmark' title='Permanent Link: Eventos en jQuery'>Eventos en jQuery</a> <small>Presentamos un repaso en profundidad a los métodos de jQuery...</small></li><li><a href='http://blog.scriptia.net/al-margen/2007/10/un-patron-de-desarrollo-de-plugins-para-jquery.html' rel='bookmark' title='Permanent Link: Un patrón de desarrollo de plugins para jQuery'>Un patrón de desarrollo de plugins para jQuery</a> <small>Mike Alsup, autor de jQuery form plugin y otras delicias,...</small></li><li><a href='http://blog.scriptia.net/articulos/2008/06/ajax-eventos-y-jquery.html' rel='bookmark' title='Permanent Link: Ajax, eventos y jQuery'>Ajax, eventos y jQuery</a> <small>Un «problema» con el que todo novato de la programación...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Días ha que escribí una nota sobre los <a href="http://blog.scriptia.net/articulos/2006/12/eventos-en-jquery.html">eventos en jQuery</a>. Y hora es de ampliar dicho artículo con las novedades que la serie 1.2 de jQuery añade al respecto.</p>
<p><span id="more-119"></span></p>
<h2>Lo de siempre</h2>
<p>Recordemos las bases de la asignación y el manejo de eventos en jQuery. La forma básica de asignar un manejador es la siguiente:</p>
<pre><code class="javascript">$('un.selector')
  .bind('click', unaFuncion);</code></pre>
<p>El manejador (<code>unaFuncion</code>) recibe como parámetro el objeto que representa el evento (normalizado para tener acceso común a sus propiedades en los distintos navegadores). La función se ejecuta en el contexto del elemento al que se ha asignado el manejador.</p>
<pre><code class="javascript">function unaFuncion(e) {
	console.log('Contexto', this);
	console.log('Evento', e);
}

$('un.selector')
	.bind('click', unaFuncion);</code></pre>
<h2>Lo nuevo</h2>
<p>Con jQuery 1.2 podemos asignar un manejador para varios eventos con una sola llamada a <code>bind()</code>. Utilizamos para ello una lista de nombres de evento separados por espacios. Observa que en el manejador tomamos una decisión basada en la propiedad <code>type</code> del objeto del evento.</p>
<pre><code class="javascript">function handle(e) {
  var $label = $(this).prev();
  if (e.type == 'focus') {
    $label.hide();
  }
  else if (this.value == '') {
    $label.show();
  }
}

$('#login input')
  .filter('[type=text], [type=password]')
    .bind('focus blur', handle);</code></pre>
<p>Otra novedad interesante es la <em>pseudonombrespaciación</em> de eventos, que se puede practicar utilizando el nombre del evento seguido de un punto y un identificador arbitrario al asignar el manejador.</p>
<p>Y esto, ¿para qué? Para facilitar la eliminación de grupos de manejadores.</p>
<pre><code class="javascript">// en algún lugar del código de un drag'n'drop
$(document)
  .bind('mousemove.rock_n_roll', some_handler)
  .bind('mouseup.rock_n_roll', mouseup_handler);

// en el código de finalización del arrastre
$(document)
  .unbind('.rock_n_roll');</code></pre>
<p>Y algo que no es exactamente nuevo pero mola todo y se conoce poco: podemos pasar un objeto de datos en la asignación. El manejador lo recibirá en la propiedad <code>data</code> del evento.</p>
<pre><code class="javascript">function handle_click(e) {
  alert(e.data.foo);
}

$.fn.somePlugin(opts) {
  var settings = $.extend({
    foo: 'bar'
  });
  this.bind('click', settings, handle_click);
  return this;
}

// mostrará "bar" al activar los enlaces
// con clase "tigre"
$('a.tigre').somePlugin();

// mostrará "tolo" al activar los enlaces
// con clase "leon"
$('a.leon').somePlugin({ foo: 'tolo' });</code></pre>
<p>Por último, se incorpora a la API el método <code>triggerHandler</code> que complementa a <code>trigger</code>. La diferencia: <code>triggerHandler</code> dispara los manejadores asignados al evento pero no ejecuta las acciones por defecto del navegador.</p>
<p>Para más y mejor información y, de paso, practicar el inglés: <a href="http://docs.jquery.com/Release:jQuery_1.2/Events" hreflang="en" xml:lang="en" lang="en">Release: jQuery 1.2/Events</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/articulos/2008/07/eventos-en-jquery-12.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Ajax, eventos y jQuery</title>
		<link>http://blog.scriptia.net/articulos/2008/06/ajax-eventos-y-jquery.html</link>
		<comments>http://blog.scriptia.net/articulos/2008/06/ajax-eventos-y-jquery.html#comments</comments>
		<pubDate>Wed, 18 Jun 2008 22:38:44 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[artículos]]></category>

		<category><![CDATA[eventos]]></category>

		<category><![CDATA[inicialización]]></category>

		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/articulos/2008/06/ajax-eventos-y-jquery.html</guid>
		<description><![CDATA[Un «problema» con el que todo novato de la programación con jQuery se encuentra tarde o temprano (y las listas de correo lo demuestran) es que el contenido cargado (o generado) dinámicamente no dispara los manejadores de eventos asignados en $(document).ready.

Y, hoygan, esto es de lo más normal.
Si repasamos nuestra forma habitual de trabajar con [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/articulos/2006/12/eventos-en-jquery.html' rel='bookmark' title='Permanent Link: Eventos en jQuery'>Eventos en jQuery</a> <small>Presentamos un repaso en profundidad a los métodos de jQuery...</small></li><li><a href='http://blog.scriptia.net/articulos/2008/07/eventos-en-jquery-12.html' rel='bookmark' title='Permanent Link: Eventos en jQuery 1.2'>Eventos en jQuery 1.2</a> <small>Días ha que escribí una nota sobre los eventos en...</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/07/elementos-de-interfaz-para-jquery.html' rel='bookmark' title='Permanent Link: Elementos de interfaz para jQuery'>Elementos de interfaz para jQuery</a> <small>Arrastrar y soltar, ordenar listas, bonitos efectos...Interface elements for jQuery....</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Un «problema» con el que todo novato de la programación con jQuery se encuentra tarde o temprano (y las listas de correo lo demuestran) es que el contenido cargado (o generado) dinámicamente no dispara los manejadores de eventos asignados en <code>$(document).ready</code>.</p>
<p><span id="more-118"></span></p>
<p>Y, <em>hoygan</em>, esto <strong>es de lo más normal</strong>.</p>
<p>Si repasamos nuestra forma habitual de trabajar con jQuery, y reflexionamos un poquito&#8230;</p>
<pre><code class="javascript">$(document).ready(function() {
  $('selecciono.algo')
    .bind('click', hazCosasBonitas);
});</code></pre>
<p>&#8230; recordaremos que estamos utilizando <code>$(document).ready</code> porque <strong>no podemos seleccionar elementos que no existen</strong>. De ahí que tengamos que esperar a disponer de un árbol DOM completo. De ahí que los manejadores de eventos no afecten a elementos <strong>nuevos</strong>.</p>
<p>¿Entonces?</p>
<p>Opciones las hay adecuadas a unos casos y a otros. La más sencilla, para casos sencillos, es inicializar los contenidos nuevos una vez los hayamos insertado en el documento.</p>
<p>Necesitamos, pues, una función que nos permita seleccionar y actuar dentro de un contexto. Recuerda que jQuery provee de selecciones basadas en contexto. Si utilizas</p>
<pre><code class="javascript">$('a');</code></pre>
<p>seleccionarás todos los enlaces del documento. Pero si usas</p>
<pre><code class="javascript">$('a', unElementoSelecto);</code></pre>
<p>seleccionarás los enlaces descendientes de <var>unElementoSelecto</var>.</p>
<p>Por tanto, podemos crear nuestra función de inicialización según contexto como sigue.</p>
<pre><code class="javascript">function initLinks(context) {
  $('a', context)
    .bind('click', hazCosasBonitas)
}</code></pre>
<p>Que ejecutaremos desde nuestro manejador para <code>$(document).ready</code>, pasando el documento como contexto de búsqueda:</p>
<pre><code class="javascript">$(document).ready(function() {
  initLinks(document);
});</code></pre>
<p>Así que estamos como al principio&#8230; pero mucho más cerca del final. Lo único que nos queda por hacer es ejecutar <code>initLinks</code> cuando recuperemos nuevo contenido. Si usamos <code>load</code>, el más simplón de los métodos Ajax de jQuery, basta con usar una función de callback:</p>
<pre><code class="javascript">function loadNewContent() {
  $('#holder').load('ajax-content.html #response p', function() {
    // `this` apunta al elemento que acabamos de rellenar
    initLinks(this);
  });
}</code></pre>
<p>Y esta es la idea básica, que he reflejado en esta <a href="http://choangalvez.nom.es/presentaciones/jquery/examples/ajax-content.html">pequeña demo en latín</a>.</p>
<p>Por supuesto, hay otras opciones. Si eres de los que para clavar un clavo usa un plugin, échale un vistazo a <a href="http://docs.jquery.com/Plugins/livequery" hreflang="en">LiveQuery</a>; si tienes un serio trasiego de elementos <em>vivos</em>, mejor apostar por la delegación de eventos. Pero esas son otras historias que contaré a su debido momento.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/articulos/2008/06/ajax-eventos-y-jquery.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Taller de jQuery en The Cocktail el 29 de mayo</title>
		<link>http://blog.scriptia.net/al-margen/2008/05/taller-de-jquery-en-the-cocktail-el-29-de-mayo.html</link>
		<comments>http://blog.scriptia.net/al-margen/2008/05/taller-de-jquery-en-the-cocktail-el-29-de-mayo.html#comments</comments>
		<pubDate>Mon, 19 May 2008 14:33:43 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[al margen]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[presentaciones]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/al-margen/2008/05/taller-de-jquery-en-the-cocktail-el-29-de-mayo.html</guid>
		<description><![CDATA[Los muchachos de The Cocktail me han invitado a impartir un taller de jQuery en The Cocktail Academy.
Será el jueves 29 de mayo de 2008, a partir de las las 19.30h en los locales de Salamanca, 17 (Madrid). Si piensas asistir (es gratis), inscríbete cuanto antes en el wiki de los talleres.
Una pista de por [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/al-margen/2006/07/elementos-de-interfaz-para-jquery.html' rel='bookmark' title='Permanent Link: Elementos de interfaz para jQuery'>Elementos de interfaz para jQuery</a> <small>Arrastrar y soltar, ordenar listas, bonitos efectos...Interface elements for jQuery....</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/08/comenzando-con-jquery.html' rel='bookmark' title='Permanent Link: Comenzando con jQuery'>Comenzando con jQuery</a> <small>Si todavía no conoces jQuery esta guía escrita por Jörn...</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/08/jquery-10.html' rel='bookmark' title='Permanent Link: jQuery 1.0'>jQuery 1.0</a> <small>jQuery 1.0 está en la calle....</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Los muchachos de <a href="http://www.the-cocktail.com/" title="The Cocktail: consultora de experiencia de usuario y diseño de interacción">The Cocktail</a> me han invitado a impartir un taller de <a href="http://jquery.com/" hreflang="en">jQuery</a> en <a href="http://aulathecocktail.pbwiki.com/" lang="en" xml:lang="en">The Cocktail Academy</a>.</p>
<p>Será el jueves 29 de mayo de 2008, a partir de las las 19.30h en los locales de <a href="http://maps.google.com/maps?q=c%2F+Salamanca+17,+Madrid,+Madrid+28020">Salamanca, 17</a> (Madrid). Si piensas asistir (es gratis), <a href="http://aulathecocktail.pbwiki.com/jQuery,+haz+m%C3%A1s+con+menos+c%C3%B3digo">inscríbete</a> cuanto antes en el wiki de los talleres.</p>
<p>Una pista de por donde irán los tiros. Hablaremos de:</p>
<ul>
<li>selección de elementos, filtrado, etc.;</li>
<li>eventos a fondo, incluyendo delegación de eventos y sus ventajas;</li>
<li>navegación por el DOM;</li>
<li>algún que otro truquito de lo más chachipiruli.</li>
</ul>
<p>Y por supuesto, de algunas razones para usar (o no usar) jQuery.</p>
<p>Después del taller, estáis todos invitados a pagarme unas cañas.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/al-margen/2008/05/taller-de-jquery-en-the-cocktail-el-29-de-mayo.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Embellecedor de código javascript</title>
		<link>http://blog.scriptia.net/al-margen/2007/11/embellecedor-de-codigo-javascript.html</link>
		<comments>http://blog.scriptia.net/al-margen/2007/11/embellecedor-de-codigo-javascript.html#comments</comments>
		<pubDate>Thu, 22 Nov 2007 12:02:10 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[al margen]]></category>

		<category><![CDATA[embellecedores]]></category>

		<category><![CDATA[herramientas]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/al-margen/2007/11/embellecedor-de-codigo-javascript.html</guid>
		<description><![CDATA[¿Diste con un código que te gustaría estudiar y está compactado en una línea? Beautify Javascript reformatea cualquier cosa para convertirla en algo legible.
Visto en Sentido web.



Related posts:<ol><li><a href='http://blog.scriptia.net/al-margen/2006/07/javascript-shell.html' rel='bookmark' title='Permanent Link: JavaScript Shell'>JavaScript Shell</a> <small>Una herramienta que uso a diario. Tan pequeña como un...</small></li><li><a href='http://blog.scriptia.net/articulos/2006/07/de-como-comprimir-ficheros-javascript.html' rel='bookmark' title='Permanent Link: De cómo comprimir ficheros javascript'>De cómo comprimir ficheros javascript</a> <small>Ahora que javascript comienza a perder la fama de lenguaje...</small></li><li><a href='http://blog.scriptia.net/al-margen/2007/06/herramientas-de-desarrollo-web-para-internet-explorer.html' rel='bookmark' title='Permanent Link: Herramientas de desarrollo web para Internet Explorer'>Herramientas de desarrollo web para Internet Explorer</a> <small>John Hrvatin presenta en IE Blog una serie de herramientas...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>¿Diste con un código que te gustaría estudiar y está compactado en una línea? <a href="http://elfz.laacz.lv/beautify/" hreflang="en" lang="en" xml:lang="en">Beautify Javascript</a> reformatea cualquier cosa para convertirla en algo legible.</p>
<p>Visto en <a href="http://sentidoweb.com/2007/11/20/beautify-javascript-aclara-codigo-javascript.php">Sentido web</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/al-margen/2007/11/embellecedor-de-codigo-javascript.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Los locos locos eventos de teclado</title>
		<link>http://blog.scriptia.net/al-margen/2007/11/los-locos-locos-eventos-de-teclado.html</link>
		<comments>http://blog.scriptia.net/al-margen/2007/11/los-locos-locos-eventos-de-teclado.html#comments</comments>
		<pubDate>Tue, 13 Nov 2007 15:19:41 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[al margen]]></category>

		<category><![CDATA[eventos]]></category>

		<category><![CDATA[referencia]]></category>

		<category><![CDATA[teclado]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/al-margen/2007/11/los-locos-locos-eventos-de-teclado.html</guid>
		<description><![CDATA[En lo que hace a eventos, los navegadores suelen ir a su bola. Y en lo que hace a eventos de teclado, el caos es absoluto: hay quien notifica las teclas modificadores en keypress, hay quien no; cada navegador es un mundo en cuanto a códigos de tecla&#8230; y dos o tres pesadillas más.
En JavaScript [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/al-margen/2006/11/referencia-de-eventos-dom-en-la-wikipedia.html' rel='bookmark' title='Permanent Link: Referencia de eventos DOM en la Wikipedia'>Referencia de eventos DOM en la Wikipedia</a> <small>Eventos DOM --estándares y propietarios-- correctamente descritos en DOM events...</small></li><li><a href='http://blog.scriptia.net/articulos/2006/12/eventos-en-jquery.html' rel='bookmark' title='Permanent Link: Eventos en jQuery'>Eventos en jQuery</a> <small>Presentamos un repaso en profundidad a los métodos de jQuery...</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/07/chuleta-de-javascript.html' rel='bookmark' title='Permanent Link: Chuletita de javascript'>Chuletita de javascript</a> <small>En I Love Jack Daniel's encontraremos multitud de chuletas para...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>En lo que hace a eventos, los navegadores suelen ir a su bola. Y en lo que hace a eventos de teclado, el caos es absoluto: hay quien notifica las teclas modificadores en keypress, hay quien no; cada navegador es un mundo en cuanto a códigos de tecla&#8230; y dos o tres pesadillas más.</p>
<p>En <a href="http://unixpapa.com/js/key.html" lang="en" xml:lang="en" hreflang="en">JavaScript Madness: Keyboard Events</a>, Jan Wolter documenta para uso y disfrute público todas las divergencias que se va encontrando.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/al-margen/2007/11/los-locos-locos-eventos-de-teclado.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Un patrón de desarrollo de plugins para jQuery</title>
		<link>http://blog.scriptia.net/al-margen/2007/10/un-patron-de-desarrollo-de-plugins-para-jquery.html</link>
		<comments>http://blog.scriptia.net/al-margen/2007/10/un-patron-de-desarrollo-de-plugins-para-jquery.html#comments</comments>
		<pubDate>Wed, 31 Oct 2007 21:03:38 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[al margen]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[patrones]]></category>

		<category><![CDATA[tutoriales]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/al-margen/2007/10/un-patron-de-desarrollo-de-plugins-para-jquery.html</guid>
		<description><![CDATA[Mike Alsup, autor de jQuery form plugin y otras delicias, nos explica cómo crear un plugin para jQuery que cumpla con las condiciones de: no contaminar el espacio de nombres, acepte opciones (y las extienda), mantenga los límites adecuados entre lo público y lo privado y saque provecho del plugin de metadatos. Ahí es nada: [...]


Related posts:<ol><li><a href='http://blog.scriptia.net/articulos/2008/07/eventos-en-jquery-12.html' rel='bookmark' title='Permanent Link: Eventos en jQuery 1.2'>Eventos en jQuery 1.2</a> <small>Días ha que escribí una nota sobre los eventos en...</small></li><li><a href='http://blog.scriptia.net/articulos/2008/10/jquery-del-espagueti-al-plugin.html' rel='bookmark' title='Permanent Link: Trabajando con jQuery: timeline arrastrable, del espaguetismo al plugin'>Trabajando con jQuery: timeline arrastrable, del espaguetismo al plugin</a> <small>En el capítulo de hoy veremos cómo reconvertir un código...</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/07/elementos-de-interfaz-para-jquery.html' rel='bookmark' title='Permanent Link: Elementos de interfaz para jQuery'>Elementos de interfaz para jQuery</a> <small>Arrastrar y soltar, ordenar listas, bonitos efectos...Interface elements for jQuery....</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Mike Alsup, autor de <a href="http://malsup.com/jquery/form/" hreflang="en">jQuery form plugin</a> y otras delicias, nos explica cómo crear un plugin para jQuery que cumpla con las condiciones de: no contaminar el espacio de nombres, acepte opciones (y las extienda), mantenga los límites adecuados entre lo público y lo privado y saque provecho del plugin de metadatos. Ahí es nada: <a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern" hreflang="en" lang="en" xml:lang="en">A Plugin Development Pattern</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/al-margen/2007/10/un-patron-de-desarrollo-de-plugins-para-jquery.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>jQuery UI y jQuery 1.2.1</title>
		<link>http://blog.scriptia.net/al-margen/2007/09/jquery-ui-y-jquery-121.html</link>
		<comments>http://blog.scriptia.net/al-margen/2007/09/jquery-ui-y-jquery-121.html#comments</comments>
		<pubDate>Mon, 17 Sep 2007 12:22:46 +0000</pubDate>
		<dc:creator>choan</dc:creator>
		
		<category><![CDATA[al margen]]></category>

		<category><![CDATA[interfaz]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[widgets]]></category>

		<guid isPermaLink="false">http://blog.scriptia.net/al-margen/2007/09/jquery-ui-y-jquery-121.html</guid>
		<description><![CDATA[Llega jQuery UI, una colección de componentes reusables y de alta calidad: jQuery UI: Interactions and Widgets.
Y también la versión 1.2.1 de jQuery, con algunas correcciones de bugs sobre la 1.2.



Related posts:<ol><li><a href='http://blog.scriptia.net/al-margen/2006/07/elementos-de-interfaz-para-jquery.html' rel='bookmark' title='Permanent Link: Elementos de interfaz para jQuery'>Elementos de interfaz para jQuery</a> <small>Arrastrar y soltar, ordenar listas, bonitos efectos...Interface elements for jQuery....</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/09/carrusel.html' rel='bookmark' title='Permanent Link: Carrusel'>Carrusel</a> <small>Continua la lluvia de plugins para jQuery. Esta vez nos...</small></li><li><a href='http://blog.scriptia.net/al-margen/2006/08/comenzando-con-jquery.html' rel='bookmark' title='Permanent Link: Comenzando con jQuery'>Comenzando con jQuery</a> <small>Si todavía no conoces jQuery esta guía escrita por Jörn...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Llega jQuery UI, una colección de componentes reusables y de alta calidad: <a href="http://jquery.com/blog/2007/09/17/jquery-ui-interactions-and-widgets/" hreflang="en" xml:lang="en" lang="en">jQuery UI: Interactions and Widgets</a>.</p>
<p>Y también la versión <a href="http://jquery.com/blog/2007/09/16/jquery-121-quick-fixes-for-12/" hreflang="en">1.2.1 de jQuery</a>, con algunas correcciones de bugs sobre la 1.2.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.scriptia.net/al-margen/2007/09/jquery-ui-y-jquery-121.html/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
