【JavaScript】１日で基本を学ぶ〜後編

# イベントとは

今回も、引き続きこちらの本を参考にさせていただいた。
[岩田宇史「いちばんやさしいJavaScriptの教本」（インプレス）](https://book.impress.co.jp/books/1116101117)

まずイベントを理解するにあたり、JavaScriptで実装できる動作の一例を紹介する。

- ボタンをクリックしたら、入力フォームが表示される
- マウスポインタが当たったら、文字の色が変わる
- 入力フォームに文字を入力したら、その文字数が表示される

どれも、``ユーザー側の動作``と``動作の結果実行されること``が対になっている。上記の例では、以下の動作が``ユーザー側の動作``に該当するだろう。

- ボタンをクリックする
- マウスポインタを特定の箇所に当てる
- 入力フォームに文字を入力する

これらのユーザー側の動作が``イベント``と呼ばれているものだ。

# イベントの設定

上記で紹介した動作を実現するためには、``イベント``と``イベントに伴い実行される内容``を設定しなければならない。その方法には幾つか種類があるのだが、今回は``イベントリスナー``による設定を行ってみる。

早速プログラムを書いてみた。

## ボタンをクリックしたら、入力フォームが表示される

このためにプログラムに必要となる要素は、当然``ボタン``と``入力フォーム``だ。``id="button"``と``id="form"``の要素を取得する。

使用するイベントは``click``だ。このイベントは、その名の通り``要素をクリックした時``に発生する。

### HTML

HTMLでは通常の入力フォームを記述する。

```test.html
<head>
  <!-- 省略 -->
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
  <button id="button">フォーム表示</button><br>
  <form action="" id="form">
    <textarea id="textarea" name="textarea"></textarea></br>
    <input type="submit" id="submit" value="送信">
  </form>
  <script src="js/app.js"></script>
</body>
```

### CSS

CSSで入力フォームの表示を阻止している。ボタンがクリックされたらフォームを表示させるため、あえて``none``にする。

```style.css
#form {
  display: none;
}
```

### JavaScript

ここで``イベントリスナー``が登場する。イベントリスナーは``イベント``と``イベントに伴い実行される内容``をそれぞれ引数に取り、処理を実行する。

``イベントに伴い実行される内容``は、基本的に``無名関数``として記述する。名前付き関数で引数をとる場合は、無名関数の中で呼び出さなければならない。

```app.js
var button = document.getElementById('button');
var form = document.getElementById('form');

button.addEventListener('click', function() {
  form.style.display = 'block';
});
```

動作の流れはこうだ。

- ``documentオブジェクトのgetElementByIdメソッド``で、HTMLに記述されている``id="button"``と``id="form"``の要素をオブジェクトとして取得する。
- ``buttonオブジェクトのaddEventListenerメソッド``を使用する。
- 上記メソッドの``第１引数``はイベントである``click``、``第２引数``はイベントに伴い実行される内容を``無名関数``として記述する。
- この場合、``formオブジェクトのstyleプロパティ``から呼び出される``display（CSSで設定されるプロパティ）``に``block``を代入している。
- 結果、CSSで設定されていた``display: none;``が``display: block;``に置き換わり、フォームが表示される。

## マウスポインタが当たったら、文字の色が変わる

ここで必要な要素は、``文字（を囲んでいる要素）``だ。``id="greeting"``の要素を取得する。

今回使用するイベントは``mouseover``だ。これは、``マウスポインタが該当する要素の上に乗った時``に発生するイベントだ。

### HTML

```test.html
<body>
  <div id="greeting">
    <h1>ようこそ！</h1>
  </div>
  <script src="js/app.js"></script>
</body>
```

### JavaScript

今回はイベントの発生により、CSSの``colorプロパティ``を変更している。マウスポインタが要素の上に乗った時、文字の色が赤に変わる。

```app.js
var greeting = document.getElementById('greeting');

greeting.addEventListener('mouseover', function() {
  greeting.style.color = '#FF0000';
});
```

## 入力フォームに文字を入力したら、その文字数が表示される

入力フォームに文字を入力した場合、新しい要素が挿入され、そこに文字数が表示される。入力フォームそのものである``id="textarea"``の要素と新要素``div``の取得が必要となる。

また、使用するイベント``keyup``はキーを離した時（=入力文字数）に発生する。

### HTML

```test.html
<body>
  <button id="button">フォーム表示</button><br>
  <form action="" id="form">
    <textarea id="textarea" name="textarea"></textarea></br>
    <input type="submit" id="submit" value="送信">
  </form>
  <script src="js/app.js"></script>
</body>
```

### JavaScript

```app.js
var button = document.getElementById('button');
var form = document.getElementById('form');

button.addEventListener('click', function() {
  form.style.display = 'block';
});

// 以下を追記

var textarea = document.getElementById('textarea');
var text_counter = document.createElement('div');
var parent = textarea.parentElement;
parent.insertBefore(text_counter, null);

textarea.addEventListener('keyup', function(event) {
  console.log(event.key);
  // console.log(textarea.value);
  text_counter.innerHTML = "<h2>現在" + textarea.value.length + "文字入力しています</h2>";
});
```

動作を解説する。

- ``documentのgetElementByIdメソッド``により``textareaオブジェクト``を取得する。
- ``documentのcreateElementメソッド``で``divタグ``を作成し``text_counter``へ代入。オブジェクトとして扱う。
- ``textareaオブジェクトのparentElementメソッド``で親要素を取得し、さらに``親要素のinsertBeforeメソッド``で``text_counterオブジェクト``を追加する。
- ``textareaオブジェクトのaddEventListenerメソッド``で、動作のタイミングとなる第１引数``keyup``を指定する。
- 第２引数である無名関数で、``text_counterオブジェクトのinnerHTMLメソッド``により入力文字数を示す文を挿入する。

入力文字数自体は、``textarea.value.length``で簡単に取得できる。また、``console.log(textarea.value);``を試してみると、１文字入力する度に``value属性の内容（=入力内容）``がコンソールに出力される。

さらに、今回の無名関数では第１引数として``event``を指定している。これは``イベントオブジェクト``と呼ばれており、イベントに関する情報が格納されている。

この情報を使用したい場合は、無名関数の第１引数として指定すれば、関数内で使用することができる。今回は``console.log(event.key)``の記述で、``eventオブジェクトのkeyプロパティ``の内容がコンソールに出力される。

# オブジェクトのメソッドを使用する

今までイベントに伴う動作には既存のメソッドを使用してきた。今回は独自のメソッドを定義し、それを使用してみる。

## オブジェクトの定義

メソッドを定義するには、まず元となるオブジェクトが必要だ。以下の構文で、オブジェクトを``変数thanks``に代入している。

定義している内容は、``messageプロパティ``と``thanksMessメソッド``の２つだけだ。

thanksMessメソッドの``return文``にある``this``は、この構文内では``thanksオブジェクト自身``を表している。``this.message``で``thanksオブジェクトのmessageプロパティ``つまり``"<h2>ありがとう！</h2>"``を呼び出している。

```app.js
var thanks = {
  message: "<h2>ありがとう！</h2>",
  thanksMess: function() {
    return this.message;    
  }
}
```
## ボタンをクリックしたら、メッセージを表示する

``id="thanks_button"``のボタンがクリックされたら、``id="message"``の中にメソッドの結果（メッセージ）が表示される仕組みだ。

### HTML

```test.html
<body>
  <input type="button" id="thanks_button" value="メッセージ表示">
  <div id="message"></div>
  <script src="js/app.js"></script>
</body>
```

### JavaScript

他のイベントリスナーの記述法とほぼ変わらない。ただし、メソッドを呼び出す場合は``thanks.thanksMess()``のように、``オブジェクト名.メソッド名``と記述しなくてはならない。

```app.js
var thanks = {
  message: "<h2>ありがとう！</h2>",
  thanksMess: function() {
    return this.message;    
  }
}

// 以下を追記

var thanks_button = document.getElementById('thanks_button');
var message = document.getElementById('message');

thanks_button.addEventListener('click', function() {
  message.innerHTML = thanks.thanksMess();
});
```

# イベントハンドラについて

イベントを記述するもう１つの方法が``イベントハンドラ``だ。よくHTMLのbuttonタグ内で``onClick``という記述を見かけるが、これがそうだ。また、JavaScript内にも記述が可能だ。

しかし、その結果実行できる関数は１つに限られるため、参考にした基本書の中ではあまり推奨されていなかった。

イベントハンドラについては、こちらの記事が参考になる。
[JavaScriptのイベントハンドラ一覧-PHP & JavaScript Room](http://phpjavascriptroom.com/?t=js&p=event)

# まとめ

結局記事の作成には２日間かかってしまったが、JavaScriptの概要はざっくり把握できたと思う。次はVue.jsにチャレンジしてみたいのがだが、jQueryにも興味がある。

自分が作成しているアプリは学習も兼ねた超小規模なものなので、それに合わせて選択したいと思う。様々なライブラリ・フレームワークの動作確認も兼ねて。

さらに、今回の学習ではイベント時の動作は実行できたが、その逆ができなかった。（もう一度クリックするとフォームが非表示になる等・・・）色々試してみたが、CSSの要素の取得が難しい。解決策としてイベントハンドラによる記述例も見かけたが、時と場合により使い分けるものなのだろうか？

課題も多いが、今回はここまで。