miércoles, 29 de junio de 2011

Selectores personalizados en jQuery

Como te decía en un anterior post, Cómo NO complicarnos la vida con jQuery, quiero que mi código jQuery sea más fácil de leer, menos extenso, más manejable y sobre todo más independiente del DOM.

Algo que tarde o temprano echas de menos es algún selector para algo que, o bien jQuery no soporta, o bien es muy complicado y tampoco sabes cuál es la expresión correcta para seleccionar tus elementos.

En estas situaciones, la solución pasa por crear un selector personalizado. Por ejemplo, imagina que quiero seleccionar las celdas de una tabla que sean del color verde y además pertenezcan a filas impares. Para hacerlo a través de jQuery, la expresión sería la siguiente:

    <table id="Table1">

        <tr>

            <td style="background-color: #008000;">Verde</td>

            <td>Sin color</td>

            <td>Sin color</td>

        </tr>

        <tr>

            <td>Sin color</td>

            <td style="background-color: #008000;">Verde</td>

            <td style="background-color: #008000;">Verde</td>

        </tr>

        <tr>

            <td style="background-color: #008000;">Verde</td>

            <td style="background-color: #008000;">Verde</td>

            <td style="background-color: #008000;">Verde</td>

        </tr>

        <tr>

            <td style="background-color: #008000;">Verde</td>

            <td>Sin color</td>

            <td>Sin color</td>

        </tr>

        <tr>

            <td>Sin color</td>

            <td>Sin color</td>

            <td>Sin color</td>

        </tr>

    </table>

    <script type="text/javascript">

        $().ready(function () {

alert($("#Table1 tr:odd td[style*='rgb(0, 128, 0)']").size());

        });       

    </script>

 

Vamos a desgranar el selector #Table1 tr:odd td[style*='rgb(0, 128, 0)']

#Table1 está claro, es una selección por el atributo id

tr:odd son elementos tr (filas) que sean impares dentro de #Table1

td son elementos td (celdas) dentro de cada fila impar

[style*=’rgb(0, 128, 0)] son elementos td que tengan una atributo style que contenga la cadena especificada. Aquí, por ejemplo, IE ha traducido #008000 a rgb(0, 128, 0) con lo que hay que buscar por esta última cadena. Sin embargo FF sí respeta #008000, así que el selector en FF tiene que ser #Table1 tr:odd td[style*='#008000']. Sinceramente, me empieza a parecer un selector un poco lioso (más si cabe con la dicotomía de IE y FF).

La solución pasa por crear nuestro propio selector y encapsular esta complejidad en un selector sencillo. Para crear un selector personalizado hay que “extender” el objeto jQuery. La sintaxis es muy sencilla y el propio código es auto-explicativo.

        $.extend(

            $.expr[":"],

            {

              celdasVerdesEnFilasImpares: function (obj, index, meta, stack) {

                    /*

                    obj - Elemento DOM de la iteración actual

                    index - Índice de obj dentro de stack

                    stack - Array de todos los elementos DOM que se evaluarán

                    */

                    var el = $(obj);

                    if (!el.is("td")) {

                        return false; //el elemento no es una celda

                    }

                    if (el.parent().get(0).rowIndex % 2 == 0) {

                        return false; //la fila es par

                    }

                    var bgColor = el.css("background-color");

                    //Con jQuery, el color es rgb para IE y FF
                   
if (bgColor != "rgb(0, 128, 0)") {

                        return false; //el color de la celda no es verde

                    }

                    return true; //el elemento cumple nuestro selector

                }

            }

        );


A partir de aquí, su utilización es muy sencilla y hemos logrado encapsular toda la complejidad del caso anterior es un selector sencillo.

alert($("#Table1 td:celdasVerdesEnFilasImpares").size());


Para finalizar con el tema de los selectores personalizados, también es importante conocer que estos pueden recibir parámetros. Es decir, si quiero celdasRojasEnFilasImpares ¿Tengo que volver a hacerme el mismo selector para sólo cambiar una línea? Pues no, estaba claro, no se a cuento de que tanto misterio ;-)

En este caso lo que nos interesa es el argumento meta. Por ejemplo, vamos a cambiar un poco nuestro selector que ahora se llamará celdasEnFilasImpares. Ahora podremos llamar a nuestro selector de la siguiente forma:

alert($("#Table1 td:celdasEnFilasImpares(rgb(0, 128, 0))").size());


El parámetro meta es un Array con los siguientes elementos:

clip_image001

Si nos fijamos, el índice 3 es justamente el parámetro del selector, así que el único cambio (además del nombre del selector) que hay que hacer es el siguiente:

if (bgColor != meta[3]) {

return false; //el color de fondo no es el color especificado

}


Un saludo!.

No hay comentarios:

Publicar un comentario