ネイティブの JavaScript を使う

以下は JavaScript(ECMAScript 5/ES5 までの機能)を使った基本的な要素の操作方法(使い方)についての覚書です。

ブラウザの対応状況

参考サイト:

関連ページ:

作成日:2020年4月10日

要素の取得

要素を操作するには、まず要素を取得する必要があります。

以下のような HTML がある場合、クラスが bar の要素を取得するにはいくつかの方法があります。

<ul id="foo">
  <li class="bar">Blue</li>
  <li>Red</li>
  <li class="boo">Green</li>
</ul>

以下はドキュメント(Document)や要素(Element)のメソッドを使って bar クラスの要素を取得する例です。

// まずは id が foo の要素(オブジェクト)を取得
var elem = document.getElementById('foo');
//取得した elem を起点にクラスが bar の要素の集合を取得し、その最初の要素 [0] 
var bar = elem.getElementsByClassName('bar')[0];
alert(bar.textContent); //Blue

//上記は以下のように続けて記述することができます。
var bar = document.getElementById('foo').getElementsByClassName('bar')[0];
alert(bar.textContent);  //Blue

//または、以下のように querySelector() でセレクタを指定して取得することもできます。
var bar = document.querySelector('#foo .bar');
alert(bar.textContent); //Blue

メソッド

ドキュメント(ブラウザーに読み込まれたウェブページ)の要素を取得するには Document オブジェクトや Element オブジェクトのメソッドが使えます。

※ querySelector() 及び querySelectorAll() は他のメソッドに比べて処理速度が遅いです。

メソッド 説明
getElementById() id 属性を指定して要素を取得
getElementsByTagName() タグ名を指定して要素の集まり(HTMLCollection)を取得
getElementsByName() name 属性を指定して要素の集まり(NodeList)を取得
getElementsByClassName() class 属性を指定して要素の集まり(HTMLCollection)を取得
querySelector() セレクタで指定された要素を1つだけ(最初の要素を)取得
querySelectorAll() セレクタで指定された要素の集まり(NodeList)を取得
getElementById

ドキュメント(文書)から指定された ID に一致する要素(Element オブジェク)を取得します。

要素の ID は固有なので、特定の要素にすばやくアクセスすることができます。

var element = document.getElementById(id);

パラメータ
id : 要素の ID(大文字と小文字の区別がある文字列)
戻り値
指定された ID に一致する DOM 要素オブジェクト(Element オブジェクト)。一致する要素がなければ null
// id が foo の要素の文字色を赤に
var elem = document.getElementById('foo');
elem.style.color = 'red';

MDN: getElementById()

getElementsByTagName

指定されたタグ名を持つ要素の集まり(HTMLCollection)を取得します。

但し、WebKit ブラウザーでは NodeList を取得します。

var elements = document.getElementsByTagName(tagName);

var elements = element.getElementsByTagName(tagName)

パラメータ
tagName: タグ名(文字列)。 "*" は全ての要素を表します。
戻り値
見つかった要素の集まり(HTMLCollection、 WebKit ブラウザーでは NodeList)。
//ドキュメント内の p 要素の数をコンソールに出力
var elems = document.getElementsByTagName('p');
//elems(HTMLCollection/NodeList)は配列のようなものなので、length で要素数を取得できます。
console.log(elems.length);

以下は id が foo の要素を取得して、その要素を起点として(Element オブジェクトのメソッド) getElementsByTagName() で li 要素を取得しています。

for 文でそれぞれの要素のテキストの最後に連番を追加しています。item() は引数に指定するインデックスの位置にあるノードを取得します。

また添字 [1] を使って2番目の要素の文字色を赤に指定しています。

<ul id="foo">
  <li>sample</li> <!-- sample 1 に -->
  <li>sample</li> <!-- sample 2 に(赤色) -->
  <li>sample</li> <!-- sample 3 に -->
</ul>

<script>
var elems = document.getElementById("foo").getElementsByTagName("li");
//要素数は length プロパティで取得できます
for(var i = 0; i < elems.length; i++) {
  //各要素のテキストを取得
  var text = elems.item(i).textContent;
  //テキストに番号を追加(例 sample → sample 1 )
  elems.item(i).textContent = text + ' ' + (i + 1);
}
//2番めの要素の色を赤に
elems[1].style.color = 'red';
</script>    

MDN : document.getElementsByTagName()

MDN : element.getElementsByTagName()

getElementsByName

指定した name 属性を持つ要素の集まり(NodeList)を取得します。

var elements = document.getElementsByName(name);

パラメータ
name:要素の name 属性の値
戻り値
指定した name 属性を持つ要素の集まり(NodeList)。 IE10 以前では指定された id 属性を持つ要素も返します。また、IE および Edge では、 NodeList ではなく HTMLCollection を返します。
//name 属性が submit の要素の NodeList を取得
var elems = document.getElementsByName("submit");
//1番めの要素の色を赤に
elems[0].style.color = 'red';
//以下でも同じ
elems.item(0).style.color = 'red';

MDN : document.getElementsByName()

getElementsByClassName

指定されたクラス名を持つすべての要素の集まり(HTMLCollection)を取得します。

document オブジェクトに対して呼び出したときは、ルートノードを含む文書全体が検索され、任意の要素に対して呼び出した場合は、指定されたルート要素下が検索されます。

var elements = document.getElementsByClassName(names);

var elements = element.getElementsByClassName(names);

パラメータ
names:クラス名。複数のクラス名を指定するにはスペースで区切ります。
戻り値
指定した class 属性(クラス名)を持つ要素の集まり(HTMLCollection
//クラス名が bar の要素を取得
var elems = document.getElementsByClassName('bar');
//取得した最初の要素の色を赤に
elems[0].style.color = 'red'; 

//foo クラスと bar クラス(の両方)を持っている全ての要素を取得
var foo_bars = document.getElementsByClassName('foo bar');

MDN : document.getElementsByClassName()

MDN : element.getElementsByClassName()

querySelector

指定されたセレクターに一致する文書内(document)の最初の要素(HTMLElement オブジェク)を取得します。一致するものが見つからない場合は null を返します。

document の代わりに対象の要素(baseElement)のメソッドとして呼び出した場合は、対象要素の子孫の中のマッチする最初の要素を取得します。

var element = document.querySelector(selectors);

var element = baseElement.querySelector(selectors);

パラメータ
selectors:1つまたは複数のセレクターを含む文字列(CSS セレクター)
戻り値
指定された CSS セレクターに最初に一致する要素(HTMLElement オブジェクト)。一致する要素がない場合は null を返します。
//container クラスの div 要素の中の最後の p 要素を赤色に
var elem = document.querySelector('div.container p:last-child');
elem.style.color = 'red'; 

MDN : document.querySelector()

MDN : element.querySelector()

querySelectorAll

指定されたセレクターに一致する文書中の要素の集まり(静的な NodeList)を取得します。

document の代わりに対象の要素(baseElement)のメソッドとして呼び出した場合は、対象要素の子孫の内のマッチする要素の集まり(静的な NodeList)を取得します。

var elementList = document.querySelectorAll(selectors);

var elementList = baseElement.querySelectorAll(selectors);

パラメータ
selectors:1つまたは複数のセレクターを含む文字列。複数のセレクターを指定する場合はカンマで区切ります。
戻り値
指定されたセレクターに一致する要素の集まり(静的な NodeList)。一致するものがなければ空の NodeList
//セレクタ(.content h2)にマッチする h2 要素の最初の要素の文字色を赤に
var matches = document.querySelectorAll(".content h2");
matches[0].style.color = 'red';

以下はマッチする li 要素のテキストを調べて、テキストが「Red」の場合は赤色に、「Blue」の場合は青色にする例です。

<ul id="foo">
  <li>Blue</li> <!-- 青色に -->
  <li>Red</li> <!-- 赤色に -->
  <li>Green</li>
</ul>

<script>
var matches = document.querySelectorAll("#foo li");
for(var i = 0; i < matches.length; i++) {
  var text = matches.item(i).textContent
  if( text === 'Red') {
    matches.item(i).style.color = 'red'; 
  }else if(text === 'Blue') {
    matches.item(i).style.color = 'blue'; 
  }
}  
</script>

MDN: document.querySelectorAll()

MDN: element.querySelectorAll

プロパティ

html や body、form 要素などは Document のプロパティとして定義されています。

Document インターフェイスのプロパティ(一部抜粋)
プロパティ 説明
body 現在の文書の <body>ノード。document.body
documentElement 文書の直接の子である要素(Element)。 HTML 文書では <html> 要素を表す HTMLElement オブジェクト。document.documentElement
forms 現在の文書の <form> 要素のリスト(HTMLCollection)。document.forms
head 現在の文書の <head> 要素。document.head
images 現在の文書の画像のリスト。document.images
links 文書内のすべてのハイパーリンクのリスト。document.links
scripts 文書内のすべての <script> 要素。document.scripts
selectedStyleSheetSet 現在使用されているスタイルシートセットの名前。document.selectedStyleSheetSet
styleSheetSets 文書で使用できるスタイルシートセットのリスト。document.styleSheetSets
form 要素

forms プロパティは読み取り専用で、文書内に含まれる全ての <form> 要素の集合(HTMLCollection)を返します。

また、 フォーム要素の elements プロパティを使用すると、form 要素に含まれるフォームコントロール(部品)にアクセスすることができます。

<form id="first_form" name="foo">
  <input type="text" value="">
</form>

<form id="second_form" name="bar">
  <input name="email" type="email" placeholder="info@example.com">
  <input name="password" type="password">
  <button type="submit">Submit</button>
</form>

<script>
//インデックスを指定してフォーム要素を取得して、その id の値を表示
console.log(document.forms[0].id);  //first_form
console.log(document.forms[1].id);  //second_form

//name 属性でフォーム要素を取得(アクセス)することもできます。
console.log(document.forms.foo.id);  //first_form
console.log(document.forms['foo'].id); //first_form

//name 属性が bar のフォーム要素を取得
var bar_form = document.forms.bar;

//フォーム要素の elements プロパティで name 属性が email の要素の placeholder 属性を取得
console.log(bar_form.elements.email.placeholder);  //info@example.com

</script>

HTMLCollection

HTMLCollection は HTML 要素(element オブジェクト)の集まりから成る配列のようなオブジェクトで、各要素にはインデックス番号でアクセスできます。

配列のようなオブジェクトとは length プロパティとインデックス付けされた要素を持つオブジェクトのことです。(参考ページ:Array-likeオブジェクト

また、HTMLCollection は元になった document が変更された時点で自動的に更新される(DOM に対する変更がリアルタイムで反映される)ライブオブジェクトです。

HTMLCollection は以下のプロパティとメソッドを提供します。

HTMLCollection のプロパティとメソッド
プロパティ 説明
length HTMLCollection に含まれる要素数(アイテム数)
メソッド 説明
item() 指定された index (先頭はゼロ) 位置にある特定の要素を返します。index が範囲外なら null を返します。添字 [ i ] を使っても要素にアクセスできます。
namedItem() 指定した文字列(id または name 属性)が一致する要素を返します。指定した要素がない場合は null を返します。

MDN: HTMLCollection

例えば、getElementsByClassName() の戻り値は HTMLCollection です。

<p class="foo">Foo 1</p>  <!-- 赤色に -->
<p class="foo">Foo 2</p>  <!-- 青色に -->
<p class="foo">Foo 3</p>
</body>
<script>
//クラス foo の要素(HTMLCollection)を取得
var elems = document.getElementsByClassName('foo');
//取得した要素(HTMLCollection)の数をコンソールに出力
console.log('length: ' + elems.length);  //length:3
//インデックス(添字)を使って1番目の要素にアクセス
elems[0].style.color = 'red'; 
//item() メソッドを使って2番めの要素にアクセス
elems.item(1).style.color = 'blue'; 
</script> 

HTMLCollection の各要素について処理を順次適用するには、以下のように for 文を使うことができます。

<div class="bar">Div</div>
<h3 class="bar">Heading</h3>
<p class="bar">Paragraph</p>

<script>
//クラス bar の要素(HTMLCollection)を取得
var collection = document.getElementsByClassName('bar');

//length プロパティで要素数を取得して各要素について処理
for (var i = 0; i < collection.length; ++i) {
  var item = collection[i];  //または collection.item(i)
  console.log(item);
} 
</script> 

<!-- 以下が出力結果
<div class="bar">Div</div>
<h3 class="bar">Heading</h3>
<p class="bar">Paragraph</p>
-->

但し、for...in や for each...in は使えません。

HTMLCollection の各要素に加えて他のプロパティやメソッドについても処理が適用されるため、要素(element オブジェクト)のみ処理すべきスクリプトではエラーが発生します。また、for..in で取得されるプロパティの順番は保証されていません。

<div class="bar">Div</div>
<h3 class="bar">Heading</h3>
<p class="bar">Paragraph</p>

<script>
//クラス bar の要素(HTMLCollection)を取得
var collection = document.getElementsByClassName('bar');

//for..in で各要素について処理(要素以外のメソッドやプロパティも処理が適用される)
for(var i in collection) {
  var node = collection.item(i);
  console.log( i + "番目: nodeType: " + node.nodeType + " nodeName: " + node.nodeName );
}
</script> 

<!-- 以下が出力結果
0番目: nodeType: 1 nodeName: DIV
1番目: nodeType: 1 nodeName: H3
2番目: nodeType: 1 nodeName: P
length番目: nodeType: 1 nodeName: DIV  ★ length プロパティ
item番目: nodeType: 1 nodeName: DIV  ★ item メソッド
namedItem番目: nodeType: 1 nodeName: DIV  ★ namedItem メソッド
-->

ES6 (ES2015) 以降であれば(IE を対象外にすれば)、for of 文を使って簡潔に記述することもできます。

NodeList

NodeList は配列のような DOM 要素(ノード)の集合を表すオブジェクトです。Node.childNodes などのプロパティや document.querySelectorAll() メソッドの戻り値は NodeList オブジェクトです。

配列のようなオブジェクトとは length プロパティとインデックス付けされた要素を持つオブジェクトのことです。

但し、Node.childNodes のプロパティは元になった document が変更された時点で自動的に更新される(DOM に対する変更がリアルタイムで反映される)ライブオブジェクトですが、querySelectorAll() は静的な(DOM 内の変更が内容に影響を与えない)NodeList オブジェクトを返します。

NodeList は以下のようなプロパティとメソッド(以下は一部)を提供します。

NodeList のプロパティとメソッド(一部抜粋)
プロパティ 説明
length NodeList に含まれる要素数(アイテム数)
メソッド 説明
item() 指定された index (先頭はゼロ) 位置にある特定の要素を返します。index が範囲外なら null を返します。nodeList[i] のアクセスの代替手段です 。
forEach() 指定された関数を NodeList の各要素に対して実行します。関数の引数には以下の三つの引数が与えられます。
  • elem:現在処理中の要素
  • index:現在処理中の要素のインデックス
  • listObj:forEach() メソッドを実行している NodeList

MDN: NodeList

例えば、querySelectorAll() の戻り値は NodeList です。

<p class="foo">Foo 1</p>  <!-- 赤色に -->
<p class="foo">Foo 2</p>  <!-- 青色に -->
<p class="foo">Foo 3</p>
</body>
<script>
//クラス foo の要素(NodeList)を取得
var nodeList = document.querySelectorAll('.foo');
//取得した要素(NodeList)の数をコンソールに出力
console.log('length: ' + nodeList.length);  //length:3
//インデックス(添字)を使って1番目の要素にアクセス
nodeList[0].style.color = 'red'; 
//item() メソッドを使って2番めの要素にアクセス
nodeList.item(1).style.color = 'blue'; 
</script> 

NodeList の各要素について処理を順次適用するには HTMLCollection 同様、以下のように for 文を使うことができます。

<div class="bar">Div</div>
<h3 class="bar">Heading</h3>
<p class="bar">Paragraph</p>

<script>
//クラス bar の要素(NodeList)を取得
var nodeList = document.querySelectorAll('.bar');
 
//length プロパティで要素数を取得して各要素について処理
for (var i = 0; i < nodeList.length; ++i) {
  var node = nodeList[i];  //または nodeList.item(i)
  console.log(node);
}
</script> 

<!-- 以下が出力結果
<div class="bar">Div</div>
<h3 class="bar">Heading</h3>
<p class="bar">Paragraph</p>
-->

但し、for...in や for each...in は使えません。

また 、反復処理を forEach や ES6 (ES2015) 以降であれば(IE を対象外にすれば)for of 文を使って簡潔に記述することもできます。

以下は for of 文(ES6)を使って前述と同じことをしています。HTMLCollection でも可能です。

for of 文
//クラス bar の要素(NodeList)を取得
var nodeList = document.querySelectorAll('.bar');
// for of 文
for (var elem of nodeList) {
  console.log(elem);  //前述と同じ出力結果
}

以下は NodeList のメソッド forEach を使って取得した要素のインデックスとノード名(nodeName)を出力する例です。

//クラス bar の要素(NodeList)を取得
var nodeList = document.querySelectorAll('.bar');
// forEach メソッドで引数に要素とインデックス番号を受け取る場合
nodeList.forEach(function(elem, index) {
  console.log(index + ': ' + elem.nodeName);
});

//出力結果
0: DIV
1: H3
2: P

ノードウォーキング

ある要素を基点にその子要素、親要素、兄弟要素などの相対的な位置関係から取得することもできます。

以下のような HTML がある場合

<body>
<div id="foo">
  <h3>Foo</h3>
  <p id="first">first</p>
  <p id="second">second</p>
  <div id="bar">
    <h4>Bar</h4>
    <p id="third">third</p>
    <p id="fourth">fourth</p>
  </div><!-- end of #bar -->
</div><!-- end of #foo -->
</body>

以下は親要素や親ノードを取得する例です。.id は要素の id 属性を返す Element のプロパティです。

parentNode や parentElement プロパティを使って親の要素を取得することができます。

closest() メソッドは引数で指定した親ノードを取得できますが、IE には対応していません。

//#first の親ノードを取得
var parent_first = document.getElementById('first').parentNode; 
console.log(parent_first.id);  //foo

//#third の親要素を取得
var parent_third = document.getElementById('third').parentElement; 
console.log(parent_third.id);  //bar

//#third の引数で指定した親ノードを取得(IE 未対応)
var closest =  document.getElementById('third').closest('#foo');
console.log(closest.id);   //foo

//parentNode と parentElement の違い
var html = document.body.parentNode;
//または var html = document.body.parentElement; でも同じ
console.log(html.parentNode); // #document
console.log(html.parentElement); // null

parentNode と parentElement の違いは「ノードを返すか要素を返すか」で、html でこのプロパティを使うと、parentNode の場合は document が返りますが、parentElement の場合は(document は要素ではないので)null が返ります。

以下は子要素や子ノードを取得する例です。

相対的な位置関係でノードを取得する場合に注意する必要があるのは、空白や改行もテキストノードとして扱われる点です。HTML を記述する際は、通常可読性を考えてタグごとに改行を入れますが、その場合改行の箇所にテキストノードが存在することになります。

この例の場合、<div id="foo"> の後に改行が入っているので、firstChild で取得されるのは改行のテキストノードになります。<div id="foo"> と <h3>Foo</h3> の間に改行がなければ結果は異なります。

<body>
<div id="foo">
  <h3>Foo</h3>
  <p id="first">first</p>
  <p id="second">second</p>
  <div id="bar">
    <h4>Bar</h4>
    <p id="third">third</p>
    <p id="fourth">fourth</p>
  </div><!-- end of #bar -->
</div><!-- end of #foo -->
</body>
//最初の子ノードを取得
var foo_fc = document.getElementById('foo').firstChild;
console.log(foo_fc); // #text(改行のテキストノード)
console.log(foo_fc.nodeType); //3(TEXT_NODE)

//最初の子要素を取得
var foo_fec = document.getElementById('foo').firstElementChild;
console.log(foo_fec);  //<h3>Foo</h3>
console.log(foo_fec.nodeType);  //1(ELEMENT_NODE)

var foo = document.getElementById('foo');
//全ての子ノード要素の最初のノード
console.log(foo.childNodes[0]); // #text(改行のテキストノード)
//全ての子要素の最初の要素
console.log(foo.children[0]); //<h3>Foo</h3>

以下は兄弟要素(ノード)などを取得する例です。ノードを取得する場合は空白、改行、コメントもテキストノードとして扱わます。

また、要素(ノード)には meta タグや script タグも含まれます。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Samples</title>
</head>
<body>
<div id="foo">
  <h3>Foo</h3>
  <p id="first">first</p>
  <p id="second">second</p>
  <div id="bar">
    <h4>Bar</h4>
    <p id="third">third</p>
    <p id="fourth">fourth</p>
  </div><!-- end of #bar -->
</div><!-- end of #foo -->
</body>
<script>
・・・
</script>
</html>
// #second の兄弟ノードと要素の取得
var elem = document.getElementById('second');
console.log(elem.nextSibling);  //#text(改行)
console.log(elem.nextElementSibling); //<div id="bar">・・・</div>

console.log(elem.previousSibling);    //#text(空白)
console.log(elem.previousElementSibling);  //<p id="first">first</p>

// #foo の兄弟ノードと要素の取得
var foo = document.getElementById('foo');
console.log(foo.nextSibling);  //<!-- end of #bar -->(コメント)
console.log(foo.nextSibling.nodeType);   // 8(COMMENT_NODE)
console.log(foo.nextElementSibling);  //<script>・・・</script>

// head タグの最初の子要素を取得する例
var head_fec = document.getElementsByTagName('head')[0].firstElementChild;
console.log(head_fec); //<meta charset="utf-8">

以下は相対的な位置関係を使ってノードや要素を取得する場合に利用できるプロパティです。

Node プロパティ

ドキュメントを構成する要素や属性、テキストなどのオブジェクトをノード(Node)と呼び、ノードには、要素ノード、テキストノード、属性ノードなどがあります。

ノードには以下のようなプロパティが提供されています。

Node インターフェイスのプロパティ(MDN : Node
プロパティ
(参照)
取得するノードや要素
parentNode このノードの親ノード(存在しない場合は null)
parentElement このノードの親要素 Element(存在しない場合は null)
childNodes このノードの全ての子孫を含む NodeList(ライブオブジェクト)
firstChild ノードの直下の最初の子ノード(存在しない場合は null)
lastChild ノードの直下の最後の最後の子ノード(存在しない場合は null)
previousSibling ツリー構造で1つ前の兄弟ノード(存在しない場合は null)
nextSibling ツリー構造で次の兄弟ノード(存在しない場合は null)
プロパティ
(その他)
説明
nodeName Node の名前(名前の構造はノードの型によって異なります)
nodeValue ノードの値を取得または設定
textContent 要素のテキストコンテンツを取得または設定
nodeType ノードの型を表す値(数値)
  • ELEMENT_NODE : 1
  • ATTRIBUTE_NODE : 2(非推奨)
  • TEXT_NODE : 3
  • PROCESSING_INSTRUCTION_NODE : 7
  • COMMENT_NODE : 8
  • DOCUMENT_NODE : 9
  • DOCUMENT_TYPE_NODE : 10
  • DOCUMENT_FRAGMENT_NODE : 11

また、空白ノードやコメントノードを除外して要素だけを取得するための以下のようなプロパティが提供されています。

ParentNode のプロパティ(MDN : ParentNode
プロパティ 説明
childElementCount 子要素の数を返します。
children 空白ノードやコメントノードを除外した全ての子要素(Element)を含むリスト HTMLCollection(ライブオブジェクト)を返します。
firstElementChild 最初の子要素(Element)を返します。存在しない場合は null
lastElementChild 最後の子要素(Element)を返します。存在しない場合は null

以下の兄弟要素への参照のプロパティも使えます。

NonDocumentTypeChildNode(Element プロパティ)
プロパティ 説明
previousElementSibling 1つ前の兄弟要素を返します。存在しない場合は null
nextElementSibling 次の兄弟要素を返します。存在しない場合は null

Element の closest() メソッドも使うことができます。※但し、IE には対応していません。

Element メソッド(MDN:Element
メソッド 説明
closest() 引数で指定されたセレクターに一致する現在の要素の最も近い祖先要素 (または現在の要素自身) を返します。存在しない場合は null

要素の操作

要素を操作する場合、Element や HTMLElement などのプロパティやメソッドを使うことができます。

Element のプロパティ・メソッド

Element は Document の中にある全ての要素オブジェクトが継承するクラス(インターフェイス)です。

Element プロパティ 抜粋(MDN:Element
プロパティ 説明
attributes 要素に関連したすべての属性のリスト NamedNodeMap(ライブオブジェクト)
classList class 属性のリスト(ライブオブジェクト)を返します。読み取り専用ですがそのリスト(DOMTokenList)のメソッドの add() や remove() で変更できます。
className 要素のクラス
clientHeight 要素の内部の高さ(パディングは含むが、ボーダー、マージン、 垂直スクロールバーは含まない)
clientWidth 要素の内部の幅(パディングは含むが、ボーダー、マージン、 垂直スクロールバーは含まない)
id 要素の id
innerHTML 要素内容のマークアップ
outerHTML その要素を内容に含むマークアップ
scrollTop 文書の上端が垂直方向にスクロールされた量(要素の内容が垂直にスクロールするピクセル数を取得または設定)
tagName 要素のタグ名。タグ名は大文字で表現されます。div 要素なら DIV、p 要素なら P になります。
Element メソッド 抜粋(MDN:Element
メソッド 説明
addEventListener() 要素にイベントハンドラーを登録。書式は target.addEventListener(type, listener[, options]) 。対象(target)は Element, Document, Window, XMLHttpRequest など。type はイベントの種類。listener は関数など。
dispatchEvent() 特定の EventTarget に Event をディスパッチ(送る)
getAttribute() 指定された名前の付いた属性値を取得してそのオブジェクトを返す
getAttributeNames() 要素の属性名の配列を返す
hasAttribute() 指定された指定された属性を持っているか否かを示す真偽値を返す
insertAdjacentElement() 指定した位置に要素ノードを挿入
insertAdjacentHTML() 指定した位置に HTML を挿入
insertAdjacentText() 指定した位置にテキストノードを挿入
removeAttribute() 指定された名前を持つ属性を削除。element.removeAttribute(属性名)
removeEventListener() EventTarget から登録されたイベントリスナーを削除。target.removeEventListener(type, listener[, options]);
setAttribute() 指定された名前を持つ属性値を設定。element.setAttribute(属性名, 値)

HTMLElement のプロパティ・メソッド

HTML 要素は HTMLElement インターフェイスを実装しているので、以下のようなプロパティやメソッドを使うことができます。

HTMLElement のプロパティ 抜粋(MDN:HTMLElement
プロパティ 説明
hidden 要素が hidden か否かを示す真偽値
innerText ノードやその子孫のテキストの内容
style 要素のインライン style の値。全ての CSS プロパティの値を取得するには window.getComputedStyle() を使用します。
tabIndex 要素の tabIndex の値
title 要素のタイトル
HTMLElement のメソッド 抜粋(MDN:HTMLElement
メソッド 説明
blur() 現在フォーカスされている要素からキーボードフォーカスを外す
click() 要素にマウスクリックイベントを送信
focus() 要素にキーボードフォーカスを当てる

属性の操作

多くの属性は以下のように、要素の属性名のプロパティとしてアクセス及び設定することができます。

但し、属性名とプロパティ名が一致していない場合もあり、クラス属性は HTML では class ですが、DOM プロパティでは className になります。

<a id="foo" href="http://example.com" target="_blank" rel="noopener" title="Link Title" class="sample external">Sample link</a>

<script>
  var link = document.getElementById('foo');
  console.log(link.id); // foo
  console.log(link.href); // http://example.com/
  console.log(link.target); //_blank
  console.log(link.rel); //noopener
  console.log(link.title); //Link Title
  //class の場合は className
  console.log(link.className); //sample external
  
  //target を変更
  link.target = '_self';
  console.log(link.target); //_self
</script>

setAttribute() / getAttribute()

Element のメソッド setAttribute() と getAttribute() を使うと、属性名とプロパティ名の違いを意識することなく属性の値を取得・変更することができます。

また、属性を削除するには removeAttribute() を、属性が指定(設定)されているかを確認するには hasAttribute() を使います。

//属性値の取得
element.getAttribute(属性名)
//属性値の設定
element.setAttribute(属性名, 属性値)
//属性の削除
element.removeAttribute(属性名)
//指定された属性が設定されているかを確認
element.hasAttribute(属性名)
<a id="foo" href="http://example.com" target="_blank" rel="noopener" title="Link Title" class="sample external" data-icon="external">Sample link</a>

<img id="bg_img" src="images/bg-img.jpg" alt="" data-bgposition="center center" data-no-retina>

<script>
  //#foo の要素を取得して変数 link に代入
  var link = document.getElementById('foo');
  //クラス名を取得
  var class_name = link.getAttribute('class');
  //クラス名を出力
  console.log(class_name); //sample external
  
  //クラス名を設定(変更)
  link.setAttribute('class', 'sample internal');
  
  //target 属性を設定(変更)
  link.setAttribute('target', '_self');
  
  //data-icon 属性を設定(変更)
  link.setAttribute('data-icon', 'internal');
  
  //rel 属性を削除
  link.removeAttribute('rel');
  
  //属性値を出力(確認)
  console.log(link.getAttribute('class')); //sample internal
  console.log(link.getAttribute('target')); //_self
  console.log(link.getAttribute('data-icon')); //internal
  console.log(link.getAttribute('rel')); //null(削除されている)
  
  //#bg_img の要素を取得して変数 img に代入
  var img = document.getElementById("bg_img");
  
  //要素に data-no-retina 属性が設定されていれば
  if(img.hasAttribute('data-no-retina')) {
    //data-bgposition を変更(設定)
    img.setAttribute('data-bgposition', 'top center');
  }
  
  //変更した属性値を出力
  console.log(img.getAttribute('data-bgposition'));

</script>

クラスの操作

class 属性の値を設定(変更)する場合は、className プロパティを使うことができますが、クラスの追加や削除などは classList プロパティを使うと便利です。

classList はその要素に設定されているクラスのリストを返します。このリストは変更がリアルタイムで反映されるライブオブジェクトで、読み取り専用ですが提供されているメソッドで変更できます。

以下が classList(DOMTokenList)で使用できるプロパティやメソッドです。

classList(DOMTokenList)のプロパティとメソッド(一部抜粋)
プロパティ 説明
length リストに格納されているオブジェクトの数(指定されているクラスの数)
value リスト(クラス)の値の文字列
メソッド 説明
add() クラスの追加
contains() 指定された値がクラスに含まれていれば true を、含まれていなければ false を返す
remove() クラスの削除
replace() 指定したクラス(old)を指定した値(new)に置き換え replace(old, new);
toggle() クラスの切り替え。指定されたクラスが存在すれば、そのクラスを削除して false を返し、指定されたクラスが存在しなければ、追加して true を返す。

以下は classList プロパティを使ってクラスの追加や切り替え、削除などを行う例です。

<p id="foo" class="text-black">Foo Bar</p> 

<script>
  //#foo の要素のクラスのリスト(ライブオブジェクト)を変数に代入
  var foo_class = document.getElementById('foo').classList;
  
  //sample クラスを追加
  foo_class.add('sample');
  
  //クラス(toggle-class)の切り替え(存在しないので追加)
  foo_class.toggle('toggle-class');
  console.log(foo_class.value);  //text-black sample toggle-class
  
  //クラス(toggle-class)の切り替え(存在するので削除)
  foo_class.toggle('toggle-class');
  console.log(foo_class.value);  //text-black sample
  
  //sample クラスを production に変更
  foo_class.replace('sample', 'production');
  
  //text-black クラスを削除
  foo_class.remove('text-black');
  
  //クラスが指定されているかの確認
  if(foo_class.contains('production')) {
    console.log('production exist!');  //production exist!
  }
  
  //クラスを出力
  console.log(foo_class.value);  //production
</script>

スタイルの操作

JavaScript で直接ドキュメントのスタイルを設定する場合、基本的にインラインスタイルを設定します。

スタイルを操作(設定)する代わりに、スタイル用のクラスを適宜スタイルシートで定義してそのクラス属性の値をスクリプトから制御(動的に変更)することもできます。また、CSSStyleSheet インターフェイスを使えばスタイルシートを操作できます。

スタイルを設定

style プロパティは、HTMLElement のプロパティとして提供されていて、CSSStyleDeclaration オブジェクトを返します。

スタイルを設定するには、style プロパティの個々のプロパティ名(color など)に対して値を設定します。値は文字列で設定するので引用符で囲みます。

// 要素(element)にスタイルを設定
element.style.スタイルプロパティ名 = "値";
          
// #foo の要素の文字色を赤に設定する例
document.getElementById('foo').style.color = 'red';

値に null を設定することでリセットすることができます。

<p id="foo" style="color:green;">Foo</p> 

<script>
//インラインスタイルをリセット(文字色はデフォルトの色で表示される)
document.getElementById('foo').style.color = null;
</script>
スタイルのプロパティ名

CSS のスタイルのプロパティ名にはハイフンが含まれるものがありますが、JavaScript ではハイフンはマイナス記号と解釈されるため、ハイフンを含む場合はキャメルケース(ハイフンを削除し、次の頭文字を大文字に)に書き換える必要があります。setProperty() メソッドを使えば、CSS のプロパティ名のまま指定できます。

//font-size は fontSize に書き換える
document.getElementById('foo').style.fontSize = '24px';

//setProperty() メソッドを使う場合
document.getElementById('foo').style.setProperty('font-size', '24px');

また float という単語は JavaScript では予約語となっているため、cssFloat というプロパティ名になります。JavaScript でアクセスできる CSS のプロパティ名は以下のリンクで確認することができます。

MDN : CSS プロパティリファレンス

CSSStyleDeclaration インターフェース

style プロパティで返される値は CSSStyleDeclaration オブジェクトです。

CSSStyleDeclaration インターフェースには以下のようなプロパティとメソッドがあります。

CSSStyleDeclaration
プロパティ 説明
cssText CSS 設定のテキスト(例 color: red;)
length プロパティの数(読み取り専用)
個々のプロパティ
例:fontSize
個々の CSS プロパティ名(ハイフンを含む場合はキャメルケース)。style.color や style.fontSize でアクセスできます(前述の例)
メソッド 説明
item() 指定された index (先頭はゼロ) 位置にあるプロパティ名を返します。index が範囲外なら空文字を返します。添字 [ i ] を使ってもアクセスできます(i が範囲外なら undefined を返します)。
getPropertyValue() CSS プロパティ名を指定して設定されている値を取得。CSS でのプロパティ名を指定。例: getPropertyValue('font-size')
setProperty() CSS プロパティ名を指定して値を設定。CSS でのプロパティ名を指定。例:setProperty('font-size', '24px')
removeProperty() CSS プロパティ名を指定してプロパティを削除。CSS でのプロパティ名を指定。例:removeProperty('font-weight')

上記のプロパティやメソッドを使ってもスタイルを設定することができます。

以下は cssText プロパティを使って設定を変更する例です。cssText プロパティを使う場合は、一部のみを変更することはできず設定を全て記述する必要があるので注意が必要です。

<p id="foo" style="color:green; font-size:30px;">Foo</p>

<script>
//style プロパティを取得
var fooStyle = document.getElementById('foo').style;
// CSS の設定(テキスト)を確認
console.log(fooStyle.cssText);  //color: green; font-size: 30px;
// CSS を設定(※ font-size を記述していないので、font-size の設定は消える)
fooStyle.cssText = 'color : orange;'
// CSS の設定(テキスト)を確認 
console.log(fooStyle.cssText);  //color : orange; 
</script>
  

以下は setProperty() を使って特定の CSS を設定したり、removeProperty() を使って特定の CSS の設定を削除する例です。この場合、CSS のプロパティ名は、CSS の記述方法で指定し、キャメルケースに変換する必要はありません。

<p id="foo" style="color:green; font-size:30px;">Foo</p>

<script>
//style プロパティを取得
var fooStyle = document.getElementById('foo').style;
//font-size を設定(変更)
fooStyle.setProperty('font-size', '24px');
//font-size の設定を確認
console.log(fooStyle.getPropertyValue('font-size')); //24px
//font-weight を !important を指定して設定(追加)
fooStyle.setProperty('font-weight', 'bold', 'important');
//color を削除
fooStyle.removeProperty('color');
// CSS の設定(テキスト)を確認 
console.log(fooStyle.cssText); //font-size: 24px; font-weight: bold !important;
</script>

以下は setProperty() の書式です。priority はオプションで、「important」を指定することができます。

style.setProperty(CSS プロパティ名, 値, priority);
スタイルを取得

設定されているインラインスタイルは「style.スタイルプロパティ名」や「style.cssText」、メソッド style.getPropertyValue('プロパティ名') を使って取得することができます。

<p id="foo" style="color:green; font-size:18px; font-weight:bold;">Foo</p>

<script>
//style プロパティを取得
var fooStyle = document.getElementById('foo').style;

//style.スタイルプロパティ名
console.log(fooStyle.color);  //green
console.log(fooStyle.fontSize);  //18px
console.log(fooStyle.fontWeight);  //bold

// style.getPropertyValue() 
console.log(fooStyle.getPropertyValue('color'));  //green
console.log(fooStyle.getPropertyValue('font-size'));  //18px
console.log(fooStyle.getPropertyValue('font-weight'));  //bold

//style.cssText
console.log(fooStyle.cssText);  //color: green; font-size: 18px; font-weight: bold;

//プロパティ名を style[i] または style.item(i) で取得
for (var i = 0; i < fooStyle.length; ++i) {
  var prop = fooStyle[i]; //または  fooStyle.item(i); 
  console.log(prop + ':' + fooStyle.getPropertyValue(prop));
}

/* 上記 for 文の出力
color:green
font-size:18px
font-weight:bold 
*/
</script>

但し、要素の style プロパティは、要素のインラインスタイル(style 属性)で設定された内容しか表していないため、適用されているススタイルシートや継承されたスタイルなどの情報は含まれていません。

要素に適用されている全ての CSS プロパティの値を取得するには、代わりに getComputedStyle() メソッドを使うことができます。

getComputedStyle() メソッドは、要素の算出スタイル(Computed Style)を取得するための API で Window オブジェクトのメソッドです。

getComputedStyle

window.getComputedStyle() はその要素のアクティブなスタイルを適用して算出したすべての CSS プロパティの値を含む(読み取り専用の)オブジェクトを返します。

var style = window.getComputedStyle(element,pseudoElt);

パラメータ
  • element:スタイルを調べる要素を指定
  • pseudoElt:疑似要素を調べる場合に指定。通常の要素には空文字列(または null)を指定。(省略可能)
戻り値
指定された要素の算出済みの CSS プロパティの値を含む読み取り専用の CSSStyleDeclaration オブジェクト。要素のスタイル(外部スタイルシート及びインライン等)が変更されると自動的に更新されます。
//以下は id 属性が foo の要素のフォントサイズの算出スタイルを取得する例
//#foo の要素を取得
var foo = document.getElementById('foo');
//#foo の算出スタイルを取得
var fooStyle = window.getComputedStyle(foo);
//#foo の算出スタイルの font-siz を出力
console.log(fooStyle.fontSize);
//以下でも同じ
console.log(fooStyle.getPropertyValue('font-size'));

MDN: window.getComputedStyle()

以下は id 属性が foo の p 要素の算出スタイルを取得する例です。

取得した算出スタイルは CSSStyleDeclaration のプロパティやメソッドが使えます。

以下の例では外部スタイルシートは使っていませんが、読み込んでいればそれらの値も含めて算出されたスタイルが取得できます。

<html>
<head>
<style>
p {
  font-size: 16px !important;
  color: #333;
}
</style>
</head>
<body>
<div style="background-color: #efefef;">
  <p id="foo" style="color:green; font-size:18px;">Foo</p>
</div>
</body>
<script>
// id 属性が foo の p 要素の算出スタイルを取得
var fooStyle = window.getComputedStyle(document.getElementById('foo'));

// 文字色を取得して出力
console.log(fooStyle.color); //rgb(0, 128, 0) → green(インラインの値)

// フォントサイズを取得(5行目の 16px !important が適用されている)
console.log(fooStyle.fontSize); //16px

// 背景色を取得(設定していないのでブラウザのデフォルト値)
console.log(fooStyle.backgroundColor);  //rgba(0, 0, 0, 0) 透過(ブラウザのデフォルト値)

// getPropertyValue() で font-weight を取得(ブラウザのデフォルト値)
console.log(fooStyle.getPropertyValue('font-weight')); //400

// マージンを取得(ブラウザのデフォルト値)
console.log(fooStyle.margin); //16px 0px
</script>
</html>

算出スタイルはブラウザのデベロッパーツールの「Computed」タブで表示される値です。

以下は id 属性が foo の要素の算出スタイルを全て出力する例です。

各プロパティ名には CSSStyleDeclaration の item() メソッドまたは添字にインデックスを指定してアクセスすることができます。

//id 属性が foo の要素の算出スタイルを取得
var fooStyle = window.getComputedStyle(document.getElementById('foo'));

//取得した算出スタイルの全てのプロパティ名を for 文で出力(総数は .length で取得)
for (var i = 0; i < fooStyle.length; ++i) {
  //プロパティ名を prop に代入
  var prop = fooStyle[i]; //または fooStyle.item(i); 
  console.log(prop + ':' + fooStyle.getPropertyValue(prop));
}

/*以下は出力例です。
animation-delay:0s
animation-direction:normal
animation-duration:0s
animation-fill-mode:none
animation-iteration-count:1
animation-name:none
animation-play-state:running
animation-timing-function:ease
background-attachment:scroll
background-blend-mode:normal
background-clip:border-box
background-color:rgba(0, 0, 0, 0)
background-image:none
background-origin:padding-box
background-position:0% 0%
background-repeat:repeat
background-size:auto
border-bottom-color:rgb(0, 128, 0)
border-bottom-left-radius:0px
border-bottom-right-radius:0px
border-bottom-style:none
border-bottom-width:0px
border-collapse:separate
・・・以下省略・・・
*/

テキストの操作

textContent

要素のテキストを取得・設定するには Node インターフェイスのプロパティ textContent が使えます。

textContent プロパティは子要素も含めたテキスト部分を取得します。以下のようにインラインスタイル(display: none)で非表示にしている部分も取得されます。

<div id="foo">
  <h3>Title</h3>
  <div><p>This is a sample text.</p></div>
  <p style="display: none;">No Display</p>
</div>

<script>
console.log(document.getElementById('foo').textContent);  
/*
以下が取得したテキストの出力結果

Title
This is a sample text.
No Display
*/
</script>

textContent プロパティを設定すると、子要素は全て削除され、テキストノードに置き換わります。

<div id="foo">
  <h3>Title</h3>
  <div><p>This is a sample text.</p></div>
  <p style="display: none;">No Display</p>
</div>
<p id="bar">ID: <strong>bar</strong> text</p>

<script>
document.getElementById('foo').textContent = 'New Text Content!'; 
document.getElementById('bar').textContent = 'New Bar!'; 
</script>

<!-- 上記 HTML は以下に置き換わります  -->
<div id="foo">New Text Content!</div>
<p id="bar">New Bar!</p>

値に HTML 文字列を指定してもそれらはエスケープされてタグは作成されません。外部からの入力などを出力する場合、XSS 攻撃を防ぐことができます。

<div id="foo"></div>

<script>
document.getElementById('foo').textContent = '<p>Sample</p>';  
</script>
<!-- HTML 文字列は以下のようにエスケープされます  -->
<div id="foo">&lt;p&gt;Sample&lt;/p&gt;</div>

HTMLElement インターフェイスのプロパティ innerText でも要素のテキストを取得(及び設定)することができますが、innerText はスタイルを反映するので「非表示」の要素のテキストを取得しません。

innerHTML

Element クラスのプロパティ innerHTML を使うと、その要素の子要素を表す HTML テキスト文字列を取得できます。

また、outerHTML は、要素とその子孫を含む部分の HTML テキスト文字列を取得します。

<div id="foo">
  <h3>Title</h3>
  <p>This is a sample text.</p>
</div>

<script>
console.log(document.getElementById('foo').innerHTML);  
console.log(document.getElementById('foo').outerHTML); 
/*
//innerHTML(7行目)の出力結果
<h3>Title</h3>
<p>This is a sample text.</p>

//outerHTML(8行目)の出力結果
<div id="foo">
  <h3>Title</h3>
  <p>This is a sample text.</p>
</div>
*/
</script>

innerHTML プロパティに値を設定すると、指定された文字列をパースし、解析結果をその要素の子要素に設定します。

<div id="foo"></div>

<script>
document.getElementById('foo').innerHTML = '<p><strong>sample</strong></p>';  
</script>

<!-- 上記 HTML は以下のようになります  -->
<div id="foo"><p><strong>sample</strong></p></div>

※外部からの入力など制御できない文字列を innerHTML を使って挿入するのはセキュリティリスクが発生するので注意が必要です。外部からの入力などを挿入する場合は innerHTML を使用せず、代わりに textContent を使用します。

また、+= 演算子を使って innerHTML プロパティに少しずつテキストを追加していくのは、あまり効率的ではないようです。

要素の作成・追加

要素は createElement() メソッドを使って作成し、必要に応じて属性を設定します。表示するテキストは createTextNode() メソッドで作成して要素に追加します。

要素は生成しただけでは、どこにも関連付けされていない(表示されない)ので appendChild() メソッドや insertBefore() メソッドを使ってドキュメントに追加します。

以下は要素を作成して指定した要素に追加する例です。

<p id="foo"></p>

<script>
//a 要素を生成
var link = document.createElement('a');
 
//生成した a 要素(link)に属性を設定
link.href = 'http://example.com';
link.target = '_blank';
 
//テキストノードを生成(表示するテキスト)
var text = document.createTextNode('Link Text');
  
//要素ノード(a 要素)の直下にテキストノードを追加
link.appendChild(text);
 
//追加先の対象ノード(id が foo の要素)を取得
var foo = document.getElementById('foo');
  
//追加先のノードに生成したノードを追加 
foo.appendChild(link);
</script>

作成したリンクが指定した要素(id が foo の要素)に追加されます。

<p id="foo"><a href="http://example.com" target="_blank">Link Text</a></p>

要素を作成して追加するには以下のようなメソッドを使うことができます。また、属性の設定は「属性の操作」を参照ください。

Document のメソッド(一部抜粋)
メソッド 説明
createElement() 指定したタグ名で新しい要素を生成
createTextNode() テキストノードを生成
Node のメソッド(一部抜粋)
メソッド 説明
appendChild() 対象ノードの最後の子として、指定したノードを追加
insertBefore() 第1引数で指定したノードを、第2引数で指定したノードの直前に挿入
cloneNode() ノードを複製

以下は作成した要素を insertBefore() を使って指定した要素の前に挿入する例です。また、以下の例ではテキストの作成は textContent を使用しています。

<p id="foo">foo</p>

<script>
//p 要素を生成
var p_elem = document.createElement('p');
//p 要素に id を設定
p_elem.id= 'bar';
//p 要素のテキストを設定
p_elem.textContent = 'new paragraph';
//対象となる要素を取得
var target = document.getElementById('foo');
//対象となる要素(target)の前に作成した要素を追加
target.parentNode.insertBefore(p_elem, target);
</script>

以下のように作成した要素が挿入されます。

<p id="bar">new paragraph</p>
<p id="foo">foo</p>

以下が insertBefore() メソッドの書式です。

insertBefore() メソッドは、ノードを指定された親ノード(parentNode)の子として挿入します。多くの場合、parentNode は対象ノード(referenceNode)の親ノードになります。

第2引数(referenceNode)に null を指定すると appendChild() 同様に、最後尾にノードを追加します。

var insertedNode = parentNode.insertBefore(newNode, referenceNode)
//newNode:追加されるノード
//referenceNode:対象ノード
//insertedNode(戻り値):挿入されたノード (newNode と同じ) 

以下は生成した要素に innerHTML を使って子要素を追加する例です。

※ 但し、外部からの入力など制御できない文字列を innerHTML を使って挿入するのはセキュリティリスクが発生するので注意が必要です。

<div id="foo"></div>

<script>
//div 要素の生成 
var div = document.createElement('div');
//生成した div 要素にクラス属性を設定
div.className = 'sample';
//innerHTML で子要素を追加
div.innerHTML = '<p class="bar"><a href="#">top</a></p>';
//追加先のノードに生成した要素を追加 
document.getElementById('foo').appendChild(div);
</script>

以下のように作成した要素が追加されます。

<div id="foo">
  <div class="sample">
    <p class="bar"><a href="#">top</a></p>
  </div>
</div>

要素の置換・削除

ノードを置換するには、replaceChild() メソッドを、ノードを削除するには innerHTML プロパティや removeChild() メソッドを使用することができます。

Node のメソッド(一部抜粋)
メソッド 説明
replaceChild() ノードを置換。置換対象のノードは、現在のノードの子ノードでなければなりません(置換対象の親ノードでこのメソッドを呼び出します)
removeChild() 子ノードを削除。削除対象のノードは、現在のノードの子ノードでなければなりません(削除対象の親ノードでこのメソッドを呼び出します)

以下は生成した p 要素で既存の p 要素を置換する例です。replaceChild() は置換対象の親ノードで実行します。

<div id="foo">
  <p>Old text</p>
</div>

<script>
//p 要素の生成 
var new_elem = document.createElement('p');
//生成した要素に class 属性 'bar' を付与
new_elem.setAttribute('class', 'bar');
//テキストノードを生成して作成した要素に追加
new_elem.appendChild(document.createTextNode('New text'));
//置換対象の親ノードを取得  
var parent_node = document.getElementById('foo');
//置換対象のノード (#foo の最初の子要素)
var old_elem = parent_node.firstElementChild;
//既存の p 要素を生成した要素に置換
parent_node.replaceChild(new_elem, old_elem);
</script> 

以下のように作成した要素で置換されます。

<div id="foo">
  <p class="bar">New text</p>
</div>

上記の場合、以下でも同じことができます。

document.getElementById('foo').innerHTML = '<p class="bar">New text</p>';

要素(ノード)の削除

全ての子ノードを削除する簡単な方法は innerHTML に空文字列(または null)を指定します。

<p id="foo"><a href="http://example.com">Link</a></p>

<script>
document.getElementById('foo').innerHTML = '';
</script>

以下が実行結果です。

<p id="foo"></p>

removeChild() メソッドを使用して子ノードを削除することもできます。

<p><a id="foo" href="http://example.com">Link</a></p>

<script>
// 削除対象のノード
var target = document.getElementById("foo");
//削除対象の親ノード(target.parentNode)で removeChild() を呼び出して削除
target.parentNode.removeChild(target); 
</script>

removeChild() は削除した子ノードへの参照を返すので、変数に保存(代入)しておけば、後でコード中で再利用することができます。

以下は削除した要素で置換する例です。

<p><a id="foo" href="http://example.com">Link</a></p>
<p id="bar">Text</p>

<script>
// 削除対象のノード  
var target = document.getElementById('foo');
//削除したノードを変数に代入(保存)
var removed = target.parentNode.removeChild(target); 
//置換対象の親ノードを取得  
var parent_node = document.getElementById('bar');
//既存のテキスト(parent_node.firstChild) を削除した要素で置換 
parent_node.replaceChild(removed, parent_node.firstChild);
</script> 

以下が実行結果です。

<p></p>
<p id="bar"><a id="foo" href="http://example.com">Link</a></p>

イベント処理

イベントの処理は Element のメソッド addEventListener() や removeEventListener()、Event のメソッド preventDefault() や stopPropagation() などを使うことができます。

Element インターフェースのメソッド(イベント関連一部抜粋)
メソッド 説明
addEventListener() 要素にイベントリスナーを登録
removeEventListener() 要素から登録したイベントリスナーを削除
dispatchEvent() イベントを発火
Event インターフェイスのメソッドとプロパティ(一部抜粋)
メソッド 説明
preventDefault() ブラウザが標準で実装している処理(デフォルトの動作)をキャンセル(停止)
stopPropagation() イベントが 伝播 (propagation) するのを停止

参考サイト:MDN イベントの紹介

イベントタイプ

利用可能なイベントタイプの一覧は「MDN イベントリファレンス」に掲載されています。

addEventListener

ある要素に対してイベントリスナー(イベントハンドラ)を登録するには、そのオブジェクトの addEventListener() メソッドを使用します。

target.addEventListener(type, listener[, options]);

target はイベントを設定する要素です。

パラメータ
  • type:イベントリスナーを登録するイベントタイプ(イベント名)。全て小文字。
  • listener:指定した種類のイベントが発生したときに呼び出されるリスナー関数。リスナー関数には Event オブジェクトが引数として渡されます。
  • options:対象のイベントリスナーの特性を指定するオブジェクトまたは真偽値(オプション)
戻り値
undefined

以下はボタンをクリックすると「Hello」とアラート表示する例です。

<button id="btn">Click Me</button>

<script>
//イベントを登録する要素を取得
var btn = document.getElementById("btn");

//イベントが発生したときに呼び出されるリスナー関数
function sayHello() {
  alert("Hello");
}

//要素にイベントリスナーを登録
btn.addEventListener('click', sayHello);
</script> 

MDN : addEventListener()

無名関数を使う

リスナー関数を無名関数(匿名関数)を使って、addEventListener() の引数に記述することもできます。

以下はボタンをクリックすると「Hello」とアラート表示する例を無名関数を使って書き換えたものです。

<button id="btn">Click Me</button>

<script>
//イベントを登録する要素を取得
var btn = document.getElementById("btn");

//匿名関数を使って要素にイベントリスナーを登録
btn.addEventListener('click', function() {
  alert("Hello");
});
</script> 

但し、無名関数を使って登録すると、リスナー関数に名前がないため removeEventListener() を使ってイベントリスナーを削除することができません。

また、以下のような場合、ループごとに無名関数が作成されるので、繰り返しが多くなると効率的ではありません。

//全ての button 要素を取得
var btn = document.getElementsByTagName('button');

//取得した button 要素の数だけイベントリスナーを無名関数を使って登録
for(var i = 0; i < btn.length; ++i){ 
  btn[i].addEventListener("click", function() {
    /*関数の処理*/
  }, false);
}    

以下のようにリスナー関数を定義しておけば、定義された同じ関数が使われるため、メモリの消費が抑えられ効率的になります。

//全ての button 要素を取得
var btn = document.getElementsByTagName('button');

//リスナー関数の定義
function dosomething() {
  /*関数の処理*/
}

//取得した button 要素の数だけイベントリスナーを登録
for(var i = 0; i < btn.length; ++i){ 
  btn[i].addEventListener("click", dosomething, false);
}
removeEventListener

removeEventListener() は登録したイベントリスナーを削除します。

target.removeEventListener(type, listener[, options]);

パラメータ
  • type:登録されたイベントを表す文字列。(addEventListener() で指定したイベント名)
  • listener:登録時のリスナー関数
  • options:登録時に指定した場合は capture/useCapture フラグは一致させる
戻り値
undefined
var btn = document.getElementById("foo");
 
function sayHello() {
  alert("Hello");
}
//イベントリスナーを登録
btn.addEventListener('click', sayHello, false);
//登録したイベントリスナーを削除
btn.removeEventListener('click', sayHello, false);  

MDN : removeEventListener

Event インターフェース

リスナー関数には発生したイベント(Event オブジェクト)が引数として渡されるので、event や e など任意の名前で参照することができます。

そしてリスナー関数では必要に応じて渡されたイベントのプロパティを調べて処理の中で利用することができます。

//イベントを登録する要素を取得
var div = document.getElementById('foo');
 
//リスナー関数の引数にはイベントのオブジェクト(以下の場合は event)が渡される
function show_target_id(event) {
  //イベントオブジェクトの target プロパティの id をコンソールに出力
  console.log(event.target.id);  //foo
}
 
//要素に click イベントのリスナーを登録
div.addEventListener('click', show_target_id);

全ての Event オブジェクトは Event インターフェースを実装しています。以下は Event インターフェースのプロパティの例です。

プロパティ 概要
type 発生したイベントタイプ。このプロパティの値はイベントタイプの名前。イベントリスナーを登録するときに使う文字列と同じ。 (「click」や「mouseover」など)
target イベントを発生させたオブジェクトへの参照。必ずしも currentTarget と同じ値とは限りません。
currentTarget イベントの現在のターゲットへの参照。(イベントリスナーを現在実行中のノード)。イベント伝播のキャプチャリング段階やバブリング段階でイベントが 処理される場合、このプロパティの値は target プロパティの値とは異なります。イベントリスナー関数中で this キーワードの代わりにこのプロパティが使えます。
eventPhase イベント伝播のどの段階を現在処理中かを表す数値(定数)。値は、Event.CAPTURING_PHASE, Event.AT_TARGET, Event.BUBBLING_PHASE のうちいずれか。
timeStamp イベントが発生した時間を表す Date オブジェクト。
bubbles このイベント(タイプ)がドキュメントのツリー構造をバブリングするかどうかを表す論理値。
cancelable イベントがデフォルトの動作を持ち、そのデフォルトの動作が preventDefault() メソッドで中止可能かどうかを表す論理値。

また、イベントには MouseEventUIEventProgressEvent などのいくつかの種類(イベント型/モジュール)があり、それぞれにプロパティやメソッドがあります。

イベントモジュールが定義するインターフェースと対応するイベントタイプの例
モジュール名 インターフェース イベントタイプ
HTMLEvents Event abort, blur, change, error, focue, load, reset, resize, scroll, select, submit, unload
MouseEvents MouseEvent click, mousedown, mousemove, mouseout, mouseover, mouseup
UIEvents UIEvent DOMActivate, dOMFocusIn, DOMFocusOut

以下はリスナー関数に渡されるイベント(この例では e)を使ってマウスダウン時に、イベント発生元の要素やイベントタイプ、マウスポインタの位置などを表示する例です。

マウスボタンのタイプは別途 getButtonType という関数を定義して取得しています。

<div id="foo">Event Area</div>
<pre id="bar"></pre>

<script>
//イベントを登録する領域の div 要素を取得
var div = document.getElementById('foo');
//イベントの内容(プロパティ)を表示する領域の pre 要素を取得
var pre = document.getElementById('bar');

//イベントリスナー関数(イベントオブジェクトは e で渡される)
function showEventProps(e) {
  var result = [];
  result.push("発生元要素:" + e.target.id);
  result.push("イベントタイプ: " + e.type);
  result.push("ボタン:" + getButtonType(e));
  result.push("X座標:" + e.clientX); //MouseEvent プロパティ
  result.push("Y座標:" + e.clientY); //MouseEvent プロパティ
  result.push("発生時刻(タイムスタンプ):" + e.timeStamp);
  //pre 要素にテキスト出力
  pre.textContent = result.join('\n'); 
}

//マウスボタンのタイプを返す関数
function getButtonType(e) {
  //e.button は MouseEvent プロパティ
  switch(e.button) {
    case 0: return "left";
    case 1: return "center";
    case 2: return "right";
  }
}

//イベントリスナーを div 要素に登録
div.addEventListener('mousedown', showEventProps, false);
</script> 

<!-- 出力例
発生元要素:foo
イベントタイプ: mousedown
ボタン:left
X座標:61
Y座標:28
発生時刻(タイムスタンプ):1087.2500000004948
-->

以下はクリックした div 要素(イベントを発生させた div 要素)の背景色をランダムに変更する例です。

event.target を使うことで、簡単にイベントを発生させた div 要素を特定することができます。

<div id="foo">
  <div></div> <div></div> <div></div> <div></div>
</div>

<script>
//イベントを登録する全ての領域の div 要素を取得
var divs = document.getElementById('foo').getElementsByTagName('div');
//背景色の配列 
var colors = ['green', 'blue', 'red', 'yellow', 'orange', 'white'];

//イベントを発生させた要素(event.target)の背景色を変更するリスナー関数
function changeBGColor(event) {

  //Math.floor(Math.random()*6) は 0~5 のランダムな整数を返します。
  event.target.style.backgroundColor = colors[ Math.floor(Math.random()*6) ];
  
  //イベントを発生させた要素(オブジェクト)をコンソールに出力
  console.log(event);
}  
 
//取得した div 要素全てにイベントリスナーを登録
for (var i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', changeBGColor);
}
</script> 

<!-- コンソール出力例(イベントオブジェクト)
MouseEvent {isTrusted: true, screenX: 311, screenY: 584, clientX: 226, clientY: 302, …}
-->

上記サンプル

preventDefault

Web ブラウザが標準で実装している処理(デフォルトの動作)を中止するには preventDefault() メソッドを使用します。

例えば、a 要素をクリックするとそのリンク先にページが移動しますが、preventDefault() メソッドを実行すると、このデフォルトの動作を止めることができます。

但し、イベントの中には、preventDefault() メソッドで中止できないイベントもあります。Event インターフェースのプロパティ cancelable で確認することができます。

以下は Email 入力欄と送信ボタンのみのフォームで、Email 入力欄が空のまま送信ボタンをクリックすると「Email を入力してください」とメッセージを表示する例です。

フォームの送信ボタンをクリックすると、submit イベントが発火してフォームが送信されます。以下の例では、入力欄が空の場合は、e.preventDefault() でデフォルトの動作(フォームの送信)を止めてメッセージを表示します。

<form>
  <div>
    <label for="email">Email: </label>
    <input id="email" type="text">
  </div>
  <div>
     <input id="submit" type="submit">
  </div>
</form>
<p class="message"></p>

<script>
//フォーム要素を取得
var form = document.forms[0];
//Email 入力欄の要素を取得
var email = document.getElementById('email');
//メッセージを表示する要素を取得
var message = document.getElementsByClassName('message')[0];
  
//リスナー関数(Email 入力欄をチェック)
function validate(e) {
  //Email 入力欄が空の場合
  if (email.value === '') {
    //デフォルトの動作(フォームの送信)を停止
    e.preventDefault();
    //メッセージを表示
    message.textContent = 'Email を入力してください';
  }
}
//フォーム要素にイベントリスナーを登録
form.addEventListener('submit', validate);
</script> 
stopPropagation

HTML ドキュメントは要素が入れ子になって構成されています。デフォルトではページ上で発生したイベントは上位の要素にも通知されます。

以下のような入れ子になった div 要素がある場合、下位の要素(id="bar")で発生したイベントは上位要素(id=""foo")にも通知されます(バブリング)。

<div id="foo">Foo
  <div id="bar">Bar</div>
</div>

以下のように両方の要素にアラートを表示するイベントリスナを登録した場合、下位の要素(id="bar")をクリックすると、イベントが上位要素に伝播するのでアラートは2回表示されます。

var foo = document.getElementById("foo");
var bar = document.getElementById("bar");
 
function fooAlert(e) {
  alert("foo: 上位要素のリスナ");
}
 
function barAlert(e) {
  alert("bar: 下位要素のリスナ");
}
 
foo.addEventListener('click', fooAlert);
bar.addEventListener('click', barAlert);
Foo
Bar

伝播のキャンセル

イベントを伝播させないようにするには、stopPropagation() メソッドを使います。以下のように伝播させたくないイベントリスナー内で実行します。

var foo = document.getElementById("foo");
var bar = document.getElementById("bar");
 
function fooAlert(e) {
  alert("foo: 上位要素のリスナ");
}
 
function barAlert(e) {
  alert("bar: 下位要素のリスナ");
  e.stopPropagation();  //バブリングを抑止
}
 
foo.addEventListener('click', fooAlert);
bar.addEventListener('click', barAlert);
Foo
Bar

配列のメソッドを使う

要素を取得するメソッドが返す値(要素の集合)は HTMLCollectionNodeList という配列のようなオブジェクトなので、配列(Array)のメソッドを直接使うことができません。

HTMLCollection や NodeList などの配列のようなオブジェクトで配列のメソッドを使うには、call や apply を利用します。

または配列のようなオブジェクトを配列に変換して、配列のメソッドを使うという方法もあります。

call()

call() は Function オブジェクトの prototype プロパティ(Function.prototype)に用意されたメソッド(全ての関数オブジェクトが持つ関数)で、このメソッドを利用すると、そのオブジェクトのメソッドであるかのように関数を呼び出すことができます。

以下が call() の書式です。function は呼び出す関数です。

function.call(thisArg, arg1, arg2, ...)
引数 説明
thisArg その関数を実行させるオブジェクトを指定します。このオブジェクトは、呼び出す関数の本体で this となるオブジェクトです。
arg1, arg2, ... 呼び出される関数に渡される引数(のリスト)を指定します(オプション)。

戻り値:関数を呼び出した結果

call() を使って配列のメソッドを呼び出す

以下は、getElementsByClassName() を使ってクラスが foo の要素(HTMLCollection)を取得し、call() を使って配列(Array.prototype)のメソッド forEach() を呼び出す例です。

var foo = document.getElementsByClassName('foo');  //HTMLCollection
        
Array.prototype.forEach.call(foo, function (elem, index) {
  console.log( index + ' : ' + elem.textContent );
}); 

Array.prototype の代わりに空の配列リテラル [] を使って以下のように記述することもできます。

//Array.prototype.forEach の代わりに [].forEach と記述
[].forEach.call(foo, function (elem, index) {
  console.log( index + ' : ' + elem.textContent );
}); 

取得した HTMLCollection を変数に格納する必要がなければ、以下のように続けて記述できます。

Array.prototype.forEach.call(document.getElementsByClassName('foo'), function (elem, index) {
  console.log( index + ' : ' + elem.textContent );
}); 

以下は配列のメソッド filter() を使って要素の種類が div の場合は配列 foo_div に格納して、配列のメソッド forEach() を使う例です。

var foo = document.getElementsByClassName('foo');  //HTMLCollection  
 
//filter で div 要素を抽出して配列に格納
var foo_div = Array.prototype.filter.call(foo, function (elem) {
  return elem.tagName === 'DIV';
});  

//foo_div は配列なので、forEach() を直接使える
foo_div.forEach(function(elem, index) {
 console.log( index + ' : ' + elem.textContent);
});      
    

配列のようなオブジェクトを配列に変換

call() と配列のメソッド slice() を使えば、HTMLCollection や NodeList などの配列のようなオブジェクトから、新たに配列を生成することができます。

以下は querySelectorAll() を使ってセレクタにマッチする全ての要素を取得した NodeList から配列を生成する例です。マッチする要素がない場合は空の配列を返します。

Array.prototype.slice.call(document.querySelectorAll(セレクタ) || []);

例えば、ページの全ての a 要素を取得する場合、getElementsByTagName を使って以下のように記述します。

var anchors = document.getElementsByTagName('a');

上記で取得した a 要素の集まり anchors は HTMLCollection(ブラウザによっては NodeList)という配列のようなオブジェクトで配列ではありません。

call() を使って anchors に配列のメソッド slice() を実行すると、anchors から要素のみを抽出して新たに配列を生成することができます。slice() を引数なしで実行すると、インデックス 0 から最後 (array.length) までを切り出した配列を返します。

//配列のようなオブジェクトを取得
var anchors = document.getElementsByTagName('a');

//配列のようなオブジェクトを配列に変換
var anchors_array = Array.prototype.slice.call(anchors);

上記はまとめて以下のように記述することもできます。

var anchors_array = Array.prototype.slice.call( document.getElementsByTagName('a')); 

上記の anchors_array は配列なので、配列のメソッドを使用することができます。

以下は、ページの全ての a 要素を取得して、配列のメソッド forEach() を使ってその要素の target 属性が _blank の場合はインデックス番号と href 属性の値を出力する例です。

var anchors_array = Array.prototype.slice.call( document.getElementsByTagName('a'));       
        
anchors_array.forEach(function(elem, index) {
  if(elem.target ==='_blank') {
    console.log(index + ': ' + elem.href);
  }
})

以下のように、call() を使って配列のようなオブジェクトに forEach() を実行させても同じことです。

Array.prototype.forEach.call(document.getElementsByTagName('a'), function (elem, index) {
  if(elem.target ==='_blank') {
    console.log(index + ': ' + elem.href);
  }
});
ES6 Array.from() メソッド

ES6(ES2015)から導入されている Array.from() メソッドを使えば、配列のようなオブジェクトから簡単に配列を生成することができます。

例えば、getElementsByTagName() を使って取得した配列のようなオブジェクトから配列を生成するには以下のように記述できます。

var anchors_array = Array.from(document.getElementsByTagName('a'));  //配列

以下の Array.from() を使わない場合と比べると簡潔に記述できるのがわかります。

var anchors_array = Array.prototype.slice.call( document.getElementsByTagName('a'));  //配列

配列のようなオブジェクト

配列のようなオブジェクト(array-like object)とは length プロパティとインデックスでアクセスできる要素を持つ(配列のように扱えるが配列ではない)オブジェクトのことです。

機能 配列 配列のようなオブジェクト
インデックス(添字 [n])でのアクセス 可能 可能
length プロパティ(長さ) ある ある
配列のメソッド 使用可能 使用できない(※)

※配列のようなオブジェクトは配列ではないので、配列のメソッドは使用できません。但し、オブジェクトによっては独自に同じ名前のメソッド(例 forEach)を持っているものもあります。

例えば、querySelectorAll() の戻り値は Nodelist なので、forEach() というメソッドを持っていますが、 getElementsByClassName() の戻り値は HTMLCollection で forEach() というメソッドを持っていないため使用するとエラーになります。

var nodelist = document.querySelectorAll('.foo');
  
var htmlCollection = document.getElementsByClassName('foo');

nodelist.forEach(function(elem) {
  console.log(elem);
});
  
//出力例(Nodelist は forEach メソッドを持っているので使用可能)
//<p class="foo"></p> 
  
htmlCollection.forEach(function(elem) {  //エラー
  console.log(elem);
});

//HTMLCollection は forEach メソッドを持っていないので以下のエラー
//Uncaught TypeError: htmlCollection.forEach is not a function

配列のようなオブジェクトで配列のメソッドを使用するには call() を使って配列のメソッドを呼び出すか、配列のようなオブジェクトを配列に変換する必要があります。

例えば以下のような HTML がある場合、

<p class="foo"></p>
<p class="foo"></p>

querySelectorAll() と getElementsByClassName() を使ってクラス foo の要素を取得すると、それぞれ Nodelist と HTMLCollection のオブジェクトを取得できます。

ブラウザのインスペクタで、NodeList(2) や HTMLCollection(2) の部分をクリックするとそのオブジェクトの概要が展開されます。

var nodelist = document.querySelectorAll('.foo');
console.log(nodelist);

var htmlCollection = document.getElementsByClassName('foo');
console.log(htmlCollection);

//出力例
NodeList(2) [p.foo, p.foo]  //この部分をクリックすると以下が展開
0: p.foo  //index と要素
1: p.foo
length: 2  //length プロパティ
__proto__: NodeList 
  
HTMLCollection(2) [p.foo, p.foo]
0: p.foo
1: p.foo
length: 2
__proto__: HTMLCollection

更に、__proto__ の部分をクリックすると __proto__ プロパティ(オブジェクトの内部のプロパティ)が展開され、Nodelist には forEach メソッドがあることが確認できます。

また、両方とも Symbol(Symbol.iterator) というプロパティを持っていて、反復可能オブジェクト(iterable オブジェクト)でもあることがわかります(for of 文が使用可能)。

配列かどうかの判定 isArray()

Array.isArray() メソッドを使用すれば、配列かどうかを判定することができます。配列のようなオブジェクトは配列ではないので結果は false になります。

var arr = [1,2,3];
console.log(Array.isArray(arr));  //true
  
var nodelist = document.querySelectorAll('.foo');
console.log(Array.isArray(nodelist));  //false
  
var htmlCollection = document.getElementsByClassName('foo');
console.log(Array.isArray(htmlCollection));  //false

ES6 for...of 文

ES6(ES2015)から導入されている for...of 文を使うと反復可能オブジェクトである HTMLCollection や NodeList に対して要素を1つずつ取り出して繰り返し処理を行うことができます。

<p class="foo">Foo 1</p>
<div class="foo">Foo 2</div>
<p><span class="foo">Foo 3</span></p>

<script>
let foo = document.getElementsByClassName('foo');
  
for (let elem of foo) {
  console.log(elem.tagName + ': ' + elem.textContent);
}
</script>
 
/* 出力
P: Foo 1
DIV: Foo 2
SPAN: Foo 3
*/