Come ottenere l'elemento figlio in base al nome della classe?


131

Sto cercando di ottenere l'intervallo figlio con classe = 4. Ecco un esempio di esempio:

<div id="test">
 <span class="one"></span>
 <span class="two"></span>
 <span class="three"></span>
 <span class="four"></span>
</div>

Gli strumenti che ho a disposizione sono JS e YUI2. Posso fare qualcosa del genere:

doc = document.getElementById('test');
notes = doc.getElementsByClassName('four');

//or

doc = YAHOO.util.Dom.get('#test');
notes = doc.getElementsByClassName('four');

Questi non funzionano in IE. Ottengo un errore che l'oggetto (doc) non supporta questo metodo o proprietà (getElementsByClassName). Ho provato alcuni esempi di implementazioni cross-browser di getElementsByClassName ma non sono riuscito a farli funzionare e ho ancora riscontrato l'errore.

Penso che ciò di cui ho bisogno sia un getElementsByClassName cross browser o ho bisogno di usare doc.getElementsByTagName ('span') e scorrere fino a trovare la classe 4. Non sono sicuro di come farlo però.



1
Abbastanza divertente, il più potente querySelectorAllè supportato da IE 8+ mentre getElementsByClassNameè supportato solo da IE 9+. Se riesci a eliminare IE 7, sei sicuro da usare querySelectorAll('.4'). A proposito, 4è un nome di classe non valido.
Prinzhorn,

@paritybit questa domanda non funziona perché utilizza ancora getElementsByClassName e la versione precedente di IE non sembra supportarla. modifica: mi dispiace che usi il nome del tag. Questo potrebbe funzionare.
spyderman4g63,

@Prinzhorn Non ho l'utilità di selezione YUI2 disponibile in questo prodotto per qualche motivo.
spyderman4g63,

@ spyderman4g63 Non ho parlato di qualcosa di specifico per YUI2. document.querySelectorAllè DOM e non ha nulla a che fare con YUI
Prinzhorn,

Risposte:


85

Utilizzare doc.childNodesper scorrere ciascuno di essi span, quindi filtrare quello il cui classNameuguale è 4:

var doc = document.getElementById("test");
var notes = null;
for (var i = 0; i < doc.childNodes.length; i++) {
    if (doc.childNodes[i].className == "4") {
      notes = doc.childNodes[i];
      break;
    }        
}


1
Il problema è che getElementsByClassName non funziona in IE8.
spyderman4g63,

7
Questo codice non funziona se l'elemento ha più di una classe. Ad esempio: se stai cercando elementi con "una" classe e i tuoi elementi hanno "una due tre", questa funzione non li troverà.
Fran Verona,

3
@FranVerona Solo per curiosità, un semplice "indexOf ('className')> -1" non risolverebbe il problema delle classi multiple?
James Poulose,

2
@JamesPoulose, non sarebbe . Considera di avere un elemento impostato su due classi: piccolo e più grande. thatElement.className restituirebbe una stringa uguale a "piccola più grande". Se stai cercando una classe chiamata big dicendo myElement.className.indexOf ("big") produrrà qualcosa di diverso dal negativo 1 nonostante ciò non faccia effettivamente parte della classe. Se hai il controllo al 100% dei nomi delle tue classi, una soluzione del genere funzionerebbe, non è garantito, specialmente quando stai scrivendo codice che interagirà con il codice su cui non hai il controllo totale.
deadboy

Dovresti usare una corrispondenza regex in questo classNamemodo: if(doc.childNode[i].className.match("\s*" + search_class + "\s*")dove la variabile search_classè il nome della classe che stai cercando.
WebWanderer,

130

Usa querySelector e querySelectorAll

var testContainer = document.querySelector('#test');
var fourChildNode = testContainer.querySelector('.four');

IE9 e superiore

;)


Grazie per la tua soluzione intelligente!
Tai JinYuan,

1
Questo controlla tutti i discendenti, non solo i bambini.
SUM1

47

La risposta accettata controlla solo i bambini immediati. Spesso cerchiamo discendenti con quel nome di classe.

Inoltre, a volte vogliamo qualsiasi figlio che contenga un className.

Ad esempio: <div class="img square"></div>dovrebbe corrispondere a una ricerca su className "img", anche se è esatto className non è "img".

Ecco una soluzione per entrambi questi problemi:

Trova la prima istanza di un elemento discendente con la classe className

   function findFirstChildByClass(element, className) {
        var foundElement = null, found;
        function recurse(element, className, found) {
            for (var i = 0; i < element.childNodes.length && !found; i++) {
                var el = element.childNodes[i];
                var classes = el.className != undefined? el.className.split(" ") : [];
                for (var j = 0, jl = classes.length; j < jl; j++) {
                    if (classes[j] == className) {
                        found = true;
                        foundElement = element.childNodes[i];
                        break;
                    }
                }
                if(found)
                    break;
                recurse(element.childNodes[i], className, found);
            }
        }
        recurse(element, className, false);
        return foundElement;
    }

7
No. Io non voglio che tutti i discendenti, solo il bambino come la domanda posta.
Paul Draper,

14
Cucciolo. Il tuo commento è stato necessario. Sono contento di aver aiutato altre 13 persone (come me) a cercare spesso risposte simili per risolvere il loro problema simile, ma forse più complesso o generale.
Augie Gardner,

5
tnx, penso che questa risposta si adatti a più casi d'uso
Boban Stojanovski

Per la cronaca, ho avuto entrambi i casi d'uso, i discendenti leggermente più spesso, ma sono venuto qui per il caso d'uso del bambino.
SUM1

14

Usa element.querySelector (). Supponiamo che 'myElement' sia l'elemento genitore che hai già. 'sonClassName' è la classe del bambino che stai cercando.

let child = myElement.querySelector('.sonClassName');

Per maggiori informazioni, visitare: https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector


Per qualche motivo ho dovuto usare let child = myElement.querySelector('sonClassName');nel mio caso
malat

Ma devi aggiungere il punto accanto al nome classe querySelector ('. SonClassName'), altrimenti lo gestirà come sonClassName è un nome tag non un nome classe
Hamza Dahmoun

10

Puoi provare:

notes = doc.querySelectorAll('.4');

o

notes = doc.getElementsByTagName('*');
for (var i = 0; i < notes.length; i++) { 
    if (notes[i].getAttribute('class') == '4') {
    }
}

1
Mi chiedevo se finalmente i browser avessero questa funzionalità senza richiedere qualcosa come jQuery, felice di vederlo. Se qualcuno è curioso, sembra supportato dalla maggior parte dei browser moderni: developer.mozilla.org/en-US/docs/Web/API/Document/…
Liron Yahdav

8

A me sembra che tu voglia la quarta luce. Se è così, puoi semplicemente fare questo:

document.getElementById("test").childNodes[3]

o

document.getElementById("test").getElementsByTagName("span")[3]

Quest'ultimo assicura che non ci siano nodi nascosti che potrebbero rovinarlo.


1
Grazie, ma ci sono una quantità variabile di elementi figlio.
spyderman4g63,

1
A me sembrava che la domanda fosse quella di ottenere sempre il bambino di quarto livello, portando così alla mia risposta. Sono ovviamente d'accordo sul fatto che una funzione per ottenere qualsiasi tipo di elemento in qualunque indice all'interno di un altro elemento sarebbe migliore, ma non ho interpretato la domanda in quel modo ... Leggendo di nuovo la domanda vedo che ho frainteso del tutto però: - )
Christian Jørgensen l'

TagNamequesto è tutto! Così semplice.
Jacksonkr,

Uso questa tecnica frequentemente per ottenere il primo elemento, ad esempio document.getElementById ("test"). ChildNodes [0]
Louise Eggleton,

@LouiseEggleton c'è .firstChilde .firstChildElementcomunque
YakovL

4

Ma tieni presente che i vecchi browser non supportano getElementsByClassName.

Quindi puoi farlo

function getElementsByClassName(c,el){
    if(typeof el=='string'){el=document.getElementById(el);}
    if(!el){el=document;}
    if(el.getElementsByClassName){return el.getElementsByClassName(c);}
    var arr=[],
        allEls=el.getElementsByTagName('*');
    for(var i=0;i<allEls.length;i++){
        if(allEls[i].className.split(' ').indexOf(c)>-1){arr.push(allEls[i])}
    }
    return arr;
}
getElementsByClassName('4','test')[0];

Sembra che funzioni, ma tieni presente che una classe HTML

  • Deve iniziare con una lettera: AZ o az
  • Può essere seguito da lettere (A-Za-z), cifre (0-9), trattini ("-") e caratteri di sottolineatura ("_")

3

Usa il nome dell'id con il getElementById, nessun #segno prima di esso. Quindi è possibile ottenere i spannodi figlio utilizzando getElementsByTagNamee scorrere attraverso di essi per trovare quello con la classe giusta:

var doc = document.getElementById('test');

var c = doc.getElementsByTagName('span');

var e = null;
for (var i = 0; i < c.length; i++) {
    if (c[i].className == '4') {
        e = c[i];
        break;
    }
}

if (e != null) {
    alert(e.innerHTML);
}

Demo: http://jsfiddle.net/Guffa/xB62U/


Mi dispiace, quel # era un errore di battitura. Posso selezionare il div contenitore, ma non posso selezionare gli elementi figlio per nome tag perché quella funzione non funziona in ie8.
spyderman4g63,

@ spyderman4g63: il getElementsByTagNamemetodo funziona in IE 8. È supportato fino a IE 5.5. developer.mozilla.org/en-US/docs/DOM/…
Guffa,

3

Secondo me, ogni volta che puoi, dovresti usare Array e i suoi metodi. Sono molto, molto più veloci del loop su tutto il DOM / wrapper o spingendo roba in array vuoto. La maggior parte delle soluzioni presentate qui è possibile chiamare Naive come descritto qui (ottimo articolo tra l'altro):

https://medium.com/@chuckdries/traversing-the-dom-with-filter-map-and-arrow-functions-1417d326d2bc

La mia soluzione : (anteprima dal vivo su Codepen: https://codepen.io/Nikolaus91/pen/wEGEYe )

const wrapper = document.getElementById('test') // take a wrapper by ID -> fastest
const itemsArray = Array.from(wrapper.children) // make Array from his children

const pickOne = itemsArray.map(item => { // loop over his children using .map() --> see MDN for more
   if(item.classList.contains('four')) // we place a test where we determine our choice
     item.classList.add('the-chosen-one') // your code here
})

1

Il modo in cui lo farò usando jquery è qualcosa del genere ..

var targchild = $ ("# test"). children (). find ("span.four");


14
la domanda riguarda javascript e non jQuery
Jya il

1

Ecco una soluzione ricorsiva relativamente semplice. Penso che una ricerca ampia prima sia appropriata qui. Ciò restituirà il primo elemento corrispondente alla classe trovata.

function getDescendantWithClass(element, clName) {
    var children = element.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (children[i].className &&
            children[i].className.split(' ').indexOf(clName) >= 0) {
            return children[i];
         }
     }
     for (var i = 0; i < children.length; i++) {
         var match = getDescendantWithClass(children[i], clName);
         if (match !== null) {
             return match;
         }
     }
     return null;
}

1

Puoi recuperare la classe genitore aggiungendo la riga seguente. Se tu avessi un ID, sarebbe più facile con getElementById. Ciò nonostante,

var parentNode = document.getElementsByClassName("progress__container")[0];

Quindi puoi utilizzare querySelectorAllil genitore <div>per recuperare tutti i messaggi corrispondenti divcon la classe.progress__marker

var progressNodes = progressContainer.querySelectorAll('.progress__marker');

querySelectorAllprenderà tutti divcon la classe diprogress__marker


1

Soluzione moderna

const context = document.getElementById('context');
const selected = context.querySelectorAll(':scope > div');

documentazione


0

Aggiornamento di giugno 2018 su ES6

    const doc = document.getElementById('test');
    let notes = null;
    for (const value of doc) {
        if (value.className === '4') {
            notes = value;
            break;
        }    
    }

-2

YUI2 ha un'implementazione cross-browser digetElementsByClassName .


Hmm. L'esempio funziona in IE8, ma forse non funziona nel caso in cui lo si applichi a un oggetto. Nel mio caso è impostato doc come oggetto yui dom e quindi uso doc.getElementsByClassName. Questo è quando fallisce. modifica: o forse non capisco come funziona quell'oggetto ed è solo un normale oggetto dom?
spyderman4g63,

@ spyderman4g63 la versione YUI di getElementsByClassNameè un metodo di YAHOO.util.Dom. Nel tuo caso, la chiamata sarebbe simile YAHOO.util.Dom.getElementsByClassName('four', 'span', 'test'). Probabilmente dovresti leggere i documenti per avere una comprensione più dettagliata di ciò che sta facendo quella chiamata. La versione breve è che ora cercherà spanelementi con la classe foursotto l'elemento DOM con testcome suo id.
Hank Gay,

@ spyderman4g63 Sì, il risultato della getchiamata è solo un elemento DOM. YUI non prende il tipo di approccio 'avvolgete tutto in un oggetto specifico per il framework' di vendita intera che fa qualcosa come jQuery, né oggetti nativi con patch scimmia come Prototype (non ho fatto casino con Protoype per sempre). A questo proposito, YUI è più simile al Dojo.
Hank Gay,

-3

Ecco come l'ho fatto usando i selettori YUI. Grazie al suggerimento di Hank Gay.

notes = YAHOO.util.Dom.getElementsByClassName('four','span','test');

dove four = classname, span = il tipo di elemento / nome tag e test = l'id parent.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.