Можно ли выбрать несколько тегов с помощью getElementsByTagName?

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

function increaseFontSize() {  

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

    for(i=0;i<paragraphs.length;i++) {   

        if(paragraphs[i].style.fontSize) { 
            var s = parseInt(paragraphs[i].style.fontSize.replace("px",""));
        } else {   
            var s = 14;
        }

        if(s != max) {  
            s += 1; 
        } 
        paragraphs[i].style.fontSize = s+"px"
    } 
} 

Как я могу также включить " li "в этот код, чтобы" p "и" li " были выбранными элементами, которые затронуты?

Я также хотел бы избежать добавления класса или идентификатора в мой "li" или "ul". Есть ли способ выбрать сразу два тега?

3 ответов


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

JSFiddle

var elems = document.querySelectorAll('p,li')

Q

можно ли выбрать несколько тегов с помощью getElementsByTagName?

A

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

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

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

вещи, чтобы отметить о уход это

  • они не могут быть изменены.
  • они live список узлов DOM
  • есть только три способа создать себе непосредственно getElementsByTagName, getElementsByClassName и getElementsByTagNameNS
  • вы можете создать объект, который может иметь свойства, которые имеют тип HTMLCollection e.g nodeList.children

As уход это не может быть изменен лучшее, что мы можем сделать, это либо возвратить объект, который напоминал уход это как можно посмотреть создать 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 был изменен. Не очень хорошая идея.

так что это оставляет нас с фальшивый уход

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

теперь, чтобы собрать все это вместе.

Ive также реализовал метод "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');
}

мы хотим только документ и элемент интерфейсы для наследования наших новых методов, потому что они вызывают методы прототипа, которые не существуют во всех узел интерфейсы. например,getElementsByClassName,querySelectorAll, etc.

если вы хотите минимизировать свой код, вы можете использовать Node.прототип вместо указания 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'); 

на год позже, но если вы намерены использовать желаемую функциональность несколько раз в своем проекте, и у вас нет доступа к 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() - по любому