javascript DOM関連

# DOM

ブラウザがHTMLを読み込むと内部的にDOMというデータ構造が作られ、ページが描画される。
javascriptが操作するのはHTMLソースではなくDOMである。
DOMはdocumentオブジェクトから扱うことができる。

# 要素の操作

```javascript
document.querySelector('h1').textContent = 'changed';
document.getElementById('targer').textContent = 'changed';
document.querySelectorAll('p').textContent = 'changed';
document.querySelectorAll('p')[1].textContent = 'changed'; // 何番めかを指定できる
document.querySelectorAll('p').forEach((p,index) => {
    package.textContent = `${index}番目のpです`;
});
```

# イベントを設定する

addEventListener(イベントの種類,関数)

```javascript
document.querySelector('button').addEventListener('click', () => {
 document.getElementById('target').textContent = 'Changed!';
});
```

# classList

クラス名に関するあれこれ。

```javascript
const target = document.getElementById('target');

target.classList.add('クラス名');
target.classList.remove('クラス名');
target.classList.contains('クラス名'); //真偽値が返る
target.classList.toggle('クラス名');
```

# カスタムデータ属性
※これはHTMLの機能
javascriptで値を書き換えたいときなどに、値をHTMLの方に記述しておくことで見やすいコードとなる。

```html:HTML
<h1 id="target" data-transition="changed">更新前</h1>
```

```javascript:JS
const target = document.getElementById('target');

target.textContent = target.dataset.transition;
```

# 要素の追加

要素を作って、DOMに追加する。

- createElement()
- appendChild()

```javascript
const item2 = document.createElement('li'); //liタグを作る
item2.textContent = 'item 2'; //中身のテキストを作る


const ul = document.querySelector('ul'); //親DOMを取得
ul.appendChild(item2);//末尾の子要素として追加
```

# 要素の複製・挿入をする

- cloneNode()
- insertBefore()

```javascript
  document.querySelector('button').addEventListener('click', () => {
    const item0 = document.querySelectorAll('li')[0]; //複製対象の要素取得
    const copy = item0.cloneNode(true); //複製する

    const ul = document.querySelector('ul'); // 親ノード取得
    const item2 = document.querySelectorAll('li')[2]; //複製箇所取得
    ul.insertBefore(copy, item2); //複製処理
  });
```

# 要素の削除

- remove()
- removeChild():一部の古いブラウザで使用不可

```javascript
 document.querySelector('button').addEventListener('click', () => {
    const item1 = document.querySelectorAll('li')[1];

    // item1.remove();
    // 親Node.removeChild(削除するNode)
    document.querySelector('ul').removeChild(item1);
  });
```

# input要素の操作

```javascript
{
  document.querySelector('button').addEventListener('click', () => {
    const li = document.createElement('li');
    const text = document.querySelector('input');
    li.textContent = text.value; //value値を取得
    document.querySelector('ul').appendChild(li); //要素を追加

    text.value = ''; //入力欄を空にする
    text.focus(); //フォーカスを当てる
  });
}
```

# イベントオブジェクト

addEventListenerのコールバック関数に引数を渡すと、ブラウザがイベントに関する情報を渡してくれる。慣習的にeとする。

```javascript
{
  document.querySelector('button').addEventListener('dblclick', () => {
    console.log('Double Clicked!');
  });
  //マウスの位置を取得する
  document.addEventListener('mousemove', e => {
    console.log(e.clientX, e.clientY);
  });
  //押されたキーボードを取得する
  document.addEventListener('keydown', e => {
    console.log(e.key);
  });
}
```

# フォーム関連のイベント

- focus:フォーカスが当たってるとき
- blur:フォーカスが外れてるとき
- input:内容が更新されたとき
- change:更新が確定したとき
- submit:フォームが送信されたとき

フォームタグの中でボタンを配置しておくとクリックした時にsubmitイベントが発生する。
submitイベントが発生するとページ遷移が発生し、フォームのデータがサーバに送られる。
このデフォルトの挙動をキャンセルするには**preventDefault()**を呼び出す。

```javascript
{
  document.querySelector('form').addEventListener('submit', e => {
    e.preventDefault();
    console.log('submit');
  });
```

# イベントの伝搬

イベントは親ノードに伝搬するため、addEventListenerを対象の親ノードに設定しても上手く動作する。
e.targetで**実際にクリックされた対象**のノードが取得できる
e.currentTargetで**イベントを設定した**ノードが取得できる。

```javascript
  document.querySelector('ul').addEventListener('click', e => {
    if (e.target.nodeName === 'LI') {
      e.target.classList.toggle('done');
    }
  });
```