記事の内容
jQueryライブラリのイベントオブジェクトについてメモ程度にまとめる。
(参考:jQuery本格入門 著:沖林正紀 出版:技術評論社)
###イベントオブジェクトとは
JavaScriptのイベントオブジェクトにいくつかメソッドやプロパティを加えて、Webブラウザごとの違いを吸収したもの。
$.Event
によって生成される。イベント処理が行われる関数の第一引数に渡される。
####マウスカーソルの位置
マウスカーソルを表すイベントプロパティは以下の表のとおりである。
x | y | |
---|---|---|
ブラウザ画面内の位置 | clientX | clientY |
Webページ内の位置 | pageX | pageY |
要素内での位置 | offsetX | offsetY |
デスクトップ画面内の位置 | screenX | screenY |
イベント発火に関連した要素
このプロパティで参照される要素はすべてDOMオブジェクト。
イベント発火した要素と、イベントを処理した要素が違う場合、そのイベントがバブリングしたとわかる。
target
イベント発火した要素
currentTarget
$(...)で指定された要素のうち、イベントが発火した要素を含むもの。
relatedTarget
・mouseoverイベントの場合
イベント発火直前にマウスカーソルが重なっていた要素。
・mouseoutイベントの場合
イベント発火時点で重なっている要素
toElement
マウス移動後の要素
delegateTarget
delegateまたはonを実行した$(...)で指定された要素のうち、
イベントが発火した要素を含むもの。
イベント処理の中止
preventDefault()
イベント処理の最後にreturn false
を実行したときのように、フォームの送信や、ページの遷移などを行わない。
stopImmediateProbagation
同じイベントに対応するイベント処理が複数登録されていても、その後のイベント処理がされない。
stopProbagation
バブリングが起こらなくなる。同じ要素で発火した特定のイベントに対応するイベントは実行される。
イベント処理にデータを受け渡す。
イベントオブジェクトをイベント処理を行う関数とは別に、引数としてオブジェクトを設定すると、イベントオブジェクトのdataプロパティの値を参照することができる。
####delegateTargetプロパティ
$(...)で設定した要素のうち、子孫要素にイベントを発火した要素を含むものを表す。
Deferredオブジェクトによる処理の実行
Deferredオブジェクトとは
オブジェクトが持つ状態を別の状態に変化させるときに処理が実行されるように設定できる。
イベント処理はイベント発火前に対応する処理が登録されていなければ、その処理を実行することができないが、Deferredオブジェクトは状態が変化した後で、対応する処理を登録しても、実行される。
$.Deferred([関数])
で生成される。関数で生成したDeferredオブジェクトに処理を追加できる。
状態と処理キューを持っていて、
オブジェクト生成時には、「保留(pending)」の状態にある。
この状態でも、処理を登録することができる。
「保留(pending)」→「解決済み(resolved)」| 「棄却済み(rejected)」と状態が変化し、状態に応じて、キューに登録されている処理が実行される。遷移した状態を元に戻すことはできない。
処理を登録するメソッド
done
状態が解放済みに遷移した後に実行される処理を登録。
fail
状態が棄却済みに遷移した後に実行される処理を登録。
progress
状態が遷移する前に実行される処理を登録。
それぞれをメソッドチェーンによってつなげて記述することができる。
Deferredオブジェクトの状態の遷移させるメソッドは
resolve
→解決済み reject
→棄却済み progress
→保留状態のまま
またnotify
メソッドを実行しても、状態はpendingのままなので、progressで登録された関数は何度でも実行することができる。
一方で解決済み、棄却済みに移行したオブジェクトの状態は戻せないため、done、failで実行した処理は一度しか実行することができない。
Deferredオブジェクトのメソッドは、複数の引数が設定されると、すべてdone、fail、progressで登録した関数の引数に引き継がれる。
複数の処理を同時に設定することもでき、メソッドに複数の引数を設定する、メソッドチェーンを用いる、引数に配列を設定するという方法がある。
実行する順序は、引数の並び、登録順、配列の要素順となっている。
状態を遷移させるメソッドの中で、
xxxWith
メソッドの第一引数を設定した引数は、処理中のthisキーワードとなる。
現在の状態を表示する
→deferred.state()
メソッドを使用。
・その他の登録方法
always(関数[, 関数,...])
→状態がresolved/rejectedどちらに移動しても、同じ関数を実行する。
then(関数1 [, 関数2[, 関数3]])
→1:doneで登録した関数の前に実行するもの、
→2:failで登録した関数の前に実行するもの
→3:notifyで登録した関数の前に実行するものを登録。
中間処理を設定することができる。
####Promiseオブジェクト
状態を遷移させる処理を先に行い、状態に応じた処理の登録を別の処理に委ねるために用意されたオブジェクト。
Deferredオブジェクトから、状態を遷移させるメソッドresolve/reject/notifyを除いたサブセット。
状態と処理キューはそのまま引き継いでいる。
これはアニメーションの動作時や、Ajaxの通信が終了した後に行う処理を設定するときにも利用する。
アニメーションでは、最後の処理が終了すると、Deferredオブジェクトの状態が、resolvedに、
途中で処理が中断されると、rejectedに遷移する。
show/hideメソッドのオプションでしてされるdone,fail,always,progressには、Promissオブジェクトのメソッドと同じ意味でつかわれる。
promise([オブジェクト])
→Promiseオブジェクトを生成する。引数にオブジェクトがあると、そのオブジェクトにPromiseオブジェクトのメソッドを追加する。
$.when(関数[,関数, ...])
→Promiseオブジェクトを返す処理を登録、すべての関数の処理が終わるまで待機する。
thenメソッドを実行した後では、実は、resolveメソッドを実行することができない。それはthenメソッドの戻り値がpromiseオブジェクトであり、resolveメソッドをもっていないからである。
PromiseオブジェクトはjQueryオブジェクトによる処理が終了するのを待ってから、次の処理を行いたいときに利用することができる。
これによって、
・HTML文書に追加した要素にテキストを補う
・アニメーションが終了してから次の処理を実行する。
などが実現できる。
流れとしては、
・promiseメソッドでPromiseオブジェクトを生成。
・doneでその後に行いたい処理を登録する。
//新しく追加した<div>にテキストを補う
$('<div>').appendTo(document.body).promise()
.done(function(){this.text('jQuery'); });
//アニメーション終了後に処理を実行
$('div').slideUp(3000).promise()
.done(function(){alert.'要素が隠れました'); });
promiseオブジェクトはアニメーションの終了について管理しているので、複数のオブジェクトがランダムに動く場合などでも、すべてが終了するのを待ってから、その後の処理を一度だけ行うことができる。
$.whenメソッド
このメソッドは
一つ、または複数のオブジェクトを引数にとって、
戻り値はPrimiseオブジェクトを返す。
引数のすべてがDeferredオブジェクト、Promiseオブジェクトでない場合、whenに続く、doneによって登録された処理が実行される。
var d = new Date();
$.when(d.getHours(), d.getMinutes()).done(function(h, m){
$('div'), {text: h + '時' + m + '分です'}).appendTo(document.body);
});
// <div>15時10分です</div>
以上のような例のように、引数のオブジェクトが、doneで登録される関数の引数に設定されている。
$.each(['red', 'blue'], function(i, name){
$('div'), {width:100, height: 100, css: {backgroundColor: name}}
.appendTo(document.body).hide();
});
// 追加した要素を表示させ、両方表示されたらテキストを追加
$.when($('div:first').show(3000), $('div:last').show(300))
.done(function(){$('div').text('jQuery'); });
$.whenの引数がDeferredオブジェクト、Promiseオブジェクトのときは、それぞれの状態がすべてresolved
に移行していれば、whenに続くdoneで登録された処理が実行される。一方で、引数の中で、どれか一つでもrejected
に移行した場合は、failで登録された処理が実行される。
progress
メソッドも続けて実行でき、登録された関数の引数には、
whenメソッドの引数に設定された、Deferredオブジェクト、Promiseオブジェクトが
notify
を実行したときの引数が
関数の引数に設定される。
元のオブジェクトの引数が複数の場合、配列で一つの引数として渡される。
#####Deferredオブジェクトに隠しdone/failの追加
$.Deferredの引数に、
生成されたDeferredオブジェクトを引数とする関数を
設定し、そこで引数の関数の引数にdoneやfailを実行すると、
元の生成されたDeferredオブジェクトに処理を追加済みにすることができる。
$.Callbacks
$.Callbacks
はCallbacksオブジェクトを生成するメソッド。
Callbacksオブジェクト
先にコールバック関数を登録しておき、それを引数を変えつつ何度も実行したり、
先に引数を登録しておいて、それらを用いて、コールバック関数を実行したりすることができる
仕組みを持ったオブジェクト。
Deferredオブジェクトの処理キューなどに利用されている。
Callbacksオブジェクトのメソッドは、返り値がBooleanでないものなら、メソッドチェーンによって連続に実行できる。
var fn = function(){
var s = $.map(arguments, function(arg){return arg.toString(); }).join();
$('<div>', {text: s}).appendTo(document.body);
};
var callbacks = $.Callbacks(); //Callbacksオブジェクト生成
callbacks.add(fn); // 関数の登録
// 引数を変えて登録した関数を実行。
callbacks.fire('A','B','C'); //ABC
callbacks.fire('D','E','F'); //DEF
callbacks.add(fn1, fn2); //複数の引数で登録
callbacks.add([fn3, fn4]); //配列で登録
callbacks.remove(fn1) //関数の削除
callbacks.remove(fn2, fn3, fn4); //複数の関数の削除
Callbacksオブジェクト生成時のメソッドの引数としてフラグ名を文字列で渡すことで、
生成するCallbacksオブジェクトにフラグを設定することができる。
var callbacks = $.Callbacks('once');
var callbacks = $.Callbacks('once memory') //空白で列挙できる。
フラグは以下のとおりである。
once
fireの実行完了後、登録された関数は削除される。
unique
同じ関数は登録されない。
stopOnFalse
戻り値がFalseの場合、それ以降関数を実行しない。
memory
登録された関数や、実行時の引数をオブジェクトに記憶する。