miércoles, 29 de junio de 2011

Cómo NO complicarnos la vida con jQuery

Estoy liado con un rediseño de la capa de presentación de una aplicación web y está claro que voy a utilizar “intensamente” jQuery.

jQuery es maravilloso, eso no lo voy a descubrir yo, pero me pasa que cuando lo utilizo tiendo a acumular cantidades ingentes de código javascript para realizar todo tipo de tareas y al final, mi inocente código se convierte en todo un mini-programa dentro de mi aplicación… o peor, dentro de una sola página.

¡Basta! ¡Hay que poner puertas al campo! Esa es mi intención de hoy. Ver cómo puedo contener la cantidad de código y además escribir un código más eficiente y sobre todo, independiente en la medida lo posible de la estructura DOM de mi página (que ya estoy harto de que cualquier cambio en el diseño de la página, lleve al traste con la mitad de mi código jQuery).

Mi primera recomendación (o bien auto-imposición) va a ser lograr la independencia del diseño y de la programación. Es decir, que cambios en la estructura del DOM no supongan, o al menos no en exceso, cambios en mi código. Para ello, primero veremos cómo hacer “mal” algo y después cómo hacerlo bien.

Haciéndolo mal…

    <div id="padre">

        <div>

            Red</div>

        <div>

            Yellow</div>

        <div>

            Olive</div>

        <div>

            Blue</div>

    </div>

    <script type="text/javascript">

        $().ready(function () {

            $("#padre div").click(function (e) {

                $(this).parent().css("background-color", $(this).html());

            });

        });       

    </script>

 

Este super-programa lo que hace es que cuando se pulsa en un div hijo, establece el color del padre al color que dice el hijo. Lo cierto es que funciona, pero vamos a criticarlo y veremos como no ha resultado el mejor de mis programas ;-)

Para seleccionar los hijos utilizo la expresión $(“#padre div”). Pues bien, como alguien (léase yo mismo o el diseñador de turno) quiera introducir más div debajo de #padre voy a tener un problema porque va a seleccionar todos (los que inicialmente eran hijos y también los que metimos después). La solución podría pasar por utilizar la expresión $(“#padre > div”), que seleccionará solo los hijos (no así los descendientes que no sean hijos) de #padre. Pero aun así, ¿Qué pasa si los nuevos div son realmente hijos (están justo debajo de #padre) y no quiero seleccionarlos?. Podríamos estar un rato largo discutiendo sobre esto, pero para abreviar mi solución pasa por agregar clases CSS de programación. ¡Uff!, suena raro, pero realmente lo que quiero decir es que utilizaré clases CSS para la selección con jQuery, pero serán clases que no tendrán un reflejo en la apariencia del documento (dicho de otro modo, no fueron pensadas para dar diseño, sino solamente para seleccionar elementos a través de jQuery). Vamos a ver cómo queda:

    <div id="padre">

        <div>

            Yo sólo pasaba por aquí, ¡no me selecciones!</div>

        <div class="slct_Hijo">

            Red</div>

        <div class="slct_Hijo">

            Yellow</div>

        <div class="slct_Hijo">

            Olive</div>

        <div class="slct_Hijo">

            Blue</div>

        <div>

            Yo soy el último de la fila, ¡nadie se acuerda de mí!

        </div>

    </div>

    <script type="text/javascript">

        $().ready(function () {

            $("#padre .slct_Hijo").click(function (e) {

                $(this).parent().css("background-color", $(this).html());

            });

        });       

    </script>

 

* Lo de slct_Nombre es simplemente una convención, en mi caso slct es la abreviatura de select

Ahora, el diseñador puede hacer lo que quiera y no habrá que cambiar el código (incluso metió 2 div hijos que quedaron excluidos de la selección). Igualmente tenemos un mismo problema con $(this).parent() ¿Qué pasa si cambia el padre?. Por otro lado, lo de tomar el color desde el contenido del div hijo tampoco es muy científico (imagínate que el diseñador decide meter un span o cualquier otra cosa dentro del hijo, para darle más vidilla al asunto?. Sin más dilaciones, solución final o cómo hacerlo bien:

    <div class="slct_Padre">

        <div>

            <div>

                Yo sólo pasaba por aquí, ¡no me selecciones!</div>

            <div class="slct_Hijo">

                Mi color es el <span class="slct_Color">Red</span></div>

            <div class="slct_Hijo">

                Yo sin embargo soy <span class="slct_Color">Yellow</span></div>

            <div class="slct_Hijo">

                El más bonito soy yo, que soy <span class="slct_Color">Olive</span></div>

            <div class="slct_Hijo">

                El color de cielo es <span class="slct_Color">Blue</span></div>

            <div>

                Yo soy el último de la fila, ¡nadie se acuerda de mí!

            </div>

        </div>

    </div>

 

    <script type="text/javascript">

        $().ready(function () {

            $(".slct_Padre .slct_Hijo").click(function (e) {

                $(this).closest(".slct_Padre").css("background-color", $(this).find(".slct_Color").html());

            });

        });       

    </script>

 

Por último, también es importante ver que utilizo .slct_Padre .slct_Hijo en vez de div.slct_Padre div.slct_Hijo. Si me está leyendo algún purista, podrá decir que el segundo selector es más óptimo (le costara menos) para jQuery. A cambio, yo le diría que si en vez de div, el diseñador decide que hablamos de p, pues ya tengo el lío. La moraleja de todo esto es que yo opino que el selector de jQuery tiene que ser lo más generalista posible (excepto en operaciones críticas donde quizás arañar un par de ciclos de CPU al navegador sea la diferencia entre la vida y la muerte).

A partir de aquí, hay otras consideraciones a tener en cuenta pero eso lo dejo para un siguiente post que tengo ya horneándose en la cocina.

Un saludo!

No hay comentarios:

Publicar un comentario