Вопрос по html, getelementsbytagname, javascript – Могу ли я выбрать несколько тегов, используя getElementsByTagName?

46

используя фрагмент JavaScript, чтобы посетители моего сайта могли увеличить размер шрифта во всех абзацах, используя следующий код JavaScript:

function increaseFontSize() {  

    var paragraphs = document.getElementsByTagName('p'); 

    for(i=0;i
Я неНе знаю, почему люди стараются избегать добавления классов и идентификаторов, они здесь, чтобы помочь. Вы должны избегать добавленияОчень много классы, но один просто хорошо. user2203117

Ваш Ответ

3   ответа
68

Нет вы можете'выбрать несколько тегов одним вызовомgetElementsByTagName, Вы можете сделать два запроса, используяgetElementsByTagName или использовать.querySelectorAll

JSFiddle

var elems = document.querySelectorAll('p,li')
Забавно, как Даниэль противоречит сам себе. Первое слово должно бытьдапросто потому, что сам Дэн дает способ сделать этос getElementsByTagName, Тем не менее, я'я пойду сquerySelectorAll потому что элементы приходят в исходном порядке. Bitterblue
@barwnikk Вот спецификации w3c и whatwg, вы можетене использовать регулярные выражения в соответствии с нимиw3.org/TR/DOM-Level-3-Core/core.html#ID-1938918D dom.spec.whatwg.org/#dom-element-getelementsbytagname Daniel Imms
getElementsByTagName поддерживает регулярные выражения. Итак, ДА ВЫ МОЖЕТЕ! barwnikk
@Bitterblue вопрос ясно спрашивает, можете ли вы сделать это вне замужем позвони ему. Невероятно очевидно, что вы можете сделать это двумя вызовами. Daniel Imms
2

Могу ли я выбрать несколько тегов, используя getElementsByTagName? A

Да, но вам придется использовать getElementsByTagName несколько раз.

Хотя ваш пример только указываетDocument.getElementsByTagName () Я предполагал, что вы хотели бы, чтобы это работало и с element.getElementsByTagName ().

getElementsByTagName возвращаетHTMLCollection объект, поэтому идеальный результат будет метод, который возвращаетHTMLCollection Объект элементов для всех имен тегов.

Что стоит отметитьHTMLCollection-х

Они не могут быть изменены.Онижить список DOM-узловЕсть только три способа создать его самостоятельно,getElementsByTagNamegetElementsByClassName а такжеgetElementsByTagNameNSВы можете создать объект, который может иметь свойства типа HTMLCollection, напримерnodeList.children

КакHTMLCollection-х не может быть изменено лучшее, что мы можем сделать, это либо вернуть объект, который напоминалHTMLCollection-х как можно больше, смСоздать HTMLCollection или создатьnodeList и вернутьchildren имущество.

Во-первых, нам нужно собрать все соответствующие элементы для нашегоHTMLCollection

Простейшим способом было бы использоватьquerySelectorAll функция, которая возвращает.nodeList

var nodeList = document.querySelectorAll(selector);

Альтернативой было бы использоватьgetElementsByTagName метод для каждого тега, преобразовать возвращенный объект HTMLCollection в массив, чтобы их можно было объединить вместе.

Вот так .

var HTMLCollectionArray = [];
var names = selector.split(",");
for (var i = 0, n = names.length; i < n; i++){
    HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(document.getElementsByTagName(names[i]))); 
}

NodeList также может быть преобразован в массив, используя тот же метод.

HTMLCollectionArray = Array.prototype.slice.call(nodeList);

Теперь мы можем либо вернуть все элементы в виде массива, либо попытаться вернуть HTMLCollection.

Если бы мы должны были вернуть HTMLCollection, нужно было бы либо переместить, либо скопировать элементы в один parentNode, чтобы мы могли получить к ним доступ.parentNode.children

Я нашел с помощьюdocument.createDocumentFragment работает лучше всего.

var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
    createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children; 
return HTMLCollection;

Хотя это вернет правильный тип (HTMLCollection), оно не вернет фактическое состояние элементов при вызове метода. DOM был изменен для достижения этой цели. Не хорошая идея.

Так что это оставляет нас с созданием поддельной коллекции HTMLC

window.MyNodeList = function(elements) {

    for ( var i = 0; i < elements.length; i += 1 ) {
        this[i] = elements[i];
    }
    Object.defineProperty( this, 'length', {
        get: function () {
            return elements.length;
        }
    });
    Object.freeze( this );
};

window.MyNodeList.prototype.item  function ( i ) {
    return this[i] != null ? this[i] : null;
}

window.MyHTMLCollection =  function(elements) {
  MyNodeList.call(this, elements);
}

MyHTMLCollection.prototype = Object.create(MyNodeList.prototype);

MyHTMLCollection.prototype.constructor = MyHTMLCollection;

window.MyHTMLCollection.prototype.namedItem =  function ( name ) {
    for ( var i = 0; i < this.length; i += 1 ) {
        if ( this[i].id === name || this[i].name === name ) {
            return this[i];
        }
    }
    return null;
}

использование

var HTMLCollection = new MyHTMLCollection(elementsArray);

Теперь собери все вместе.

Я также реализовалgetElementsByClassNames' метод и хорошо, какgetElementsByTagNames' которые оба используют один и тот же основной метод.getElementsBySelector

Element.prototype.getElementsByTagNames = Document.prototype.getElementsByTagNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Element.prototype.getElementsByClassNames = Document.prototype.getElementsByClassNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByClassName');
}

Мы ТОЛЬКО хотимДокумент а такжеЭлемент интерфейсы для наследования наших новых методов, потому что они вызывают методы-прототипы, которые не существуют во всехУзел интерфейсы. например ,getElementsByClassNamequerySelectorAll, так далее.

Если вы хотите минимизировать свой код, вы можете использовать Node.prototype вместо указанияElement.prototype. а такжеDocument.prototype.

Node.prototype.getElementsByTagNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Node.prototype.getElementsByClassNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByClassName');
}

Просто убедитесь, что вы нене пытайтесь использовать его на любом узле, который неДокумент или жеЭлемент.

Element.prototype.getElementsBySelector = Document.prototype.getElementsBySelector = function (selector, HTMLCollectionType) {

    var HTMLCollectionArray = [];

    if(typeof this.querySelectorAll !== 'undefined'){

        var nodeList = this.querySelectorAll(selector);
        HTMLCollectionArray = Array.prototype.slice.call(nodeList);

    } else {

        if(typeof HTMLCollectionType !=='undefined' && typeof this[HTMLCollectionType] !== 'undefined'){

            var names = selector.split(",");
            for (var i = 0, n = names.length; i < n; i++){
                HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(this[HTMLCollectionType](names[i]))); 
            }
        }
    }

    return new MyHTMLCollection(HTMLCollectionArray);

    /* 
    var createDocumentFragment = document.createDocumentFragment();
    for (var i = 0; i < HTMLCollectionArray.length; i++) {
        createDocumentFragment.appendChild(HTMLCollectionArray[i]);
    };
    HTMLCollection = createDocumentFragment.children;
    return HTMLCollection;
    */
}

использование

var element = document.getElementById('id');
element.getElementsbyClassNames('class1,class2,class2'); 
element.getElementsbyTagNames('li,div,p'); 

document.getElementsbyClassNames('class1,class2,class2'); 
document.getElementsbyTagNames('li,div,p'); 
1

Год спустя, но если вы намерены использовать нужную функциональность несколько раз в своем проекте, и вы нене имеет доступа кquerySelector (), возможно, стоит расширитьNode объект спросто функция:

JavaScript

/**
 * @param {Array} tags - The array of tagNames to search for.
 * @return {Array}     - The elements with matching tagNames.
 */
Node.prototype.getElementsByTagNames = function (tags) {
    var elements = [];

    for (var i = 0, n = tags.length; i < n; i++) {
        // Concatenate the array created from a HTMLCollection object
        elements = elements.concat(Array.prototype.slice.call(this.getElementsByTagName(tags[i])));
    }

    return elements;
};

Рабочая демонстрация на JSFiddle.

Все, что он делает - это перебирает массив имен тегов, затем получает соответствующие элементы, используяgetElementsByTagName() за каждую итерацию.

Это может тогда, конечно, использоваться налюбой элемент точно так же, как вы используете аналогичные функции - например,getElementById() - на любомNode объект, которым вы не ограниченыdocument

Похожие вопросы