JavaScriptでDOMを使う

DOM(Document Object Model)とは?

DOMはHTMLの特定の要素を参照するための仕組みで、以下の3つのメソッドが使われます(例外的にname属性を指定できる要素に関してはname属性の値で要素を選択できる)。

  • document.getElementById("id値")
  • document.getElementsByTagName("タグ")
  • document.getElementsByname("name値")
  • document.name値・・・nameを指定できるもの要素だけ

ただし、getElementByIdとgetElementsByTagNameはdocumentに限らず、ほかの要素に対するメソッドとして使用できますが、getElementsBynameだけはdocumentオブジェクトに対してしか指定することができません。

DOM操作はその要素が読み込まれた後でしかできないため、必然的にjavascriptの記述はhead内ではなく、idとかが出てきた後、/body直前とかに記述しなければならない。

getElementById("id値")

HTML内の任意のIDを入れることで、そのIDが付いた要素を選択することができます。

<--HTML-->
<html>
<head></head>
<body>
<h1 id="a1">見出し</h1>
<p id="a2">段落</p>
</body>
</html>
//js内
var a = document.getElementById("a1");
var b = a.innerHTML;
alert(b); //見出しが表示

getElementsByTagName("タグ")

IDがセットされていない要素を選択するときに使用するメソッド。引数に指定した要素をリストとして返してくれます。

このメソッドの返り値は、要素のインデックス番号(0から始まる番号)を返すitemメソッドと、格納されている要素の数を返すlengthプロパティが指定できます。該当するインデックス番号がない場合はnullが返ります。

<--HTML-->
<html>
<head></head>
<body>
<h1 id="a1">見出し</h1>
<p">段落1</p>
<p">段落2</p>
</body>
</html>
//js内
var a = document.getElementsByTagName("p");
var b = a.item(1);
var c = b.innerHTML;
alert(c); //段落2が表示

getElementsByName("name値")

name属性がセットされているinputとa要素への参照として使う。name属性はidとは違って複数の要素に振られる可能性があるため、これもitemメソッドで該当インデックスを指定する必要があります。

<--HTML-->
<html>
<head></head>
<body>
<h1 id="a1">見出し</h1>
<a name="a2">リンク1</a>
<a name="a2">リンク2</a>
</body>
</html>
//js内
var a = document.getElementsByName("a2");
var b = a.item(0); //a[0]でも同じ
var c = b.innerHTML; //inputだとinnerHTMLでなくvalue
alert(c); //リンク1が表示

alert(a.length); //2が表示

radioボタンのようなinput要素のvalue値を知りたい場合によく使用すると思います。item(0)だけでは対象のinput要素が指定されてしまうので、「a.item(0).value」のようにすることを忘れずに。

itemを使わず、配列で指定しても同じ要素を取り出すことができます。a.item(0)はa[0]と同じ。

これを使って選択されているラジオボタンのようなinput要素を知りたいときは以下のように記述する。checkedがついているinput要素があったならそのvalue値をbに入れろというもの。

//js内
for(var i = 0; i < a.length; i++) {
if(a[i].checked) {
b = a[i].value;
}
};

document.name値

name属性を指定できる要素(iframe、img、button、input、select、form、textarea、applet、object、param、meta、frame)に対してはgetうんたらを使わなくてもname名で対象要素を指定できる。

name属性を指定できない要素(pやa,div等)に対しては効果なし。

<form id="form1" name="form1" action="#" method="post">
<input type="text" name="x4" id="x4" value="" size="40" />
<input type="submit" name="search" value="検索" />
</form>
document.form1.x4.value = "aaa";

子・親要素の参照

DOMでは上記の3つのタグを使用することがほとんどですが、それ以外にも特定の要素の子や親要素を指定するためのプロパティがあります。

  • childNodes:子要素のリストをNodelistとして返す
  • firstChild:子要素のうち、最初の要素を返す
  • lastChild:子要素のうち、最後の要素を返す
  • parentNode:親要素を返す
  • nextSibling:次のノード
  • previousSibling:1つ前のノード

実はこれらのプロパティの挙動は見たままのような簡単なものではありません。これらのプロパティが参照するのは要素ではなくノードだからです。

<h1>とか<p>はHTML上でタグと呼ばれ、別名として要素と呼ばれています。これらの要素はノードの一部であり、ノード上では要素ノードと呼ばれています。

ノードにはこれを含めて、

  • 要素ノード
  • 属性ノード
  • テキストノード
  • コメントノード
  • 文書ノード

の5つがあります。

空白もテキストノードとして扱われ、改行も含まれます。IE以外のブラウザでは改行のところに空白ノードが出現するため、ul.firstChildと指定しても、ulタグの後に改行してli要素が記述されていたら、空白ノードが指定されてしまいます。親要素を指定するparentNode以外を指定する際は十分注意が必要です。

そこで、parentNode以外を使うときは、Element Traversal APIを使った表記を使用するとよいでしょう。IE11は問題ないことを確認したものの、他一部IEでchildrenが空白ノードを含んだNodelistを返すらしい。

<table id="sample" border="1">
    <tbody id="a1">
        <tr id="b1">
            <td id="c1">1行目1列目</td>
            <td id="c2">1行目2列目</td>
            <td id="c3">1行目3列目</td>
        </tr>
    </tbody>
    <tbody id="a2">
        <tr id="b2">
            <td id="d1">2行目1列目</td>
            <td id="d2">2行目2列目</td>
            <td id="d3">2行目3列目</td>
        </tr>
        <tr id="b3">
            <td id="e1">3行目1列目</td>
            <td id="e2">3行目2列目</td>
            <td id="e3">3行目3列目</td>
        </tr>
    </tbody>
</table>
var a = document.getElementById("b1");
var elm;
// ------------------------------------------------------------
// 関連ノードを参照するためのプロパティ
// ------------------------------------------------------------
//親要素の取得
elm = a.parentNode.id; //b1の親要素は、a1

//子要素の取得
elm = a.firstChild.id; //b1の最初の子要素は、undefined(空白ノード)
elm = a.lastChild.id; //b1の最後の子要素は、undefined(空白ノード)

var clist = a.childNodes; //子要素のリスト[改行,c1,改行,c2,改行,c3]
elm = clist[1].id; //c1

//兄弟要素の取得
elm = a.nextSibling.id; //b1の次のノードは、undefined
elm = a.previousSibling.id; //b1の1つ前のノードは、undefined
//elm = a.previousSibling.previousSibling.id; //b1の前の前のノードは、null
var b = document.getElementById("b2");
elm = b.nextSibling.nextSibling.id; //b2の次の次のノードは、b3


// ------------------------------------------------------------
// Element Traversal APIを使用した場合
// ------------------------------------------------------------
//子要素の取得
elm = a.firstElementChild.id; //b1の最初の子要素は、c1
elm = a.lastElementChild.id; //b1の最初の子要素は、c3
clist = a.children;//[td#c1, td#c2, td#c3]

//兄弟要素の取得
elm = b.nextElementSibling.id; //b2の次のノードは、b3
elm = b.previousElementSibling.id; //b2の前のノードは、null

ノードの名前、種類を取得する

ノードの名前を取得するには、nodeNameプロパティを使います。要素ノードではタグ名となりますが、コメントノードでは"#comment"、テキストノードでは"#text"という文字が得られます。

ノードの種類を取得するには、nodeTypeプロパティを使います。要素ノードが1、テキストノードが3、コメントノードが8になります。

ノードの中身を取得するには、nodeValueプロパティを使います。テキストノードとコメントノードでは中身のテキストが得られますが、それ以外ではnullになります。

<div id="a1">あいうえお</div>
var a = document.getElementById("a1");

console.log(a.nodeName); //div
console.log(a.nodeType); //1(要素ノード)
console.log(a.Value); //undefied

XPathを使う

idやnameよりもさらに細かく要素を指定したい場合、XPathを使うと良い。

ただし、IEは対応できてないんでIEでXPathを使用可能にするために、ライブラリ(JavaScript-XPath)を利用する必要がある。latest versitionをDLして下記のようにhead内で読みこめば良い。他ブラウザは読み込まなくても動く。

<script type="text/javascript" src="javascript-xpath.js"></script>
指定したい要素 XPath
全div //div
idがmainのdiv //div[@id="main"]
classがhogeのp //p[@class="hoge"]
formの3番目のinput //form/descendant:input[3]
divの中でhrefがhttps://nkdesk.com/から始まるa //div/a[starts-with(@href,"https://nkdesk.com/")]
チェックされたチェックボックスの親 //input[@checked="checked":]/
<div id="a1">あいうえお</div>

XPathはevaluate()関数を使用する。

var result = document.evaluate(
               'id("a1")',            // XPath式を文字列で指定
               document,           // 文書内のノードを指定。範囲を縮小したほうがパフォーマンス上昇
               null,               // 名前空間URIを返す。HTMLではnullでよい
               7,                  // 評価した結果を返す。基本は 6 か 7 でいい。 6 だったら結果がソートされない可能性がある。
               null                // 既存のXPathResultオブジェクトを指定する。nullでいい。
             );

var b = result.snapshotLength;  // 取得した要素(正確にはノード)の数。
var c = result.snapshotItem(0); // 1 個目の要素
var d = result.snapshotItem(1); // 2 個目の要素
console.log(b); //1
console.log(c); //<div id="a1">
console.log(d); //null

第四引数の値と返り値が以下。

定数 返されるオブジェクト
ANY_TYPE 0 評価結果に応じて適切な方を格納した結果の場合
NUMBER_TYPE 1 数値
STRING_TYPE 2 文字列
BOOLEAN_TYPE 3 真偽値
UNORDERED_NODE_ITERATOR_TYPE 4 ノード集合のイテレータ。順番は不定
ORDERED_NODE_ITERATOR_TYPE 5 ノード集合のイテレータ。順番は文書内に現れる順番に一致
UNORDERED_NODE_SNAPSHOT_TYPE 6 ノード集合のスナップショット。順番は不定
ORDERED_NODE_SNAPSHOT_TYPE 7 ノード集合のスナップショット。順番は文書内に現れる順番に一致
ANY_UNORDERED_NODE_TYPE 8 式にマッチしたノードのうちどれか1tu。式にマッチした最初のノードとは限らない
FIRST_ORDERED_NODE_TYPE 9 文書内で式にマッチした最初のノード

要素の作成と挿入

要素を作成するにはcreateElement()、挿入にはappendChild()やinsertBefore()を使用する。

var a = document.createElement("div"); //要素を作成する
var b = document.createTextNode("aaaa"); //テキストノードを作成する
document.body.appendChild(a); //作成した要素を/bodyの直前に挿入
a.appendChild(b); //作成した要素の閉じタグの直前にテキストノードを挿入
a.innerHTML = "bbbb"; //テキストノードの中身をbbbbへ変更
var c = document.createElement("p"); //要素を作成する
document.body.insertBefore(c,a); //div要素の直前にp要素を挿入
<!--before-->
<div id="a1">あいうえお</div>

<!--after-->
<div id="a1">あいうえお</div>
<p></p>
<div>bbbb</div>

コメントor補足情報orご指摘あればをお願いします。

(件名or本文内でキーワード検索できます)



  • << 前のページ
  • 次のページ >>
ページトップへ