利用頻度の高いDOM操作まとめ【JavaScript】

# 前置き
日頃よく使うDOM操作を備忘録としてまとめておいたメモです。
気分で更新する可能性あり。

# DOM取得/生成/削除

## 要素取得

### セレクタ指定
以下はdata属性から取得する例。

```js
const $button = document.querySelector('[data-button]');
```

idやclassに`[]`がある場合はバックスラッシュ2つを直前につける。

```html
<div id="[test]">test</div>
```
```js
const $test = document.querySelector('#\\[test\\]');
```

### 親要素

```js
const $parent = $element.parentNode;
```

### 兄弟要素

```js
const $prev = $element.previousElementSibling; // 直前の兄弟要素
const $next = $element.nextElementSibling; // 直後の兄弟要素
```

### 子要素

```js
const $top = $element.firstElementChild; //最初の子要素
const $last = $element.lastElementChild;  //最後の子要素
const $children = $element.children; //子要素リスト
```

## 要素生成
```js
const $element = document.createElement('div');
```

## 要素コピー 
```js
const $copyWithAllDescendants = $target.cloneNode(true);
```

Nodeの複製。子要素も含めてコピるときはtrueを渡す。

## 要素の挿入

以下はIE11非対応のため注意。

共通の仕様は

- 複数要素を指定可能(指定順に追加)
- 文字列指定可能(テキストとして挿入)
- 戻り値なし

### 最後の子要素として
`ParentNode.append()`

```js
const $parent = document.createElement('div');
const $child1 = document.createElement('p');
$child1.append('child1');
const $child2 = document.createElement('i');
$parent.append($child1, $child2); // <div><p>child1</p><i></i></div>
```

### 最前の子要素として
`ParentNode.preppend()`
### 直前の兄弟要素として
`ChildNode.before()`

### 直後の兄弟要素として
`ChildNode.after()`

### IE11も対応する時は

`Element.insertAdjacentElement(position, Element)`
または
`Element.insertAdjacentHTML(position, text)`

後者は文字列をHTMLとして挿入する。
`position`の値は以下。

- `beforeend` 最後の子要素として
- `afterbegin` 最前の子要素として
- `beforebegin` 直前の兄弟要素として
- `afterend` 直後の兄弟要素として

```js
$element.insertAdjacentHTML('afterend', '<div></div>');
```

## 要素の削除
```js
$element.parentNode.removeChild($element);
```

### 小要素をすべて削除する場合
```js
$list.textContent = null;
```

# DOMに対する操作

## 要素内のテキスト取得、設定

```js
// 取得
const text = document.querySelector(".class").textContent;
// 設定
$element.textContent = "this is some sample text";
```

## 要素の座標/幅/高さ取得

### 座標(現在のViewportに対する位置)の取得
`$element.getBoundingClientRect()` 

```js
const domRect = $element.getBoundingClientRect();
console.log(domRect);
// width:669.59375
// height:869
// top:1460
// bottom:2329
// left:293.203125
// right:962.796875
```

なお、`display: none;` のものはすべての値が0で返ってくる。

### スクロール量も加味した絶対位置を取得する場合

```js
const scrollY = window.pageYOffset || document.documentElement.scrollTop; // スクロール量
const elementTop = $element.getBoundingClientRect().top + scrollY; // スクロール量によらず一定な値が返される
```

### 幅/高さ取得バリエーション

```js
// border、padding、スクロールバーを含んだ幅(小数点以下あり)
element.getBoundingClientRect().width;
// border、padding、スクロールバーを含んだ幅(小数点切り上げ)
element.offsetWidth;
// paddingを含んだ幅
element.clientWidth;
// paddingを含んだ画面上に表示されていないコンテンツを含む幅
element.scrollWidth;

// スクリーンの幅取得
const vw = window.innerWidth;

// 端末の画面全体の大きさ
const screenHeight = window.screen.height;
// ヘッダーやフッターを除いた表示領域
const innderHeight = window.innerHeight;
```

### style取得

```js
const cssStyleDeclaration = getComputedStyle(document.querySelector('.selector'));
console.log(cssStyleDeclaration.opacity); // 1
```

#### 値をnumber型で取得する場合
```js
const heightNumber = parseInt(
  getComputedStyle($element).height.replace('px', ''),
  10,
);
```

# 参考にした記事

- [ライブラリを使わない素のJavaScriptでDOM操作 - Qiita](https://qiita.com/kouh/items/dfc14d25ccb4e50afe89)
- [全部言えたらDOMマスター！　HTML+DOMでノードを挿入する方法大全 - Qiita](https://qiita.com/uhyo/items/1c565b61d934cbb88c2e#nodeappendchild)