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

46

Я использую фрагмент кода 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". Есть ли способ выбрать два тега одновременно?

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

Ваш Ответ

3   ответа
2
Q

A

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

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

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

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

Они не могут быть изменены.Онижить список DOM-узловЕсть только три способа создать его самостоятельноgetElementsByTagName, getElementsByClassName а также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');
}

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

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

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

JSFiddle

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

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