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

<channel>
	<title>elBlëg - Interactividad, usabilidad y web &#187; Javascript</title>
	<atom:link href="http://www.elbleg.com/category/web-dev/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://www.elbleg.com</link>
	<description>Interactividad, usabilidad y web</description>
	<lastBuildDate>Thu, 11 Mar 2010 17:17:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Optimizando JavaScript para un rendimiento extremo y bajo consumo de memoria</title>
		<link>http://www.elbleg.com/web-dev/javascript/optimizando-javascript-para-un-rendimiento-extremo-y-bajo-consumo-de-memoria.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/optimizando-javascript-para-un-rendimiento-extremo-y-bajo-consumo-de-memoria.html#comments</comments>
		<pubDate>Sun, 15 Nov 2009 08:07:24 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=244</guid>
		<description><![CDATA[
			En mis muy esporádicos ratos libres estoy haciendo un pequeño juego en JavaScript y he tenido que tomar algunas medidas para agilizar el código. La idea en este post es mostrar algunos trucos que he aprendido en el proceso, algunos no los he visto mencionados en otras partes, así que no está de más compartirlos.
		

			Muchos [...]]]></description>
			<content:encoded><![CDATA[<p>
			En mis muy esporádicos ratos libres estoy haciendo un pequeño juego en JavaScript y he tenido que tomar algunas medidas para agilizar el código. La idea en este post es mostrar algunos trucos que he aprendido en el proceso, algunos no los he visto mencionados en otras partes, así que no está de más compartirlos.
		</p>
<p>
			Muchos de los tips de optimización para JavaScript involucran cosas que se ven más típicamente en otros sitios, como por ejemplo minimizar la cantidad de modificaciones al DOM. Pero en este caso es un poco diferente, ya que era el script por sí mismo era quien debía correr más rápido &#8211; No trabaja con el DOM ni nada, solo procesa muchos datos.
		</p>
<p><span id="more-244"></span></p>
<h2>
			Encontrando la raíz del problema<br />
		</h2>
<p>
			Antes de iniciar cualquier optimización, el código debe ser perfilado para saber qué parte es la que está corriendo despacio. La mejor herramienta para lograr esto, es definitivamente el Profiler de Firebug. Sin este probablemente hubiese tenido muchas más dificultades para encontrar problemas y probar cómo las cosas que cambiaba afectaban la velocidad.
		</p>
<p>
			El Profiler lo encontrás en la consola del Firebug. Solo dale clic en el botón ‘profiler’ una vez para iniciar el <em>perfilamiento (si es que existe la palabra)</em> y clicás de nuevo para detenerlo. Después de detenerlo vas a recibir una lista informativa de las funciones que han sido llamadas y cuanto tiempo tomó cada una en ejecutarse.
		</p>
<h3>
			Problema 1: Iteraciones, cantidad de datos<br />
		</h3>
<p>
			El primer problema que me abofeteó fué la enorme cantidad de datos que se debían de guardar. Un mapa de 128&#215;128 requiere 16,384 iteraciones para ser completamente procesado. A primer vista no parece tanto, pero solamente iterar la data, sin hacer nada más, causaba un golpe mucho mayor del que pasaría en muchos otros lenguajes. Por extraño que pueda parecer, podés usar un do-while invertido para acelerar las iteraciones, o sea en lugar de usar un ciclo con for y contar sumando, usás un ciclo con do-while y contás restando. </p>
<pre class="js" name="code">
			var i = data.length;
			do {
			 /* algo que hacer */
			} while(--i);
</pre>
<p>Por qué es más rápido? Aparentemente el simple hecho de remover la condicion usada para comprobar cuando el loop termine hace gran parte de la diferencia. Hacer -i en vez de i- también ayuda un poco. </p>
<p>El problema con este enfoque es que no siempre es aplicable.</p>
<h3>Problema 2: Llamar funciones</h3>
<p>Fué curioso encontrar que el simple hecho de llamar una función agrega un overhead significativo. Así que llamar una función dentro de uno de esos ciclos grandes en los for puede agregar mucho tiempo de procesamiento.</p>
<p>Como resolverlo? Colocando el código de la función dentro del loop.</p>
<p>Sí, raro. Pero si mueves el código de la función y lo colocas dentro del loop en lugar de llamar la función vas a tener una mejora significativa.  Tiene como gran desventaja que reduce la legibilidad del código, además de que le abre las puertas a la duplicación de código si la función se usa en más de un lugar.</p>
<p>Por raro que sea, esto fué uno de los propulsores más grandes de performance, que en este caso particular, era más importante que un código legible.</p>
<h3>Problema 3: Limitaciones de la memoria</h3>
<p>Dado al bajo monto de memoria disponible en el dispositivo al que va dirigido el juego. La aplicación se quedó sin memoria en varias ocasiones.</p>
<p>Primero, el tamaño del mapa era de 300&#215;300, lo que hacía que el teléfono se quedara sin memoria casi de inmediato. Para esto no hubo más remedio que reducir el tamaño a un 128&#215;128. Usar 300&#215;300 pudo también tener otras repercusiones con el performance, porque la cantidad de data hubiese sido mucho mayor para dibujarlo.</p>
<p>Segundo, cuando implementé la funcionalidad para cargar y salvar el juego, el app de nuevo se quedaba sin memoria. Esto probablemente causado porque el data del mapa era serializado a JSON.</p>
<p>La idea que resolvió esto: Cortar el data en pedazitos pequeños.</p>
<p>Entonces, en lugar de guardar todo el array del mapa de 128&#215;128 de una sola vez, el código lo hace en 8 partes. De este modo el tamaño del JSON serializado se mantiene pequeño y la aplicación no se queda sin memoria.</p>
<p>Lo mismo se hace cuando carga, Como el JSON es guardado en 8 bloques separados, al cargar se meten dentro del array uno por uno.</p>
<h3>Más optimizaciones: Dividir y Flood numbers</h3>
<p>Como parte de la lógica del juego también eran necesario dividir algunos numeros y asegurarme de que los valores eran números enteros.</p>
<p>Típicamente esto requeriría dividir primero y luego aplicar Math.floor. Como mencioné hace un rato. Llamar funciones puede salir caro.</p>
<p>Hay un truco ‘limpio’ para esto. Y limpio entre comillas porque para algunas personas puede ser confuso si no están familiarizadas con la sintáxis, y esto, pues hace el código un poco dificil de leer.</p>
<p>El truco consiste en usar un bit-shift (no conozco el término en español&#8230;):</p>
<pre class="js" name="code">
				var foo = 10;
				//la mayoría de veces, esto es lo mismo que hacer Math.floor(foo / 4)
				var result = foo >> 2;
</pre>
<p>Hacer  <code> >> 2</code> es, como menciona el comentario, practicamente lo mismo que dividir por 4 y despues llamar un <code>Math.floor</code>. Pero en lugar de dos operaciones, tenés solamente una, por lo tanto puede ser un poco más rápido.</p>
<p>Si no entendés de matemática binaria los bitshifts pueden ser un poco enredados. En palabras simples, si hacés  <code>>></code> con 1, es lo mismo que dividir por 2, 2 es dividir entre 4, 3 es dividir entre 8, y 4 es dividir entre 16 y ahí sigue la idea&#8230;</p>
<p>Como es costumbre, <a target="_blank" href="http://en.wikipedia.org/wiki/Bit_shift#Bit_shifts">hay un buen articulo en Wikipedia sobre esto</a>, el cual es un buen recurso si querés leer más información al respecto.</p>
<h3>Más?: Mete el código en funciones anónimas</h3>
<p>Esta es una sugerencia vieja vieja vieja, pero buena buena buena&#8230; Mete el código en funciones anónimas incluso si no son o usan globales.</p>
<p>Por alguna razón que no podría explicar apropiadamente, esto afecta también la velocidad de ejecución de los scripts.</p>
<p>Así que cuando sea que tengas código en JS en un archivo, recuerda envolverla en una función anónima auto ejecutable como esta:</p>
<pre class="js" name="code">
(function(window) {
  /* todo el código va acá!!*/
})(window);
			</pre>
<p>También podés hacer que la función reciba el objeto window como un argumento para una posible pequeña mejora.</p>
<h3>Por último: Reducí el scope</h3>
<p>Esta amarra con la anterior, agregá variables locales dentro de la función anónima para funciones que se usan normalmente, como Math.round or Math.random</p>
<pre class="js" name="code">
(function(window) {
  var round = Math.round;
  var random = Math.random;
  /* todo el código va acá!!*/
})(window);
</pre>
<h3>Conclusión</h3>
<p>Solo porque ya se me hizo costumbre hacer conclusión&#8230;. En fín. La idea detrás de todo esto es mostrar que hay formas de mejorar la velocidad del JavaScript, incluso cuando no tenga nada que ver con el DOM, pero si de igual modo trabajas con el, no está de más agregar unos tips a lo que ya conoces.</p>
<p>Agregando una cosa más a lo anterior. Hay una cosa más que intenté: Probar si había alguna diferencia entre llamar una función objeto vs una función instancia:</p>
<pre class="js" name="code">
				var x = new Foo();
				x.someFunc();
				//or
				bar.someFunc();
</pre>
<p>Yo no ví diferencia alguna, pero si estás usando las clasicas intancias de POO en lugar de funciones estáticas. Puede que te sirva.</p>
<p>Solo recordá que debes perfilar el código siempre antes y después de una optimización. Para ver donde están las partes que realmente necesitan optimizarse y su hubieron mejoras después de algún cambio.</p>
<p>También considerá que muchas optimizaciones pueden hacer que el código sea dificil de mantener. Así que puedes poner en una balanza que tanto necesitas mejorar el performance. Si no es tanto, a veces es mejor no hacerlo.</p>
<p>Espero que te sirva de algo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/optimizando-javascript-para-un-rendimiento-extremo-y-bajo-consumo-de-memoria.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nombres de Funciones dinámicos con JavaScript</title>
		<link>http://www.elbleg.com/web-dev/javascript/nombres-de-funciones-dinamicos-con-javascript.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/nombres-de-funciones-dinamicos-con-javascript.html#comments</comments>
		<pubDate>Tue, 27 Oct 2009 06:01:59 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=236</guid>
		<description><![CDATA[Si te toca hacer aplicaciones un poco avanzadas con JavaScript, vas a toparte con un problema en un punto u otro donde vas a necesitar generar dinámicamente el nombre de una función que quieras llamar. Algo como el equivalente a call_user_func() de PHP.


Algo así es como podés hacerlo:
// Definimos algunas variables
var foo = &#34;Hola&#34;;
var bar [...]]]></description>
			<content:encoded><![CDATA[<p>Si te toca hacer aplicaciones un poco avanzadas con JavaScript, vas a toparte con un problema en un punto u otro donde vas a necesitar generar dinámicamente el nombre de una función que quieras llamar. Algo como el equivalente a <code>call_user_func()</code> de PHP.
</p>
<p><span id="more-236"></span></p>
<p>Algo así es como podés hacerlo:</p>
<pre class="js" name="code">// Definimos algunas variables
var foo = &quot;Hola&quot;;
var bar = &quot;Mundo&quot;;
var nombre_funcion = &quot;decir_&quot; + foo + bar;

/*  Dado que estamos generandolo din&aacute;micamente,
* siempre hay que asegurarse de que la funci&oacute;n
* exista en realidad. */

if (typeof(window[nombre_funcion]) === &quot;function&quot;)
{
	window[nombre_funcion](&quot; Mundo!&quot;);
}
else
{
	throw(&quot;Error.  La funci&oacute;n &quot; + nombre_funcion + &quot; no existe...duh!&quot;);
}

function decir_holaMundo(la_palabra)
{
	alert(&quot;Hola &quot; + la_palabra);
}

// Browser va a alertar un trillad&iacute;simo &quot;Hola Mundo!&quot;</pre>
<p>Cuando lo pensás un rato, tiene mucho sentido considerando que todos los objetos globales en JavasScript son en realidad propiedades del objeto <code>“window”</code>. Fijate en este ejemplo de manzanas y naranjas para entender un poco mejor el concepto.</p>
<pre class="js" name="code">var foo = &quot;manzana&quot;;

function foobar()
{
	var foo = &quot;naranja&quot;;
	alert(window[&quot;foo&quot;]); // alerta &quot;manzana&quot;
	alert(foo); // alert &quot;naranja&quot;
	alert(window[&quot;foobar&quot;]); // alerta la funci&oacute;n foobar
}

foobar();
</pre>
<p>Acá hay otro ejemplo de cuando usar strings para llamar una función puede ser útil. Esta vez llamamos la propiedad de un objeto que hemos creado.</p>
<pre class="js" name="code">function Persona()
{
	this.mensaje = &quot;Hola Mundo!&quot;;
	this.decir_hola = function(a)
	{
		alert(this.mensaje);
	}
}

var Yeco = new Persona();
nombre_funcion = &quot;decir_hola&quot;;
Yeco[nombre_funcion]();</pre>
<p>Ves como es casi lo mismo que el método de arriba usando una función global?</p>
<p>Espero que te sirva en algún momento.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/nombres-de-funciones-dinamicos-con-javascript.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 formas de escribir un mejor código en jQuery</title>
		<link>http://www.elbleg.com/web-dev/javascript/10-formas-de-escribir-un-mejor-codigo-en-jquery.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/10-formas-de-escribir-un-mejor-codigo-en-jquery.html#comments</comments>
		<pubDate>Sun, 23 Aug 2009 07:14:00 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web Dev]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[chaining]]></category>
		<category><![CDATA[encadenado]]></category>
		<category><![CDATA[jquery data]]></category>
		<category><![CDATA[jquery document ready]]></category>
		<category><![CDATA[optimización]]></category>
		<category><![CDATA[toggleClass]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=227</guid>
		<description><![CDATA[Sin duda alguna, jQuery se ha vuelto la biblioteca de javascript por excelencia, y no lo digo solamente porque me agrade, la gran cantidad de recursos, plugins, tutoriales y documentación, hacen que a muchos les entre la curiosidad y se inicien en javascript aún cuando nunca les atrajo el lenguaje. 
Y bien, ya que la [...]]]></description>
			<content:encoded><![CDATA[<p>Sin duda alguna, jQuery se ha vuelto la biblioteca de javascript por excelencia, y no lo digo solamente porque me agrade, la gran cantidad de recursos, plugins, tutoriales y documentación, hacen que a muchos les entre la curiosidad y se inicien en javascript aún cuando nunca les atrajo el lenguaje. </p>
<p>Y bien, ya que la usamos seguido, o pensamos aprenderla, no nos queda de más conocer unos cuantos tips que nos sirvan para que funcione de un modo más adecuado.<br />
<span id="more-227"></span><br />
Andando por ahí me encontré un post de <a rel="external" href="http://www.myinkblog.com/2009/08/04/10-tips-for-writing-better-jquery-code/">Giulio Bai</a> que aborda este tema en específico y nos dá unas buenas sugerencias al respecto:</p>
<h2>1. $(document).ready (); Siempre</h2>
<p>Todo lo que contenga será ejecutado tan pronto el DOM sea cargado y antes de que los contenidos sean llenados. Te permite agregar eventos a cualquier elemento en la página sin interferir directamente con el markup; todos esos metiches de <code>onload</code>, <code>onclick</code> y <code>onLoQueSea</code> ya no son necesarios, solo escribílos encapsulados ahí.</p>
<p>Un pequeño ejemplo podría ser:</p>
<pre name="code" class="js">$(document).ready(function()
 {
    $(&quot;.dummy&quot;).click(function()
    {
        $(this).css(&#039;color&#039;, &#039;#000000&#039;);
    });
});</pre>
<h2>2. Usá $(window).load ()</h2>
<p>Aunque la vasta mayoría de ejemplos vienen usando el método descrito anteriormente, a veces es mejor evitar poner todo ahí.</p>
<p><code>$(document).ready ()</code> es increíblemente útil, pero ocurre durante el rendering de la página, cuando los objetos aún se están descargando. Por eso las funcionalidades supérfluas como scrollings, arrastrar y soltar, podrían ponerse dentro de una función <code>$(window).load ()</code> ya que esta ejecuta después de que todos los hayan sido descargados y evita que algo se rompa mientras carga la página.</p>
<p>La sintáxis es casi la misma que la de <code>$(document).ready ()</code>:</p>
<pre name="code" class="js">$(window).load (function () {
// métodos de scrolling
});</pre>
<h2>3. Carga sólo lo que realmente necesitas</h2>
<p>Todos han sido tentados a escribir JavaScript que va a ser usado en una sola página de un sitio y luego cargarlo por todas partes, aunque no se use. jQuery se toma el tiempo de revisar todos y cada uno de los elementos que se le dan, y eso pone las cosas un poco lentas.</p>
<p>Hay dos formas que se sugieren para evitar este problema. El más sencillo sería simplemente agregar una clase en el <code>body</code> del html que sea identificador para correr ahí solamente el código necesario.</p>
<pre name="code" class="js">$(document).ready(function()
 {
    if (&#039;body&#039;).hasClass(&#039;home&#039;)
    {
        // home page code
        }
    else if (&#039;body&#039;).hasClass(&#039;blog&#039;)
    {
        // blog code
        }
    // Y as&iacute; sucesivamente
});
</pre>
<p>El otro método, un poco más enredado, sería construir una biblioteca para llamar el código que se necesite desde cada página:</p>
<pre name="code" class="js">var jslib =
{
    home:
    {
        init: function() {
            // home page code
            }
    },

    blog:
    {
        init: function() {
            // blog code
            }
    }

    // Y as&iacute; sucesivamente
}</pre>
<h2>4. Aprende qué es el método &#8216;Data&#8217; y usálo</h2>
<p>Esto es algo muy común, la gente no piensa en ello y siempre escriben cosas como:</p>
<pre name="code" class="js">$('.selector').attr ('alt', 'naranja');</pre>
<p>para guardar y asociar datos misceláneos en el DOM. Esto, es técnicamente incorrecto, además de que es fácil confundirse, sobre todo para las personas que entren al proyecto después.</p>
<p>jQuery ya tiene un método que sirve para guardar datos en el DOM llamado &#8216;data&#8217;. El ejemplo de arriba vendría siendo algo como esto:</p>
<pre name="code" class="js">$('.selector').data ('miColor', 'azul');
// que puede ser pedido con
$('.selector').data ('miColor');</pre>
<p>Este método te permite asociar y guardar datos en cualquier elemento de la página y tener un nombre de referencia.</p>
<h2>5. Usá los selectores personalizados</h2>
<p>Estar familiarizado con los selectores de CSS es util cuando se trata de jQuery. Pero conocer los selectores que trae la biblioteca es de verdad un empujón increíble. Date una vuelta por <a href="http://docs.jquery.com/Selectors">http://docs.jquery.com/Selectors</a> para conocer más de ellos.</p>
<p>Por ejemplo, podrías usar:</p>
<pre name="code" class="js">$("div:contains('hola')").css ('background-color', '#cc0000');</pre>
<p>para pintar de rojo todos los div que contengan la palabra &#8220;hola&#8221; ó</p>
<pre name="code" class="js">$('input:password')</pre>
<p> para obtener todos los campos que sean para password.</p>
<h2>6. Indicadores con clases</h2>
<p>Podés usar indicadores ó flags para monitorear lo que el usuario está haciendo o bien revisar si algo en particular se efectuó o no. El método <code>addClass</code> es bastante útil en este caso ya que provee una forma fácil de agregar una nueva clase css a un elemento. Así que podés chequear la existencia de la clase con la función <code>hasClass</code>.</p>
<p>Un uso muy común de los indicadores se da cuando a aplicación tiene uno o más modos de trabajo; al entrar en el segundo modo, el indicador se fija a un elemento predeterminado y, cuando se necesite, el método <code>hasClass</code> es usado para revisar el modo de trabajo actual. Sencillo no?</p>
<pre name="code" class="js">function editModeOn ()
{
// Inicializa el modo de edición y fija un indicador
$(&#039;#flags&#039;).addClass (&quot;editModeOn&quot;);
// hacer otras cosas
}

function saveData ()
{
// guarda los datos pero primero sale del modo de edición (si está ahí)
if ($(&#039;#flags&#039;).hasClass (&#039;editModeOn&#039;)) {
exitEditMode ();
$(&#039;#flags&#039;).removeClass (&#039;editModeOn&#039;);
}

save ();
}</pre>
<h2>7. No llamés el mismo selector cientos de veces</h2>
<p>De verdad, no lo hagas. Perfectamente en lugar de hacer algo como:</p>
<pre name="code" class="js">$(&#039;p.hola&#039;).css (&#039;color&#039;, &#039;#000000&#039;);
$(&#039;p.hola&#039;).text (&#039;hoola&#039;);
$(&#039;p.hola&#039;).addClass (&#039;parrafo&#039;);
$(&#039;p.hola&#039;).fadeTo (1000, 1);
</pre>
<p>Podés hacer algo como:</p>
<pre name="code" class="js">var $p = $(&#039;p.hola&#039;);
$p.css (&#039;color&#039;, &#039;#000000&#039;);
$p.text (&#039;hola&#039;);
$p.addClass (&#039;parrafo&#039;);
$p.fadeTo (1000, 1);
</pre>
<p>Eso va a mantener la información del selector lista para ser reutilizada.</p>
<h2>8. Encadenando (Casi) todo</h2>
<p>El encadenado, o chaining de jQuery es muy útil.<br />
El código anterior podría ser reescrito como:</p>
<pre name="code" class="js">
$(&#039;p.hola&#039;).css (&#039;color&#039;, &#039;#000000&#039;).text (&#039;hola&#039;).addClass (&#039;parrafo&#039;).fadeTo (1000, 1);</pre>
<p>Eso sí, sin exagerar, es sabido que este patrón puede ser un poco lento.</p>
<h2>9. La utilidad toggleClass</h2>
<p>Podés encender y apagar la clase de un elemento para variar su comportamiento sin mucho esfuerzo. Digamos que tenés una clase <code>.hidden</code> que esconde los elementos que la usen. Fácilmente podrías mostrar los elementos de nuevo usando:</p>
<pre name="code" class="js">
$(&#039;p.hidden&#039;).toggleClass ();
</pre>
<p>Otro punto de <code>toggleClass</code> es que, con el nuevo release de jQuery 1.3.3, el método .toggleClass() va a tener nuevas formas de operar. Va a ser capaz de cambiar multiples clases, además de que podrá quitar y poner todas las clases.</p>
<p>Estás son las formas en que vas a poder usar <code>toggleClass</code>:</p>
<pre name="code" class="js">// Con un elemento dado

	// Cambiar todas las Clases
	$(&#039;div&#039;).toggleClass(); //
	&lt;div&gt;
	$(&#039;div&#039;).toggleClass(); //
	&lt;div class=&quot;a b c&quot;&gt;
	$(&#039;div&#039;).toggleClass( false ); //
	&lt;div&gt;
	$(&#039;div&#039;).toggleClass( true ); //
	&lt;div class=&quot;a b c&quot;&gt;

	// Cambiar m&uacute;ltiples clases
	$(&#039;div&#039;).toggleClass( &quot;a b&quot; ); //
	&lt;div class=&quot;c&quot;&gt;
	$(&#039;div&#039;).toggleClass( &quot;a c&quot; ); //
	&lt;div class=&quot;a&quot;&gt;
	$(&#039;div&#039;).toggleClass( &quot;a b c&quot;, false ); //
	&lt;div&gt;
	$(&#039;div&#039;).toggleClass( &quot;a b c&quot;, true ); //&lt;/div&gt;
	&lt;/div&gt;
	&lt;/div&gt;
	&lt;/div&gt;
	&lt;/div&gt;
	&lt;/div&gt;
	&lt;/div&gt;</pre>
<h2>10. Guardá los resultados de jQuery</h2>
<p>Cuando se trata de funciones, podrías querer tener algunos resultados disponibles en otros lugares. Acá hay dos posibilidades.</p>
<p>Una posible solución sería guardar los resultados dentro de objetos dentro de una variable global, así se pueden usar después:</p>
<pre name="code" class="js">// usamos el objeto Window
	window.$resultados = {
	uno : 0,
	dos : 0
	};

	// esta es la funci&oacute;n que podria corre m&aacute;s de una vez
	function getResults (first, second)
	{
	$resultados.uno = first;
	$resultados.dos = second;
	}

	// corre la funcion
	getResults ($(&#039;li.azul&#039;), $(&#039;a.rojo));
	$resultados.uno.hasClass (&#039;azul&#039;); // true
	$resultados.dos.hasClass (&#039;azul&#039;); // false

	// corre de nuevo
	getResults ($(&#039;li.rojo&#039;), $(&#039;a.azul));
	$resultados.uno.hasClass (&#039;azul&#039;); // false
	$resultados.dos.hasClass (&#039;azul&#039;); // true
</pre>
<p>La otra, y a mi parecer la mejor, como se recomienda en el punto 4 es usar el método Data en lugar de crear una variable global.</p>
<pre name="code" class="js">$.data(window, &quot;resultados&quot;, { uno: false, dos: true });

//Para accesar los valores:

$.data(window, &quot;resultados&quot;).uno; // false
$.data(window, &quot;resultados&quot;).dos; // true

// Y para cambiarlos:

$.data(window, &quot;resultados&quot;).uno = true;
$.data(window, &quot;resultados&quot;).dos = false;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/10-formas-de-escribir-un-mejor-codigo-en-jquery.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Singleton en JavaScript, o: Cómo convertir constructores a JSON</title>
		<link>http://www.elbleg.com/web-dev/javascript/singleton-en-javascript-o-como-convertir-constructores-a-json.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/singleton-en-javascript-o-como-convertir-constructores-a-json.html#comments</comments>
		<pubDate>Fri, 24 Jul 2009 07:54:13 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[singleton]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=219</guid>
		<description><![CDATA[Cuando necesités una sola instancia de una clase de JavaScript, no te molestés escribiendo un constructor, escribí un solo JSON.
El gran poder de los objetos es que los datos y las funciones que hacen algo pueden estar encapsuladas en un mismo objeto. Así que aprovechandonos de ello y para seguir buenas prácticas, a veces metemos [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando necesités una sola instancia de una clase de JavaScript, no te molestés escribiendo un constructor, escribí un solo JSON.</p>
<p>El gran poder de los objetos es que los datos y las funciones que hacen algo pueden estar encapsuladas en un mismo objeto. <span id="more-219"></span>Así que aprovechandonos de ello y para seguir buenas prácticas, a veces metemos todas las utilidades necesarias al &#8220;desnudo&#8221; en el namespace global. Algo así:</p>
<p><code>function getElementsByClassName(cssClassName) {...}</code></p>
<p>Aunque en esto veo dos problemas:</p>
<ul>
<li>Uno pequeño: el nombre de la función es extremadamente largo&#8230; que feo</li>
<li>y uno grande: si estás trabajando con alguna librería, es muy probable que colisione con otra función con un nombre similar y que se comporte diferente</li>
</ul>
<h3>Vamos a arreglarlos</h3>
<p>Podemos crear una clase de utilidades que nos sirva para encapsular esta función (y otras) más o menos así:</p>
<pre name="code" class="js">function DomUtilityBag() {
this.getByClass= function(cssClassName) {...}
}</pre>
<p>e instanciarla:</p>
<pre name="code" class="js">var domUtils = new DomUtilityBag();</pre>
<p>Si has usado constructores, parece obvio y familar no?. Pero los constructores fueron hechos para permitir instanciar cualquier número de objetos del mismo prototype. Por qué necesitaríamos hacer eso con un conjunto de utilidades misceláneas? Usualmente no hay razón, porque no hay datos que se diferencien de una instancia a otra.</p>
<p>Acá entra Singleton y es donde JSON se vuelve muy útil. Con él podemos declarar una única instancia y todos sus miembros de una sola llamada, sin meternos con los constructores:</p>
<pre name="code" class="js">var domUtils = {
getByClass: function(cssClassName) {...}
}</pre>
<h3>haciendolo aún mejor</h3>
<p>Mientras estamos haciendo el <code>domUtils</code> asumamos que esa librería de utilidades podría crecer bastante (siempre lo hacen). Así que vamos a seguir la técnica de YUI para el namespacing, categorizando más las utilidades, y como solo necesitamos una copia, utilizamos JSON para hacerlo. Acá está el esqueleto de mi librería, y le vamos a poner&#8230; eeehh, hmm&#8230; ZAQ, sí ZAQ:</p>
<pre name="code" class="js">var ZAQ = {}  //esto crea un objeto namespace vac&iacute;o

ZAQ.util = {} //un sub-objeto para el paquete de utilidades

//lo granulamos m&aacute;s, con utilidades espec&iacute;ficas para el DOM
ZAQ.util.dom = {
getByClass: function(cssClassName) {...},
elemHasClass: function(elem, className) {...}
}

//podemos agregar m&aacute;s tipos de utilidades en sus propias &quot;categorias&quot;
ZAQ.util.array = {
contains: function(theArray, match) {...}
}
ZAQ.util.string = {
startsWith: function(theString, match) {...},
endsWith:   function(theString, match) {...}
}</pre>
<p>Y así sucesivamente.</p>
<h3>Conclusión?</h3>
<p>Necesitamos una?</p>
<p>Ok, ok&#8230; El fín es que podés usar el poderoso patrón singleton en JavaScript, funciona perfecto para este tipo de librerías de utilidades y un sin fín de cosas más en las que solo necesités una copia corriendo. Mantiene el código fácil de leer, mantiene el namespace intacto y ordenado y además previene colisiones con otras funciones cuando estás integrando otras librerías.</p>
<p>Que te sirva de algo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/singleton-en-javascript-o-como-convertir-constructores-a-json.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Snippet: Detectar un bloqueador de pop-ups</title>
		<link>http://www.elbleg.com/web-dev/javascript/snippet-detectar-un-bloqueador-de-pop-ups.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/snippet-detectar-un-bloqueador-de-pop-ups.html#comments</comments>
		<pubDate>Fri, 24 Jul 2009 07:03:21 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=217</guid>
		<description><![CDATA[Algunas veces no tenemos más alternativa que desplegar información utilizando los abominables pop-ups o ventanas emergentes, en casos como esos topamos como obstáculo que si el usuario tiene el bloqueador activado no podrá ver lo que necesitamos desplegar.

Para casos como esos, este pequeño script, que revisa si el blocker está activado o no con la [...]]]></description>
			<content:encoded><![CDATA[<p>Algunas veces no tenemos más alternativa que desplegar información utilizando los abominables pop-ups o ventanas emergentes, en casos como esos topamos como obstáculo que si el usuario tiene el bloqueador activado no podrá ver lo que necesitamos desplegar.<br />
<span id="more-217"></span><br />
Para casos como esos, este pequeño script, que revisa si el blocker está activado o no con la única forma de hacerlo, creando un pop-up, devolviendo un valor booleano dependiendo si tuvo exito o no. Así si falla podemos pedirle amablemente al usuario que habilite los pop ups.</p>
<pre name="code" class="js">function detectarBlocker() {
    var intento = window.open(&quot;about:blank&quot;,&quot;&quot;,&quot;directories=no,height=100,width=100,menubar=no,resizable=no,scrollbars=no,status=no,titlebar=no,top=5000,location=no&quot;);     if(intento) { // no hay bloqueo
        intento.close();
        return 1;
     } else { // est&aacute; bloqueado
        return 0;
     }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/snippet-detectar-un-bloqueador-de-pop-ups.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Snippet: Arreglar el Z-Index en IE7 con jQuery o MooTools</title>
		<link>http://www.elbleg.com/web-dev/javascript/jquery/snippet-arreglar-el-z-index-en-ie7-con-jquery-o-mootools.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/jquery/snippet-arreglar-el-z-index-en-ie7-con-jquery-o-mootools.html#comments</comments>
		<pubDate>Mon, 13 Jul 2009 07:01:53 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[mootools]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[z-index]]></category>
		<category><![CDATA[Zindex]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=208</guid>
		<description><![CDATA[Por alguna razón malvada, Internet Explorer 7 hace algunas cosas raras  (además de tener una larga lista bugs conocidos en su motor) que siempre se las ingenian para volver a los web developers locos. Mientras algunos errores ocurren de forma oscura y dificil de notar, hay algunos que causan que pasemos horas tratando de [...]]]></description>
			<content:encoded><![CDATA[<p>Por alguna razón malvada, Internet Explorer 7 hace algunas cosas raras  (además de tener una larga lista <a href="http://www.quirksmode.org/bugreports/archives/explorer_7/index.html">bugs conocidos</a> en su motor) que siempre se las ingenian para volver a los web developers locos. Mientras algunos errores ocurren de forma oscura y dificil de notar, hay algunos que causan que pasemos horas tratando de arreglarlos. La forma en que IE7 renderiza el orden del z-index es una de ellas. </p>
<p>Una de las formas de arreglarlo es cambiando dinámicamente el orden por default de los elementos de la página. Esto asegura que los elementos en el código HTML tengan el índice adecuado, resolviendo la mayoría de los problemas que causa IE7. </p>
<p>El modo de hacerlo usando jQuery sería algo como:</p>
<pre name="code" class="js">$(function() {
	var zIndexNumber = 1000;
	$(&apos;div&apos;).each(function() {
		$(this).css(&apos;zIndex&apos;, zIndexNumber);
		zIndexNumber -= 10;
	});
});</pre>
<p>Con esto básicamente lo que hacemos es comenzar con un z-index de 1000 y decrementar el indice de cada div de la página en tractos de 10, es decir, el primer elemento tendrá un z-index de 1000, el segundo 990 el tercero 980 y así sucesivamente. Notá que el selector de jQuery encuentra todos los divs con el codigo “<code>$(’div’)</code>”, usando la misma syntaxis que los selectores de CSS, nada dificil.</p>
<p>Ah&#8230; y así se hace lo mismo pero con MooTools, por si estás usando esa biblioteca:</p>
<pre name="code" class="js">if(Browser.Engine.trident){
	var zIndexNumber = 1000;
	$$(&apos;div&apos;).each(function(el,i){
		el.setStyle(&apos;z-index&apos;,zIndexNumber);
		zIndexNumber -= 10;
	});
};</pre>
<p>Saluuú.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/jquery/snippet-arreglar-el-z-index-en-ie7-con-jquery-o-mootools.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Generador de Bookmarklets [actualizado]</title>
		<link>http://www.elbleg.com/web-dev/javascript/generador-de-bookmarklets.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/generador-de-bookmarklets.html#comments</comments>
		<pubDate>Mon, 06 Jul 2009 22:01:30 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Utilidades]]></category>
		<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://eldomo.net/yeco_blog/archives/generador-de-bookmarklets</guid>
		<description><![CDATA[Como últimamente los bookmarklets se han puesto muy de moda, no está de más publicar uno que sirva en el trabajo.
La idea con este es ayudar con los forms, evitandonos el engorroso trabajo de llenarlos una y otra vez para probarlos.
El generador toma el form en que estás trabajando y  crea un bookmarklet específico [...]]]></description>
			<content:encoded><![CDATA[<p>Como últimamente los bookmarklets se han puesto muy de moda, no está de más publicar uno que sirva en el trabajo.</p>
<p>La idea con este es ayudar con los forms, evitandonos el engorroso trabajo de llenarlos una y otra vez para probarlos.</p>
<p>El generador toma el form en que estás trabajando y  crea un bookmarklet específico para los campos que necesitas, con la info que necesitas.<br />
<span id="more-69"></span></p>
<h3>Cómo se usa?</h3>
<p>Simple, solo agregas un bookmark y a este lo editas y le cambias la url colocando en su lugar este script.<br />
<!-- ALERTA: hay estilos incrustados en el textarea!!, perdon perdon!! --><br />
<textarea wrap="on" class="js" style="width: 100%; height: 100px; font-size: 8pt;">javascript:var fz=new Array();var z=new Array();function F(p){var m=new Array();for(n=0;n
<p.length;n++){var q=new Array();for(ind=0;ind<p[n].length;ind++){q.push('\''+p[n][ind]+'\'')}m[n]=eval('['+q.join(',')+']');}return m;}function C(n,cz){var i=-1;for(ab=0;ab<cz.length;ab++){if(cz[ab][1]==n)i=ab;}return i;}function B(){fz.length=0;if(!document.forms.length){alert('There are no forms in this page.');return;}for(fi=0;fi<document.forms.length;fi++){z.length=0;f=document.forms[fi];for(i=0;i<f.length;i++){ip=f.elements[i].type;iv=f.elements[i].value;ix=f.elements[i].name;if(!iv){continue;}if(ip=='text'||ip=='textarea'||ip=='select-one'||ip=='password')z.push(['d',ix,iv]);if(ip=='radio'||ip=='checkbox'||ip=='select-multiple'){x=C(ix,z);if(x==-1){if(ip=='select-multiple'){iv=%22%22;for(g=0;g<f.elements[i].length;g++){if(f.elements[i][g].selected){iv+=f.elements[i][g].value+%22|%22;}}z.push(['s',ix,iv]);}if(ip=='radio'){if(f.elements[i].checked){z.push(['c',ix,iv]);}}else{if(f[ix].length){if(f.elements[i].checked){z.push(['c',ix,iv]);}}else{if(f.elements[i].checked){z.push(['n',ix,'']);}}}}else{if(f.elements[i].checked){z[x][2]+=%22|%22+iv;}}}}fz.push(F(z));}bms=new Array();for(f=0;f<fz.length;f++){if (!fz[f].length){continue;}bm=%22java%22+%22script:function D(a,b){c=b.split('|');d=false;for(q=0;q<c.length;q++){if(c[q]==a)d=true;}return d;}%22;bm+=%22function E(){f%22+f+%22=document.forms[%22+f+%22];%22;for(k=0; k<fz[f].length; k++){if(fz[f][k][0]==%22d%22){bm+=%22f%22+f+%22['%22+fz[f][k][1]+%22'].value='%22+fz[f][k][2]+%22';%22;}if(fz[f][k][0]==%22n%22){bm+=%22f%22+f+%22['%22+fz[f][k][1]+%22'].checked=true;%22;}if(fz[f][k][0]==%22c%22){bm+=%22for(i=0;i<f%22+f+%22['%22+fz[f][k][1]+%22'].length;i++){if(D(f%22+f+%22['%22+fz[f][k][1]+%22'][i].value,'%22+fz[f][k][2]+%22')){f%22+f+%22['%22+fz[f][k][1]+%22'][i].checked=true;}}%22;}if(fz[f][k][0]==%22s%22){bm+=%22for(i=0;i<f%22+f+%22['%22+fz[f][k][1]+%22'].length;i++){if(D(f%22+f+%22['%22+fz[f][k][1]+%22'][i].value,'%22+fz[f][k][2]+%22')){f%22+f+%22['%22+fz[f][k][1]+%22'][i].selected=true;}}%22;}}bm+=%22}E()%22;bms.push(bm);}w= window.open('','','toolbar,width=150,height=100');for(f=0;f<bms.length;f++){w.document.write(%22<a href=\%22%22+bms[f]+%22\%22>Form #%22+(f+1)+%22</a><br />%22);}w.document.write(%22Arrastra el link a tu toolbar.%22);w.document.close();}B();</textarea></p>
<p>Luego, llenas los campos del form en que estás trabajando, das click en el generador y este abre un popup con un link al bookmarklet generado. Arrastrás el link a tu barra de bookmarks y listo, cada que lo actives te llena los campos solo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/generador-de-bookmarklets.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo solucionar el error de window.onload</title>
		<link>http://www.elbleg.com/web-dev/javascript/como-solucionar-el-error-de-windowonload.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/como-solucionar-el-error-de-windowonload.html#comments</comments>
		<pubDate>Mon, 29 Jun 2009 04:58:05 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[onload]]></category>
		<category><![CDATA[SwfObject]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=168</guid>
		<description><![CDATA[Esta tarde, revisando los blogs de mis amigos me topé con un post de Oscar Godson, en el cual aporta una solución al ya famoso &#8220;Internet Explorer no puede abrir el sitio. Operación anulada&#8221; que tan malos momentos me hizo pasar alguna vez.

La solución de Oscar, consiste en usar jQuery para solucionar el bug con [...]]]></description>
			<content:encoded><![CDATA[<p>Esta tarde, revisando los blogs de mis amigos me topé con <a rel="friend" href="http://kneedeepincode.com/topics/ie-cannot-open-the-internet-site/">un post</a> de Oscar Godson, en el cual aporta una solución al ya famoso <cite>&#8220;Internet Explorer no puede abrir el sitio. Operación anulada&#8221;</cite> que tan malos momentos me hizo pasar alguna vez.<br />
<span id="more-168"></span><br />
La solución de Oscar, consiste en usar jQuery para solucionar el bug con una sencilla función:</p>
<pre name="code" class="xml">
$(window).load(function(){
//Acá tu código
});
</pre>
<p>De verdad sencilla y conveniente si ya estás usando jQuery en el proyecto, pero qué pasa si no? Ahí es donde cobra sentido este post. No nos conviene cargar 30k de código extra para poder resolver este problema solamente, sería matar una mosca con un cañón.</p>
<p>Hace poco más de un año dí con una solución, eficiente, agnóstica y que responde bien en todos los browsers&#8230; Para <abbr title="Internet Explorer">ie</abbr> a veces basta con agregar <code>defer</code> cómo atributo.</p>
<pre name="code" class="js">
&lt;script defer src=&quot;ie_load.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
</pre>
<p>Y el contenido del <code>ie_load.js</code> sería el script que <abbr title="Internet Explorer">ie</abbr> debe cargar cuando esté listo. Suena bien, pero es una solución que no funciona adecuadamente con los otros browsers que simplemente ignorarían el <code>defer</code>, Mozilla y Safari quedarían rezagados.</p>
<p>Afortunadamente Mozilla responde a su propio <code>DOMContentLoaded</code> entonces solo queda escuchar el evento y ejecutar lo que queramos con él:</p>
<pre name="code" class="js">
document.addEventListener(&quot;DOMContentLoaded&quot;, init, false);
</pre>
<p>Y John Resig, el creador de jQuery, dió con la solución para safari hace un tiempo:</p>
<pre name="code" class="js">
if (/WebKit/i.test(navigator.userAgent)) { // sniff
		var _timer = setInterval(function() {
			if (/loaded|complete/.test(document.readyState)) {
				init(); // call the onload handler
			}
		}, 10);
	}
</pre>
<p>Para los demás browsers, solo nos queda hacer uso del <code>window.onload</code> común y corriente que todos conocemos:</p>
<pre name="code" class="js">
window.onload = init;
</pre>
<p>Ya teniendo todos estos ingredientes dispuestos, solo queda hacerlos funcionar en conjunto, haciendo uso del soporte para compilaciones condicionales que tiene <abbr title="Internet Explorer">ie</abbr> <del datetime="2009-06-29T04:27:13+00:00">(para que no se meta con lo demás)</del> y uno que otro tweak, ponemos todo en un solo script que se encargue del <code>onload<code> adecuado para cada browser. </p>
<pre name="code" class="js">
function init() {
 		if (arguments.callee.done) return;

 		arguments.callee.done = true;

 		if (_timer) {
			clearInterval(_timer);
			_timer = null;
		}

		// Ac&aacute; va lo que queramos ejecutar

	};

	/* Para Mozilla */
	if (document.addEventListener) {
		document.addEventListener(&quot;DOMContentLoaded&quot;, init, false);
	}

	/* Para Internet Explorer */
	/*@cc_on @*/
	/*@if (@_win32)
		document.write(&quot;&lt;script id=__ie_onload defer src=javascript:void(0)&gt;&lt;\/script&gt;&quot;);
		var script = document.getElementById(&quot;__ie_onload&quot;);
		script.onreadystatechange = function() {
			if (this.readyState == &quot;complete&quot;) {
				init(); // call the onload handler
			}
		};
	/*@end @*/

	/* Soluci&oacute;n de John Resig Para Safari */
	if (/WebKit/i.test(navigator.userAgent)) { // sniff
		var _timer = setInterval(function() {
			if (/loaded|complete/.test(document.readyState)) {
				init(); // call the onload handler
			}
		}, 10);
	}
	window.onload = init;
</pre>
<p>Recuerdo que esta solución me ayudó bastante, en especial con SwfObject, así que espero que a alguien más le sirva de algo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/como-solucionar-el-error-de-windowonload.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Snippet: Arrays asociativos en Javascript</title>
		<link>http://www.elbleg.com/web-dev/javascript/snippet-arrays-asociativos-en-javascript.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/snippet-arrays-asociativos-en-javascript.html#comments</comments>
		<pubDate>Wed, 24 Jun 2009 02:21:24 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[arrays]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=158</guid>
		<description><![CDATA[Esta es una pequeña clase que nos permite sacar provecho al máximo de los arrays en javacript.


var Class = {
			  create: function() {
			    return function() {
			      this.initialize.apply(this, arguments);
			    }
			  }
			}

			var AArray = Class.create();

			AArray.prototype = {
			  AA: {},
			  initialize: function() {
			 [...]]]></description>
			<content:encoded><![CDATA[<p>Esta es una pequeña clase que nos permite sacar provecho al máximo de los arrays en javacript.<br />
<span id="more-158"></span></p>
<pre name="code" class="js">
var Class = {
			  create: function() {
			    return function() {
			      this.initialize.apply(this, arguments);
			    }
			  }
			}

			var AArray = Class.create();

			AArray.prototype = {
			  AA: {},
			  initialize: function() {
			    args = this.initialize.arguments;
			    if(args.length &gt; 0) {
			      this.add(args[0], args[1]);
			    }
			  },
			  add: function(key, value) { this.AA[key] = value; },
			  num: function() { return this.AA.length; },
			  get: function(key) { return this.AA[key]; },
			  set: function(key, value) { this.add(key, value); },
			  test: function() {
			    var aa = &#039;&#039;;
			    var num = this.num();
			    for(key in this.AA) aa += &#039;[&#039; + key + &#039;]: &#039; + this.AA[key] + &quot;\n&quot;;
			    alert(aa);
			  }
			}</pre>
<h3>Ejemplo de uso</h3>
<pre name="code" class="js">
var colors = new AArray(); colors.add(&quot;k01&quot;, {bk:&quot;#fff&quot;,tk:&quot;b&quot;,it:&quot;Hola&quot;});

var oC = colors.get(&quot;k01&quot;);

var tT = &#039;&#039;; for(K in oC) tT += &quot;[&quot; + K + &quot;]: &quot; + oC[K] + &quot;\n&quot;;

tT += &quot;\n\n&quot;; tT += oC.bk + &quot;\n&quot;; tT += oC.tk + &quot;\n&quot;; tT += oC.it + &quot;\n&quot;;

alert(tT);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/snippet-arrays-asociativos-en-javascript.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creando una ventana de login con ExtJS</title>
		<link>http://www.elbleg.com/web-dev/javascript/extjs/creando-unaventana-de-login-con-extjs.html</link>
		<comments>http://www.elbleg.com/web-dev/javascript/extjs/creando-unaventana-de-login-con-extjs.html#comments</comments>
		<pubDate>Sun, 21 Jun 2009 07:37:22 +0000</pubDate>
		<dc:creator>Yëco</dc:creator>
				<category><![CDATA[ExtJS]]></category>
		<category><![CDATA[login]]></category>

		<guid isPermaLink="false">http://www.elbleg.com/?p=137</guid>
		<description><![CDATA[Algunos de los que me conocen saben que me paso la mitad de mi tiempo peleando contra ExtJS… esa biblioteca es completamente imposible cuando se le mete el diablo. Otras veces, es increíblemente potente y sencilla de usar.


En este caso -aunque al final me quedé con una solución que hice en jQuery- muestra a grandes [...]]]></description>
			<content:encoded><![CDATA[<p>Algunos de los que me conocen saben que me paso la mitad de mi tiempo peleando contra ExtJS… esa biblioteca es completamente imposible cuando se le mete el diablo. Otras veces, es increíblemente potente y sencilla de usar.
</p>
<p>
En este caso -aunque al final me quedé con una solución que hice en jQuery- muestra a grandes rasgos lo potente y sencillo que puede ser ExtJS cuando le da la gana. <span id="more-137"></span>Para efectos del ejemplo, voy a basarme en la estructura de archivos que trae ExtJS por defecto, además de usar varios de los estilos disponibles que trae.
		</p>
<h3>
			Ya entrando en materia<br />
		</h3>
<p>
			Creamos un archivo html dentro del folder &#8220;examples&#8221; del ExtJS y en el <code>&lt;head&gt;</code> agregamos estos estilos:
		</p>
<pre name="code" class="xml">
        &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;../docs/resources/docs.css&quot;/&gt;
        &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;../resources/css/ext-all.css&quot; /&gt;
        &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;../resources/css/xtheme-gray.css&quot; /&gt;

    &lt;style&gt;
        #loading_mask{
        	width:100%;
        	height: 100%;
        	background: #c3daf9;
        	position :absolute;
        	z-index: 20000;
        	left: 0;
        	top: 0;
        }
        .loading-indicator img{
        	 width:16px;
        	height:16px;
        }
        &lt;/style&gt;
</pre>
<p>
			Ahora, siempre en el <code>&lt;head&gt;</code> del documento, agregamos los script básicos de la biblioteca:
		</p>
<pre name="code" class="xml">
  &lt;script src=&quot;../adapter/ext/ext-base.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;../ext-all-debug.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
</pre>
<p>
			Dentro del cuerpo agregamos algo como esto:
		</p>
<pre name="code" class="xml">
&lt;div id="loading-mask"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id="loading"&gt;
&lt;div class="loading-indicator"&gt;
	&lt;img src="../resources/images/default/grid/loading.gif" align="absmiddle"&gt;&amp;nbsp;Loading…
&lt;/div&gt;
</pre>
<p>
			Ya con eso listo, es cosa de poner unos cuantos boxes y windows de ExtJS para terminar el login:
		</p>
<pre name="code" class="js">
var loadMask = function(){

    return {

        init: function() {
            // Creamos el cargador
            var loading = Ext.get('loading');
            var mask = Ext.get('loading-mask');
            mask.setOpacity(0.8);
            mask.shift({
                xy: loading.getXY(),
                width: loading.getWidth(),
                height: loading.getHeight(),
                remove: true,
                duration: 1,
                opacity: 0.3,
                easing: 'bounceOut',
                callback: function(){
                    // Desvanece cuando la carga termina
                    loading.fadeOut({
                        duration: 0.2,
                        remove: true
                    });
                }
            });
        }};
}();

Ext.onReady(loadMask.init, loadMask, true);
Ext.onReady(function(){

        Ext.QuickTips.init();
        Ext.form.Field.prototype.msgTarget = 'side';
        // Usamos un FormPanel para crear la caja de Login

        var login = new Ext.FormPanel({
            labelWidth: 80,
            url: "autenticar.php",
            frame: true,
            title: 'Iniciar sesi&oacute;n',

            width: 230,
            padding: 10,
            defaultType: 'textfield',
            monitorValid: true,
            items: [{
                fieldLabel: 'Usuario',
                name: 'user',
                allowBlank: false
            },
            {
                fieldLabel: 'Contrase&ntilde;a',
                name: 'password',
                inputType: 'password',
                allowBlank: false
            }],
            buttons: [{
                text: 'Inicio',
                formBind: true,
                handler: function()
                {
                    login.getForm().submit({
                        method: 'POST',
                        waitTitle: 'Authenticando..',
                        waitMsg: 'Enviando datos...',

                        success: function()
                        {
                            var redirect = "http://google.com";
                            window.location = redirect;

                        },
                        failure: function(form, action)
                        // Pero si falla
                        {
                            if (action.failureType == 'server')
                            {
                                obj = Ext.util.JSON.decode(action.response.responseText);
                                Ext.Msg.alert('Intenta de nuevo!', obj.errors.reason);
                                // Le decimos al usuario que el logueo falló y le damos el motivo
                            }
                            else
                            {
                                Ext.Msg.alert('Ouch!', 'el servidor no contesta : ' + action.response.responseText);
                                // O bien si hubo algún error en el sistema
                            }
                            login.getForm().reset();
                        }
                    });
                }
            }]
        });
        // Usamos un Window para mostrar el Login en una ventanita

        var win = new Ext.Window(
            {
                layout: 'fit',
                width: 300,
                height: 150,
                closable: false,
                resizable: false,
                plain: true,
                items: [login] // y acá cargamos el panel con el login
            }
        );
        win.show();
    }
);
</pre>
<p>
Y listo, ya el login está listo, lo que queda es el response que te va a enviar backend cuando las credenciales sean correctas o no.</p>
<p>No voy a poner cómo generarlo, porque ya eso depende del lenguaje que estés usando en backend, voy a limitarme solamente a las respuestas que espera el javascript.
</p>
<p>
Éxito:</p>
<pre name="code" class="js">echo "{success: true}";</pre>
</p>
<p>
Fallo:</p>
<pre name="code" class="js">echo "{success: false, errors: { reason: 'Password error.' }}";</pre>
</p>
<p>Ahora sí, estamos listos. Espero que haya servido para despertar algo de curiosidad por ExtJS.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elbleg.com/web-dev/javascript/extjs/creando-unaventana-de-login-con-extjs.html/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>
