2011-08-16 21 views
88

Sin usar jQuery, ¿cuál es la forma más eficiente de seleccionar todos los elementos dom que tengan un determinado atributo data- (digamos data-foo). Los elementos pueden ser diferentes elementos de etiqueta.javascript: seleccione todos los elementos con el atributo "data-" (sin jQuery)

<p data-foo="0"></p><br/><h6 data-foo="1"></h6> 
+0

Tenga en cuenta que 'document.querySelectorAll' no funciona en IE7. Tendría que crear un script alternativo que * recorra * el árbol DOM y verificando el atributo en cada etiqueta (en realidad no tengo idea de qué tan rápido es 'querySelectorAll', e iría para la verificación manual de las etiquetas). –

+0

¿Cuál es el motivo por el que no utilizas jQuery? Es bastante irremplazable en situaciones como esta ... –

+0

@hay, en absoluto, puedes incluso seleccionar estos elementos en css puros también. – Knu

Respuesta

198

Puede utilizar querySelectorAll:

document.querySelectorAll('[data-foo]'); 
+4

Perfecto, gracias! Nota semi relacionada: si desea seleccionar un atributo con dos puntos en el nombre, debe escapar de los dos puntos (al menos en Chrome) así: querySelectorAll ('[attribute \\: name]') (consulte: http : //code.google.com/p/chromium/issues/detail? id = 91637) – Jeremy

0
var matches = new Array(); 

var allDom = document.getElementsByTagName("*"); 
for(var i =0; i < allDom.length; i++){ 
    var d = allDom[i]; 
    if(d["data-foo"] !== undefined) { 
     matches.push(d); 
    } 
} 

No estoy seguro de que me sonó con un -1, pero aquí está la prueba.

http://jsfiddle.net/D798K/2/

+1

su mayoría de "derecha" simplemente no es correcto. Estoy bastante seguro de que alguien te dio el -1 porque estás haciendo mucho trabajo extra para obtener los elementos, y luego colocando la colección en una matriz. No le di el -1 solo me desagrada cuando no hay explicación para uno. – Loktar

+1

caro (todos los elementos en la página), también usa la notación literal de la matriz (es decir, []) y, además, no funciona. compruébalo tú mismo -> http://jsbin.com/ipisul/edit#javascript,html – shawndumas

+2

Aunque el OP está usando HTML 5 de todos modos, 'getElementsByTagName' con un selector global (' * ') se rompe en versiones anteriores de IE. Aquí es donde una búsqueda DOM recursiva hace el trabajo. Tampoco hay una propiedad "data-foo" en un ElementNode mapeado del atributo 'data-foo'. Está buscando el objeto 'dataset' (es decir:' node.dataset.foo'. –

91
document.querySelectorAll("[data-foo]") 

conseguirá que todos los elementos con ese atributo.

document.querySelectorAll("[data-foo='1']") 

se consigue solamente con ustedes los de un valor de 1.

7

Try it → here

<!DOCTYPE html> 
    <html> 
     <head></head> 
     <body> 
      <p data-foo="0"></p> 
      <h6 data-foo="1"></h6> 
      <script> 
       var a = document.querySelectorAll('[data-foo]'); 

       for (var i in a) if (a.hasOwnProperty(i)) { 
        alert(a[i].getAttribute('data-foo')); 
       } 
      </script> 
     </body> 
    </html> 
+0

Usar hasOwnProperty es la mejor respuesta para mí hasta el momento en 2016, esto es muy rápido con respecto a otras formas de iteración [Mdn hasOwnProperty] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) – Cryptopat

-1

Here es una solución interesante: se utiliza el motor de navegadores CSS para añadir una propiedad ficticia a los elementos haciendo coincidir el selector y luego evalúa el estilo calculado para encontrar elementos coincidentes:

Crea dinámicamente una regla de estilo [...] Luego escanea todo el documento (usando el documento muy desacreditado y específico de IE pero muy rápido) y obtiene el estilo calculado para cada uno de los elementos. Luego buscamos la propiedad foo en el objeto resultante y verificamos si se evalúa como "barra". Para cada elemento que coincida, lo agregamos a una matriz.

+2

está marcado html5 por lo que no va a ser shawndumas

+1

Correcto, eliminé el insinuación sobre navegadores antiguos. –

+0

buen trabajo;) ... – shawndumas

2

Aunque no es tan bonita como querySelectorAll (que tiene una larga lista de temas), he aquí una función muy flexible que recursivamente el DOM y debería funcionar en la mayoría de los navegadores (antiguos y nuevos). Siempre que el navegador admita su condición (es decir, atributos de datos), debe poder recuperar el elemento.

Para curiosos: No se moleste en probar esto en comparación con QSA en jsPerf. Los navegadores como Opera 11 almacenarán en caché la consulta y sesgarán los resultados.

Código:

function recurseDOM(start, whitelist) 
{ 
    /* 
    * @start:  Node - Specifies point of entry for recursion 
    * @whitelist: Object - Specifies permitted nodeTypes to collect 
    */ 

    var i = 0, 
    startIsNode = !!start && !!start.nodeType, 
    startHasChildNodes = !!start.childNodes && !!start.childNodes.length, 
    nodes, node, nodeHasChildNodes; 
    if(startIsNode && startHasChildNodes) 
    {  
     nodes = start.childNodes; 
     for(i;i<nodes.length;i++) 
     { 
      node = nodes[i]; 
      nodeHasChildNodes = !!node.childNodes && !!node.childNodes.length; 
      if(!whitelist || whitelist[node.nodeType]) 
      { 
       //condition here 
       if(!!node.dataset && !!node.dataset.foo) 
       { 
        //handle results here 
       } 
       if(nodeHasChildNodes) 
       { 
        recurseDOM(node, whitelist); 
       } 
      } 
      node = null; 
      nodeHasChildNodes = null; 
     } 
    } 
} 

A continuación, puede iniciar con la siguiente:

recurseDOM(document.body, {"1": 1}); para la velocidad, o simplemente recurseDOM(document.body);

Ejemplo con sus especificaciones: http://jsbin.com/unajot/1/edit

Ejemplo con diferentes especificación: http://jsbin.com/unajot/2/edit

+10

¿Cuál es la letanía de problemas con 'querySelectorAll'? – ShreevatsaR

+3

También me encantaría escuchar acerca de estos problemas. –

Cuestiones relacionadas