HTML
CSS
JavaScript
HTML5
localStorage

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

editable_localStorage.gif

はじめに

過去の投稿「HTML要素を編集可能にする方法」、「文字を装飾するボタンをつくる方法」に続いて、編集した内容を保存する方法を紹介します。
今回は比較的簡単な、localStorageによる保存方法を紹介します。

localStorageについて

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

データの保存

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タグを追加します。

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

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には、テキストだけでなく、そのテキストを囲むタグが含まれます。
前回の記事で、execCommandを使用したテキスト装飾を行えるようにしています。これは、対象のテキストをタグで囲み装飾する仕組みです。そのため、アンダーラインを引いた、などの装飾を保存するにはouterHTMLを用いてタグ情報も保存することが必要です。

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

データの取得

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

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を使用します。

過去記事から追加するコードは以上になります。

さいごに

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

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