メモ帳をつくる - 文字を装飾するボタンをつくる方法

![editable_decorate.gif](https://qiita-image-store.s3.amazonaws.com/0/268390/a526882c-01e8-1336-6cc9-1f433a49d55e.gif)


#はじめに
この記事では、HTMLの文字要素を装飾するボタンを作成する方法を紹介します。
execCommandを使用するため、コード量も少なく簡単です。
 [HTML要素を編集可能にする方法](https://qiita.com/elBlanco/items/c7c7a8e8124ed5b9c3f7)、[編集したHTML要素をlocalStorageに保存する方法](https://qiita.com/elBlanco/items/08e60c648b3ca4c7fdfe)と組み合わせれば、Evernoteのようなメモアプリを作成することができます。

#事前準備

GIFのサンプルでは、わかりやすい見た目にするため、CSSファイルを使って背景色などを変更しています。
今回は、その中身は紹介しません。

```html:editable.html
<head>
　　　　　　　　<!-- 中略 -->
    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/editable.css">
</head>
```

そして、ボタンの動作を記述するJavascriptファイルを作成し、下記の通りHTMLファイルから参照します。

```html:editable.html
<body>
　　　　　　　　<!-- 中略 -->
    <script src="js/editable.js" type="text/javascript"></script>
</body>
```

#HTMLファイルの記述
##HTML要素を編集できるようにする
今回はtextareaを使用するのではなく、h1ダグ、pタグのinnnerHTMLを編集できるようにします。
そのやり方は、[こちら](https://qiita.com/elBlanco/items/c7c7a8e8124ed5b9c3f7)に記載していますので、ここでは割愛します。

##ボタンを配置する
下記の装飾を紹介します。HTMLの記述方法によって、3パターンに区分しています。
　　button: イタリック/ボールド/アンダーライン/インデント/アウトデント/オーダーリスト/unオーダーリスト
　　select: カラー/フォント
　　range:  サイズ

わかりやすさのため、上記3区分ごとに紹介します。

###button
inputタグのtypeにbuttonを指定します。
valueは、ボタンに表示される文字です。
idは、Javascriptファイルでボタンを判別するために使用しますので、Javascriptファイルの記述と合わせてください。

```html:editable.html
<body>
　　　　　　　　<!-- 中略 -->
    <input id="italic" type="button" value="ITAL" />
    <input id="bold" type="button" value="BOLD" />
    <input id="underLine" type="button" value="UDL"/>
    <input id="inDent" type="button" value="IND"/>
    <input id="outDent" type="button" value="OUTD"/>
    <input id="ordList" type="button" value="ORD"/>
    <input id="unordList" type="button" value="UORD"/>
　　　　　　　<!-- 中略 -->
</body>
```


###select
optionタグを使用して、必要な分だけ記述します。
idは、Javascriptファイルでボタンを判別するために使用しますので、Javascriptファイルの記述と合わせてください。

```html:editable.html
<body>
　　　　　　　　<!-- 中略 -->
    <select id="color">
      <option>m-Blue</option>
      <option>Blue</option>
      <option>Green</option>
      <option>Red</option>
      <option>Black</option>
     </select>

     <select id="fontSelect">
      <option>Arial</option>
      <option>LudicaSansUnicode</option>
      <option>Impact</option>
      <option>YuGothic</option>
     </select>
　　　　　　　<!-- 中略 -->
</body>
```

###range
これは好みですが、ここでは文字の大きさを調整するのに、rangeを使用しています。selectを使用しても構いません。
min、maxで最小最大値を指定し、stepでは、どれくらいの刻みでrangeの調整をするか指定します。
valueは初期値です。
idは、Javascriptファイルでボタンを判別するために使用しますので、Javascriptファイルの記述と合わせてください。

```html:editable.html
<body>
　　　　　　　　<!-- 中略 -->
　　　　　　　　<input type="range" id="fontSize" value="3" min="1" max="7" step="0.5">
　　　　　　 <!-- 中略 -->
</body>
```


###3パターンまとめ
```html:editable.html
<body>
　　　　　　　　<!-- 中略 -->
    <input id="italic" type="button" value="ITAL" />
    <input id="bold" type="button" value="BOLD" />
    <select name="" id="color">
      　　<option>m-Blue</option>
       <option>Blue</option>
       <option>Green</option>
       <option>Red</option>
       <option>Black</option>
    </select>
    
    <select name="" id="fontSelect">
       <option>Arial</option>
       <option>LudicaSansUnicode</option>
       <option>Impact</option>
       <option>YuGothic</option>
     </select>
     <input type="range" name="" id="fontSize" value="7" min="7" max="8" step="0.5">
     <input id="underLine" type="button" value="UDL"/>
     <input id="inDent" type="button" value="IND"/>
     <input id="outDent" type="button" value="OUTD"/>
     <input id="ordList" type="button" value="ORD"/>
     <input id="unordList" type="button" value="UORD"/>
　　　　　　　　<!-- 中略 -->
</body>
```
#Javascriptファイルの記述

##基本構文

```javascript:
//HTMLファイルの要素を取得
const boldButton = document.getElementById("{HTMLファイルに記載したid}");

//取得した要素にイベントを付与
boldButton.addEventListener("{イベントの種類}", function(){
    //execCommandを記述
    document.execCommand("{コマンドの種類}", false, "{コマンド実行時に渡す値}" );
}, false);
```

{コマンド実行時に渡す値}がない場合は、「""」と記述します。

##サンプル記載内容
ボタンの並び順に、一つずつ紹介します。
###イタリック
{コマンド実行時に渡す値}はありませんので、「""」と記述しています。

```javascript:
const italicButton = document.getElementById("italic");
italicButton.addEventListener("click", function(){
    document.execCommand("italic", false, "" );
}, false);
```
###ボールド
{コマンド実行時に渡す値}はありませんので、「""」と記述しています。

```javascript:
const boldButton = document.getElementById("bold");
boldButton.addEventListener("click", function(){
    document.execCommand("bold", false, "" );
}, false);
```
###カラー
{コマンド実行時に渡す値}は、selectのvalueです。

```javascript:
const colorSelect = document.getElementById("color");
colorSelect.addEventListener("change", function(){
    //「m-Blue」というオリジナルのカラーを作り、それが選択された場合のための条件分岐
    //この例では、「m-Blue」を選択した場合には、"#185687"に色を変更する。
    if(colorSelect.value == "m-Blue") {
        document.execCommand("foreColor", false, "#185687");
    } else {
        document.execCommand("foreColor", false, colorSelect.value);
    }
}, false);
```

###フォント
{コマンド実行時に渡す値}は、selectのvalueです。
フォントは「"Arial"」のように「""」で囲み指定する必要がありますが、
selectのoptionに「""」が書いてあると見映えが悪いので、Javascript側で補完してあげます。

```javascript:
const fontChanger = document.getElementById("fontSelect");
fontChanger.addEventListener("change", function(){
    //""をここで補完し、{コマンド実行時に渡す値}とする
    document.execCommand( "fontName", false, '"' + fontChanger.value + '"');
}, false);
```
###サイズ
{コマンド実行時に渡す値}は、rangeのvalueです。

```javascript:
const fontSize = document.getElementById("fontSize");
fontSize.addEventListener("change", function(){
    document.execCommand( "fontSize", false, fontSize.value);
}, false);
```
###アンダーライン
{コマンド実行時に渡す値}はありませんので、「""」と記述しています。

```javascript:
const underLine = document.getElementById("underLine");
underLine.addEventListener("click", function(){
    document.execCommand( "underline", false, "" );   
}, false);
```
###インデント
{コマンド実行時に渡す値}はありませんので、「""」と記述しています。

```javascript:
const inDent = document.getElementById("inDent");
inDent.addEventListener("click", function(){
    document.execCommand( "indent", false, "" );   
}, false);
```
###アウトデント
{コマンド実行時に渡す値}はありませんので、「""」と記述しています。

```javascript:
const outDent = document.getElementById("outDent");
outDent.addEventListener("click", function(){
    document.execCommand( "outdent", false, "" );   
}, false);
```
###オーダーリスト
{コマンド実行時に渡す値}はありませんので、「""」と記述しています。

```javascript:
const ordList = document.getElementById("ordList");
ordList.addEventListener("click", function(){
    document.execCommand( "indent", false, "" );
    document.execCommand( "insertOrderedList", false, "" );   
}, false);
```

###unオーダーリスト
{コマンド実行時に渡す値}はありませんので、「""」と記述しています。

```javascript:
const unordList = document.getElementById("unordList");
unordList.addEventListener("click", function(){
    document.execCommand( "indent", false, "" );
    document.execCommand( "insertUnorderedList", false, "" );  
}, false);
```

###全パターンまとめ

```javascript:editable.js
const italicButton = document.getElementById("italic");
italicButton.addEventListener("click", function(){
    document.execCommand("italic", false, "" );

}, false);

const boldButton = document.getElementById("bold");
boldButton.addEventListener("click", function(){
    document.execCommand("bold", false, "" );
}, false);

const colorSelect = document.getElementById("color");
colorSelect.addEventListener("change", function(){
    if(colorSelect.value == "m-Blue") {
        document.execCommand("foreColor", false, "#185687");
    } else {
        document.execCommand("foreColor", false, colorSelect.value);
    }
}, false);

const fontChanger = document.getElementById("fontSelect");
fontChanger.addEventListener("change", function(){
    document.execCommand( "fontName", false, '"' + fontChanger.value + '"');
}, false);

const fontSize = document.getElementById("fontSize");
fontSize.addEventListener("change", function(){
    document.execCommand( "fontSize", false, fontSize.value);
}, false);

const underLine = document.getElementById("underLine");
underLine.addEventListener("click", function(){
    document.execCommand( "underline", false, "" );   
}, false);

const inDent = document.getElementById("inDent");
inDent.addEventListener("click", function(){
    document.execCommand( "indent", false, "" );   
}, false);

const outDent = document.getElementById("outDent");
outDent.addEventListener("click", function(){
    document.execCommand( "outdent", false, "" );   
}, false);

const ordList = document.getElementById("ordList");
ordList.addEventListener("click", function(){
    document.execCommand( "indent", false, "" );
    document.execCommand( "insertOrderedList", false, "" );   
}, false);

const unordList = document.getElementById("unordList");
unordList.addEventListener("click", function(){
    document.execCommand( "indent", false, "" );
    document.execCommand( "insertUnorderedList", false, "" );  
}, false);
```

#さいごに
今回紹介したコマンドは一部です。他のコマンドに興味がある方は、[こちらのサイト](https://instructobit.com/tutorial/36/Using-the-document.execCommand-function-in-Javascript-to-style,-modify-and-insert-content-within-a-content-editable-container)をご覧ください。

また、編集した内容を保存する方法は、[こちらの記事](https://qiita.com/elBlanco/items/08e60c648b3ca4c7fdfe)で紹介しています。