JavaScriptによるDOM操作




## インターフェース(単数ノード)

```:継承
 Node
  └ Element
  │  └ HTMLElement
  │     ├ HTMLAnchorElement
  │     ├ HTMLAreaElement
  │     ├ HTMLAudioElement
  │     ├ ....
  │
  ├ Text
  ├ Comment
```


### Node
DOMを構成する文字列、コメント、タグなどを扱うためのインターフェースです。
例
`<!DOCTYPE html>` 
`<!-- cmment -->` 
`<p>Text</p>` (p要素も、その中のテキストも別のノード)


### Element
Nodeを継承しています。
例
 `<xml>` 
 `<svg>`

### HTMLElement
Elementを継承しています。
例
`<header>`
`<main>`
`<footer>`
`<article>`
`<section>`
`<aside>`
`<nav>`


### HTML(*)Element
HTMLElementを継承しています。

|HTMLタグ|インターフェース|
|---|---|
|`<a>`|HTMLAnchorElement|
|`<area>`|HTMLAreaElement|
|`<audio>`|HTMLAudioElement|
|`<br>`|HTMLBRElement|
|`<base>`|HTMLBaseElement|
|`<blockquote>`、`<q>`|HTMLQuoteElement|
|`<body>`|HTMLBodyElement|
|`<button>`|HTMLButtonElement|
|`<canvas>`|HTMLCanvasElement|
|`<dl>`|HTMLDListElement|
|`<data>`|HTMLDataElement|
|`<datalist>`|HTMLDataListElement|
|`<details>`|HTMLDetailsElement|
|`<div>`|HTMLDivElement|
|`<embed>`|HTMLEmbedElement|
|`<fieldset>`|HTMLFieldSetElement|
|`<form>`|HTMLFormElement|
|`<h1>`～`<h6>`|HTMLHeadingElement|
|`<head>`|HTMLHeadElement|
|`<hr>`|HTMLHRElement|
|`<html>`|HTMLHtmlElement|
|`<iframe>`|HTMLIFrameElement|
|`<img>`|HTMLImageElement|
|`<input>`|HTMLInputElement|
|`<label>`|HTMLLabelElement|
|`<legend>`|HTMLLegendElement|
|`<li>`|HTMLLIElement|
|`<link>`|HTMLLinkElement|
|`<map>`|HTMLMapElement|
|`<media>`|HTMLMediaElement|
|`<meta>`|HTMLMetaElement|
|`<meter>`|HTMLMeterElement|
|`<del>`、`<ins>`|HTMLModElement|
|`<ol>`|HTMLOListElement|
|`<object>`|HTMLObjectElement|
|`<optgroup>`|HTMLOptGroupElement|
|`<option>`|HTMLOptionElement|
|`<output>`|HTMLOutputElement|
|`<p>`|HTMLParagraphElement|
|`<param>`|HTMLParamElement|
|`<pre>`|HTMLPreElement|
|`<progress>`|HTMLProgressElement|
|`<script>`|HTMLScriptElement|
|`<select>`|HTMLSelectElement|
|`<slot>`|HTMLSlotElement|
|`<source>`|HTMLSourceElement|
|`<span>`|HTMLSpanElement|
|`<style>`|HTMLStyleElement|
|`<caption>`|HTMLTableCaptionElement|
|`<th>`、`<td>`|HTMLTableCellElement|
|`<col>` 、`<colgroup>`|HTMLTableColElement|
|`<table>`|HTMLTableElement|
|`<tr>`|HTMLTableRowElement|
|`<thead>`、`<tbody>`、`<tfoot>`|HTMLTableSectionElement|
|`<template>`|HTMLTemplateElement|
|`<textarea>`|HTMLTextAreaElement|
|`<time>`|HTMLTimeElement|
|`<title>`|HTMLTitleElement|
|`<track>`|HTMLTrackElement|
|`<ul>`|HTMLUListElement|
|`<video>`|HTMLVideoElement|
※`<audio>`と`<video>`はHTMLMediaElementも継承しています。

### Text
Node を継承しています。

### Comment
Node を継承しています。


### ノードの種類の判定

```:js
console.log(sampleNode.nodeType);
```

|ノードの種類|nodeTypeの返り値|
|---|---|
|ELEMENT_NODE|1|
|TEXT_NODE|3|
|PROCESSING_INSTRUCTION_NODE|7|
|COMMENT_NODE|8|
|DOCUMENT_NODE|9|
|DOCUMENT_TYPE_NODE|10|
|DOCUMENT_FRAGMENT_NODE|11|



## インターフェース(複数ノード)

### HTMLCollectionとNodeListの共通点
配列風インターフェースです。
動的(取得後にDOMに変更があった場合はリアルタイムで中身が変わる)※querySelectorAll()を除く

### HTMLCollectionとNodeListの違い

|インターフェース|違い|
|---|---|
|HTMLCollection|要素ノード以外のノードを含まない|
|NodeList|要素ノード以外のノードを含んでいる可能性がある|




### HTMLCollectionを取得するメソッド

#### getElementsByTagName
`document.getElementsByTagName()`
`element.getElementsByTagName()`
タグ名を指定して取得します。

```:html
<div>a</div>
<div>b</div>
<div>c</div>
```

```:js
const sampleDivs = document.getElementsByTagName("div");
console.log(sampleDivs);
```


#### getElementsByClassName
`document.getElementsByClassName()`
`element.getElementsByClassName()`
クラス名を指定して取得します。

```:html
<div class="box">a</div>
<div class="box">b</div>
<div class="box">c</div>
```

```:js
const boxes = document.getElementsByClassName("box");
console.log(boxes); //HTMLCollection(3) [div.box, div.box, div.box]
```

### HTMLCollectionを取得するプロパティ

|HTMLCollectionを返すプロパティ|内容|
|---|---|
|document.forms|ドキュメント内のform要素ノードを全て格納したもの|
|document.images|ドキュメント内のimg要素ノードを全て格納したもの|
|document.links|ドキュメント内のa、area要素ノードを全て格納したもの|
|node.children|指定したノードの子要素ノード全て格納したもの|




### HTML(*)Collection
HTMLCollectionを継承した独自のインターフェースです。



|HTML(*)Collection|内容|
|---|---|
|HTMLFormControlsCollection |<form> 要素内のフォーム系要素|
|HTMLOptionsCollection|option要素のコレクション|









### NodeListを取得するメソッド

#### getElementsByName
`document.getElementsByName()`
name属性の値で取得します。
※IE,EdgeはHTMLCollectionを返します。

```:html
<div name="box">a</div>
<div name="box">b</div>
<div name="box">c</div>
```

```:js
const boxes = document.getElementsByName("box");
console.log(boxes);
```

#### querySelectorAll()
`document.querySelectorAll()`
`element.querySelectorAll()`
CSSセレクタでマッチした要素全てを取得します。

```:html
<div class="box">a</div>
<div class="box">b</div>
<div class="box">c</div>
```
```:js
const box = document.querySelectorAll(".box");
console.log(box); //NodeList(3) [div.box, div.box, div.box]
```

##### 静的なNodeList
`querySelectorAll()`で取得した場合、静的なNodeListになります。
取得後にDOMに変更があった場合も中身が変わりません。
その時点でのノードを静的リストに集めるので、取得時にパフォーマンスの低下を引き起こします。



### NodeListを取得するプロパティ

|NodeListを返すプロパティ|内容|
|---|---|
|node.childNodes|指定したノードの子ノード全て格納したもの|







### NodeListとHTMLCollectionの使い方
NodeList、HTMLCollectionはそのままでは要素を扱えません。

#### for文を使う
##### HTMLCollection

```:html
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
```

```:js
const divCollection = document.getElementsByTagName("div");
console.log(divCollection); //HTMLCollection

for (let i = divCollection.length; i--;) {
  console.log(divCollection[i]); //各div
}
```

##### NodeList

```:html
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
```

```:js
const divList = document.querySelectorAll("div");
console.log(divList); //NodeList

for (let i = divList.length; i--;) {
  console.log(divList[i]); //各div
}
```


#### for ...ofを使う
##### HTMLCollection

```:html
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
```

```:js
const divCollection = document.getElementsByTagName("div");
console.log(divCollection); //HTMLCollection

for (const div of divCollection) {
  console.log(div); //各div
}
```

##### NodeList

```:html
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
```

```:js
const divList = document.querySelectorAll("div");
console.log(divList); //NodeList

for (const div of divList) {
  console.log(div);
}
```

#### forEachを使う
##### HTMLCollection
HTMLCollectionはforEachが使えません。

##### NodeList

```:html
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
```

```:js
const divList = document.querySelectorAll("div");
console.log(divList); //NodeList

divList.forEach((div) => {
  console.log(div); //各div
})
```

#### 配列に変換する
[JavaScriptの配列](https://qiita.com/takeshisakuma/items/b23b1a748098f30e2ff2) 記事書きました。

##### HTMLCollection

```:html
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
```

```:js
const divCollection = document.getElementsByTagName("div");
console.log(divCollection); //HTMLCollection 

//配列化
const divArray = [...divCollection];

//配列か判定
console.log(Array.isArray(divArray)); //true
```




##### NodeList

```:html
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
```

```:js
const divList = document.querySelectorAll("div");
console.log(divList); //NodeList
 
//配列化
const divArray = [...divList];
 
//配列か判定
console.log(Array.isArray(divArray)); //true
```


#### HTMLCollection、NodeListからノードを取り出す

```:html
<div class="box" id="sampleDiv1">1</div>
<div class="box" id="sampleDiv2">2</div>
<div class="box" id="sampleDiv3">3</div>
<div class="box" id="sampleDiv4">4</div>
```

```:js
const sampleHTMLCollection = document.getElementsByClassName("box");
const sampleNodeList = document.querySelectorAll("box");

//HTMLCollectionを取得
console.log(sampleHTMLCollection);

//NodeListを取得
console.log(sampleNodeList); 

//HTMLCollectionの長さを取得
console.log(sampleHTMLCollection.length); 

//NodeListの長さを取得
console.log(sampleNodeList.length); 

//0番目の要素ノードを取得
console.log(sampleHTMLCollection[0]); 

//0番目のノードを取得
console.log(sampleNodeList[0]); 
```

### インターフェースの判定
例：divならNode、Element、HTMLElement、HTMLDivElementの4つがtrueになります。

```:js
console.log(sampleNode instanceof Node);
console.log(sampleNode instanceof Element);
console.log(sampleNode instanceof HTMLElement);
console.log(sampleNode instanceof HTMLDivElement);//divの場合(他の要素ノードの場合はHTML(*)Elementの表参照)
console.log(sampleNode instanceof Text);
console.log(sampleNode instanceof Comment);
console.log(sampleNodes instanceof HTMLCollection);
console.log(sampleNodes instanceof NodeList);
```








## 取得

親要素への参照を取得済みの場合はdocument全体を指定する代わりに要素の子だけを指定可能です。
(対象を絞ってセレクターをシンプルにしてパフォーマンスを向上)


### HTMLElementを取得するメソッド

#### getElementById
`document.getElementById()`
`element.getElementById()`はありません。
IDを指定して要素を取得します。
もし存在しなかった場合は null を返します。
※同じIDを持つ要素が複数存在する場合は最初の要素のみ取得



```:html
<div class="first">a</div>
<div class="second">b</div>
<div class="third">c</div>
```

```:js
const secondBox = document.getElementById("second");
console.log(secondBox);
```

#### querySelector()
`document.querySelector()`
`element.querySelector()`
CSSセレクタでマッチした最初の要素を取得します。

```:html
<div class="box">a</div>
<div class="box">b</div>
<div class="box">c</div>
```

```:js
const box = document.querySelector(".box");
console.log(box);//<div class="box">a</div>
```




### html要素、head要素、body要素の取得

```:js
const html = document.documentElement;
console.log(html);

const head = document.head;
console.log(head);

const body = document.body;
console.log(body);
```





### 要素がCSSセレクタと一致しているか確認

```:html
<div id="parent">
  <p id="child" class="great">
    サンプルテキスト
  </p>
</div>
```

```:js
//調べたいノードを取得
const child = document.getElementById("child");

//CSSセレクタと一致しているか確認
console.log(child.matches("div#parent p.great")); //true
```






### 祖先
#### 取得
CSSセレクタで祖先を取得します。
(自分自身も取得できます。)

```:html
<div id="ancestor">
  <div id="parent">
    <div id="child">
      <div id="grandchild">
      </div>
    </div>
  </div>
</div>
```

```:js
//基準となる#childを取得
const childElement = document.getElementById("child");

//祖先の取得
console.log(childElement.closest("#ancestor")); //取得可能

//親の取得
console.log(childElement.closest("#parent")); //取得可能

//自身の取得
console.log(childElement.closest("#child")); //取得可能

//子の取得
console.log(childElement.closest("#grandchild"));//null
```




### 親




#### 取得

||ノード全種|要素ノードのみ|
|---|---|---|
|親ノードを取得|parentNode|parentElement|



##### parentNodeとparentElementの違い

|プロパティ|html要素の親取得時|
|---|---|
|parentNode|Documentを返す|
|parentElement|nullを返す|

```:html
<div id="parent">
  <div id="child"></div>
</div>
```

```:js
//基準となる子要素の取得
const child = document.getElementById("child");

//子要素の親の取得
const parent = child.parentElement;
//const parent = child.parentNode;

//指定した要素ノードの親を取得
console.log(parent);
```

##### 子ノードを持つか判定

```:html
<div id="parent">
  <div id="child"></div>
</div>
```

```:js
//基準となる親要素の取得
const parent = document.getElementById("parent");

//指定の要素ノードが子ノードを持つか判定
console.log(parent.hasChildNodes()); //true
```






### 子


|プロパティ|ノード全種|要素ノードのみ|
|---|---|---|
|最初のノードを取得|firstChild|firstElementChild|
|親ノードを取得|parentNode|parentElementNode|
|子ノード(複数)|childNodes|children|
|最初の子ノード|firstChild|firstElementChild|
|最後の子ノード|lastChild|lastElementChild|







#### element.childrenとNode.childNodesの違い

|プロパティ|内容|
|---|---|
|element.children|HTMLCollectionになる|
|Node.childNodes|NodeList になる|



#### 子要素の取得

```:html
<div id="parent">
  <div id="child1"></div>
  <div id="child2"></div>
  <div id="child3"></div>

  <div id="childx"></div>
</div>
```

```:js
//基準となる親要素の取得
const parent = document.getElementById("parent");
 
//最初の子の取得
const child1 = parent.firstElementChild;
console.log(child1);
 
//最後の子の取得
const childx = parent.lastElementChild;
console.log(childx);
``` 


### 兄弟

|内容|ノード全種|要素ノードのみ|
|---|---|---|
|前のノード|previousSibling|previousElementSibling|
|次のノード|nextSibling|nextElementSibling|



```:html
<div class="box" id="box1">1</div>
<div class="box" id="box2">2</div>
<div class="box" id="box3">3</div>
```

```:js
const box2 = document.getElementById("box2");
 
console.log(box2.previousElementSibling);
console.log(box2.nextElementSibling);
```











## 要素ノードの作成

```:js
//要素ノードの作成
const sampleElement = document.createElement("div");
sampleElement.textContent = "サンプルテキスト";

//ドキュメント内に配置
document.body.appendChild(sampleElement);
```









## 要素ノードの追加

### 長子の追加

```:html
<div id="parent">
  <div id="child"></div>
</div>
```

```:js
//基準となる親ノードの取得
const parent = document.getElementById("parent");

//追加する要素ノードの作成
const newChild = document.createElement("div");
newChild.setAttribute("id", "newChild");

//最初の子として追加
parent.prepend(newChild);
``` 


### 末子の追加

```:html
<div id="parent">
  <div id="child"></div>
</div>
```

```:js
//基準となる親ノードの取得
const parent = document.getElementById("parent");

//追加する要素ノードの作成
const newChild = document.createElement("div");
newChild.setAttribute("id", "newChild");

//最後の子として追加
parent.appendChild(newChild);
``` 
appendChild()に似たメソッドとしてappend()があります。


||append()|appendChild()|
|---|---|---|
|対象|DOMStringも追加可能|Node オブジェクトのみ|
|戻り値|なし|追加されたNode オブジェクトを返す|
|数|複数のノードや文字列を追加可能|一つのノードだけ|



### 指定の子要素の前に追加

```:html
<div id="parent">
  <div id="child_1"></div>
  <div id="child_2"></div>
</div>
```

```:js
//基準となる親ノードの取得
const parent = document.getElementById("parent");
         
//基準となる二番目の子の取得
const child2 = document.getElementById("child_2");
 
//追加する要素ノードの作成
const newChild = document.createElement("div");
newChild.setAttribute("id", "newChild");
 
//二番目の子の前に追加
parent.insertBefore(newChild, child2);
```


### 指定要素の前に追加

```:html
<div id="parent">
  <div id="child_1"></div>
  <div id="child_2"></div>
</div>
```

```:js
//基準となる二番目の子の取得
const child2 = document.getElementById("child_2");
 
//追加する要素ノードの作成
const newChild = document.createElement("div");
newChild.setAttribute("id", "newChild");
 
//二番目の子の前に追加
child_2.before(newChild);
```

### 指定要素の後に追加

```:html
<div id="parent">
  <div id="child_1"></div>
  <div id="child_2"></div>
</div>
```

```:js
//基準となる1番目の子の取得
const child1 = document.getElementById("child_1");
 
//追加する要素ノードの作成
const newChild = document.createElement("div");
newChild.setAttribute("id", "newChild");
 
//1番目の子の後に追加
child_1.after(newChild);
```







### HTML要素の追加



|引数|挿入位置|
|---|---|
|beforebegin|親要素の直前|
|afterbegin|親要素内の先頭|
|beforeend|親要素の末尾|
|afterend|親要素の直後|

```:html
<div id="parent">
  <div id="child1"></div>
  <div id="child2"></div>
</div>
```

```:js
//基準となる親を取得
const parent = document.getElementById("parent");
 
//div要素を作成して親の前に追加
const newDiv = document.createElement('div');
parent.insertAdjacentElement("beforebegin", newDiv);
 
//p要素を作成して親の後に追加
const newP = document.createElement('p');
parent.insertAdjacentElement("afterend", newP);
 
//span要素を作成して最初の子として追加
const newSpan = document.createElement('span');
parent.insertAdjacentElement("afterbegin", newSpan);
 
//strong要素を作成して最後の子として追加
const newStrong = document.createElement('strong');
parent.insertAdjacentElement("beforeend", newStrong);
```







### 文字列をHTMLとして追加

|引数|挿入位置|
|---|---|
|beforebegin|親要素の直前|
|afterbegin|親要素内の先頭|
|beforeend|親要素の末尾|
|afterend|親要素の直後|


```:html
<div id="parent">
  <div id="child1"></div>
  <div id="child2"></div>
</div>
```

```:js
//基準となる親を取得
const parent = document.getElementById("parent");

//div要素を作成して親の前に追加
const inserBeforeParent = "<div>parentの前</div>"
parent.insertAdjacentHTML("beforebegin", inserBeforeParent);

//div要素を作成して親の後に追加
const inserAfterParent = "<div>parentの後</div>"
parent.insertAdjacentHTML("afterend", inserAfterParent);

//div要素を作成して最初の子として追加
const inserBeforeFirstChild = "<div>parentの最初の子の前</div>"
parent.insertAdjacentHTML("afterbegin", inserBeforeFirstChild);

//div要素を作成して最後の子として追加
const inserAfterLastChild = "<div>parentの最後の子の後</div>"
parent.insertAdjacentHTML("beforeend", inserAfterLastChild);
```










## 削除
### ノードの削除

```:html
<div id="parent">
  <div id="child1"></div>
  <div id="child2"></div>
</div>
```

```:js
const child1 = document.getElementById("child1");
child1.remove();
```

### 子ノードの削除

```:html
<div id="parent">
  <div id="child1"></div>
  <div id="child2"></div>
</div>
```

```:js
const parent = document.getElementById("parent");

const child1 = document.getElementById("child1");
        
parent.removeChild(child1);
```






## 置換
### ノードの置換

```:html
<div id="parent">
  <div id="child"></div>
</div>
```

```:js
//置換対象の要素ノードを取得
const child = document.getElementById("child");

//新しい要素ノードを作成
const newChild = document.createElement("div");
newChild.classList.add("newChild");

//置換
child.replaceWith(newChild);
```

### 子ノードの置換

```:html
<div id="parent">
  <div id="child"></div>
</div>
```

```:js
const parent = document.getElementById("parent");

const child = document.getElementById("child");

const newChild = document.createElement("newChild");
newChild.classList.add("newChild");

parent.replaceChild(newChild, child);
```













## 複製

### ノードの複製

|cloneNodeの引数|内容|
|---|---|
|true|子ノードを含めて複製|
|false|子ノードを含めず複製|


```:html
 <div id="box"></div>
```

```:js
//複製元の要素の取得
const box = document.getElementById("box");

//複製
const clonedBox = box.cloneNode(true);

//配置
document.body.appendChild(clonedBox);
```





## テーブル

### table

#### table用の情報の取得

|プロパティ|内容|
|---|---|
|caption|table要素のcaption要素を返す|
|tHead|table要素のthead要素を返す|
|tBodies|table要素のthead要素を返す(bodyは複数ある可能性があるのでHTMLCollectionで返る)|
|tBodies.length|tBodiesの数を返す|
|tFoot|table要素のtfoot要素を返す|


```:html
<table id="sampleTable">

  <caption>キャプション</caption>

  <thead>
    <tr id="sampleTr1">
      <th>ヘッダーセル1</th>
      <th>ヘッダーセル2</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>データセル1</td>
      <td>データセル2</td>
    </tr>
  </tbody>
  
  <tfoot>
    <tr>
      <td>フッターセル1</td>
      <td>フッターセル2</td>
    </tr>
  </tfoot>
  
</table>
```

```:js
const sampleTable = document.getElementById("sampleTable");
        
console.log(sampleTable.caption); //table要素のcaptionを取得
console.log(sampleTable.tHead); //table要素のtHeadを取得
console.log(sampleTable.tBodies); //table要素のtBodiesを取得
console.log(sampleTable.tBodies.length); //table要素のtBodiesの数を取得
console.log(sampleTable.tFoot); //table要素のtFootを取得
```

#### 作成

|メソッド|内容|
|---|---|
|createCaption()|captionを作成(captionが存在した場合は既存のtheadを返す)|
|createTHead()|theadを作成(theadが存在した場合は既存のtheadを返す)|
|createTBody()|tbodyを作成|
|createTFoot()|tfootを作成(tfootが存在した場合は既存のtfootを返す)|





```:html
<table id="sampleTable">
</table>
```

```:js
const sampleTable = document.getElementById("sampleTable");

sampleTable.createCaption(); //table要素にcaptionを作成
sampleTable.createTHead(); //table要素にtHeadを作成
sampleTable.createTBody(); //table要素にtBodyを作成
sampleTable.createTFoot(); //table要素にtFootを作成
```

#### 削除

|メソッド|内容|
|---|---|
|deleteCaption()|captionが無い場合は何も起きない(エラーにもならない)|
|deleteTHead()|theadが無い場合は何も起きない(エラーにもならない)|
|deleteTBody()|tbodyが無い場合は何も起きない(エラーにもならない)|
|deleteTFoot()|tfootが無い場合は何も起きない(エラーにもならない)|


```:html
<table id="sampleTable">

  <caption>キャプション</caption>

  <thead>
    <tr id="sampleTr1">
      <th>ヘッダーセル1</th>
      <th>ヘッダーセル2</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>データセル1</td>
      <td>データセル2</td>
    </tr>
  </tbody>
  
  <tfoot>
    <tr>
      <td>フッターセル1</td>
      <td>フッターセル2</td>
    </tr>
  </tfoot>
  
</table>
```

```:js
const sampleTable = document.getElementById("sampleTable");

sampleTable.deleteCaption(); //table要素のcaptionを削除
sampleTable.deleteTHead(); //table要素のtHeadを削除
sampleTable.deleteTFoot(); //table要素のtFootを削除
```








### 列・セル

#### 列・セルの取得

|プロパティ|要素|内容|
|---|---|---|
|rows|table要素のプロパティ|そのテーブルが持つtr要素をHTMLCelloctionで返す|
|cells|tr要素のプロパティ|その列が持つセルをHTMLCelloctionで返す|

```:html
<table id="sampleTable">

  <caption>キャプション</caption>

  <thead>
    <tr id="sampleTr1">
      <th>ヘッダーセル1</th>
      <th>ヘッダーセル2</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>データセル1</td>
      <td>データセル2</td>
    </tr>
  </tbody>
  
  <tfoot>
    <tr>
      <td>フッターセル1</td>
      <td>フッターセル2</td>
    </tr>
  </tfoot>
  
</table>
```

```:js
const sampleTable = document.getElementById("sampleTable");
console.log(sampleTable.rows);

const sampleTr1 = document.getElementById("sampleTr1");
console.log(sampleTr1.cells);
```

#### 列・セルの追加

|メソッド|要素|内容|
|---|---|---|
|insertRow()|table要素のメソッド|指定した番目の列の追加|
|insertCell()|tr要素のメソッド|指定した番目のセルの追加|

```:html
<table id="sampleTable">

  <caption>キャプション</caption>

  <thead>
    <tr id="sampleTr1">
      <th>ヘッダーセル1</th>
      <th>ヘッダーセル2</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>データセル1</td>
      <td>データセル2</td>
    </tr>
  </tbody>
  
  <tfoot>
    <tr>
      <td>フッターセル1</td>
      <td>フッターセル2</td>
    </tr>
  </tfoot>
  
</table>
```

```:js
const sampleTable = document.getElementById("sampleTable");
sampleTable.insertRow(3); //テーブル内に4番目のtrが追加される

const sampleTr1 = document.getElementById("sampleTr1");
sampleTr1.insertCell(0); //sampleTr1の最初の子としてtdが追加される
```

#### 列・セルの削除

|メソッド|要素|内容|
|---|---|---|
|deleteRow()|table要素のメソッド|指定した番目の列の削除|
|deleteCell()|tr要素のメソッド|指定した番目のセルの削除|

```:html
<table id="sampleTable">

  <caption>キャプション</caption>

  <thead>
    <tr id="sampleTr1">
      <th>ヘッダーセル1</th>
      <th>ヘッダーセル2</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>データセル1</td>
      <td>データセル2</td>
    </tr>
  </tbody>
  
  <tfoot>
    <tr>
      <td>フッターセル1</td>
      <td>フッターセル2</td>
    </tr>
  </tfoot>
  
</table>
```

```:js
const sampleTable = document.getElementById("sampleTable");
sampleTable.deleteRow(1); //テーブル内の2番目のtrが削除される

const sampleTr1 = document.getElementById("sampleTr1");
sampleTr1.deleteCell(0); //sampleTr1の最初のセルが削除される
```

#### 列・セルの位置

|プロパティ|要素|内容|
|---|---|---|
|rowIndex|tr要素のプロパティ|テーブル要素の中でそのtrが何番目か|
|cellIndex|th要素、td要素のプロパティ|列の中でそのセルが何番目か|


```:html
<table id="sampleTable">

  <caption>キャプション</caption>

  <thead>
    <tr id="sampleTr1">
      <th id="sampleTh1">ヘッダーセル1</th>
      <th>ヘッダーセル2</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>データセル1</td>
      <td>データセル2</td>
    </tr>
  </tbody>
  
  <tfoot>
    <tr>
      <td>フッターセル1</td>
      <td>フッターセル2</td>
    </tr>
  </tfoot>
  
</table>
```

```:js
const sampleTr1 = document.getElementById("sampleTr1");
console.log(sampleTr1.rowIndex); //table内の何番目のtrかを取得

const sampleTd1 = document.getElementById("sampleTd1");
console.log(sampleTd1.cellIndex); //tr内の何番目のセルかを取得
```










## テキストノード

### テキストノードの作成

```:js
テキストノードの作成
const sampleText = document.createTextNode("サンプルテキスト");

//ドキュメント内に配置
document.body.appendChild(sampleText);
```


### テキストノードの取得
#### textContentによる取得

```:html
<div id="box">サンプルテキスト
  <span>サンプルテキスト</span>
  <span>サンプルテキスト</span>
</div>
```

```:js
const box = document.getElementById("box");

console.log(box.textContent); //boxの子ノードのテキストノード3つのテキストを併せたものを取得
```

#### nodeValueによる取得

```:html
<div id="box">サンプルテキスト
  <span>サンプルテキスト</span>
  <span>サンプルテキスト</span>
</div>
```

```:js
const box = document.getElementById("box");

console.log(box.firstChild.nodeValue); //box直下のテキストノードのみ取得
```

### テキストノードの置換
HTMLを書いてもタグは文字列として出力されます。

#### textContentによる置換

```:html
<div id="box">サンプルテキスト
  <span>サンプルテキスト</span>
  <span>サンプルテキスト</span>
</div>
```

```:js
const box = document.getElementById("box");

box.textContent = "書き換えたテキスト";//boxの子ノードがテキストノード「書き換えたテキスト」だけになる
```

#### nodeValueによる置換

```:html
<div id="box">サンプルテキスト
  <span>サンプルテキスト</span>
  <span>サンプルテキスト</span>
</div>
```

```:js
const box = document.getElementById("box");

box.firstChild.nodeValue = "書き換えたテキスト";//box直下のテキストノードだけが「書き換えたテキスト」になる
```

### テキストノードの削除
#### textContentによる削除

```:html
<div id="box">サンプルテキスト
  <span>サンプルテキスト</span>
  <span>サンプルテキスト</span>
</div>
```

```:js
const box = document.getElementById("box");

box.textContent = ""; //boxの子ノード全てが削除される
```

#### nodeValueによる削除

```:html
<div id="box">サンプルテキスト
  <span>サンプルテキスト</span>
  <span>サンプルテキスト</span>
</div>
```

```:js
const box = document.getElementById("box");

box.firstChild.nodeValue = ""; //box直下のテキストノードだけが削除される
```





## コメントノード

### コメントノードの作成

```:js
コメントノードの作成
const myComment = document.createComment('サンプルテキスト');

//ドキュメント内に配置
document.body.appendChild(myComment);
```

















## 属性ノード

属性ノードは、要素ノードの中にありますが、子ノードではありません。


|テキストノードと属性ノードの違い|関係性|
|---|---|
|要素ノードとテキストノード|親と子供|
|要素ノードと属性ノード|親とアクセサリー|



### 属性ノードの取得

```:html
<a href="https://www.google.co.jp" target="_blank" id="anchor">サンプルテキスト</a>
```

```:js
const sampleAnchor = document.getElementById("anchor");

console.log(sampleAnchor.getAttribute("target")); //_blank
```




### 特定の属性を持つ要素の取得
```:html
<a href="test1.html">サンプルテキスト1</a>
<a href="https://www.google.co.jp" target="_blank">サンプルテキスト2</a>
<a href="test2.html">サンプルテキスト3</a>
```

```:js
const sampleAnchor = document.querySelector("[target]");
console.log(sampleAnchor);

```

### 特定の属性が特定の値を持つ要素を取得する
```:html
<a href="https://www.google.co.jp" target="_blank">サンプルテキスト1</a>
<a href="https://www.google.co.jp" target="_self">サンプルテキスト2</a>
<a href="https://www.google.co.jp" target="_top">サンプルテキスト3</a>
<a href="https://www.google.co.jp" target="_parent">サンプルテキスト4</a>
```

```:js
const sampleAnchor = document.querySelector('[target="_top"]');
console.log(sampleAnchor);

```




### 属性ノードの置換

```:html
<a href="https://www.google.co.jp" target="_blank" id="anchor">サンプルテキスト</a>
```

```:js
const sampleAnchor = document.getElementById("anchor");

sampleAnchor.setAttribute("target", "_self");
```

### 属性ノードの削除

```:html
<a href="https://www.google.co.jp" target="_blank" id="anchor">サンプルテキスト</a>
```

```:js
const sampleAnchor = document.getElementById("anchor");

sampleAnchor.removeAttribute("target");
```

### 属性ノードの属性の作成、追加
作成はdocumentオブジェクトに対して行います。

```:html
<a href="https://www.google.co.jp" id="anchor">サンプルテキスト</a>
```

```:js
//属性を追加する要素を取得
const sampleAnchor = document.getElementById("anchor");

//属性の作成
const sampleAttribute = document.createAttribute("target");

//属性に値を与える
sampleAttribute.value = "_blank";
 
//要素に属性を追加する
sampleAnchor.setAttributeNode(sampleAttribute);
```

### 属性ノードの有無の判定

```:html
<a href="https://www.google.co.jp" target="_blank" id="anchor">サンプルテキスト</a>
```

```:js
const sampleAnchor = document.getElementById("anchor");

console.log(sampleAnchor.hasAttribute("target")); //true
```





## カスタムデータ属性
``` data-*="値" ```の形
属性ノードなのでgetAttribute()、setAttribute()、hasAttribute()、removeAttribute()も使用できます。

例として、data-testとして追加します。

### カスタムデータ属性の追加、更新



```:html
<div id="box"></div>
```

```:js
const box = document.getElementById("box");

box.dataset.test = "myValue";
```

### 特定のカスタムデータ属性を持つ要素の取得
data属性の存在自体の有無で絞り込み

```:html
<div data-test="box">1</div>
<div>2</div>
<div data-test="box">3</div>
```


```:js
const boxes = document.querySelectorAll("[data-test]");
console.log(boxes);
```

### 特定の カスタムデータ属性が特定の値を持つ要素を取得する

```:html
<div data-test="box1">1</div>
<div data-test="box2">2</div>
<div data-test="box3">3</div>
```

```:js
const boxes = document.querySelectorAll('[data-test="box2"]');
console.log(boxes);
```


## クラス
### クラスの追加

```:html
<div id="box"></div>
```

```:js
const box = document.getElementById("box");

box.classList.add("great");
```

### クラスの削除

```:html
<div id="box" class="great"></div>
```

```:js
const box = document.getElementById("box");

box.classList.remove("great");
```

### クラスの有無の判定

```:html
 <div id="box" class="great"></div>
```

```:js
const box = document.getElementById("box");

console.log(box.classList.contains("great")); //true
```

### クラスの有無のスイッチング

```:html
<div id="box1" class="great"></div>
<div id="box2"></div>
```

```:js
const box1 = document.getElementById("box1");
const box2 = document.getElementById("box2");
 
box1.classList.toggle("great");
console.log(box1); //.greatなし
 
box2.classList.toggle("great");
console.log(box2); //.greatあり
```












## スタイル
### スタイルの取得
要素.style.プロパティでは、外部のCSS取得できないので、getComputedStyle(要素ノード).プロパティを使います。

```:html
 <div id="box">サンプルテキスト</div>
```

```:css
#box{
  color:red;
}
```

```:js
//.boxを取得
const box = document.getElementById("box");

/計算後のスタイルを取得
console.log(getComputedStyle(box).color); //rgb(255, 0, 0)
```


### スタイルの変更

```:html
<div id="box" style="color:red">サンプルテキスト</div>
```

```:js
const box = document.getElementById("box");

box.style.color = "blue";
```

### スタイルの追加

```:html
<div id="box" style="color:red">サンプルテキスト</div>
```

```:js
const box = document.getElementById("box");

box.style.fontWeight="bold";
```

### スタイルの削除

```:html
<div id="box" style="color:red">サンプルテキスト</div>
```

```:js
const box = document.getElementById("box");

box.style.color = "";
```





## HTML

### 指定要素内のHTML操作
#### 指定要素内のHTMLの取得

```:html
<div id="parent">
  <div id="child">サンプルテキスト</div>
</div>
```

```:js
const parent = document.getElementById("parent");

console.log(parent.innerHTML);
```

#### 指定要素内のHTMLの置換

```:html
<div id="parent">
  <div id="child">サンプルテキスト</div>
</div>
```

```:js
const parent = document.getElementById("parent");

parent.innerHTML = "<p>書き換えられたHTML</p>";
```

#### 指定要素内のHTMLの削除

```:html
<div id="parent">
  <div id="child">サンプルテキスト</div>
</div>
```

```:js
const parent = document.getElementById("parent");

parent.innerHTML = "";
```

### 指定要素自体を含むHTML操作

#### 指定要素自体を含むHTMLの取得

```:html
<div id="parent">
  <div id="child">サンプルテキスト</div>
</div>
```

```:js
const parent = document.getElementById("parent");

console.log(parent.outerHTML);
```

#### 指定要素自体を含むHTMLの置換

```:html
<div id="parent">
  <div id="child">サンプルテキスト</div>
</div>
```

```:js
const parent = document.querySelector(".parent");

parent.outerHTML = "<div id='newParent'><div id='newChild'>書き換えられたHTML</div></div>";
```

#### 指定要素自体を含むHTMLの削除

```:html
<div id="parent">
  <div id="child">サンプルテキスト</div>
</div>
```

```:js
const parent = document.querySelector(".parent");

parent.outerHTML = "";
```












## DocumentFragment
アクティブなドキュメントツリー構造の一部ではないので、変更を行っても、ドキュメントに影響を与えません。

### メソッドの制限
DocumentFragment では使えるメソッドが限られています。

#### DocumentFragment 内にある要素を取得しようとした場合に使えるメソッド
`getElementById()`
`querySelector()`
`querySelectorAll()`

### パフォーマンスへの配慮
ブラウザー再描画の回数を減らすために、すべてのノードを一度DocumentFragmentに集めたあとにドキュメントに追加します。

```:html
<div id="parent"></div>
```

```:js
//親になる要素ノードを取得
const parent = document.getElementById("parent");
 
//DocumentFragmentを作成
const fragment = document.createDocumentFragment();
 
//追加する要素ノードを作成
const newDiv = document.createElement("div");
 
//属性ノードを作成
const newStyle = document.createAttribute("style");
newStyle.value = "color:red";
 
//テキストノードを作成
const newText = document.createTextNode("あたらしいテキスト");
 
//DocumentFragmentに、追加する要素ノードを追加
fragment.appendChild(newDiv);
 
//要素ノードに属性ノードを追加
newDiv.setAttributeNode(newStyle);
 
//要素ノードにテキストノードを追加
newDiv.appendChild(newText);
 
//DocumentFragmentを親になる要素ノードに追加
parent.appendChild(fragment);
```

## MutationObserver
DOMの変化を監視して処理を行う事ができます。

### オブザーバーの操作

#### オブザーバーの作成

```:js
const observer = new MutationObserver(records => {
 //監視対象に変化があったときの処理
})
```

#### 監視の開始
```:js
observer.observe(target, {
  //オプションの指定
})
```

#### 監視の停止

```:js
observer.disconnect()
``` 



### サンプル
#### 属性の変化を監視

|オプション|無い用|必須/任意|
|---|---|---|
|attributes|属性の変化を監視|必須|
|attributeFilter|監視対象とする属性名を配列で指定|任意|
|attributeOldValue|変更前の属性を記録|任意|


```:html
<p id="js-target">あああああ</p>
<button id="js-button">ボタン</button>
```

```:js
//監視対象の取得
const target = document.querySelector("#js-target");
 
//observerの作成
const observer = new MutationObserver(records => {
  // 属性が変更されたときの処理
  console.log("属性が変更された");
});
 
//監視の実行
observer.observe(target, {
  attributes: true,
  attributeFilter: ["class"],
  attributeOldValue: true
});
 
//監視のテスト用のボタンの取得
 const button = document.querySelector("#js-button");
 
//ボタンを押すと対象のクラスのトグル
button.addEventListener("click", () => {
  target.classList.toggle("active");
})
```

#### 文字データの変化を監視

|オプション|無い用|必須/任意|
|---|---|---|
|characterData|文字データの変化を監視|必須|
|characterDataOldValue|変更前の文字データを記録|任意|


```:html
<p id="js-target" contenteditable="true">あああああ</p>
```

```:js
//監視対象の取得
const target = document.querySelector("#js-target");
 
//observerの作成
const observer = new MutationObserver(records => {
  //テキストが変更されたときの処理
  console.log("テキストが変更された");
});
 
//監視の実行
observer.observe(target.childNodes[0], {
  characterData: true
});
```

#### 子要素リストの変化を監視

|オプション|無い用|必須/任意|
|---|---|---|
|childList|属性の変化を監視|必須|
|subtree|子孫ノードも監視対象にする|任意|


```:html
<p id="js-target">あああああ</p>
<button id="js-button">ボタン</button>
```

```:js
//監視対象の取得
const target = document.querySelector("#js-target");

//observerの作成
const observer = new MutationObserver(records => {
  // 子要素が変更されたときの処理
  console.log("属性が変更された");
});

//監視の実行
observer.observe(target, {
  childList: true
});

//監視のテスト用のボタンの取得
const button = document.querySelector("#js-button");

//ボタンを押すと監視対象の子要素spanを追加
button.addEventListener("click", () => {
  const child = document.createElement("span");
  target.appendChild(child);
})
```