クロージャ(2)

クロージャのポイントはreturnでfunctionを返すところですが、returnでは1つの値しか
返せないため、1つの機能しか返せません。しかし配列やオブジェクトを利用すれば
複数の機能を利用できるものが作成できるので紹介します。サンプル02_closure_04.html
を開いてソースを確認してください。
http://www.designdrill.jp/jquery/11/02_closure_04.html
 
 

作成

まずクロージャの仕組みをもつcountMaster内を確認します。前回と異なる点として
returnで返すためのobjectを作成します。オブジェクト名はmyObjとしました。

var myObj = new Object();

 
続いて、このオブジェクトのプロパティにfunctionで機能を代入します。プロパティとは
いいましたが、functionを代入しているので、メソッドのように扱えるため以降では
メソッドと呼ぶことにします。

myObj.countUp = function () {
 cnt ++;
 $(".cnt").text(cnt);
}

 
上記のcountUpメソッドはカウントアップする処理を入れていますが、同じようにgetCnt
メソッドは変数cntの値を返す処理を入れています。そしてcountMasterの最後で、
作成したオブジェクトをreturnで返しています。
 
 

初期化

初期化は前回と同じですが、オブジェクトが返ってくるので受け取る変数名をcntObjとしました。

cntObj = countMaster();

 
 

利用

利用する場合は、以下の様に「オブジェクト.メソッド()」の形で機能を実行します。
.dispボタンのように返値を返すメソッドも利用できるのが確認できます。

cntObj.countUp();

 
 
 

引数を利用してみた

クロージャで作成できるメソッドには引数を渡すことも可能です。
サンプル02_closure_04b.htmlを開いてソースを確認してください。countUpメソッドの
作成時に引数を受け取る変数iをおきました。このサンプルではcountUpを実行する際10を
渡しているので10ずつカウントアップしていきます。
http://www.designdrill.jp/jquery/11/02_closure_04b.html
 
 

初期化にも引数を利用してみた

初期化の際にも引数を利用できます。サンプル02_closure_05.htmlでは初期化の際に
カウンターをどの場所に表示するか引数で指定するようにしました。
http://www.designdrill.jp/jquery/11/02_closure_05.html
 
 

もはやクラスっぽいです

このように作成したクロージャの仕組みはクラスっぽくりようできます。
サンプル02_closure_06.htmlを確認してください。htmlにはteamAとteamBでidを分けた
2つのセットがあります。続いてjQueryではクロージャの初期化を2回行い、それぞれ
別のオブジェクト()を作成しました。
http://www.designdrill.jp/jquery/11/02_closure_06.html
 
こうして作成したオブジェクトは、それぞれ個別に機能させることができます。
実際2つのセットのcount upボタンをクリックすると、対応するカウントの表示だけが
増えていきます。元のcountMasterは1つですが、そこから作成された2つのオブジェクト
(cntObj_A / cntObj_B)は個別にカウントを管理しているのです。
作成してみたら、ムービークリップというよりはクラスの様になってしまいました…。
 
 

countMasterを外部jsにする

クロージャの説明は終わりですが、ついでにcountMasterを外部jsにしてみたいと思います。
まずはサンプル02_closure_07.htmlを確認してください。
http://www.designdrill.jp/jquery/11/02_closure_07.html
 
サンプルではcountMasterをreadyイベントの外に出しています。誤解しがちですが、
readyイベントの外でもjQueryを利用することができます。readyイベントは単純にhtmlページ
読み込まれてから開始する処理を書く場所なのです。countMasterはhtmlページが
読み込まれる前に設定しても問題ないので、きちんと機能します。
 
さらにサンプル02_closure_08.htmlではcountMasterを外部jsファイル02_closure.jsとして
外部に出しリンクして利用してます。ソースを確認してください。
http://www.designdrill.jp/jquery/11/02_closure_08.html
 
 
 

まとめ

ムービークリップっぽいものを作成しようとしたら、クラスっぽくなってしまいました。
とはいえムービークリップのテクニックもなんちゃってクラスなので同じようなものです。
waitFuncのシンボルにActionScriptを書いて、インスタンスごとにインスタンス名を利用して
個別の待ち時間を設定したのと似ています。
 
でもjQueryのクロージャで検索すると、このような利用方法のサンプルがありません。
ここまでするならクラス(プラグイン)にしろ、ということなのでしょうか?
 
ともあれ、このような仕組みはゲームのような複雑なコンテンツでしか利用しない気が
するので理解できなくても良いと思います。
 
おしまい
 
 
 

クロージャ(1)

Flashがデザイナーや初心者プログラマーにとって扱いやすいのはムービークリップごとに
機能を分けて作成できる点です。私の講座を受講された方はbuttonMasterやtimeMasterなどを
作成したことを覚えていると思います。
 
javaScriptでは外部jsファイルを持つことができますが、外部のjsをhtml内のjsに流し込んでいる
だけでFlashのムービークリップのようには扱えません。つまりjavaScriptでプログラムを書く
場合はFlashで1箇所にまとめてソースを書くことと近い状態になります。
 
もちろんFlashで1カ所にまとめてActionScriptを書くことは可能ですが、クラスなどを有効に
利用したりと初心者には難しいと思います。

ちなみにjQueryではクラスはcssの方を指すため、プログラム的なクラスはプラグインと
呼ぶそうです(google検索)。これは別の機会に挑戦したいと思います。
 
ムービークリップがないjavaScriptでは、プログラム初心者でも強制的にこのレベルに立たされる
ことに成ります。ですから、ちょっと複雑なコンテンツを作成する場合はFlashよりも難しくなる
と思います。
 
ですが、クロージャを利用すればクラス(プラグイン)を利用しなくても、管理用の
仕組みを作成できるので紹介しようと思います。とはいえ講座カリキュラムで学ぶレベルの
コンテンツでは必要ないと思うので、覚えなくても良いと思います。
 
 
 

なるべくローカル変数を利用する

Flashではムービークリップを分けてしまえば、同じ名前でも別の変数として個別に
扱えます。しかしムービークリップがないjavaScriptでは、その手は利用できません。
ですからローカル変数を上手く利用します。
 
まずはサンプル02_closure_01.htmlを開いてソースを確認してください。ボタンをクリック
するたびカウントアップするシンプルなサンプルです。変数cntはvarがついていますから
jQueryのreadyイベント内のローカル変数です。
http://www.designdrill.jp/jquery/11/02_closure_01.html

しかしjQueryでは多くのコードをこのreadyイベント内に書くので、このレベルでは
まだ足りません。さらに変数cntをローカルにすることは可能でしょうか?
まずは安直な方法で作成したサンプル02_closure_02.htmlを確認してください。
http://www.designdrill.jp/jquery/11/02_closure_02.html
 
変数cntはcountMasterの中に入ったのでcountMasterのローカル変数になりました。
これでボタンをクリックしても1から先にすすみません。それもそのはずです…
countMaster内で毎回cnt = 0;と初期化しているのですから…。

では最初に一回初期化するようにすればイイじゃん、ということで02_closure_02b.html
を確認してください。カウントアップするようになりましたが、結局functionの外に
変数cntを出してしまったので、02_closure_01.htmlと同じです…。
http://www.designdrill.jp/jquery/11/02_closure_02b.html

 
というように、通常の方法ではこのcntをローカル変数にできないのですが、
クロージャというテクニックを利用すれば可能なのです。
 
 
 

クロージャの構造

すこしトリッキーなので、最初にサンプルを紹介して構造を説明していきます。
サンプル02_closure_03.htmlを開いてください。変数cntがfunction内に入ったにも
かかわらずcount upボタンをクリックするとカウントアップします。
http://www.designdrill.jp/jquery/11/02_closure_03.html
 
ではクロージャの構造を説明します。サンプルではcountMasterの部分です。
このfunctionをクロージャと呼ぶのではなく、利用する仕組みも含め、まとめてクロージャ
とよびます。

function 任意の名前() {
 最初に1回実行すれば良いことを書くエリア
 
 function 任意の名前() {
  利用したい機能はfunctionを作成してその中に書く
  サンプルではカウントアップして表示する機能
 }
 return 作成したfunction名を書く
}

 
通常はfunction内のreturnには計算結果などの数値や文字列を渡しますが、このサンプルのように
functionを渡すこともできるのです。ここでは分かりやすいようにcountUpFuncのfunctionを
作成しましたが、サンプル02_closure_03b.htmlの用に無名関数として返されることが多いです。
http://www.designdrill.jp/jquery/11/02_closure_03b.html
 
 
 

初期化

こうしてクロージャの仕組みを利用して作成したcountMasterですが、利用する前に
初期化しなければなりません。サンプル02_closure_03b.htmlでは以下の行が初期化に
あたります。

cntFunc = countMaster();

 
右辺のcountMaster()によって、1回countMasterが実行され、中の変数cntに0が設定されます。
そして、その返値を左辺のcntFuncに代入しています。countMasterはreturnでfunctionを
返しているため、cntFuncにはfunctionの機能が代入されることになります。今回の例では
カウントアップして表示する機能です。これで初期化が完了です。
 
 
 

利用

そしてサンプル02_closure_03b.htmlでは以下の部分で、初期化したcountMasterを利用してます。
初期化の段階で、機能をcntFuncに代入したので、実際に利用するのはcntFuncになります。
これにはfunctionが入っているので、実行する場合は以下の様に最後に()を付けることを忘れないで
ください。

cntFunc()

 
 
 

まとめ

これで目的通りcntをローカル変数にすることができました。ローカル変数になったので
watch cntボタンをクリックしてもcntを取得できません。クロージャの仕組みを利用する
以外では、もうcntは操作されないのです。ですから、不用意なミスでcntが改変される
事もなくなり、複雑なソースでもバグを出しにくくなります。
 
しかし、これだけではムービークリップの代わりにはなりません。次回は
さらに発展させてムービークリップっぽい仕組みにします。
 
おしまい
 
 
 

名前空間(namespace)

今回は名前空間(namespace)というものを紹介します。
 

bind / unbind

名前空間のメリットを説明するためにbind / unbindのサンプルを紹介します。
bindを利用すると要素に特定のイベントに特定のfunctionを割り当てることができます。
unbindは特定のイベントから特定のfunctionのbindを解除することができます。
今回の例ではbindを利用していますが、liveやdelegateそしてonでも利用できます。
リファレンス:unbind([type], [data])
リファレンス:bind(type, [data], fn)
 
 
サンプル01_namespace_01.htmlを開いてソースを確認してください。
http://www.designdrill.jp/jquery/11/01_namespace_01.html
 
このサンプルではbindを利用してdiv#testのクリックイベントにwidthFuncとheightFuncを
割り当てています。なのでdiv#testをクリックすると縦と横の両方向に伸びていきます。
 
一番下に追加されたunbindボタンをクリックするとdiv#testのクリックイベントからheightFunc
だけをunbindします。ですのでunbindボタンをクリックするとdiv#testをクリックしても
横にしか伸びなくなります。
※undindは引数を設定しないと全てのbindを解除します。またイベント名だけ指定すると、
 そのイベントの全てのfunctionのbindを解除します。

 
 
 

無名関数

一度しか利用しないfunctionに名前を付けていくと、function名が増えて管理しにくくなります。
ですから一度しか利用しないfunctionはサンプル01_namespace_02.htmlのようにfunctionを設定
するところに、直接functionを設定します。これにはfunction名が必要ないので無名関数と呼ばれます。
http://www.designdrill.jp/jquery/11/01_namespace_02.html
 
Flashでもイベントの設定などで「this.onRelease = function () {…」とやるのと同じです。
また、このようにして作成されるfunctionは名前がないので、他から操作されることが無いのも
メリットの1つです(ローカル変数が他のfunctionから操作されないメリットと同じです)。
 
 
しかしサンプル01_namespace_02.htmlでは、bindしたfunctionに名前がないため、特定の
functionだけunbindする事ができません
。unbindにclickしか設定しないとサンプルのように
clickにbindされた全てのfunctionが解除されてしまいます。そこで利用するのが名前空間です。
 
 
 

名前空間

他の言語では名前空間はイベントの他変数などにも利用できるのですが、jQueryでは
イベントで利用できるそうです。リファレンス:Namespaced Events
 
利用方法は簡単です。サンプル01_namespace_03.htmlを開いてソースを確認してください。
イベント名の後にドットを挟んで任意の名前を付けるだけです。このように名前空間を設定して
おけばunbindするときにも特定のfunctionだけ削除できます。
http://www.designdrill.jp/jquery/11/01_namespace_03.html

$('div#test').bind('click.name_2', function(){

 
つまりメリットの1つとして、無名関数を利用しているときにもbind / unbindが可能になります。
そして、他にもメリットがあるので以下に紹介していきます。
 
 
 

名前空間のグループ(その1)

同じ名前空間を利用するとグループとして扱うこともできます。サンプル01_namespace_04.html
を確認してください。click.name_2にもう1つfunctionを登録しました。つまりclick.name_2には2つの
functionがbindされています。この状態でclick.name_2をunbindすると2つのfunctionをまとめて
unbindできます。
http://www.designdrill.jp/jquery/11/01_namespace_04.html
 
 
 

名前空間のグループ(その2)

名前空間によるグループ分けは異なるイベント感でも可能です。サンプル01_namespace_05.html
を確認してください。mouseenterとmouseleaveの2つのイベントが設定されていますが、両方
とも名前空間でname_1と名付けています。そしてunbindの部分を確認してください。
ここでイベント名を省略して名前空間だけ指定してあります。これによりボタンをクリックすると
name_1と名付けられたイベントが全て解除されます。
http://www.designdrill.jp/jquery/11/01_namespace_05.html
 
以上のグループ化を利用すれば、複雑なボタンの挙動を簡単に管理できそうです。
例えば、検索モードのボタンの振る舞いと結果表示モードでボタンの振る舞いを切り替えるなど
 
 
 

複数の名前空間を登録

最後に利用ケースがなかなか思いつかないのですが、1つのイベントに複数の名前空間を設定
するサンプルも紹介しておきます。こうすると、そのイベントはどちらの名前でも操作する事
が可能になります。サンプル01_namespace_06.htmlで確認してください。
設定方法はドットで名前をつなげていくだけです。
何に利用できるか想像しにくいのですが、機能として頭に入れておこうと思います。
http://www.designdrill.jp/jquery/11/01_namespace_06.html
 
おしまい
 
 
 

mouseoverとmouseenter、mouseoutとmouseleave

バブリングついでにマウスに関する以下のイベントの説明をしておきたいと思います。
英語の意味をみると2つのペアとも、意味が非常に似ていて違いが分かりません。
 
このペアのそれぞれの違いはバブリングを受け取るか否かです。

mouseover:バブリング受け取る   mouseenter:バブリングをスルー
mouseout:バブリング受け取る   mouseleave:バブリングスルー

 
まずはバブリング受け取らないmouseenterから観察します。サンプル06_mouseEvent_01.html
を開いてソースを確認してください。
http://www.designdrill.jp/jquery/10/06_mouseEvent_01.html
 
inとoutというクラスを付けたdivが作成されイベントは外側(.out)のdivに付けられています。
外側のdivにマウスを入れるとalertがでるのでイベントが発生していることが確認できます。
次にそのまま内側のdivにマウスを入れてください。ここではalertが表示されません。
 
これは当たり前のように見えますが、プログラム的にはバブリングを受け取るmouseoverの
方が当たり前の動作になります。サンプル06_mouseEvent_02.htmlでmouseoverの動作を
確認しましょう。外側のdivにマウスが入るとalertが表示されるのは同じですが…
内側のdivに入るときにもalertがでます。
http://www.designdrill.jp/jquery/10/06_mouseEvent_02.html
 
 
ここでまたデリゲート(1)のサンプルで考えます。ulにイベントを設定したのに
その中にあるliの操作ができました。それはliがクリックされ(li自身にはイベントが
設定されてないのでli自身は何もしませんが)そのイベントがバブリングの仕組みで
ulに上がり、そこでイベントに補足されるのです。
 
06_mouseEvent_02.htmlのサンプルも同じです。内側のdivのイベントがバブリングで
親のdivに上がって、そこで補足されるため内側のdivに入ってもalertがでるのです。
 
 
前回のイベントフローのサンプルのため、誤解されそうなので、もう少し補足します。
今回もdivは入れ子になっているから、内側のdivにマウスを入れたら2回alertが出ない
とおかしいのでは?と感じる方がいるかもしれません。
 
しかし違います。今回イベントを設定したのはdivではなくoutクラスを持った要素に
対してです。outクラスを持っているのは1つだけですから1つしかalertはでません。
pタグを入れたサンプルで、pタグをクリックしても3回しかalertが出なかったことを
思い出してください。
 
ちなみに06_mouseEvent_02.htmlのサンプルでは内側のdivから外側のdivにマウスを
移動させたときにもalertがでます。これは内側のdivから抜けて再び外側のdivに入った
ためです。
 
 
mouseleaveとmouseoutに関しても同じなので、説明はせずサンプルだけにします。
※mouseleaveはバブリングをスルーして、mouseoutはバブリングを受け取ります
 
mouseleaveのサンプル:http://www.designdrill.jp/jquery/10/06_mouseEvent_03.html
mouseoutのサンプル:http://www.designdrill.jp/jquery/10/06_mouseEvent_04.html
 
 
 
今回参考にしたサイトは以下の通り
mouseenter(fn)
mouseleave(fn)
 
おしまい
 
 
 

イベントフロー(2)

今回はイベントフローに関するメソッドを紹介していきます。
 
 
 

バブリングの停止

前回の最後にバブリングによって効率が悪くなる例を紹介しました。しかしイベントオブジェクト
に対してstopPropagationメソッドを利用すると、バブリングを停止することができます。
リファレンス:event.stopPropagation()
サンプル05_eventFlow_07.htmlを開いてソースを確認してください。
http://www.designdrill.jp/jquery/10/05_eventFlow_07.html

eventObject.stopPropagation();

 
stopPropagationメソッドはイベントオブジェクトに利用することに気を付けてください。
これによって以降のバブリングが停止され、どのdivをクリックしても1回しかalertが
表示されません。前回の対応策(セレクタをidで絞る方法)では緑以外のクリックを
取得できませんでしたが、この方法であれば他のdivのクリックも取得できます。
 
ついでにクリックされたdivのidを報告するように変更したサンプルも紹介します。
きちんとクリックされたdivが1回だけ報告することを確認してください。 
http://www.designdrill.jp/jquery/10/05_eventFlow_07b.html
 
 
またreturnでfalseを返すことでもバブリングを停止できます。
サンプル04_eventFlow_08.htmlで確認してください。
http://www.designdrill.jp/jquery/10/05_eventFlow_08.html
 
 
 
 

preventDefaultメソッド

イベントメソッドついでにpreventDefaultを紹介します。これはjavaScriptからブラウザに
流れるイベントを停止するメソッドです。つまりブラウザ本来の機能を停止させるメソッド
で、これを利用すればaタグをクリックしてもリンクさせないこと等できます。また、
これはバブリングは停止しません。
リファレンス:event.preventDefault()
 
preventDefaultのサンプルを紹介する前に以下のサンプル05_eventFlow_09.htmlを確認
してください。バブリングのサンプルにリンクを追加したものです。緑のdivをクリック
してバブリングが完了してからリンクします。
http://www.designdrill.jp/jquery/10/05_eventFlow_09.html
 
ちなみにstopPropagationメソッドでバブリングを停止してもリンクは機能します。
サンプル04_eventFlow_10.htmlでバブリングを停止してもリンクすることを確認してください。
http://www.designdrill.jp/jquery/10/05_eventFlow_10.html
 
 
ではpreventDefaultメソッドのサンプルです。05_eventFlow_11.htmlを開いてください。
preventDefaultメソッドによって緑のdivをクリックしてもリンクしないことが確認できます。
バブリングに影響はありません。
http://www.designdrill.jp/jquery/10/05_eventFlow_11.html

eventObject.preventDefault();

 
 
 

returnでfalseを返す

return falseでバブリングを停止することは説明しましたが、これはさらにブラウザ本来の
機能も停止させます。つまりstopPropagationメソッドとpreventDefaultメソッドの両方
実行しているのと同じ結果となります。サンプル05_eventFlow_12.htmlで確認してください。
http://www.designdrill.jp/jquery/10/05_eventFlow_12.html
 
 
 

stopImmediatePropagationメソッド

最後に何に利用できるか想像できないけれど、ついでにstopImmediatePropagationを紹介
します。リファレンス:event.stopImmediatePropagation()
 
これはfunctionを伝わるイベントフローを停止するメソッドです。機能を確認する前に
以下のサンプル05_eventFlow_13.htmlで、どの様な順番でalertされるか確認してください。
http://www.designdrill.jp/jquery/10/05_eventFlow_13.html
 
functionは処理が終了すると、呼び出された場所に戻り、そこで処理を続けるので
サンプルでは「largeFunc:1→middleFunc:1→smallFunc→middleFunc:2→largeFunc:2」
と表示されます。この流れを中断するのがstopImmediatePropagationメソッドです。
ちなみにバブリングがあればバブリングも停止させます。サンプル05_eventFlow_14.htmlで
イベントフローが中断されるためalertがmiddleFunc:1で停止します。
http://www.designdrill.jp/jquery/10/05_eventFlow_14.html
 
今まで幾つかの言語で仕事をしてきましたが、こういうことが必要になるケースが
無かったので、何に利用できるかいまいち分かりません…。
 
ちなみにreturnも似ていますが、フローは止めずに、そのfunctionから抜けるだけです。
http://www.designdrill.jp/jquery/10/05_eventFlow_15.html
 
おしまい
 
 
 

イベントフロー(1)

デリゲートのサンプルでulにしかイベントを設定していないのに、liのクリックが検知
できるのは不思議に感じるかもしれませんが、これは多くのプログラム/スクリプト言語に
見られる仕様です。言葉では説明しにくいので、たくさんのサンプルを通して理解する
ようにしましょう。
 
まずサンプル05_eventFlow_01.htmlを確認してください。このサンプルで緑のdiv(id:small)は
階層化されたdivで最下層のdivです。緑のdivをクリックしてalertで表示されるidを予想して
ください。そして注目なのは「何回アラートが表示されるか」です。
http://www.designdrill.jp/jquery/10/05_eventFlow_01.html
 
緑をクリックすると3回もalertが表示されることに驚くと思います。これは次の様に
理解しておくと良いかもしれません。

青い正方形の上にピンクの紙が重ねられ、その上にさらに緑の紙が重ねられている。
つまり緑の紙の下にはピンク、青の紙があるので、クリックした刺激はピンクや
青にも伝わる。

 
上記の理解であれば、表示されるalertの順番がsmall→middle→largeなのも理解できる
とおもいます。これは入れ子の階層でいえば深いところから上に向かってイベントが
伝わっている
ことを示します。このようなイベントが伝わる流れをイベントフロー
とよび、下から上に流れることをバブリングと呼びます。
泡が下から上に上がっていくことを想像すると覚えやすいと思います。
ですから入れ子になっていない赤いdivはクリックしても1回しかalertされません。
 
javaScriptではバブリングだけ注意すれば良いようですが、他の言語では上から下の流れ
「キャプチャリング」というのもあります。ActionScript3.0の例
 
 
 

イベントオブジェクト再び

ここでデリゲート(1)で紹介したイベントオブジェクトのtargetプロパティを利用して
何が表示されるかを予想しましょう。デリゲート(1)ではulにイベントを設定しても
targetプロパティでクリックされた要素であるliを取得できました。
http://www.designdrill.jp/jquery/10/05_eventFlow_02.html
 
結果は全てクリックされた要素であるsmallが表示されました。
デリゲートのサンプルで説明したように、targetプロパティではクリックされた要素を
取得できるのです。
 
次にここでデリゲート(1)の最後の部分で紹介したcurrentTargetの動作も確認します。
以前説明したようにthisと同じ振る舞いになるので結果は05_eventFlow_01.htmlと
同じになります。
http://www.designdrill.jp/jquery/10/05_eventFlow_03.html
 
 
 

イベントはあくまでセレクタで設定した要素だけです

デリゲートの仕様を再確認しましょう。デリゲートのサンプルではliにはイベントが設定
されていないにも拘わらずliを操作する事ができました。ここで誤解されがちなのは
liにもイベントが設定されている?ということです。
 
分かりにくいと思うのでサンプル05_eventFlow_04.htmlを用意しました。このサンプルには
イベントの設定されていないpタグ(黒丸)がsmallの中に入っています。イベントオブジェクト
のtargetを利用しているのでクリックされたpタグのidであるpがalertされますが、その回数を
カウントしてください。05_eventFlow_01.htmlと同じように階層化されたdivの数だけ、
つまり3回だけalertされます。
http://www.designdrill.jp/jquery/10/05_eventFlow_04.html
 
ここで理解しておくのは、pタグをクリックしたけれどpタグにはイベントが設定されて
いないのでpタグはクリックの反応をしません。クリックに反応したのはイベントを
設定したdivだけなのです。targetプロパティのおかげでpタグが取得できているだけ
なのです。勘違いしないようにしましょう。
ついでにtargetプロパティとcurrentTargetを比較するサンプルも作成しました。
http://www.designdrill.jp/jquery/10/05_eventFlow_04b.html
 
 
 

バブリングが不都合な場合

デリゲートに必要なこのバブリングですが、場合によっては効率が落ちます。
サンプル05_eventFlow_05.htmlを開いてソースを確認してください。
divがクリックされたらtestFuncに報告するようになっています。
http://www.designdrill.jp/jquery/10/05_eventFlow_05.html
 
サンプル04_eventFlow_05.htmlでは緑をクリックすると3回も報告されてしまいます。
報告は1回すればよい場合では、余分に報告してしまい効率が悪いです。次回は
この問題を解決する仕組みを紹介します。
 
ただしデリゲートの仕組みを使わないのであれば、サンプル05_eventFlow_06.htmlの
ようにセレクタをidで絞るだけです。ただしこの方法だとピンクや青は反応しなくなる
ので次回のテクニックも覚えるようにしましょう。
http://www.designdrill.jp/jquery/10/05_eventFlow_06.html
 
おしまい
 
 
 

デリゲート(2)

jQueryのver1.4.2からはdelegateイベントが追加されています。日本のリファレンスにはまだ書いて
ないので、英語のリファレンスへのリンクを書いておきます。
リファレンス:.delegate()

しかし、これは最新のver1.7以降onメソッドに代替されます、以後のサンプルは最新の1.7を利用するので
onイベントを利用しますが、デリゲートのことを思い浮かべて理解するようにしましょう。
リファレンス:.on()
※delegeteと第1引数と第2引数の順番が異なっているのに注意しておきましょう。
これを利用すればタブメニューを完成させたliveイベントでもデリゲートすることができます。

サンプル:liveイベントをonイベントに置き換える
http://www.designdrill.jp/jquery/10/04_delegate_03.html
※ソースを確認してliveがonに置き換わっていることを確認してください。

 
サンプルのソースを確認して、liveイベントをonイベントに書き換えても機能している
ことを確認してください。見た目は変わりませんがデリゲートの仕組みを利用しているので
効率が良くなっています(セレクタが複雑で分かりにくいですが、liveでは5つのliにイベント
を設定していますが、onでは#tabArea1つにイベントを付けています)。とはいえ
これくらいのサンプルではデリゲートなんて気にしなくても良いと思います。
 
今回の記事で参考にしたサイトは以下の2つです。2つともliveイベントよりdelegeteの方が
処理が速くなると書いています(onは登場したばかりなので記事はありませんでした)。
 
<s>gnarl,</s>技術メモ”’<marquee><textarea>¥
一番下の「まとめ」を読むと良いと思います。

The Difference Between jQuery’s .bind(), .live(), and .delegate()
ページの始めの方に「Why .delegate() is better than .live()」(なぜliveよりdelegateのほうが良いか)
とあります。ここでも速度が速くなると書いてあります。
 
 
おしまい。
 
 

デリゲート(1)

これからしばらくはdelegate(デリゲート)について書きたいと思います。jQueryでデリゲートを
利用すると速度アップにつながるそうです。しかし膨大な処理をするアプリ以外では目に見える効果
は無いと思います。
 
実際にデリゲートを利用したサンプルと、していないサンプルを比較してみましょう。

サンプル:デリゲート
デリゲートを利用していないサンプル(04_delegate_01.html)
デリゲートを利用しているサンプル(04_delegate_02.html)
※2つのサンプルのソースにコメントで説明があります。

 
デリゲートを利用していないサンプルではliにイベントを設定しているため、liの数(つまり5つ)だけ
イベントが設定されています。5つくらいでは問題ないと思いますが、イベントを多く設定しすぎると
処理が大変で速度が低下するそうです。最新のver1.7ではイベント関連の速度もアップしているようです。
この記事の「Improved Performance on Delegated Events」参照
 
ですので「デリゲートを利用しているサンプル」のように親の要素にイベントを設定するようにします。
このサンプルではulが1つだけなので、イベントの設置数も1つに節約できます。しかし、それでは
どのliがクリックされたか分かりません。そこで利用するのが以下のイベントオブジェクトです。
※liもulに含まれるため、liのクリックをulでキャッチすることができます。この辺はデリゲートのあとで説明したいと思います。

$("ul").click(function(eventObject){
 $(eventObject.target).css("color","#66ccff");
})

 
 
 

イベントオブジェクト

まずイベントオブジェクトを利用するためには上記1行目のようにイベントハンドラとして設定する
functionに引数を受け取るための変数を書きます(上記例ではeventObjectですが何でも構いません)。
 
で、このイベントオブジェクトは色々なプロパティを持っていてリファレンスで確認することが
できます。リファレンス:Events/jQuery.Event
色々なプロパティがありますが、今回利用するのはAttributeの項目にあるtargetプロパティです。
これを利用するとイベントの発生源となった要素を取得することができます。
サンプル:04_delegate_02.htmlでは以下の部分で利用しています。

$("ul").click(function(eventObject){
 $(eventObject.target).css("color","#66ccff");
})

 
このイベントオブジェクトとtargetプロパティのおかげで、ulにしかイベントを設定していないのに
どのliがクリックされたかを判断することができるのです。
 
ちなみに今回利用したtargetプロパティと似ているものとしてcurrentTargetプロパティがあります。
これをイベントハンドラ内で利用するとthisと同じものを指します。分かりにくいので以下の
サンプルで確認してください。liをクリックしてもイベントハンドラ内のthis、つまりulを指す
ため、ul全体が青くなってしまいます。
http://www.designdrill.jp/jquery/10/04_delegate_02b.html
※targetとcurrentTargetの違いはデリゲートの後に説明するイベントフローのサンプルでまた確認します。
 
 
delegeteの意味は「委譲」です。大まかな理解として「別のオブジェクトに処理を肩代わりして
もらう」と覚えておくと良いでしょう。今回の例ではliがulにクリックの処理を肩代わりして貰っています。
 
おしまい
 
 

セレクタを自作する(2)

前回作成したセレクタを改良して引数を利用して色を指定できるようにします。

サンプル:自作セレクタ(引数あり)
http://www.designdrill.jp/jquery/10/03_selector_02.html
セレクタに引数を付けて色を指定できるようにしました。

 
変更箇所はあまりありません。まずはセレクタを実行している部分を確認します。まず
セレクタ名は:backColorに変更しました。それに続き()内に引数を渡す構文になります。

$("div:backColor(#66ccff)").text("水色");	

 
続いて受け取る方の変更を確認しましょう。異なるのは2カ所だけです。
まず以下の部分で引数を受け取ります。前回のサンプルではobjだけでしたが
今回はiとdataObjが追加されています。iは単純に要素に付けられる連番で
今回は利用しません。引数の情報はdataObjに渡されます。

backColor: function(obj,i,dataObj) {	

 
しかしdataObjは配列データとなっており、引数を得るためにはここから
さらに抽出しなければなりません。alertを利用して調べると要素番号3の場所に
引数が格納されていましたので、以下の様に色を比較する部分を書き換えています。

return targetColor == dataObj[3];

 
今回参考になったのは以下のページでした。
jQueryのセレクタを自作してみる
 
 
 

セレクタを自作する(1)

jQueryではextendメソッドを利用するとセレクタを自作できるそうなので
試しに挑戦してみました。何に利用できるか現時点では不明だけれど…。
リファレンス:jQuery.extend(target, object1, [objectN])
 
自作セレクタの説明は色々なサイトで紹介されているので、かぶらない
サンプルを作成してみました。
google検索:jquery セレクタ自作

サンプル:自作セレクタ
http://www.designdrill.jp/jquery/10/03_selector_01.html
背景色が#66ccffのdivに「水色」と文字を表示するサンプルです。

 
他とネタが被らないように背景色のセレクタを作成したら、セレクタの自作に
関係ない部分でコードが増えてしまいました…。ですのでここで説明しておきます。
 

色情報を変換

jQueryのcssメソッドで背景色が取得できるのですが、これが16進数の#ffffffの
形式ではなくrgbフォーマット「rgb(255,255,255)←こんなやつ」でした。
ですので、rgbフォーマットを16進数のフォーマットに変換する関数を作成
しました。引数としてgrbフォーマットを受け取り、#プラス6桁の16進数を
返します。引数チェックやエラー処理をしていない簡易的な関数です。

function rgbToHex(str) {
 var myData = str.substring(4, str.indexOf(")")).split(",");
 var r = Number(myData[0]).toString(16);
 var g = Number(myData[1]).toString(16);
 var b = Number(myData[2]).toString(16);
 return "#" + addZero(r,2) + addZero(g,2) + addZero(b,2);
}

 
でもって、上記の変換で各色必ず2桁の数値にするように桁を合わせる関数も
作成する羽目になりました。

function addZero(num,keta){
 var str=String(num);//---念のため文字列化
 while(str.length<keta){str="0"+str}
 return str;
}

 
上記2つの関数はセレクタの自作とは関係ありません。
 
 
 

セレクタの自作

まずは構文を少しずつ確認します。extendメソッドはセレクタを作成するメソッド
ではなく、セレクタ以外にもjQueryの機能を拡張するためのものです。ですので
以下の様に引数を設定することでjQueryの:を利用するセレクタを拡張できるのです。
jQuery.expr[“:”]はjQueryの:を利用したセレクタ設定の部分を指します。ここに
新しいセレクタを追加するのです。このサイトが理解を助けると思います。

$.extend(jQuery.expr[":"], {

 
次の行では新しいセレクタ名を設定します。サンプルではwaterColorとしました。
function内の引数(ここではobj)にhtml上の要素が渡されます。

新しいセレクタ名: function(obj) {

 
残りの3行で渡された引数(つまりhtmlの要素)を調べて、背景色が
水色(”#66ccff”)だったら選択するようにします。選択するかしないかは
returnで決めます。trueを返せば選択され、falseなら選択されません。
今回のサンプルでは、比較式を利用しているのでtargetColor == “#66ccff”
が正しければtrueとなり選択されます。

var targetColor = $(obj).css("background-color");
var targetColor = rgbToHex(targetColor);
return targetColor == "#66ccff";

上記の1行目で、選択された要素の背景色を調べます。cssメソッドでは
rgbフォーマットでデータが返されます。2行目で最初に説明した自作の関数で
16進数のフォーマットに変換します。
3行目で色を比較して、その結果を返しています。
 
 
サンプルの説明は以上なのですが、今回作成したセレクタは背景色が
「”#66ccff”」の時だけしか利用できない、なんとも使い勝手の悪いセレクタ
です。ですので、次回は色を指定できるように改造したいと思います。