divタグをカスタマイズしてWYSIWYGエディタっぽいものを自作する

# 概要

divタグをカスタマイズしてWYSIWYGエディタっぽいものを作りたい。
WYSIWYGエディタ**っぽい**ものということで、WEBサイトの装飾ごとコピペができるようになるまで作ります。

# 環境
- html
- scss
- javascript

# 実装

### まずは見た目をテキストエリアに近づける

```html:html
<div class="textarea"></div>
```
```scss:scss
.textarea {
    width: 200px;
    height: 100px;
    border: solid 1px #a9a9a9;
    padding: 3px;
    overflow: auto;
}
```


### 入力を可能にする

devタグに`contenteditable="true"`を指定すると入力できるようなります

```html:html
<div
    class="textarea"
    contenteditable="true"
></div>
```
```scss:scss
.textarea {
    width: 200px;
    height: 100px;
    border: solid 1px #a9a9a9;
    padding: 3px;
    overflow: auto;
}
```

これで、他のページからhtmlタグやスタイルごとコピペできるようになります。

# placeholderを作る

### html部分
divタグにdata属性を付けて実装します

- `data-placeholderactive`でplaceholderのon/offできるようにする。デフォルトはon(true)
- `data-placeholder`でplaceholderとして表示するテキスト指定してする

```html:html
<div
    class="textarea"
    contenteditable="true"
    data-placeholderactive="true"
    data-placeholder="ここに文章を入力してください"
></div>
```

### CSS部分
data-placeholderactiveがtrueの時だけ、placeholderを表示するように設定します

```scss:scss
.textarea {
  width: 200px;
  height: 100px;
  border: solid 1px #a9a9a9;
  padding: 3px;
  overflow: auto;
  &[data-placeholderactive="true"]::before {
    content: attr(data-placeholder);
    opacity: .6;
  }
}
```

### javascript部分

- `textarea`クラスに対してイベントを設定
- 文字が入力されていたら、placeholderactiveをon(true)、そうでない場合はoff(false)とする

```javascript:javascript
var ele = document.getElementsByClassName("textarea")[0];
ele.addEventListener('input', function() {
    if ( ele.textContent.length === 0 ) {
        ele.setAttribute('data-placeholderactive','true');
    } else {
        ele.setAttribute('data-placeholderactive','false');
    }
});
```

# (仮)完成

こんな感じになります。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="ishi720" data-slug-hash="bGVQeEG" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="make wysiwyg editor div  @v1">
  <span>See the Pen <a href="https://codepen.io/ishi720/pen/bGVQeEG">
  make wysiwyg editor div  @v1</a> by ishi720 (<a href="https://codepen.io/ishi720">@ishi720</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>



# バグ修正

これで完成。と言いたいところですがバグがあります。
ということで、修正していきます。(コードは差分のみ記述します)

### 未入力の状態で改行するとplaceholderが残る問題

- (問題) Ender & backspaceすると想定した動きをしていない
- (原因) ele.textContent.lengthで改行がカウントされていない
- (対策) 文字数が0・改行コードが1の時は空にする必要がある

ということで修正(ちょっと雑ですが...)

```diff:javascript
var ele = document.getElementsByClassName("textarea")[0];
ele.addEventListener('input', function() {
-   if ( ele.textContent.length === 0 ) {
+   if ( ele.textContent.length === 0 && ( ele.innerText.match(/\r\n|\n/g) === null || ele.innerText.match(/\r\n|\n/g).length === 1 ) ) {
+       ele.textContent = "";//強制的に中身を空にする
        ele.setAttribute('data-placeholderactive','true');
    } else {
        ele.setAttribute('data-placeholderactive','false');
    }
});
```

# 完成したもの

まだバグがあるかもですが、以下が完成物となります。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="ishi720" data-slug-hash="YzymdOx" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="make wysiwyg editor @v2">
  <span>See the Pen <a href="https://codepen.io/ishi720/pen/YzymdOx">
  make wysiwyg editor @v2</a> by ishi720 (<a href="https://codepen.io/ishi720">@ishi720</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 終わり