Javascript selectors

El uso de «selectores» en JavaScript permite encontrar y seleccionar elementos del DOM bien sea para extraer información de cada nodo o para manipularlos de ser necesario.

Estos selectores funcionan de forma  muy similar a los selectores que se usan en CSS, como veremos a continuación:

.divClass {
    background: red;
}

div {
   background: red;
}

#myDiv {
    background: red;
}

Utilizando JavaScript podemos encontrar un elemento de la siguiente manera:

<div id="myDiv" class="divClass"></div>

<script>
    document.querySelector('#myDiv');
</script>

En este caso, se obtiene el nodo por medio del id #myDiv. En caso de que se desee obtener una lista de nodos que compartan una misma característica, como por ejemplo un nombre de clase, o tipo de elemento, se puede utilizar lo siguiente:

// By class name
document.querySelectorAll('.divClass');

// By type
document.querySelectorAll('div');

El método document.querySelector(selector) devuelve un único nodo en caso de encontrar una coincidencia con el criterio de búsqueda mientras que document.querySelectorAll(selector) devuelve una lista de nodos, incluso si solo se encuentra una sola coincidencia.

Es posible que se desee realizar una búsqueda un poco más compleja combinando una o más características que pudiera contener el nodo que se desea obtener.

<div class="divClass"></div>
<div class="divClass"></div>
<div class="divClass active"></div>

Si se quiere obtener el div con clase divClass que a su vez sea activese pueden combinar ambos criterios de la siguiente manera:

document.querySelector('div.divClass.active');

document.querySelector('div[class="divClass active"]');

La ventaja de comprender un poco más a fondo cómo funcionan estos selectores, es que se pueden utilizar para acceder a un nodo con criterios muy específicos, sin necesidad de hacer una búsqueda genérica y luego tratar de filtrar cada resultado:

// Divs list
list = document.querySelectorAll("div.divClass");

activeItems = [...list].find(el => el.classList.contains('active'));

Veamos un ejemplo más práctico

Vamos a construir una herramienta de debug que permita verificar si se están cumpliendo con algunas reglas de SEO más comunes dentro del contenido de una página, como el uso de la propiedad alt en etiquetas <img>, que todos los enlaces internos contengan el protocolo https, que los enlaces externos abran en una nueva pestaña, etc.

Lo primero que haremos será crear una lista de reglas y un mensaje que acompañe a cada resultado, es decir, si por ejemplo se encuentra algún enlace interno sin https:// , obtener algo de información al respecto.

const debugRules = [
        {
            selector: 'a[href*="styde.net"]:not([href^="https"])',
            message: 'Local non-https links'
        },
        {
            selector: 'a:not([href*="styde.net"]):not([target="_blank"])',
            message: 'External links without target attribute found'
        },
        {
            selector: 'a:not([href*="styde.net"]):not([rel])',
            message: 'External links without rel attribute found'
        },
        {
            selector: 'img:not([alt])',
            message: 'Images without alt attribute found'
        },
        {
            selector: 'img:not([title])',
            message: 'Images without title attribute found'
        }
        // ... ya tienes una idea.
    ];

Ahora necesitamos una función que busque los nodos que coinciden con cada uno de los selectores y en caso de encontrarlo muestre el mensaje definido para cada regla.

function debugHtml(selector, message) {
    let nodes = document.querySelectorAll(selector);
    if (nodes !== null) {
        console.log(message);
        console.log(nodes);
    }
}

Finalmente debemos hacer que esta función se ejecute para cada regla contenida en el objeto debugRules

debugRules.forEach((rule) => debugHtml(rule.selector, rule.message));

Tomando este código HTML como ejemplo

<a href="http://styde.net">Styde.net</a>
<a href="styde.net">Styde.net</a>
<a href="www.styde.net">Styde.net</a>
<a href="https://www.styde.net">Styde.net</a>
<a href="https://www.google.net">Google.net</a>
<a href="https://www.google.net" target="_blank"></a>>Google.net</a>
<img src="https://styde.net/wp-content/themes/styde/img/styde-w-b.png">

El resultado en la terminal del navegador es el siguiente:

javascript-selectors

Con este pequeño ejemplo puedes comenzar a crear un herramienta de debug para verificar el código HTML de tu aplicación.

Aquí puedes ver una lista de los selectores más usados:

  • E#myid  un elemento E con ID igual a myid.
  • E[foo]  un elemento E con un atributo foo
  • E[foo="bar"]  un elemento E cuyo valor de atributo foo es exactamente igual a bar
  • E[foo="bar" i] un elemento E cuyo valor de atributo foo es exactamente igual a cualquier permutación de caso (rango ASCII) de bar
  • E[foo~="bar"] un elemento E cuyo valor de atributo foo es una lista de valores separados por espacios en blanco, uno de los cuales es exactamente igual a bar
  • E[foo^="bar"] un elemento E cuyo valor de atributo foo comienza exactamente con el string bar
  • E[foo$="bar"] un elemento E cuyo valor de atributo foo finaliza exactamente el string bar
  • E[foo*="bar"] un elemento E cuyo valor de atributo foo contiene el substring bar
  • E[foo|="en"]  un elemento E cuyo valor de atributo foo es una lista de valores separados por guiones que comienzan con «en»
  • E:visited un elemento E que es el origen de un hipervínculo cuyo destino ya se ha visitado
  • E:not(s1, s2) un elemento E que no coincide con el selector compuesto s1 o el selector compuesto s2
  • E:matches(s1, s2) un elemento E que coincide con el selector compuesto s1 y / o el selector compuesto s2
  • E:something(s1, s2) un elemento E que coincide con el selector compuesto s1 y / o el selector compuesto s2, pero no aporta especificidad.
  • E:has(rs1, rs2)  un elemento E, si cualquiera de los selectores relativos rs1 o rs2, cuando se evalúa con E como los elementos del «:scope», coincide con un elemento

Puedes encontrar una documentación más completa sobre este tema en la W3C Editor’s Draft’s

 

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.