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


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.