Як отримати дочірній елемент за назвою класу?


131

Я намагаюся отримати дочірній проміжок, який має клас = 4. Ось елемент прикладу:

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

У мене є інструменти JS та YUI2. Я можу зробити щось подібне:

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

//or

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

Вони не працюють в IE. Я отримую помилку, що об’єкт (doc) не підтримує цей метод або властивість (getElementsByClassName). Я спробував кілька прикладів крос-браузерних реалізацій getElementsByClassName, але мені не вдалося змусити їх працювати, і я все-таки отримав цю помилку.

Я думаю, що мені потрібно це перехресний браузер getElementsByClassName або мені потрібно використовувати doc.getElementsByTagName ('span') і перебирати, поки я не знайду клас 4. Я не впевнений, як це зробити.



1
Як не дивно, більш потужний querySelectorAllпідтримується IE 8+, тоді getElementsByClassNameяк підтримується лише IE 9+. Якщо ви можете скинути IE 7, ви безпечні для використання querySelectorAll('.4'). До речі, 4це недійсне ім’я класу.
Prinzhorn

@paritybit це питання не працює, оскільки воно все ще використовує getElementsByClassName та старішу версію IE, схоже, це не підтримують. редагувати: Вибачте, що використовується ім'я тегу Це може спрацювати.
spyderman4g63

@Prinzhorn У мене в цьому виробі чомусь немає утиліти для вибору YUI2.
spyderman4g63

@ spyderman4g63 Я нічого не говорив про YUI2. document.querySelectorAllє DOM і не має нічого спільного з YUI
Prinzhorn

Відповіді:


85

Використовуйте doc.childNodesдля повторення кожного span, а потім відфільтруйте той, чий classNameдорівнює 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
Проблема полягає в тому, що getElementsByClassName не працює в IE8.
spyderman4g63

7
Цей код не працює, якщо елемент має більше одного класу. Наприклад: якщо ви шукаєте елементи з класом "один", а у ваших елементів клас "один два три", ця функція їх не знайде.
Fran Verona

3
@FranVerona Щойно з цікавості, чи не простий "indexOf ('className')> -1" не вирішить проблему з кількома класами?
Джеймс Поулоз

2
@JamesPoulose, це не буде . Розглянемо наявність елемента, встановленого на два класи: малий і більший. thatElement.className поверне рядок, що дорівнює "малому більшому". Якщо ви шукаєте клас під назвою велика приказка myElement.className.indexOf ("великий"), ви отримаєте щось нерівне до негативного 1, незважаючи на те, що насправді не є частиною класу. Якщо у вас 100% контроль над іменами вашого класу, таке виправлення спрацює, це просто не гарантується, особливо коли ваш код написання, який буде взаємодіяти код, ви не маєте повного контролю над.
мертвий

Ви повинні використовувати збіг регулярних виразів classNameподібним чином: if(doc.childNode[i].className.match("\s*" + search_class + "\s*")де змінна search_class- це назва класу, який ви шукаєте.
WebWanderer


47

Прийнята відповідь перевіряє лише безпосередніх дітей. Часто ми шукаємо будь-яких нащадків з таким ім'ям класу.

Крім того, іноді ми хочемо, щоб будь-яка дитина, яка містить класне ім’я.

Наприклад: <div class="img square"></div>повинен відповідати пошуку по className "img", навіть якщо це точно className не "img".

Ось вирішення обох цих питань:

Знайдіть перший екземпляр елемента нащадка з класом 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
Ні. Я не хочу всіх нащадків, просто таку дитину, як запитання.
Пол Дрейпер,

14
Whelp. Ваш коментар був необхідним. Радий, що я допоміг 13 іншим людям, які (як я) часто шукають подібні відповіді, щоб вирішити свою подібну, але, можливо, більш складну або загальну проблему.
Огі Гарднер

5
tnx, я думаю, що ця відповідь підходить для більшої кількості випадків використання
Бобан Стояновський

Для запису у мене були випадки обох випадків використання, нащадки дещо частіше, але я прийшов сюди за випадком використання дітей.
SUM1

14

Використовуйте element.querySelector (). Припустимо: 'myElement' є батьківським елементом, який ви вже маєте. 'sonClassName' - клас дитини, яку ви шукаєте.

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

Для отримання додаткової інформації відвідайте: https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector


Чомусь мені довелося використовувати let child = myElement.querySelector('sonClassName');в моєму випадку
малат

Але ви повинні додати крапку поруч із іменем класу querySelector ('. SonClassName'), інакше вона буде обробляти її як sonClassName - це тег, а не ім'я класу
Hamza Dahmoun

10

Ви можете спробувати:

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

або

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

1
Мені було цікаво, чи нарешті браузери отримали цю функціональність, не вимагаючи чогось на зразок jQuery, радий це бачити. Якщо хтось цікавий, схоже, що він підтримується в більшості сучасних браузерів: developer.mozilla.org/en-US/docs/Web/API/Document/…
Liron Yahdav

8

Мені здається, ти хочеш четвертого прольоту. Якщо так, ви можете просто зробити це:

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

або

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

Останній гарантує відсутність прихованих вузлів, які могли б зіпсувати це.


1
Дякую, але дочірні елементи є різною.
spyderman4g63

1
Мені здавалося, що питання полягає у тому, щоб завжди отримати четверту дитину, що призвело до моєї відповіді. Я, звичайно, погоджуюся, що функція отримати будь-який тип елемента при будь-якому індексі в межах іншого елемента буде кращою, але я не трактував таке питання ... читаючи питання ще раз, я бачу, що я абсолютно не зрозумів, хоча: - )
Крістіан Йоргенсен

TagNameЦе воно! Так просто.
Джексонкр

Я часто використовую цю техніку, щоб отримати перший елемент, наприклад document.getElementById ("тест"). ChildNodes [0]
Луїза Еглтон

@LouiseEggleton є .firstChildі .firstChildElementхоча
YakovL

4

Але майте на увазі, що старі браузери не підтримують getElementsByClassName.

Тоді, ви можете зробити

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];

Здається, це працює, але пам’ятайте, що це клас HTML

  • Починати треба з літери: AZ чи az
  • Можуть супроводжуватися літерами (A-Za-z), цифрами (0-9), дефісами ("-") та підкресленнями ("_")

3

Використовуйте ім'я ідентифікатора разом із знаком, перед ним getElementByIdніяких #знаків. Тоді ви можете отримати spanдочірні вузли за допомогою getElementsByTagNameта перегляньте їх, щоб знайти потрібний клас:

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);
}

Демонстрація: http://jsfiddle.net/Guffa/xB62U/


Вибачте, що # був помилковим. Я можу вибрати контейнер div, але не можу вибрати дочірні елементи за назвою тегів, оскільки ця функція не працює у ie8.
spyderman4g63

@ spyderman4g63: getElementsByTagNameМетод працює в IE 8. Він підтримується ще в IE 5.5. developer.mozilla.org/en-US/docs/DOM/…
Guffa

3

На мою думку, кожен раз, коли можна, слід використовувати Array та його методи. Вони набагато, набагато швидше, ніж перекидання по всьому DOM / обгортці або переміщення матеріалів у порожній масив. Більшість представлених тут рішень ви можете назвати Naive, як описано тут (чудова стаття btw):

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

Моє рішення : (попередній перегляд у програмі 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

Те, як я буду робити це за допомогою jquery, є щось подібне ..

var targetchild = $ ("# test"). діти (). find ("span.four");


14
питання про javascript not jQuery
Jya

1

Ось відносно просте рекурсивне рішення. Я думаю, що тут потрібен пошук в першу чергу. Це поверне перший елемент, що відповідає класу, який знайдено.

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

Ви можете отримати батьківський клас, додавши рядок нижче. Якби у вас був ідентифікатор, було б простіше getElementById. Тим не менш,

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

Тоді ви можете використовувати querySelectorAllна батьківській програмі <div>для отримання всіх відповідних divs класу.progress__marker

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

querySelectorAllзнайде кожного divз класуprogress__marker



0

Оновлення червня 2018 року до ES6

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

-2

Хм. Приклад працює в IE8, але, можливо, він не працює в тому випадку, якщо ви застосовуєте його до об'єкта. У моєму випадку встановлюється doc як об’єкт yui dom, а потім використовується doc.getElementsByClassName. Ось тоді це не вдається. редагувати: а може, я не розумію, як працює цей об’єкт, і це просто звичайний об'єкт dom?
spyderman4g63

@ spyderman4g63 версія YUI getElementsByClassName- це метод YAHOO.util.Dom. У вашому випадку дзвінок виглядатиме приблизно так YAHOO.util.Dom.getElementsByClassName('four', 'span', 'test'). Вам, мабуть, варто прочитати документи, щоб отримати більш детальне розуміння того, що робить цей дзвінок. Коротка версія полягає в тому, що тепер вона буде шукати spanелементи класу fourпід елементом DOM, testяк його id.
Хенк Гей

@ spyderman4g63 Так, результат getвиклику - це лише елемент DOM. YUI не приймає подібного типу "обгортати все під конкретний рамковий" підхід, що робить щось на зразок jQuery, а також не робить майстерні патчі об'єктів, як прототип (так? Я не заплутався з прототипом у вічно). У цьому відношенні YUI більше схожий на Dojo.
Хенк Гей

-3

Ось як я це зробив за допомогою селекторів YUI. Завдяки пропозиції Хенка Гей.

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

де four = ім'я класу, span = тип елемента / назва тегу та test = батьківський ідентифікатор.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.