メモ帳をつくる - 編集したHTML要素をlocalStorageに保存する方法

![editable_localStorage.gif](https://qiita-image-store.s3.amazonaws.com/0/268390/d92288b3-42ac-3c15-484c-1c8558671a8b.gif)

#はじめに
過去の投稿「[HTML要素を編集可能にする方法](https://qiita.com/elBlanco/items/c7c7a8e8124ed5b9c3f7)」、「[文字を装飾するボタンをつくる方法](https://qiita.com/elBlanco/items/46a5a608206fe1c17245)」に続いて、編集した内容を保存する方法を紹介します。
今回は比較的簡単な、localStorageによる保存方法を紹介します。

#localStorageについて
Javascriptを用いて、ユーザーのローカル(ブラウザ)上にデータを保存することができます。
サーバーサイドを扱う必要がなく、永続的にデータを保存できるので手軽で便利です。
詳しくは[こちらのサイト](https://qiita.com/elBlanco/items/c7c7a8e8124ed5b9c3f7)をご覧ください。
ここでは簡単な使い方の解説を行います。

##データの保存

```
localStorage.setItem('key', 'value');
```

「key」は任意の内容で構いませんが、keyを見て何を保存しているか分かる内容にしましょう。
「value」には保存したい内容を指定します。

##データの取得

```
localStorage.getItem('key');
```

「key」は保存したときに入力したkeyを指定します。

#HTMLの記述
##方針
・保存ボタンは使わず、編集の都度保存される仕組みにする
・HTML要素は、タイトルにh1タグ、コンテンツにdivタグを使用する
・h1タグ、divタグはJavascriptの処理によって、読み込み時に毎回HTMLファイルに追加されるようにする

データを保存するために使われる方法としては、ボタンの押下が一般的ではありますが、
今回は、ボタンを押さずとも、テキストを編集する都度保存する方法をとりたいと思います。
この方法であれば、「*あッ保存し忘れた！*」なんてことも起こりません。


##記述内容
h1タグ、divタグはJavascriptの処理で追加するため、HTMLに記述する内容はわずかです。
"wrapper"をidに指定したdivタグの中に、h1タグとdivタグを追加します。

```html:editable.html
<body>
   <div id="wrapper">
    <!-- Javascriptの処理により、h1タグ、divタグをこの場所に追加する -->            
   </div>
</body>
```

#Javascriptの記述
##データの保存
まずはデータの保存から。

```javascript:editable.js
//idを格納する変数を宣言
var thisId = "";

//編集された都度、内容をlocalStorageに保存する関数
function onInput(){
    //編集中のHTML要素のidを変数thisIdに格納
    thisId = document.activeElement.id;
    //編集中のHTML要素の内容を変数latestContentに格納
    const latestContent = document.getElementById(thisId).outerHTML;
    //変数latestContentの値をlocalStorageに保存。keyは変数thisId
    localStorage.setItem(thisId, latestContent);
}
```

編集中のHTML要素の内容を変数latestContentに格納する際、outerHTMLを使用しています。
outerHTMLには、テキストだけでなく、そのテキストを囲むタグが含まれます。
[前回の記事](https://qiita.com/elBlanco/items/46a5a608206fe1c17245)で、execCommandを使用したテキスト装飾を行えるようにしています。これは、対象のテキストをタグで囲み装飾する仕組みです。そのため、アンダーラインを引いた、などの装飾を保存するにはouterHTMLを用いてタグ情報も保存することが必要です。

ピンと来ない場合、ご自身で装飾をしてみて、管理画面のElementsタブ(Chromeの場合。Safariの場合は要素タブ)で確認することをオススメします。

##データの取得
続いて、データの取得です。
タイトルとなるh1タグ、コンテンツとなるdivタグは、ページ読み込み時に毎回取得する方針です。

```javascript:editable.js
//追加する先である、"wrapper"のidを変数targetに格納します。
var target = document.getElementById("wrapper");
//HTMLに追加する内容を格納する変数を宣言
let addContents = "";

//localStorageにタイトルの内容が保存されているか確認をして、処理を分岐させることでエラーを回避します。
if(localStorage.getItem("editableTitle")){
    //localStorageから、保存したタイトル(キーはeditableTitle)を取得し、変数addContentsに追加します。
    addContents += localStorage.getItem("editableTitle");
} else {
    //localStorageに保存したタイトルがない場合は、デフォルトの内容を変数addContentsに追加します。
    addContents += '<h1 id="editableTitle" contenteditable="true" onInput="onInput();">編集可能タイトル</h1>';
}

//localStorageにコンテンツの内容が保存されているか確認をして、処理を分岐させることでエラーを回避します。
if(localStorage.getItem("editableContent")){
    //localStorageから、保存したコンテンツ(キーはeditableContent)を取得し、変数addContentsに追加します。
    addContents += localStorage.getItem("editableContent");
} else {
    //localStorageに保存したコンテンツがない場合は、デフォルトの内容を変数addContentsに追加します。
    addContents += '<div id="editableContent" contenteditable="true" onInput="onInput();">編集可能コンテンツ</div>';
}

//最後に変数addContentsの内容をid"wrapper"の中身に追加します。
document.getElementById("wrapper").outerHTML = addContents;
```

localStorageに保存したタイトル、コンテンツがない場合の、デフォルトの内容について解説します。
h1タグ、divタグ共に同じ属性「contenteditable="true" onInput="onInput();"」が指定されています。
「contenteditable="true"」はそのタグの中身をブラウザ上で編集できるようにします。

「onInput="onInput();"」のonInput()はデータの取得で記述した関数です。
onInput、つまりこのタグの中身にブラウザ上で何かが書き込まれた場合、「=」の右辺に指定したonInput()関数を実行する、という意味になります。

最後、変数addContentsの内容をid"wrapper"の中身に追加する際も、保存のときと同様にouterHTMLを使用します。


[過去記事](https://qiita.com/elBlanco/items/46a5a608206fe1c17245)から追加するコードは以上になります。

#さいごに
ポイントは、HTML要素のidと、localStorageのkeyに注意することです。
1字でも異なると、正しい結果になりません。
idとkeyを同じ値にすることで、わかりやすくなります。

今回はlocalStorageを使用していますが、
データの保存、取得の流れを抑えれば、他の保存先でも対応できるかと思います。