読者です 読者をやめる 読者になる 読者になる

ハロトレWebデザインの勉強03月14日開講クラス授業補足ブログ

DOM まとめ

ダイナミックHTML

  • JavaScript のようなクライアント側のプログラムを使って HTML の内容を動的に変化させる概念を、「ダイナミックHTML」 といいます
  • JavaScript」 から HTML の内容を制御する事ができるので、HTML が動的に変化するインタラクティブなコンテンツを作成する事ができます
  • 登場初期の頃はブラウザごとに制御方法が違っていたので、ブラウザごとに専用の JavaScript のコードを用意する必要がありました
  • そこで制御方法を統一するために DOM という仕様が生まれました

Document Object Model(DOM)

  • プログラムから「HTML 文書」や「XML 文書」を利用するための、標準化された仕様です
  • HTML 文書は、「タグ」「属性」「値」「文書」などの部品で構成されています
  • HTML 文書がブラウザに読み込まれると、JavaScript 内でこれらの部品1つ1つが「DOM オブジェクト」として自動的に生成されます
  • 「DOM オブジェクト」から、メソッドやプロパティを利用することができます
  • 「DOM オブジェクト」であれば、共通して利用できる基本的な機能として、Node というインターフェースが定められています
  • Node インターフェースには、すべての「DOM オブジェクト」で利用できる、基本的な機能がまとまっています
  • 「ノードインターフェース」を使用すると、木構造の親子関係を構築することができます
ノードのインターフェース
  • 主に使用するインターフェースは、
    1. Document(ドキュメント、階層のルートに相当)
    2. Element(エレメント、要素に相当)
    3. Text(テキストノード、タグ以外の文字データに相当)
    4. Attr(アトリビュート、属性に相当)

の4つです

Documentインターフェース

  • Documentは、文書全体を管理するための機能がまとめられています
  • Documentは、DOMノード全体のルート(最上位)部分に相当します
  • Documentは、文書のルートに相当するエレメントを1つだけ保持しています

 

JavaScript から Documentオブジェクトを取得する

  • window.document プロパティを使用します
// HTMLDocument オブジェクトを取得する
var document_obj = window.document;

// 出力テスト
console.log(document_obj);


Elementインターフェース

  • エレメントは、HTML のタグ(要素)に相当します
  • 基本的なタグは、「HTMLElement」というインターフェースになります
  • タグの種類によっては、HTMLElement インターフェースから、更に派生します
  • 専用の機能や、メソッド、プロパティなどが追加されます
  • 例えば、「div」タグは「HTMLDivElement」となります
  • 例えば、「img」タグは「HTMLImageElement」となります


Textインターフェース

  • テキストノードは、タグ以外の文字データに相当します
  • 空白、タブ、改行などのインデント整形用の文字であっても、すべてテキストノードとなります
  • テキストノードは、子を持つ事はできません


Attrインターフェース

DOM オブジェクトを取得する
  • 取得したいタグに、id 属性を追加して、好きな識別名を設定します
  • 取得したいタグに、class 属性を追加して、好きな識別名を設定します
  • 取得したいタグに、name 属性を追加して、好きな識別名を設定します


ID 属性からエレメントを取得する

  • ID 属性から、1つのエレメントを取得する
  • document.getElementById( ) メソッドを使用します
  • 戻り値からは、マッチするエレメントが1つ得られます
  • 見つからなかった場合は、null が得られます

DOM操作のメソッド

HTMLドキュメントの階層構造
  • DOMを使用すると、HTMLドキュメント内のすべての要素を「html」を頂点とする階層構造でアクセスできます
  • この階層構造を「DOMツリー」と呼びます
  • DOMツリー内の個々の要素を「ノード」と呼びます
ノードを取得する getElementByIdメソッド
  • プログラムで目的のノードを取り出す
  • 引数には、HTMLにはタグで設定したid属性を指定します(HTMLタグにあらかじめid属性を指定しておく必要があります)
ノードにHTMLを設定する innerHTMLプロパティ
  • DOMの各ノードは、innerHTMLというプロパティが用意されています
  • 「innerHTML」は日本語にすると「内部」ですが、文字通りノードの内部のHTMLを表します
  • innerHTMLの値を変更することにより、ノードのHTMLを動的に変更できます


《例》

	var myArea = document.getElementById('myArea');
	myArea.innerHTML = '<h2>中見出し</h2>';

DocumentオブジェクトによるHTML要素の操作

要素へのアクセス(要素の取得)
  • Documentオブジェクトのメソッドでよく利用されるのは、「getElementById」と「getElementsByName」です
  • どちらも戻り値としてHTML要素を返します
IDを指定して要素を取得
  • id属性はHTML文書内で一意となる値が設定されるので「getElementById」メソッドで取得される要素は1つだけです

document.getElementById( 'id属性値' );


《getElementByIdの利用》

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>getElementByIdの利用</title>
<script>
  function setValue() {
    var elm = document.getElementById('tx1');
    elm.value = 'Hello!';
  }
</script>
</head>
<body>
<input id="tx1" type="text">
<input id="tx2" type="text">
<input id="tx3" type="text">
<button onclick="setValue();">クリック</button>
</body>
</html>

《実行結果》

  • ボタンがクリックされると「tx1」というID値をもつ要素を探し出し、value属性に値を設定します


変数を使わず1行で記述することも可能です。

document.getElementById('tx1').value = 'Hello';
name属性値を指定して要素を取得
  • name属性の値は重複が許されているので、複数件の要素が該当する可能性があります。そのため「getElementsByName」メソッドの戻り値は、配列と同様の「0」から始まるインデックスを持ったオブジェクトになります

document.getElementsByName( 'name属性値' );


《getElementsByNameの利用》

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>getElementsByNameの利用</title>
<script>
  function setValue() {
    var elm = document.getElementsByName('tx1');
    for (var i = 0; i < elm.length; i++) {
      elm[i].value = 'Hello!';
    }
  }
</script>
</head>
<body>
<input name="tx1" type="text">
<input name="tx1" type="text">
<input name="tx1" type="text">
<button onclick="setValue();">クリック</button>
</body>
</html>

《実行結果》

  • ボタンがクリックされると「tx1」というname属性値をもつ要素を探し出し、value属性に値を設定します
  • 「getElementsByName」は、戻り値として配列と同じ形式のオブジェクトを返すため、for文で要素数分だけ繰り返し処理をしています
  • 該当するname属性値をもつ要素が1件だけだった場合でも、戻り値は配列形式になるため、インデックスは必ず指定しなければなりません
その他のHTML属性

《属性値の変更》

要素 . 属性名 = 値 ;


ただし、class属性だけは例外です。
classは予約語候補なので、そのままの名称では使えません。

  • classNameといプロパティを使います


CSSクラスの変更》

要素 . className = 'CSSクラス名' ;


表示エリアの切り替え

  • CSSクラスを切り替えることで、ページレイアウトを大幅に変更することが可能です
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>表示エリアの切り替え</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script>
  function showIppan() {
    document.getElementById('ippan_area').className = 'active';
    document.getElementById('hojin_area').className = 'passive';
  }
  function showHojin() {
    document.getElementById('ippan_area').className = 'passive';
    document.getElementById('hojin_area').className = 'active';
  }
</script>
</head>
<body>
<input type="radio" name="target" value="i" onChange="showIppan();" checked>一般用
<input type="radio" name="target" value="h" onChange="showHojin();">法人用
<ul id="ippan_area" class="active">
  <li>氏名<input type="text" name="name"></li>
  <li>住所<input type="text" name="address"></li>
  <li>電話番号<input type="text" name="tel"></li>
</ul>
<ul id="hojin_area" class="passive">
  <li>会社名<input type="text" name="company"></li>
  <li>部署名<input type="text" name="busho"></li>
  <li>担当者名<input type="text" name="tanto"></li>
  <li>住所<input type="text" name="address"></li>
  <li>電話番号<input type="text" name="tel"></li>
  <li>内線番号<input type="text" name="naisen"></li>
</ul>
</body>
</html>


《style.css

.active {
  display: block;
}
.passive {
  display: none;
}

《実行結果》


  • JavaScriptでどちらか一方だけが表示するよう制御しています
  • 初期値は、一般用入力エリアのclass属性は要素を表示する「activeクラス」、法人用入力エリアのclass属性には要素を非表示にする「passiveクラス」を設定しています
  • この2つのクラスを、ラジオボタンの選択状態が変更されたタイミングで交互に切り替えるよう設定しています

要素内容の操作

  • 要素が持つ内容を操作するための「innerHTMLプロパティ」


《要素の中身を書き換える》

要素 . innerHTML = 文字列 ;

たとえば、

document.getElementById( 'hoge' ).innerHTML


は、以下のHTML文書では、ID名hogeがついたp要素の範囲を示します。

<div>
  <p id="hoge">
    文章
    <a href="xxx.html">リンク</a>
  </p>
</div>

画像タグの生成

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>画像タグの生成</title>
<script>
  function showImage() {
    var htmlstr = '';
    for(var i=1; i<=3; i++) {
      htmlstr += '<img src="images/img' + i + '.jpg">';
    }
    document.getElementById('imageArea').innerHTML = htmlstr;
  }
</script>
</head>
<body>
<button id="btn" onClick="showImage();">読込</button>
<div id="imageArea">ここに画像が読み込まれます。</div>
</body>
</html>

《実行結果》


DOMによって、要素の属性や内容を変更することができる

おみくじプログラム
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>DOMによるおみくじ</title>
<style>
body, div, h1, h2, h3, h4 {
  margin: 0;
  padding: 0;
}
body {
  font-size: 16px;
  text-align: center;
  background-color: #FFF;
  padding-top: 50px;
}
#myArea {
  background: #F0F0F0;
  margin: 0 auto;
  width: 600px;
  line-height: 120px;
}
#myArea h1 {
  font-size: 36px;
  color: #390;
}
#myArea h1.today {
  color: #000;
}
#myArea h4 {
  color: #F00;
}
</style>
</head>
<body>
<h1>今日の運勢</h1>
<form>
<p>
<input type="button" value="占う" onClick="unsei();">
</p>
</form>
<div id="myArea">
<h1 class="today">今日はどんな運勢でしょう?</h1>
</div>
<script>
var kuji = new Array(4);
kuji[0] = '<h1>大吉</h1>';
kuji[1] = '<h2>中吉</h2>';
kuji[2] = '<h3>小吉</h3>';
kuji[3] = '<h4>凶</h4>';

function unsei(){
	var myArea = document.getElementById('myArea');
	var num = Math.floor(kuji.length * Math.random());
	myArea.innerHTML = kuji[num];
}
</script>
</body>
</html>


  1. 素数が4の配列「kuji」を生成する
  2. 各要素におみくじのテキストを代入する
  3. 「unsei」関数を定義する
  4. ID名「myArea」のdiv要素におみくじを表示する
  5. フォーム内「占う」ボタンに、onclickイベントハンドラを追加
  6. クリックされると定義した「unsei」関数を呼び出す

《実行結果》