DOM操作系　まとめ

DOM(Document Object Model)とは、マークアップ言語（HTML,CSS)で書かれたドキュメントにアクセスするための標準的な仕組み。
DOMではドキュメントを文書ツリー（ドキュメントツリー）と言う、ツリー構造として扱う。１つ１つの要素をノードと呼び、要素ノード、属性ノードなど種類別に呼称する。

あるHTMLのdivタグの文章を変えたいとなると

 - 要素ノードを取得
   - 直接取得
   - 文書ツリー間の行き来
   - イベントドリブンモデル
 - 属性値やテキストを取得・設定
   - 取得・設定
   - フォームタグ
 - ノードを追加・置換・削除

と言う順序をもって、HTMLに対して更新していく。

##要素ノードの取得
取得のためには、id,タグ名、class,セレクター方式があり、取得するデータが単数か複数かで扱い方やメソッドが複数になるかが変わるので注意！


###直接取得

| メソッド| 概要| 
|:-----------------|:------------------|
| getElementById(id) | id値をキーとして要素を取得|
| querySelector（selector）| セレクター※後述参照でより複雑な条件で検索する。戻り値は１つで、複数ある場合は一致した最初の値を返す。|
| querySelectorAll（selector）|querySelectorの複数版、一致した全ての要素を返す|
| getElementsByTagName(name)| タグ名をキーとして一致したものを返す。複数出る可能性があるので複数形になっている 　　　　　　　　　　　　メンバー：length(要素数),item(i)(i番目の要素),namedItem(name)(id,name属性が一致する要素)|
| getElementsByClassName(class)| class値をキーとして要素を取得複数ある場合があるため複数形|

| セレクター| 概要| 
|:-----------------|:------------------|
| *| 全ての要素を取得 |
| #id| 指定したid要素を取得 |
| .class| 指定したclass要素を取得 |
| *| 全ての要素を取得 |
など多くあるので、都度調べた方がいいと思います。

####getXxxxxとqueryXxxxxメソッドの違い
getXxxxxは高速、queryXxxxxは低速と言う処理速度の違いはあるものの、試行回数が多い場合にしか差は出てこず、場合によってはqueryXxxxxの方が簡潔に記述できるので、都度必要に応じて使い分ける。


##文書ツリー間の行き来
文書全体から指定のノードを探すことはパフォーマンスの低下になります。そこでDOMではある起点から相対的な位置で探すことができます。これがノードウォーキングと言われるノード間を移動していくやり方です。
コードは長くなりますが、小回りが効くので
**getXxxxx/queryXxxxxで特定した後、近接するノードはノードウォーキングで取得する**
ことが一般的である。

基準となるノードに対して

|　プロパティ | 概要| 
|:-----------------|:------------------|
| parentNode|　親ノード |
| previousSibling/nextSibling|　兄/弟ノード |
| previousElementSibling/nextElementSibling|　兄/弟の要素オブジェクトを返す |
| firstChild/lastChild|　子の最初のノードから最後のノードを順次に取得する |
| firstElementChild/lastElementChild|　子の最初の要素オブジェクトをから最後の要素オブジェクトを順次に取得する |
| childNodes| 子のノード郡を返す |

Elementが付いていないものは要素以外の改行や空白のテキストノードも取得してしまう。
そのため、 nodeType　プロパティで調べる必要がある。

nodeTypeの返り値の数値と対応表

|戻り値| 概要| 戻り値| 概要| 
|:--|:--|:--|:--|
| 1| 要素ノード | 7| 処理命令ノード|
| 2| 属性ノード| 8| コメントノード|
| 3| テキストノード| 9| 文書ノード|
| 4| CDATAセクション| 10| 文書型宣言ノード|
| 5| 実体参照ノード| 11| 文書の断片|
| 6| 実体宣言ノード| 12| 記法宣言ノード|


##イベントドリブンモデル
HP上では、イベントを基準として特定の処理を開始する。このモデルのことをイベントドリブンモデルと言う。イベントには、click,load,scrollなど多くの種類がありこのイベントが処理の発火基準となる。そして、このイベントをもとに発火される処理のことをイベントハンドラー・イベントリスナーと呼ぶ。違いは書き方で以下参照
定義の仕方は以下の手順となる。

 - どの要素で発生した
 - どのイベントを
 - どのイベントハンドラー・イベントリスナーに紐付けるか

となり、書き方は以下のよ３つがある

 - タグ内に直接記入　（イベントハンドラー）
 - 要素オブジェクトのプロパティとして宣言　（イベントハンドラー）
 - addEventListenerメソッドを使う　（イベントリスナー）

###タグ内に直接記入
タグ内に直接記入するのは、本当に簡単な処理のみの場合となるが、基本的にコードの可読性から「ページ構成と処理とは明確に分離させる」と言う考えからあまりしない方がいい。
例

```html
<input type="button" value="ダイアログ表示" onclick="window.alert('ボタンが表示されました。');"/>
```

イベントをonイベント名="JSのコード"　と書く。

###要素オブジェクトのプロパティとして宣言
HTMLとJSのファイルに分けて、ページ構成と処理を分離させる。
例

```html
<input id="btn" type="button" value="ダイアログ表示" />
```

```js
window.onload = function(){
  document.getElementById('btn').onclick = function(){
    window.alert('ボタンがクリックされました');
  };
};
```

getElementByIdにおいてid指定で要素を取得、onclickでクリックイベントに =function で処理の関数と定義している。
onloadはページが全て読み込まれた際に実行されるイベントハンドラーを登録している。

###addEventListenerメソッドを使う
上記まででかけるのでは？addEventListenerは何のためにあるのか？と思うが、その違いは
・onxxxxは**同一要素/同一のイベントに対して、複数のイベントハンドラーを紐付けられない**
・addEventListenerは**複数のイベントリスナーを紐付けられる**
と言う違いがあります。イベントに複数のイベントリスナーを定義したい場合はこちらを使う。
書き方は、少し変わってくるので注意

```html
<input id="btn" type="button" value="ダイアログ表示" />
```

```js
document.addEventListener('DOMContentLoaded',function(){
  document.getElementById('btn').addEventListener('click',function(){
    window.alert('ボタンがクリックされました');
  },false);
},false);
````

となる。「DOMContentLoaded」はonloadと同じだが、
・onloadは全てのページを読み込んでから処理を実行
・DOMContentLoadedはコンテンツ本体がロード（画像のロードを待たない）されたところで実行
と言う違いがあり、後者の方が処理が早くなる。基本は後者を使う。

addEventListener('イベント名','処理','イベントの方向')と書く。


以上が、DOMにおいての要素の特定方法となる。これをもとに次は値の取得や設定を行う。

→　次回：[属性値やテキストの取得](https://qiita.com/TaHiroki/items/5e6b818e13e927f8a2ef)