web-dev-qa-db-ja.com

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」が影響を受ける選択された要素になるようにするにはどうすればよいですか?

また、クラスまたはIDを「li」または「ul」に追加しないようにします。一度に2つのタグを選択する方法はありますか?

47
biddybump

いいえ、getElementsByTagNameの1回の呼び出しで複数のタグを選択することはできません。 getElementsByTagNameを使用して2つのクエリを実行するか、querySelectorAllを使用できます。

JSFiddle

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

Q

GetElementsByTagNameを使用して複数のタグを選択できますか?

A

はい。ただし、getElementsByTagNameを複数回使用する必要があります。

この例では Document.getElementsByTagName() のみを指定していますが、これもelement.getElementsByTagName()で動作することを想定しています。

getElementsByTagNameは HTMLCollection オブジェクトを返すため、理想的な結果は、指定されたすべてのタグ名の要素の HTMLCollection オブジェクトを返すメソッドになります。

注意事項 HTMLCollection's

  • 変更できません。
  • それらは live DOMノードのリストです
  • 自分で直接作成する方法は3つしかありませんgetElementsByTagNamegetElementsByClassNameおよびgetElementsByTagNameNS
  • hTMLCollection型のプロパティを持つオブジェクトを作成できます。例:nodeList.children

HTMLCollection's を修正できないため、できる限り HTMLCollection's に似たオブジェクトを返すか、 HTMLCollection を参照するか、 nodeListを作成し、childrenプロパティを返します。

まず、HTMLCollectionに一致するすべての要素を収集する必要があります

最も簡単な方法は、nodeListを返す querySelectorAll 関数を使用することです。

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.childrenにアクセスできるように、要素を単一のparentNodeに移動またはコピーする必要があります。

document.createDocumentFragmentを使用すると最適に機能することがわかりました。

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

これは正しいtype(HTMLCollection)を返しますが、メソッドが呼び出されたときの要素の実際の状態は返しません。これを実現するためにDOMが変更されました。良い考えではありません。

そのため、偽のHTMLCollectionを作成することになります。

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'メソッドと、同じコアメソッドgetElementsBySelectorを使用する 'getElementsByTagNames'も実装しました。

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

Document および Element インターフェイスは、すべての Node インターフェイスに存在しないプロトタイプメソッドを呼び出すため、新しいメソッドを継承したいだけです。例えばgetElementsByClassNamequerySelectorAllなど.

コードを縮小したい場合は、Element.prototype.およびDocument.prototype.と記述する代わりにNode.prototypeを使用できます。

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

Document または Element でないノードでは使用しないでください。

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'); 
2
TarranJones

1年遅れですが、プロジェクトで目的の機能を複数回使用する予定で、 querySelector() にアクセスできない場合は、Nodeを拡張する価値があるかもしれませんsimple関数を持つオブジェクト:

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()を使用して対応する要素を取得するだけです。

これはもちろん、any要素で、同様の関数を使用するのとまったく同じ方法で使用できます-getElementById()-Nodeでオブジェクト、documentに限定されません。

1
John Weisz