==============================
画面に動作を仕込もう。
==============================
現在のindex.htmlは見た目こそそれっぽいものを表示していますが、押してみたところでうんともすんとも言いません。ボタンを押したら何らかの事が起きるようにしなければなりません。具体的にはindex.htmlのあるボタンが押されたら、それに対応するsampleCalc.js内のプログラムが実行されるようにします。今は別で疎遠になっている両ファイルを結びつけてあげましょう。
イベント
=================
ブラウザである要素をクリックしたり、マウスカーソルが重なったり、キーボードでキーが押されたりすると、ある信号が通知され *JavaScript* プログラムでも知る事ができます。この信号を受け取る事を **イベントが起こる** という言い方をします。起こるイベントに対応して処理を行うようにプログラムする事を **イベントドリブンプログラミング** と呼び、一般的なGUIアプリケーションでも同様の手法が使われています。また、そのイベントに対応した処理の事を **イベントハンドラ/イベントリスナ** と呼びます。
.. note::
イベントハンドラとイベントリスナの違いは設定方法です。ハンドラは一つの処理しか設定できませんが、リスナは複数の処理を設定できます。……そうだったのか。
.. image:: images/eventDriven.png
:alt: Event driven programming
:align: center
.. warning::
実際のプログラムでは各イベントが起こった場合に実行する処理をあらかじめ設定しておきます。
イベントは表示しているページ全体で起こる事もあれば、個別の要素で起こる事もあります。SampleCalcではボタンを押されたら何かしらの処理を行います。具体的には、7と表示されているボタン要素の上でマウスがクリックされたら(イベント発動)、7を入力しその時々に応じた処理(イベントリスナ)を行います。イベントリスナとして設定する処理はsampleCalc.jsにこれから実装するinputValueメソッドです。
全てのボタンに対応するメソッドをイベントリスナとして設定する事から始めましょう!
$関数による要素の取得
==============================
イベントリスナをボタンに設定するには設定を行いたいボタン要素をまず取得しなければなりません。その時に威力を発揮するのが *jQuery* の **$関数** です。$関数にセレクタ文字列を渡すとそれにマッチする要素を返してくれます。セレクタは *CSS* 準拠のものあれば独自のものもあります。
.. warning::
返される要素はもちろん **jQueryオブジェクト** へ変換済みです。
index.htmlにある要素にはそれぞれは個別に判断できるようにID属性が振られていますのでそれを使って取得する事ができますし、classにもグループ化して名前を振っていますのでそれを使って取得する事ができます。数字や演算子のボタンは設定するイベントリスナは同じものになりそうなのでクラス名を使って一気に取得しましょう。
::
$('#buttonAdd'); // +ボタンの要素を返します。
$('.num'); // classにnumが指定されている要素を返します。数字ボタン。
$関数による要素の取得は第二引数に検索する範囲を与えられたり、スペース区切りで連続してセレクタを記述する事でさらに絞り込めたり、またそのセレクタ構文もたくさんあります。上記は一番単純な例です。
.. note::
上手に使うとほぼ全て場合で要素を一発で取得する事ができます。是非活用してください。
* `jQuery() – jQuery API `_
* `Selectors – jQuery API `_
.click()
==============================
ボタン要素が取得できたのでイベントリスナを設定していきます。設定するイベントリスナ用のメソッドの中身はまだからっぽですが。
イベントハンドラ/イベントリスナを設定するには幾つかの方法がありますが、今回は *jQuery* のイベントリスナ設定用のメソッドを使いましょう。 *jQuery* にはイベントとイベントリスナをそれぞれ設定する汎用メソッドが用意されていますが、よく使われるイベントにはイベントリスナを渡すだけで設定してくれる省略形が用意されています。
.. note::
こちらもたくさんのイベント用のメソッドが用意されています。
* `Events – jQuery API `_
ボタンが押されるイベントですから、そのものズバリな *.click()* を使います。これらのメソッドも *jQuery* らしくメソッドチェーンに対応していますので、前述の要素取得のための$関数にそのまま続けて記述する事ができます。
::
$('.num').click(function () {
calc.inputValue();
});
.. note::
第一引数にイベントリスナで使うデータを渡す事もできます。::
$(spam).click({'ham': 'eggs'}, function (event) {
console.log(event.data.ham); // eggsが出力される。
});
.. warning::
引数として受け取ったEventオブジェクトを使ってアクセスする必要があります。
.. note::
*JavaScript* ではコールバックとして無名関数を渡す技法がよく使われます。イベントドリブンにコールバックの相性は抜群ですからね。
数字だけでなく、演算子などの他のボタンにも同様にイベントリスナを設定をやってしまいましょう。
console.log()
==============================
*.click()* でイベントリスナを設定しましたから、ボタンとSampleCalcのメソッドは間違いなく接続されています。接続されていますが、実際の処理が何も書かれていませんから何も変化も起きずに本当に繋がっているのかわかりません。正直なところ怪しいものです。そこで、 *console.log()* を用いてログを出力させて見る事にしましょう。実際に呼ばれているメソッドはどれなのか、渡された値は何だったのか、その辺りを出力しておけばデバッグ時にも役立ちます。
各メソッドの先頭にメソッド名と、引数で値が渡ってくる場合はその値を出力するようにしましょう。
::
...
SampleCalc.prototype = {
...
inputValue: function (value) {
console.log('inputValueに渡された値は ' + value + ' です。');
},
...
clear: function () {
console.log('Cボタンが押されました。');
},
...
};
さて、index.htmlをリロードし、コンソール画面を表示させて、適当に電卓のボタンをぽちぽちしてみてください。コンソールに想定する文字が出力されるはず……、とは行きませんよね、まだ値を渡すようになっていませんから。
.. note::
*Safari* を使っている場合は、“環境設定” -> “詳細”で“メニューバーに“開発”メニューを表示”にチェックを入れた後、“開発”メニューから“エラーコンソールを表示”を選択。
*Google Chrome* を使っている場合は、“表示”メニューから“開発/管理” -> “JavaScript コンソール”を選択してください。Windowsの方は“Google Chromeの設定” -> “ツール” -> “JavaScript コンソール”です。
*Firefox* を使っている場合は、 *Firebug* のインストールが必要になります。
コンソールは *Firebug* 由来の機能ですが、広く使われるようになりました。実行上のちょっとした確認などにも便利に使えます。こちらも是非活用していきましょう :-)
`Chrome デベロッパー ツール: コンソール - Google Chrome デベロッパー ツール - Google Code `_
.data()
==============================
index.htmlの説明の時に「data-value属性を持たせて値を格納し、それを参照して渡す」と書きました。要素内でdata-\*という名前で属性を持たせると先頭の **data-** を取り除き **\*** の部分を使ってアクセスする事ができます。その為のメソッドが *.data()* です。
::
7
$('#button7').data('value') === 7;
SampleCalcでいうと、上記のような関係になります。IDがbuttonAddの属性より取得すると'add'となります。一発で取れます。
*click()* でイベントリスナとして設定しているinput系メソッドに引数として *.data()* で取得した値を渡せばいいわけですが、イベントリスナ内で元の要素(押されたボタン)へアクセスするにはどうすればいいのでしょう。それには **this** を使います。実はイベントリスナ内では **this** が参照するオブジェクトはイベントリスナを設定した要素自身になります。つまり、「押された」イベントを発動したボタンそのものです。
::
$('.num').click(function () {
var value = $(this).data('value');
calc.inputValue(value);
});
イベントリスナ内では **this** が親要素になりますからそれを$関数で *jQuery* オブジェクト化して($関数の空気を読んだ処理の一つです)属性値を取得し、それを適切なメソッドへ引数として渡します。これで本当にコンソールに想定する文字が出力されるはず!
.. warning::
*JavaScript* では **this** が参照するオブジェクトが状況に応じてコロコロ変わるので取り扱いには注意が必要です。でも、ビビることもありません。
さぁ、これで画面とプログラムが結びつきました。後は仕様を満たすように、おかしな動きをしないように処理を書いていくだけです。楽しいプログラミングが始まりますよ。