Obtenir des éléments par attribut lorsque querySelectorAll n'est pas disponible sans utiliser de bibliothèques?


123
<p data-foo="bar">

Comment pouvez-vous faire l'équivalent de

document.querySelectorAll('[data-foo]')

querySelectorAll n'est pas disponible ?

J'ai besoin d'une solution native qui fonctionne au moins dans IE7. Je me fiche d'IE6.


consultez la bibliothèque de sélecteur javascript sizzle.js
époque

1
Bien oui, la seule sélection que je dois faire est les attributs de données, donc j'essayais de trouver le moyen le plus simple de corriger cela sans utiliser un moteur de sélection complet comme Sizzle. Mais bon point à regarder dans la source. BTW, un autre excellent moteur de sélection est github.com/ded/qwery
ryanve le

@ryanve, merci je vais jeter un oeil :)
epoch

La solution de travail que j'ai utilisée est dans github.com/ryanve/dope/blob/master/dope.js dans la méthode appelée 'queryAttr'
ryanve

7
Lol, ta question est ma réponse. Donc cela vient avec une autre question. Dans quelle situation qui querySelectorAlln'est pas disponible? note - I don't care all IE
vzhen le

Réponses:


136

Vous pouvez écrire une fonction qui exécute getElementsByTagName ('*') et ne renvoie que les éléments avec un attribut "data-foo":

function getAllElementsWithAttribute(attribute)
{
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++)
  {
    if (allElements[i].getAttribute(attribute) !== null)
    {
      // Element exists with attribute. Add to array.
      matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

Ensuite,

getAllElementsWithAttribute('data-foo');

8
L'utilisation != nullest le moyen idéal (mieux que mon commentaire ci-dessus) car dans l'ancien IE, il est possible pour getAttribute de renvoyer une valeur qui typeofest'number'
ryanve

1
Pourquoi utiliser document.getElementsByTagName('*')au lieu de document.all?
pedrozath

1
Pourquoi ne pas utiliser hasAttributeplutôt que getAttribute() !== null, puisque vous voulez seulement vérifier l'existence et non sa valeur?
rvighne le

61

Utilisation

//find first element with "someAttr" attribute
document.querySelector('[someAttr]')

ou

//find all elements with "someAttr" attribute
document.querySelectorAll('[someAttr]') 

pour rechercher des éléments par attribut. Il est désormais pris en charge dans tous les navigateurs pertinents (même IE8): http://caniuse.com/#search=queryselector


2
Comment cela a-t-il autant de votes positifs lorsque la question demande explicitement: "J'ai besoin d'une solution native qui fonctionne au moins dans IE7 ". Deuxièmement, ce lien indique que la prise en charge commence dans IE11 même si elle commence en fait à partir d'IE8 - peut-être que cela devrait être échangé vers developer.mozilla.org/en-US/docs/Web/API/Element/... donc il prend en charge la réponse. ..?
Zze

7
La raison de tous les votes positifs, et la raison pour laquelle j'ai répondu, est que cette question SO est vraiment ancienne, donc lorsque vous recherchez comment trouver des éléments DOM, vous trouvez cette question très haut dans les résultats de recherche, et puisque c'est ce que les gens sont à la recherche de leur vote positif. Utilité> exactitude historique. Deuxièmement, le lien fonctionne toujours très bien, c'est juste que caniuse.com a caché d'anciens navigateurs, si vous passez à "Utilisation relative", vous verrez toujours les anciens navigateurs.
Pylinux

A parfaitement fonctionné. Rapide et simple
Dawson B

Nous sommes en 2020. Cela devrait être la réponse acceptée maintenant.
NearHuscarl

44

J'ai joué un peu et j'ai fini avec cette solution brute:

function getElementsByAttribute(attribute, context) {
  var nodeList = (context || document).getElementsByTagName('*');
  var nodeArray = [];
  var iterator = 0;
  var node = null;

  while (node = nodeList[iterator++]) {
    if (node.hasAttribute(attribute)) nodeArray.push(node);
  }

  return nodeArray;
}

L'utilisation est assez simple et fonctionne même dans IE8:

getElementsByAttribute('data-foo');
// or with parentNode
getElementsByAttribute('data-foo', document);

http://fiddle.jshell.net/9xaxf6jr/

Mais je recommande d'utiliser querySelector/ Allpour cela (et pour prendre en charge les navigateurs plus anciens, utilisez un polyfill ):

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

Oui, +1 pour querySelectorAll. Un test rapide de jsperf jsperf.com/custom-vs-selectorall-attributes montre que c'est beaucoup plus rapide que la réponse acceptée ... malheureusement ce n'est pas compatible avec IE 7 :(
Sebastien Daniel

11

Essayez ça ça marche

document.querySelector ('[attribut = "valeur"]')

exemple :

document.querySelector('[role="button"]')

5

Cela fonctionne aussi:

document.querySelector([attribute="value"]);

Alors:

document.querySelector([data-foo="bar"]);

2
Il manque les guillemets simples dans le querySelector réel. Devrait être: document.querySelector('[data-foo="bar"]');
Brettins le

1

Essayez ceci - j'ai légèrement changé les réponses ci-dessus:

var getAttributes = function(attribute) {
    var allElements = document.getElementsByTagName('*'),
        allElementsLen = allElements.length,
        curElement,
        i,
        results = [];

    for(i = 0; i < allElementsLen; i += 1) {
        curElement = allElements[i];

        if(curElement.getAttribute(attribute)) {
            results.push(curElement);
        }
    }

    return results;
};

Ensuite,

getAttributes('data-foo');

3
Qu'avez-vous changé et pourquoi?
Artjom B.

1

Une petite modification sur la réponse de @kevinfahy , pour permettre d'obtenir l'attribut par valeur si besoin:

function getElementsByAttributeValue(attribute, value){
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++) {
    if (allElements[i].getAttribute(attribute) !== null) {
      if (!value || allElements[i].getAttribute(attribute) == value)
        matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

0

Ne pas utiliser dans le navigateur

Dans le navigateur, utilisez document.querySelect('[attribute-name]').

Mais si vous faites des tests unitaires et que votre dom fictif a une implémentation floconneuse de querySelector, cela fera l'affaire.

C'est la réponse de @ kevinfahy, juste réduite pour être un peu avec les fonctions de grosse flèche ES6 et en convertissant HtmlCollection en un tableau au détriment de la lisibilité peut-être.

Cela ne fonctionnera donc qu'avec un transpileur ES6. De plus, je ne sais pas à quel point ce sera performant avec beaucoup d'éléments.

function getElementsWithAttribute(attribute) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) !== null);
}

Et voici une variante qui obtiendra un attribut avec une valeur spécifique

function getElementsWithAttributeValue(attribute, value) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) === value);
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.