命令が実行されるタイミングを決める「イベント」
これまで見てきたように、jQueryを使ったプログラムは、セレクターで特定の(X)HTML要素を指定し、(X)HTMLやCSSを追加・変更します。サンプルプログラムは理解しやすいように、Webブラウザーで開くといきなりプログラムが実行されるものでしたが、本来必要なのはサイト制作者が意図したタイミングで実行されるプログラムですよね。では、タイミングはどのようにして指定するのでしょうか?
たとえば、第1回で紹介したアコーディオンパネルは「ユーザーが特定の要素をマウスでクリックしたときに、要素の高さを変更する」プログラムでした。ほかにも、マウスオーバーで画像が切り替わるメニュー、ドラッグ&ドロップで並び順を変更できるナビゲーションなど、jQueryやJavaScriptを使ったユーザーインターフェイス(UI)を改めて見てみると、どれも何らかのきっかけとなる出来事があって、(X)HTMLやCSSが変更されていることが分かります。
こうした、プログラムが実行される“きっかけ”を「イベント」と言います。jQueryでは(というよりもJavaScript一般に言えることですが)、イベントを感知(発見)したタイミングで、設定しておいたプログラムが実行されます。
イベントを感知するにはいくつかの命令を使います。
(X)HTMLが読み込まれたタイミングで実行するready()
「命令が実行されるきっかけ」は、クリックやマウスオーバーのように、ブラウザー上のユーザーによる操作だけではありません。「ブラウザーがWebページを読み込み終わった」というきっかけも立派なイベントです。
これまで、“お約束”ということで使ってきた以下のコードを改めて見てみましょう。
$(function(){
//(X)HTMLが読みこまれた際に実行したい命令
})
第3回で紹介したように、上記のコードは以下の省略形でした。
$(document).ready(function(){
//(X)HTMLが読みこまれた際に実行したい命令
})
ready() は、「(X)HTMLの読み込みが完了した」というイベントを感知する命令です。ready()の左側では、セレクターを $(document) のように記述して、Webページ全体(document)を対象にしています。したがって、$(function(){...}) は、「Webページ全体の読み込みが終わり、準備ができたら命令を実行しなさい」という処理の省略形だったのです。
ready(...) の括弧には function(){...} と記述し、その内側に実行したい処理を記述します。括弧内に function(){...} と書くのは、ready()に限らず、イベントを感知して命令を実行するときに一貫した決まりです。
他のイベント処理でもready()は必須
ready() はイベントを感知する命令の一種ですが、他のイベントを感知したい場合にも、 $(function(){...}) の内側に処理の内容を記述します。たとえば、以下のソースコードは、「button要素がクリックされたら命令を実行する」というプログラムです。詳細は後述しますが、click() は「特定の要素がクリックされた」というイベントを感知する命令です。
<script type="text/javascript">
$("button").click(function(){
//button要素がクリックされた際に実行したい命令
})
</script>
このscript要素をhead要素内に記述した場合、ブラウザーはページの読み込みがまだ終わっていないためbutton要素の存在を見つけられず、プログラムは正常に動作しません(第3回を参照)。
そこで、次のようにプログラム全体を $(function(){...}) の内側に入れ込みます。
<script type="text/javascript">
$(function(){
$("button").click(function(){
//button要素がクリックされた際に実行したい命令
})
})
</script>
これでブラウザーはscript要素の記述位置に関係なくbutton要素を発見でき、プログラムはページの読み込みが終わったあとに実行されます。 $(function(){...}) を使えば、button要素がクリックされたタイミングで実行したい命令を設定できます。
jQueryでプログラムを記述する際には、$(function(){...}) の内側に記述していくことを改めて覚えておきましょう。
それでは、次ページからはjQueryでイベントを感知するための具体的な方法について紹介していきます。
イベントの基本をクリックで学ぶ
■click()の基本の書き方
特定の要素がクリックされたときに何らかの命令を実行したい場合は、click() を使います。よく使う命令ですので、click() を例に、イベントの基本を学んでいきましょう。
click() は、ready() と同様に括弧内に function(){...} と記述し、その内側に実行したい命令を記述します。
$(セレクター).click(function(){
//セレクターで指定した要素がクリックされた際に実行したい命令
})
具体的なサンプルプログラムを見てみましょう。下記のコードを実行すると、button要素がクリックされたときに、img要素のsrc属性の値が「sea.jpg」に、alt属性の値が「海」に書き換わります。attr()は、,(カンマ)区切りで指定した属性値を変更する命令でしたね(関連記事)。
サンプルでは、複数の命令を.(ドット)でつないで連続して実行する「メソッドチェーン」の仕組みを使って、src属性とalt属性を一度に書き換えています(メソッドチェーンについては第5回を参照)。
▼サンプル01(スクリプト部分)
$(function(){
$("button").click(function(){
$("img").attr("src","sea.jpg").attr("alt","海");
})
})
▼サンプル01((X)HTML部分)
<button>画像を変更</button>
<p><img src="flower.jpg" alt="花" /></p>
▼サンプル01(実行結果)
<button>画像を変更</button>
<p><img src="sea.jpg" alt="海" /></p>
サンプル01の実行画面。button要素をクリックするとimg要素のsrc属性とalt属性が書き換わる |
このように、指定した要素がクリックされ、クリックイベントが発生したときの処理を記述できるのが、click() です。
【実務でハマる落とし穴】
「a要素に設定したクリックイベントの処理が動かない!」
click()は、セレクターでさまざまな(X)HTML要素を指定できますが、もともと「クリックされるとhref属性に書かれたリンク先に移動する」働きが設定されているa要素を指定した場合はどうなるでしょうか?
a要素にdblclick()を設定する場合には、実はもう一工夫必要です。サンプルを見てみましょう。
▼サンプル02(スクリプト部分)
$(function(){
$("a").click(function(){
$("img").attr("src","sea.jpg").attr("alt","海");
})
})
▼サンプル02((X)HTML部分)
<a href="sea.jpg">画像を変更</a>
<p><img src="flower.jpg" alt="花" /></p>
このコードをブラウザーで開いてa要素をクリックしてみると、クリックイベントが発生し、jQueryの命令が実行されます。ところが次の瞬間には、イベントの発生を感知したWebブラウザーは、a要素のhref属性に設定されたリンク先のURLを開いてしまいます。
問題を回避するにはいくつかの方法があります。
■その1.javascript:void(0)を使う
ひとつは、a要素のhref属性に javascript:void(0) と設定し、a要素の機能を殺してしまう方法です。
▼サンプル03((X)HTML部分)
<a href="javascript:void(0)">画像を変更</a>
<p><img src="flower.jpg" alt="花" /></p>
これでjQueryの命令だけが実行され、リンク先に移動しなくなります。
ただ、javascript:void(0) を使うと、ユーザーがJavaScriptをオフにしている場合、リンクをクリックしても何も変化が起きないため、混乱してしまう恐れがあります。JavaScriptを使う場合は、JavaScriptオフの環境にもなるべく配慮するべきです。
■その2.return false; を追加する
もう1つは、クリックイベントの最後に return false; と記述する方法です。
▼サンプル04(スクリプト部分)
$(function(){
$("a").click(function(){
$("img").attr("src","sea.jpg").attr("alt","海");
return false;
})
})
▼サンプル04((X)HTML部分)
<a href="sea.jpg">画像を変更</a>
<p><img src="flower.jpg" alt="花" /></p>
この場合も、a要素がクリックされた際にはjQueryの命令だけが実行され、href属性に設定されたリンク先には移動しません。一方、JavaScriptがオフの場合はa要素のリンクが有効になるので、jQueryの命令で指定している内容に近いURLをhref属性に設定しておけば、ユーザーはとりあえず最低限の情報をつかめます。
「a要素に設定したイベント処理がうまく動かない」––そんなときは return false; が忘れずに設定されているか、確認してください。
■イベントが発生した要素を取得する
前ページでイベントの基本的な使い方を紹介しましたが、イベントを設定したい要素は1つとは限りません。複数の要素に対して設定したい場合もあります。
次のサンプル05は、eqフィルターを利用して複数のa要素に対してそれぞれ異なるクリックイベントを設定しています。eqフィルターは特定の要素のうち、指定した順番の要素を取得するセレクターでした(関連記事)。
▼サンプル05((X)HTML部分)
<ul>
<li><a href="fower.jpg">花</a></li>
<li><a href="sea.jpg">海</a></li>
<li><a href="Jellyfish.jpg">くらげ</a></li>
<li><a href="Building.jpg">建物</a></li>
</ul>
<p><img src="flower.jpg" alt="花" /></p>
▼サンプル05(スクリプト部分)
$(function(){
$("a:eq(0)").click(function(){
$("img").attr("src","flower.jpg").attr("alt","花");
return false;
})
$("a:eq(1)").click(function(){
$("img").attr("src","sea.jpg").attr("alt","海");
return false;
})
$("a:eq(2)").click(function(){
$("img").attr("src","Jellyfish.jpg").attr("alt","くらげ");
return false;
})
$("a:eq(3)").click(function(){
$("img").attr("src","Building.jpg").attr("alt","建物");
return false;
})
})
▼サンプル05(実行結果)
サンプル05の実行画面。a要素をクリックすると画像が変更される |
画像を変更する機能は実装できましたが、このままだとコードがかなり長い上に、あとで変更する場合にややこしくなります。a要素の出現順が変更されたらeqフィルターの番号を変更しなくてはなりませんし、項目が追加されたらその分プログラムを追加しなくてはいけません。
そこで便利なのが、イベントが発生した要素を取得するセレクター $(this) です。イベントを設定している click(function(){...})内 で $(this) と書くと、イベントが発生した要素を取得できます。 $(this) を使えば、先ほどの長いプログラムを以下のように短く記述できます。
▼サンプル06(スクリプト部分)
$(function(){
$("a").click(function(){
$("img").attr("src",$(this).attr("href")).attr("alt",$(this).text());
return false;
})
})
このサンプルでは、$(this).attr("href") でクリックされた要素のhref属性、$(this).text() でクリックされた要素内のテキストを取得し、それぞれimg要素のsrc属性、alt属性に設定しています。これならソースコードもすっきりしますし、li要素の数や順番を変えたい場合も(X)HTMLを書き換えるだけで済みます。
イベントが発生した要素を取得する $(this) はクリックイベント以外でも重宝しますので覚えておきましょう。
ダブルクリックイベントを感知する dblclick()
■dblclick()の基本の書き方
特定の要素がダブルクリックされたときに何らかの命令を実行したい場合は、 dblclick() を利用します。記述方法は click() と同じで、括弧内に function(){..} を書き、その中に実行したい命令を記述します。
$(セレクター).dblclick(function(){
//セレクターで指定した要素がダブルクリックされた際に実行したい命令
})
以下のサンプルでは、button要素がダブルクリックされたときに、img要素のsrc属性の値を「sea.jpg」に、alt属性の値を「海」に書き換えます。
▼サンプル07(スクリプト部分)
$(function(){
$("button").dblclick(function(){
$("img").attr("src","sea.jpg").attr("alt","海");
})
})
▼サンプル07((X)HTML部分)
<button>画像を変更</button>
<p><img src="flower.jpg" alt="花" /></p>
▼サンプル07(実行結果)
<button>画像を変更</button>
<p><img src="sea.jpg" alt="海" /></p>
【実務でハマる落とし穴】
「a要素に設定したdblclick()がやっぱり動かない!」
click() と同じように、 return false; も設定したのに、a要素に設定した dblclick() がうまく動かない……。
先に説明したとおり、(X)HTMLのa要素にはもともと、href属性に書かれたリンク先に移動する働きが設定されているため、jQueryのイベント処理を設定してもうまく動作しません。そこで、click(function(){…})内の最後にreturn false;と追加し、a要素のリンク機能を無効にする必要がありました。
ところが、dblclick() の場合は、以下のように return:false; を設定してもうまく動作しません。
$(function(){
$("a").dblclick(function(){
$("img").attr("src",$(this).attr("href")).attr("alt",$(this).text());
return false;
})
})
dblclick()で指定した命令は、ダブルクリックが発生したタイミング(2回目のクリックの後)で初めて実行されます。一方、ブラウザーは、ユーザーがダブルクリックのつもりでクリックした1回目のクリックの後にクリックイベントを感知し、a要素のhref属性に設定されたリンクの処理を実行してしまいます。
そこで、a要素にdblclick()を設定する場合は、メソッドチェーンを利用し、click() と dblclick() の両方のイベント処理を設定します。dblclick() にはダブルクリック時に実行したい命令を、click() に return false; を設定すれば、1回目のクリック時のリンクを無効にできます。
次のサンプルのような書き方を覚えておくと便利です。
▼サンプル08(スクリプト部分)
$(function(){
$("a").dblclick(function(){
$("img").attr("src",$(this).attr("href")).attr("alt",$(this).text());
}).click(function(){
return false;
})
})
マウスのボタン操作を感知する mousedown() と mouseup()
mousedown() と mouseup() は、特定の要素上でマウスのボタン(右ボタン、左ボタン、中ボタンなど)が押されたり離されたりしたときに、命令を実行します。
click() と非常によく似ていますが、click() は特定の要素上にマウスカーソルがある状態で左ボタンが押され、そのままボタンが離されたときに命令を実行します。細かな違いではありますが、mousedown() /mouseup() はドラッグ&ドロップなどのマウスを使ったインタラクティブな操作を実現したい場合に使います。
■mousedown()
mousedown() は、特定の要素上にマウスカーソルがある状態でマウスのボタン(右ボタン、左ボタン、中ボタンなど)が押されたときに命令を実行します。
$(セレクター).mousedown(function(){
//セレクターで指定した要素でマウスダウンされた際に実行したい命令
})
次のサンプルでは、a要素の上にマウスカーソルがある状態でマウスのボタンが押されたら、img要素のsrc属性とalt属性を書き換えます。
▼サンプル09(スクリプト部分)
$(function(){
$("a").mousedown(function(){
$("img").attr("src",$(this).attr("href")).attr("alt",$(this).text());
}).click(function(){
return false;
})
})
■mouseup()
mouseup() は、特定の要素上にマウスカーソルがある状態で、すでに押されているマウスのボタン(右ボタン、左ボタン、中ボタンなど)が離されたタイミングで命令を実行します。
$(セレクター).mouseup(function(){
//セレクターで指定した要素がマウスアップされた際に実行したい命令
})
次のサンプルは、a要素の上にマウスカーソルがある状態でマウスのボタンが離されたら、img要素のsrc属性とalt属性を書き換えます。マウスのボタンをしばらく押したままにしてからボタンを離すと、mousedown() との違いが確認できると思います。
▼サンプル10(スクリプト部分)
$(function(){
$("a").mouseup(function(){
$("img").attr("src",$(this).attr("href")).attr("alt",$(this).text());
}).click(function(){
return false;
})
})
dblclick()と同様、a要素に対してマウスダウンイベントやマウスアップイベントを設定する場合は、 return false; を設定した click() をメソッドチェーンで追記する必要があります。