Elementオブジェクト

Elementオブジェクトは、HTMLまたはXMLの要素を表します。

要素の属性

要素のタグ名

要素のタグ名は、tagNameプロパティで取得できます。そのタグ名の大文字/小文字は、XMLベースの言語では原型が保たれますが、HTMLではつねに大文字となります。Element.tagName - Web APIs | MDN

var a = document.createElement( 'span' );

alert( a.tagName );  // SPAN
alert( a.nodeName ); // SPAN

なお、このプロパティは継承元のNodeではnodeNameというプロパティ名で、同じ値を持ちます。

要素の大きさ

プロパティ 説明 書き込み ※1
Element.
scrollWidth/Height
要素の大きさ (表示されていない領域を含む) ×
Element.
clientWidth/Height
要素の表示領域の大きさ
(表示領域の大きさ + padding)
×
HTMLElement.
offsetWidth/Height
要素の表示領域の大きさ
(表示領域の大きさ + padding + スクロールバーの幅 + border)
×
Determining the dimensions of elements | MDN

※1 大きさはElementのプロパティから変更できないため、styleプロパティのwidthやheightから指定します。

表示される前の要素は、大きさとして0を返します。よって正しい値は、ドキュメントの構築を待ってから取得します。

要素ではなくドキュメントの表示領域の大きさは、ブラウザによって取得方法が異なります。

width: 200px;
height: 100px;
padding: 3px;
border: 2px;
Width Height
scrollWidth   scrollHeight  
clientWidth   clientHeight  
offsetWidth   offsetHeight  

要素の位置

プロパティ 説明 書き込み
HTMLElement.
offsetLeft / offsetTop
offsetParent要素に対する、相対的な位置
※ 親要素に対する位置ではない
×
Element.
scrollLeft / scrollTop
要素の内容がスクロールされた量

scrollLeftの最大値 = scrollWidth - clientWidth

要素ではなくドキュメントのスクロール位置は、ブラウザによって取得方法が異なります。

要素のサイズやスクロール位置を変更したときの、プロパティの変化を確認できます。

ボックスの右下にリサイズハンドルが表示されているならば、それをドラッグすることで要素の大きさを変更できます。そのとき下表の値が変わらないならば、スクロールすることで更新されます。

※ リストの数値は、親要素からのオフセット
大きさ
Width Height
scrollWidth   scrollHeight  
clientWidth   clientHeight  
offsetWidth   offsetHeight  
位置
Left Top
offsetLeft   offsetTop  
scrollLeft   scrollTop  

要素を含むドキュメントのスクロール

scrollLeft、scrollTopは書き込みできるプロパティであり、値を設定すると要素を含むドキュメントがスクロールします

scrollTopの値を変更すると、下の要素が移動します。

※ リストの数値は、親要素からのオフセット
number.oninput = number.onchange = function()
{
    element.scrollTop = this.value;
}

element.onscroll = function()
{
    number.value = this.scrollTop;
}
親要素の上端の位置になるように、要素をスクロール

要素の親要素を、その要素の上端位置 (親要素との相対位置) までスクロールします。

elem.parentNode.scrollTop = elem.offsetTop - elem.parentNode.offsetTop;

offsetParent

offsetParentは、要素のオフセットの基準となる要素への参照を返します。HTMLではたいていbody要素が返されますが、例外が多くあります。offsetTop/offsetLeft/offsetParentの闇 - Backstage of theater.js

要素の属性の操作

Element.attributesにより、すべての属性をNamedNodeMapインターフェイスとして取得できます。NamedNodeMap - Web API Interfaces | MDN

属性を操作するメソッド
操作 メソッド
設定※1
void setAttribute( String name, String value );
element.setAttribute - Web API インターフェイス | MDN
取得※1
String getAttribute( String name );
element.getAttribute - Web API インターフェイス | MDN
削除
void removeAttribute( String name );
element.removeAttribute - Web API インターフェイス | MDN
調査
boolean hasAttribute( String name );
element.hasAttribute - Web API インターフェイス | MDN

※1 設定と取得のメソッドは、HTMLの非標準の属性を対象とする場合にのみ使用します。標準の属性ならば、次に示すようにプロパティとしてアクセスできます。

var input = document.createElement( 'input' );

// メソッドでアクセス
input.setAttribute( 'readOnly', '' ); // <input readonly="">
input.removeAttribute( 'readOnly' );  // <input>

// プロパティでアクセス
input.readOnly = true;  // <input readonly="">
input.readOnly = false; // <input>

属性の設定

次の2つは、同一の属性を設定します。

Element.name = value;
Element.setAttribute( name, value );

setAttribute()で設定するvalueは、つねに文字列です。一方で標準の属性をプロパティで設定するときは、そのプロパティによって型が異なります

var input = document.createElement( 'input' );
input.setAttribute( 'disabled', 'disabled' ); // true
input.setAttribute( 'disabled', 'true' );     // true
input.setAttribute( 'disabled', '' );         // true

input.setAttribute( 'disabled', 'false' );    // true
input.setAttribute( 'disabled', false );      // true

input.disabled = false;              // false
input.removeAttribute( 'disabled' ); // false

また属性が設定される順は、ブラウザによって異なります。

var a = document.createElement( 'a' );
a.setAttribute( 'p1', '' );
a.setAttribute( 'p2', '' );
a.setAttribute( 'p3', '' );

alert( a.outerHTML );
// Internet Explorer 11 … <a p1="" p2="" p3=""></a>
// Chrome               … <a p1="" p2="" p3=""></a>
// Firefox              … <a p3="" p2="" p1=""></a>

属性の取得

標準の属性ならば、

var value = Element.name;

とすることで取得できます。一方で非標準の属性はこの方法ではundefinedを返すため、

var value = Element.getAttribute( name );

とします。

属性の削除

属性の内容を削除するだけならば空文字などを代入することで事足りますが、属性自体を削除するにはremoveAttribute()を用います。

var a = document.createElement( 'div' );
var b = document.createElement( 'div' );

a.className = 'A'             // <div class="A"></div>
b.className = 'B'             // <div class="B"></div>

a.className = null;           // <div class="null"></div>
a.className = '';             // <div class=""></div>

b.removeAttribute( 'class' ); // <div></div>

要素の内容の操作 (innerHTML)

innerHTMLプロパティで、要素の内容の取得や設定を行えます。

var markup = element.innerHTML; // 取得
element.innerHTML = markup;     // 設定
element.innerHTML - Web API インターフェイス | MDN

要素のテキストノードに「&」「<」「>」が含まれる場合

HTMLのマークアップに使用される文字「&」「<」「>」の3文字をinnerHTMLから取得すると、文字参照の表記として返されます。これをテキストノードの内容と同じに取得するには、代わりにtextContentを使用する必要があります。

var a = document.createElement( 'div' );
a.innerHTML = '& < >';

alert( a.innerHTML );   // &amp; &lt; &gt;
alert( a.textContent ); // & < >

なお文字参照でinnerHTMLに設定した場合には、textContentはデコードした結果を返します。

var b = document.createElement( 'div' );
b.innerHTML = '&amp; &lt; &gt;';

alert( b.innerHTML );   // &amp; &lt; &gt;
alert( b.textContent ); // & < >

イベントハンドラを含む要素の複製

innerHTMLの戻り値を他の要素のinnerHTMLに設定すると、要素の内容をそのまま複製できます。ただしイベントハンドラは複製されません。これはcloneNode()で要素を複製する場合の挙動と同じです。

var link = document.createElement( 'a' );
link.innerHTML = 'Click';
link.onclick = function() { alert( 'OK' ); };

var a = document.createElement( 'span' );
a.appendChild( link );

var b = document.createElement( 'span' );
b.innerHTML = a.innerHTML;

document.body.appendChild( a );
document.body.appendChild( b );

複製元の要素に続けて、それを複製した要素を並べて表示します。左の要素はクリックに反応しますが、右の要素はそうはならないはずです。

イベントハンドラを含む要素の親要素への設定

親要素の子要素、つまり要素自身を書き換えるとハンドラは無効となります。

var parent = document.body.appendChild( document.createElement( 'p' ) );

var link = document.createElement( 'a' );
link.innerHTML = 'Click';
link.onclick = function() { alert( 'OK' ); };
parent.appendChild(link);

link.innerHTML += 'A';   // 子要素を書き換えても影響はない
parent.innerHTML += 'B'; // 親要素を書き換えるとハンドラは無効となる

Elementオブジェクトの取得

さまざまな条件でDOMからElementを取得できます。

各オブジェクトのElementを取得するメソッド
オブジェクト Elementの特定方法
id属性の値 name属性の値 HTMLのタグ名
Document getElementById - -
HTMLDocument - getElementsByName getElementsByTagName
Element - -

id属性から (getElementById)

Document.getElementById()

IE8より前では、このメソッドはname属性も取得対象となっています。

name属性から (getElementsByName)

Element[] getElementsByName( string elementName );
document.getElementsByName - Web API インターフェイス | MDN

このメソッドが返すElementの配列のようなオブジェクトは、HTMLCollectionです。このオブジェクトは配列のように振る舞いますが、その実体は配列ではないため扱いには注意が必要です。

またgetElementsByName()はHTMLDocumentのメソッドのため、その探索範囲はドキュメント全体となります。

利用例

name属性を対象とするため、たとえば

document.getElementsByName( 'description' )

とすれば、meta要素の

<meta name="description" content="" />

が、HTMLMetaElementオブジェクトとして取得できます。

HTMLタグから (getElementsByTagName)

Element[] getElementsByTagName( string tagName );
element.getElementsByTagName - Web API インターフェイス | MDN

このメソッドもgetElementsByName()と同様、結果をHTMLCollectionオブジェクトで返します。なおtagNameプロパティはHTMLでは大文字ですが、このメソッドの引数のtagName小文字で指定します。

getElementsByTagName()は2つのオブジェクトに実装されています。これらは機能的には同じですが、Elementを探索する範囲が異なります。

  • HTMLDocument.getElementsByTagName() … ドキュメント内のすべて
  • Element.getElementsByTagName() … 指定要素の子孫要素のみ

これらの違いは探索を開始する位置にあり、いずれにしても子孫の要素まですべて探索されることになります。それを次に例示します。

<div id="foo"> <!-- 探索対象のツリー -->
    <ul>
        <li id="a"></li>
        <li id="b">
            <ul>
                <li id="c"></li>
            </ul>
        </li>
    </ul>
</div>

<script type="text/javascript">
  var target = document.getElementById( 'foo' );

  var tag = target.getElementsByTagName( 'li' );
  // HTMLCollection[li#a, li#b, li#c]
</script>

これを直接の子供の要素だけに限定するには、Nodeオブジェクトのプロパティを参照します。

HTMLDocumentには、ドキュメント内の特定のすべての要素を格納するプロパティが用意されています。該当するプロパティがあるならば、こちらを使用する方が簡単です。

イベント

以下のメソッドにより、イベントハンドラの追加や削除を行えます。

操作 メソッド
追加
void addEventListener(
    String type,
    Function listener,
    boolean useCapture
    );
削除
void removeEventListener(
    String type,
    Function listener,
    boolean useCapture
    );
発生
boolean dispatchEvent( Event evt );

Internet Explorer固有のメソッド

Internet Explorerでは上記のメソッドが使用できないため、以下のもので代替します。

操作 メソッド
追加
void attachEvent( String type, Function listener );
削除
void detachEvent( String type, Function listener );

これをクロスブラウザとするためには、実装されているメソッドを確認して使用することになります。