2009-09-10 8 views
0

Sans utiliser de framework open source (jQuery, etc.) :), en JavaScript, quel est le moyen le plus efficace de rechercher des attributs dans les contrôles. (Tous les anciens/nouveaux navigateurs)Attribut de recherche en JavaScript

C'est le modèle que je suis en quelque sorte. Yat-il un meilleur moyen ou une meilleure méthode getElementByAttribute()? Merci!

par exemple

<input type="button" id="b1" value="Continue" a1="something" /> 
<input type="text" id="t1" a1="something1" /> 

<script> 
var attrToFind = "something;something1"; 

var elems = document.all ? document.all : document.getElementByTagName("*"); 
//assume elems work always 
for(var i = 0 ; i < elems.length; i++) 
{ 
    var att = elems[i].getAttribute("a1"); 
    if (typeof att == "string") 
    { 
    if (att.indexOf(attrToFind) > -1) 
    ... //search which attr you find, create array, save value, etc. 
    } 
} 
</script> 

+1

Je pense que vous avez déjà à peu près la bonne idée ... Votre test est faible - il va correspondre à "quelque chose" si la valeur est "somethingelse" - mais c'est assez facile à corriger. Le plus gros problème est simplement que ce sera assez lent pour les documents volumineux, car il doit traverser le DOM entier à chaque fois. C'est pourquoi les moteurs de sélecteurs tels que jQuery/Sizzle encouragent des sélecteurs plus spécifiques: 'input [a1 = something]' n'a besoin que de tester les éléments d'entrée. – Shog9

Répondre

1

Il y a. Étant donné que le navigateur prend en charge d'autres moyens de collecte d'éléments, tels que document.querySelectorAll (expression css) ou document.evaluate (expression xpath), ces méthodes «spécialisées» sont généralement plus efficaces.

document.querySelectorAll('*[foo="bar"]'); 
document.evaluate("//*[@foo='bar']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 
+0

@kangax: Intéressant ... ne connaissait pas du tout querySelectorAll. Je crois que cela ne fonctionnera pas sur les navigateurs nouveaux et anciens, donc je ne peux pas vraiment l'utiliser. @ Shog9: Yup, être plus lent avec mon chemin est aussi ma peur. C'est pourquoi j'ai posté la question ici pour demander aux gourous de JS. –

+0

Oui, vous finissez par avoir à écrire une fonction wrapper qui utilise l'une de ces méthodes si disponible, sinon revient à marcher tout le document. C'est ce que font beaucoup de frameworks (bien que certains d'entre eux n'obtiennent pas l'échappement de la chaîne à droite ...) – bobince

1

accès à un HTMLCollection (retourné par getElement[s]By* fonctions) est lent par rapport à l'accès aux réseaux, car un HTMLCollection doit correspondre au document à tout moment (il est en direct).

Pour cette raison, il est préférable de créer un tableau à partir du HTMLCollection et de le parcourir par-dessus.

C'est un peu plus optimisé pour la vitesse:

var attrToFind = "something;something1", 
    elems = document.all ? document.all : document.getElementByTagName('*'), 
    i, attr; 

// Works in Firefox; not sure about other browsers and engines. 
elems = Array.prototype.slice.call(elems); 

i = elems.length; 

while(i --> 0) { 
    attr = elems[i].getAttribute('a1'); 

    // Are you sure you want indexOf? 
    // att === attrToFind may be faster, as it requires one less comparison. 
    if(typeof att !== 'string' || att.indexOf(attrToFind) < 0) { 
     continue; 
    } 

    // Do stuff. 
} 
+0

@stranger: l'extrait de code semble optimiste. Laisse-moi essayer. THX! –

+0

Oui, IE6 n'a pas aimé Array.prototype.slice.call (elems) et malheureusement (pour nous tous) que je dois le supporter. –

+0

@ Rac123, Vous pouvez probablement itérer et copier dans un nouveau tableau pour IE6. Ajoutez un bloc try, peut-être, autour de la ligne collection-to-array actuelle, plutôt que dans la capture catch the naïve. – strager

0

C'est peut-être la solution que vous aurez besoin:

function $$$$(obj) { 

var attrToFind = obj; 
var elements = document.getElementsByTagName('*'); 
var attrResults = []; 

var x = 0; 
while (x < elements.length) { 
    var attr = elements[x].getAttribute('a1'); 

    if (attr !== null) { 
     if (attr.indexOf(attrToFind) > -1) { 
      attrResults.push(elements[x]); 
     } 
    } 
    x++ 
} 
return attrResults; 

}

Run Fonction:

$$$$('something'); 

Le résultat est un Array avec tous les éléments avec la classe 'quelque chose'. Peut-être que quelqu'un peut refactoriser mon code, donc cela fonctionne aussi avec plus d'un paramètre.

J'espère pouvoir vous aider.

Questions connexes