12 | 2008/01 |  02

  1. 無料サーバー

search phpbb-phpbb-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut

CSSやJavascript自習の苦闘史を綴っていきたい。恐縮ですがJavascriptを有効にしてご覧ください。
2005年12月から社会問題も掲載!


jQuery()の挙動を解読する(20) $(args).unbind()、$.event.remove()、$.removeData() 解読 ──jQuery解読(31)

$(args).unbind() 【ver1.2.2で変化なし】について

イベントの登録メソッドに較べて、それを削除する $(args).unbind() は余り使用頻度の高いメソッドではないでしょう。登録したイベントハンドラーをわざわざ解除する必要性は、決して高いとは思えないからです。

そのことはさて置き、$(args).unbind() メソッドは僅か数行のもので、全ての処理を $.event.remove() メソッドに委ねており、更に $.event.remove() メソッドの骨格は $(args).data() と $(args).removeData() メソッドによって構成されています。

ここでも $(args).add() メソッド同様に、本家サイトで Internals ジャンルに分類されている Data Cache を取り扱うメソッドが不可欠となっています。

$(args).unbind() のコードは以下の通りです。対象要素ノード毎に $.event.remove() を呼び出してその結果を受け取っています。

2199: unbind: function( type, fn ) {
2200:  return this.each(function(){
2201:   jQuery.event.remove( this, type, fn );
2202:  });
2203: },

$.event.remove() 【ver1.2.2で部分的に変更された】について

引数と変数指定

unbind() メソッドから3つの引数を受け取り、実際にイベントをアンバインドするメソッドです。

elem がテキストノードかコメントだった場合には何もせずに終わります。

1902 行の data() メソッドにより、当該対象要素ノードに対応する Namespaced event handlers をData Cache から抽出し、変数 events に代入します。なお、変数を3つ指定していますが、index はどこでも使われていません。

1896: // Detach an event or set of events from an element
1897: remove: function(elem, type, handler) {
1898:  // don't do events on text and comment nodes
1899:  if ( elem.nodeType == 3 || elem.nodeType == 8 )
1900:   return;
1901:
1902:  var events = jQuery.data(elem, "events"), ret, index;
1903:

ここで、events 変数には何が代入されるのか、視覚的にも明らかにしておくことが得策だと思います。

下図はあるサイトのある要素ノードに、クリックとダブルクリックの2つのイベントハンドラーをバインドした時の、Namespaced events handlers と jQuery.js が呼んでいるオブジェクトの一部、つまり jQuery.cache オブジェクトの一部を切り取ったものです。

この図にある events オブジェクトと同じような構造の、「 element 」要素ノードに対応するオブジェクトが 1651 行の変数 events に代入されます。

Namespaced_Eents_Object
jQuery ネームスペース内のイベントハンドラー
   // 当該対象ノードにイベントハンドラーが登録されていれば
1904: if ( events ) {

 /* 削除その1
  * 第2引数の type が与えられていない場合の処理である。
  * この場合には、events オブジェクト内の全ての type プロパティ、つまり登録
  * されている全てのイベントハンドラー毎に、remove() メソッドを再帰呼び出し
  * する。再帰的に呼び出す場合には、events オブジェクトから type 名称を取り
  * だして第2引数としている。
  * このブロックの処理によって、対象要素ノードに登録されている Namespaced 
  * イベントハンドラーの全てを削除することになる。
  */
1905:  // Unbind all events for the element
1906:  if ( types == undefined )
1907:   for ( var type in events )
1908:    this.remove( elem, type );

 /* イベントオブジェクトが引数となった場合の処理
  * 「type.type がある場合」とは、何らかの事情によって第2引数の type が
  * 文字列ではなく、イベントオブジェクトであった場合を指している。
  * その場合には、handler にはイベントオブジェクトの handler プロパティを
  * type にはイベントオブジェクトのtypeプロパティを代入している。
  */
1909:  else {
1910:   // types is actually an event object here
1911:   if ( types.type ) {
1912:    handler = types.handler;
1913:    types = types.type;
1914:   }
 /* の処理
  * 複数イベント一括 bind() メソッド に呼応して、unbind()メソッドもマルチ
  * イベント対応としている。
  * つまり、各イベントタイプ毎にイテレートして登録解除を進めることになる。
  * type にはイベントtype名が入る。
  */
1916: // Handle multiple events seperated by a space
1917: // jQuery(...).unbind("mouseover mouseout", fn);
1918: jQuery.each(types.split(/\s+/), function(index, type){
1919:  // Namespaced event handlers
1920:  var parts = type.split(".");
1921:  type = parts[0];
 /* 削除その2
  * 次は第2引数の type が与えられていて、それが events オブジェクトの
  * プロパティと一致する場合── if ( events[type] ) ──の処理である。
  * 1925行……第3引数 handler が与えられていれば、
  * 1926行……登録されているプロパティ=ハンドラー関数を削除する。
  * ここでは type 名のオブジェクトは削除せず、その handler 名の関数
  * だけを削除する。
  * ここに handler.guid プロパティの値はハンドラー関数である。
  * ※ event.add() メソッド参照。
  */
1923:  if ( events[type] ) {
1924:   // remove the given handler for the given type
1925:   if ( handler )
1926:    delete events[type][handler.guid];
1927:
  * 削除その3
  * 第3引数の handler が与えられていない場合には(1929行以下)
  * events[type] オブジェクト内の各プロパティに対して(1930行)
  * カスタムイベントがないか(!parts[1])、又は登録されているカスタムイベ
  * ントタイプと、指定されたカスタムイベントタイプが一致すれば(1932後段)、
  * handler プロパティを削除する。
  * これにより指定した type で登録されているイベントハンドラー関数を
  * 全て削除する。
  */
1928:   // remove all handlers for the given type
1929:   else
1930:    for ( handler in events[type] )
1931:     // Handle the removal of namespaced events
1932:     if ( !parts[1] || events[type][handler].type == parts[1] )
1933:      delete events[type][handler];
1934:
一般のイベントハンドラーの削除
 /* event[type] オブジェクト内にプロパティが残ってないかチェックする。
  * もし、残っていれば for loop を 中止する。
  */
1935:   // remove generic event handler if no more handlers exist
1936:   for ( ret in events[type] ) break;
 /* 削除その4
  * もし、 event[type] オブジェクト内にプロパティが残っていれば、 
  * !ret は false となるので 1938行以下は実行されない。
  * さて、もはや eventsオブジェクトに type プロパティが存在しない場合
  * ──if ( !ret )──には、一般的なイベントハンドリングによって登録した
  * ハンドラー関数の登録を解除する。
  * ここに jQuery.data(element, "handle") はイベントハンドラー登録時に利用
  * される代理母的な関数である。既に add() 及び handle() メソッドの項で述べ
  * たように、add()メソッドによってNamespaced イベントハンドラーに登録済みの
  * 関数から、jQuery.event.handle() メソッドがバインドする関数を選択し登録する。
  */
1937:   if ( !ret ) {
1938:    if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
1939:     if (elem.removeEventListener)
1940:      elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
1941:     else if (elem.detachEvent)
1942:      elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
1943:    }
1944:    ret = null;
1945:    delete events[type];
1946:   }
1947:  }
1948:  });
1949: }
 /* 削除その5
  * 最後の処理は再び Data Cache オブジェクト内のクリーニングである。
  * これまでの処理で全てのイベントハンドラー(タイプ、カスタムイベント、
  * ハンドラー関数、id 番号など)を削除するが、まだ Data Cache オブジェク
  * ト内には残存物がある。それは events と handle オブジェクトである。
  * これらを以下の数行で削除する。
  * ret がないことつまり events オブジェクト内が空であることを確認して、
  * events と handle オブジェクトを削除する。
  * 以上の結果、当該要素ノードelementに関してData Cache オブジェクト内に
  * 存在するオブジェクトは、当該要素ノードに対応するuuid番号を振られた空
  * のオブジェクトだけとなる。
  */
1951:   // Remove the expando if it's no longer used
1952:   for ( ret in events ) break;
1953:    if ( !ret ) {
1954:     var handle = jQuery.data( elem, "handle" );
1955:     if ( handle ) handle.elem = null;
1956:      jQuery.removeData( elem, "events" );
1957:      jQuery.removeData( elem, "handle" );
1958:     }
1959:  }
1960: },

▲ToTop

jQuery.removeData( elem,name ) 【 ver1.2.2 で変化なし】解読

jQuery.removeData() メソッドは、jQuery.data()メソッドで構築した Data Cache オブジェクト内のオブジェクトを削除するためのもので、jQuery.event.remove()メソッドの最後に登場します。その働きは既に上で述べたので、ここでは当該メソッドの解読を行ってこのエントリイを閉めます。

コード全体は name 引数がある場合とない場合の2通りに大別されます。

変数初期化
668: removeData: function( elem, name ) {
669:  elem = elem == window ?
670:    windowData :
671:    elem;
672:

 /* data() メソッドで elem, name を登録する時に、elemには、expando
  * プロパティが付与される。
  * ( data() メソッドの 518行 id = elem[ expando ] = ++uuid;)
  * ここではこれを取りだして改めて地域変数 id に代入している。
  * なお、この id は先の 518 行により、個々の elem に対応して
  * cache オブジェクト内のプロパティとして割り振られているので、
  * cache[id]とすれば 当該 uuid番号 のプロパティ値を指すことになる。
  * 勿論 elem の指定ミスがあればこの行は通過し、540行でも撥ねられ、
  * その先に進んでも全てスルーする。
  * また name がないか間違っている場合も全ての行がスルーされる。
  */
673:  var id = elem[ expando ];
674:
削除その1──cache.id オブジェクト内のプロパティ削除
 /* 抽出された id 番号を頼りに、その中にある name プロパティを削除する。
  * 1697、1698 行の引数に置き換えれば events と handle を削除することに
  * なります。
  */
675:  // If we want to remove a specific section of the element's data
676:  if ( name ) {
677:   if ( jQuery.cache[ id ] ) {
678:    // Remove the section of cache data
679:    delete jQuery.cache[ id ][ name ];
680:
削除その2── element に対応する id 番号名のオブジェクト削除
 /* id オブジェクト内に何もないことを確認し(546行)、
  * なければ(547行)、elem つまり当該 elementに対応する id 番号名のオブ
  * ジェクトそのものを、removeData()を再帰呼び出しして削除する。(548行)
  * なお 548 行を 564 行と同様のコードとしなかったのは、別の name 名のオブ
  * ジェクトが残っているケースもあるため、これに配慮したものと推測される。
  * 例えば、events オブジェクトを削除する段階では、まだ handle オブジェクト
  * が残っている。(1697-1698行参照)
  */
681:    // If we've removed all the data, remove the element's cache
682:    name = "";
683:
684:    for ( name in jQuery.cache[ id ] )
685:     break;
686:     if ( !name )
687:     jQuery.removeData( elem );
688:   }
689:
削除その3──elemオブジェクトのexpando プロパティ削除 及び cache 内の elem id プロパティ削除
 /* name 引数が与えられなかった場合の処置
  * elem の expando プロパティ削除を行う(556行)。
  * IE ではエラーが発生するのでDOMの removeAttribute メソッドを使って
  * elem の expando プロパティを削除する。
  * 最後に cache オブジェクト内の id プロパティを削除し、elem に対応する
  * cache オブジェクト内の全ての痕跡を消し去る。
  */
691:  // Otherwise, we want to remove all of the element's data
692:  } else {
693:   // Clean up the element expando
694:   try {
695:    delete elem[ expando ];
696:   } catch(e){
697:    // IE has trouble directly removing the expando
698:    // but it's ok with using removeAttribute
699:    if ( elem.removeAttribute )
700:     elem.removeAttribute( expando );
701:   }
702:
703:   // Completely remove the data cache
704:   delete jQuery.cache[ id ];
705:  }
706: },

jQuery()の挙動を解読する(19) jQuery.extend()メソッドのバグについて ──jQuery解読(30)

バグ修正が施された jQuery.1.2.2b2.js をゲット

jQuery() の挙動を解読する(3) jQuery.extend()及びjQuery.prototype.extend()──jQuery解読(7) において、jQuery.extend() メソッドの deep copy 部分にバグがあることを示唆しました。

そのバグは通常のメソッド拡張やオブジェクト拡張の場合には出現しないものなので、直ぐに発覚しなかったのでしょう。また、そもそも deep copy を利用するユーザーが余り多いとは思えないので、その点からも発覚しにくかったものと思われます。

さて、別件で本家サイトを閲覧していて、「ところでこのサイトは、どの版の jQuery.js を利用しているのだろうか?」とふと疑問に思い、本家サイトが利用している版を調べました。

すると、それは公開されている最新版である 1.2.1 ではなく、1.2.2b2 という版でしたので早速ゲットし、jQuery.extend()メソッドに変更が加えられてないかどうか確認してみました。

案の定 jQuery.extend()メソッドには大幅に手が加えられていた

1.2.2b 版の jQuery.extend() メソッドは、利用変数名が大幅に変更され、かつ指摘したバグ箇所には修正が施されていました。

修正箇所の詳細は別途述べるとして、参考のために 1.2.2b2 版の jQuery.extend() メソッドを以下に掲載しておきます。

なお、ここで触れている1.2.2b2 版は Date: 2007-12-20 10:14:13 -0500 付けのものです。直近のnightly 版は同じ1.2.2b2 ですが、日付は Date: 2008-01-14 14:17:35 -0500 となっています。

1.2.2b2 版 jQuery.extend() メソッドコード

jQuery.extend = jQuery.fn.extend = function() {
 // copy reference to target object
 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

 // Handle a deep copy situation
 if ( target.constructor == Boolean ) {
  deep = target;
  target = arguments[1] || {};
  // skip the boolean and the target
  i = 2;
 }

 // Handle case when target is a string or something (possible in deep copy)
 if ( typeof target != "object" && typeof target != "function" )
  target = {};

 // extend jQuery itself if only one argument is passed
 if ( length == 1 ) {
  target = this;
  i = 0;
 }

 for ( ; i < length; i++ )
  // Only deal with non-null/undefined values
  if ( (options = arguments[ i ]) != null )
   // Extend the base object
   for ( var name in options ) {
    // Prevent never-ending loop
    if ( target === options[ name ] )
     continue;

    // Recurse if we're merging object values
    if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
     target[ name ] = jQuery.extend( target[ name ], options[ name ] );

    // Don't bring in undefined values
    else if ( options[ name ] != undefined )
     target[ name ] = options[ name ];

   }

 // Return the modified object
 return target;
};

jQuery()の挙動を解読する(18) $(args).trigger()、$(args).triggerHandler()、$.event.trigger() 解読 ──jQuery解読(29)

$(args).trigger()、$(args).triggerHandler()

これらのメソッドに該当するコードは jQuery.js ver1.2.2 の 2205-2215 行です。2214 行だけが1.2.1とことなる箇所で新規追加行になります。バグフィックスと言うところでしょう。

2205: trigger: function( type, data, fn ) {
2206:  return this.each(function(){
2207:   jQuery.event.trigger( type, data, this, true, fn );
2208:  });
2209: },
2210:
2211: triggerHandler: function( type, data, fn ) {
2212:  if ( this[0] )
2213:   return jQuery.event.trigger( type, data, this[0], false, fn );
2214:  return undefined;
2215: },

これらのインスタンスメソッドは、全く同様の引数をとり、共に対象要素に登録されている、type で指定されたイベントタイプに対応するイベントハンドラー関数を起動します。しかし、微妙に異なる引数(上のピンク色の2箇所)を $.event.trigger() に渡してこのクラスメソッドを起動し、このメソッドに全ての処理を委ねた上で処理結果を return します。したがってこれらの2つのインスタンスメソッドの挙動を知るには $.event.trigger メソッドを理解する必要があります。

しかしその前に、2つのメソッドの差異を外観しておきます。

  • trigger インスタンスメソッドはその対象要素の各々に対して、jQuery.event.trigger メソッドを適用し、各々の結果を返します。他方、triggerHandler インスタンスメソッドは、対象要素の最初の1つの要素に対してだけ作用し結果を返します。 return 値は全て jQuery インスタンスです。
    なお、何故対象ノードを複数( trigger )と1つだけ( triggerHandler )に分けたのか、その理由は分かりません。triggerHandler() メソッドでも trigger() メソッド同様に、複数の要素ノードを対象として作動するようにしても問題はないと思われるのですが..。
  • trigger インスタンスメソッドは、対象要素に登録され、type で指定されたイベントタイプに対応するイベントハンドラー関数を起動し、かつ jQuery.event.trigger メソッドに渡される4番目の引数を true とすることにより、当該イベント発生時のブラウザ固有の動きを抑制しません。
  • 他方、triggerHandler インスタンスメソッドは、対象要素に登録されているイベントタイプに対応するイベントハンドラー関数を起動させる点は trigger メソッドと同様ですが、jQuery.event.trigger メソッドに渡される4番目の引数を false とすることにより、type で指定されたイベントタイプに対応するブラウザ固有の動きを抑制します。

▲ToTop

$(args).trigger() と $(args).triggerHandler() の実例

更に、$.event.trigger() クラスメソッドの解読を行う前に、これらのインスタンスメソッドの実例を見ておきます。これらのメソッドが何を行うのか理解することが先決であり、本家 jQuery サイトにいくつかの例示がありますが、第三引数の fn を与えた例はなく、また例そのものが分かりやすいとは言えないからです。

独自に作成した $(args).trigger() メソッドの実例

例は、$(args).trigger() メソッドの引数が1つだけ、2つ及び3つの場合の各々の違いが分かるように3パターン作成し、更にtriggerされるイベントタイプも click、dblclick 及び mouseover の3種類とし、合計9つのパターンの例を作成しました。

複雑な挙動をするtrigger()インスタンスメソッドを十分に理解するには、これだけの例が必要でした。

使い方

  • 下のカラーボックス上ではそれぞれの説明にあるマウスイベントタイプが発生します。この場合に起こることは、それぞれのボックスにバインドされたイベントハンドラーが、各々のイベント発生によって働いただけに過ぎません。
  • これらの3つのボックスには同じ class 名 "Box" が振ってあり、トリガーメソッドの対象としてこの class 名をもつ3つのボックスを指定してあります。つまり jQuery(".Box").trigger(・・・)です。trigger() メソッドはこれらの3つの要素ノードにバインドされた、異なるイベントタイプのイベントハンドラーを励起させ得ることになります。
  • カラーボックスの下にあるボタンが triggerメソッドを起動させる起動ボタンです。縦4行、横3列の10個のボタンがありますが、一番下のボタンは初期化ボタンで、他の各行は trigger メソッドの引数が異なり、各列はトリガーするイベントが異なります。各々はボタン名に書いてあるような設定となっており、各々のボタンに記されているような trigger() インスタンスメソッドがバインドされています。これらのボタンをクリックすると各々にバインドされた異なる trigger メソッドが呼び出され、trigger対象要素ノードにバインドされているイベントハンドラーをトリガー(励起)させます。
  • 1行目のボタンをクリックすると、3つの trigger メソッド対象要素ノードから、対象となるイベントタイプがバインドされている要素ノードだけのイベントがトリガーされます。当該イベントタイプがバインドされていない他の2つの要素ノードのイベントハンドラーは起動されません。
  • 2行目のボタンには第2引数が与えられています。ここでも対象となるイベントハンドラーがバインドされている要素ノードだけが反応します。第2引数はトリガー先のイベントに情報などを付加する働きをし、各々のボタンをクリックするとボックスの下に文字列が現れます。これが付加された情報です。なお、再びクリックすると付加された文字列が消えるような toggle() メソッドが設定されています。
  • 3行目のボタンは、3つの引数を与えた trigger メソッドをバインドしたものです。このボタンで初めて、triggerメソッドの対象要素ノードが3つのボタンであったことが明示的に明らかにされます。第3引数の fn 関数はイベントタイプに無関係に triggerメソッドの対象要素ノードの全てに作用するため、3行目のどのボタンをクリックしても、3つのボックスの背景色が同一色に変化します。
  • しかし、その場合であっても trigger メソッドは、第1引数で指定されたイベントタイプがバインドされた要素ノードのイベントハンドラー関数だけを起動させるので、当該イベントタイプがバインドされた要素ノードのイベントハンドラーしか起動されません。
    ここで興味深いことが確認できます。ブルーボックスには click イベントがバインドされており、3行のボタンの第1列に登録されている trigger メソッドは イベントタイプ click を起動します。
    この結果、clickイベントがバインドされているボックス、ブルーボックス及びレッドボックスのイベントハンドラーが反応します。(レッドボックスにはダブルクリックで付加される文字を消すためにクリックイベントがバインドされています。)
    従って、例えばレッドボックスをダブルクリックした後に、第1列目の3つのいずれかのボタンをクリックすると、ブルーとレッドの2つのボックスのクリックイベントが励起(トリガー)されます。レッドボックスのその他の場合によるダブルクリック後においても同様です。
Box A:このボックスを click すると一旦透明化され、その後元に戻ります。
Box B:このボックスを double click するとボックス内に文字が増え、その後このボックスをクリックすると増えた文字が消えます。

Box C:このボックスに mouseover し続けると透明度が変化しながら上下にスライドし続けます。
  

▲ToTop

$(args).triggerHandler() メソッドの実例

triggerHandler() メソッドは、後に $.event.trigger() メソッドの解読でその仕組みを明らかにしますが、trigger メソッドと異なるのは、ブラウザ既定の動作を停止させる点です。

ですから、既定の動作を持たないタイプのイベントがバインドされた要素ノードを対象として、このメソッドを適用しても何も意味がありません。

ここに既定の動作を持つイベントタイプには何があるのか、その点は不明です。分かっていることはfocus()、blur()、click()などの、a タグやinput、textarea タグなどが元々有しているメソッド名と一致するイベントタイプが「ブラウザ既定の動作を有する」ということが出来るであろうことです。

さて、実例を作ってみようとしたのですが、jQuery本家サイト以上のそれは作れませんでしたので、本家サイトの例を引用して解説しようと思います。

本家サイトからの引用サンプル

  
  1. input ボックスにはイベントタイプ focus のイベントハンドラーが登録されています。ハンドラー関数によりフォーカスが input ボックスに移ると Focused! という文字を表示してから、フェードアウトします。
    そのことを確認するには input ボックス内でマウスをクリックすれば分かります。その末尾に Focused! と表示され、その後1.5秒掛けてフェードアウトします。これが設定されている focus イベントの発生と実行です。
  2. 次に、マウスを input ボックス外でクリックしてフォーカスをはずしてから、Button1 をクリックします。すると inputタグ既定の focus イベントが起動して、 Focused! と表示し、かつ trigger されたイベントハンドラーが Focused! と表示します。つまり2つの Focused! が表示されます。そして共に1.5秒間でフェードアウトします。この時、input ボックスがフォーカスされ、マウスカーソルがその中で点滅していることを確認できます。
    ここでは、input タグに設定された focus イベントのデフォルト動作(=フォーカスすると言う動作)が trigger() メソッドによって行われ、同時に trigger() メソッドによってイベントハンドラー関数が起動されたため、2つの文字が表示されたことになります。
    なお、これまでのことはIEでの確認です。Firefox と Opera ではこの違いが出現せず、trigger() でも triggerHandler() でも結果は変わりませんでした。理由は不明です。
  3. 次に、念のために input ボックス外でクリックしてフォーカスをはずしてから、Button2 をクリックします。すると focus イベントハンドラーが起動して、Focused! と表示され1.5秒間でフェードアウトします。しかし、今度は input タグ内にフォーカスは当たっていません。input ボックス内でマウスカーソルは点滅していません。また表示される Focused! も1つだけです。
    これで triggerHandler() メソッドと trigger() メソッドとの効果の違いが確認出来ました。

▲ToTop

$.event.trigger()

愈々、trigger() 及び triggerHandler() がどのようにして作用しているのか、その挙動を探ります。これらの2つのメソッドから呼び出される $.event.trigger() を解読します。

$.event.trigger() の引数について

trigger() クラスメソッドは type、data、elem、donative 及び extra の5つの引数を取ります。

これらは順に、

  • tyoe: 励起させたいイベントタイプ
  • data: type イベント発生時のイベントオブジェクト並びに trigger により励起させるハンドラー関数で利用させる引数によって構成される配列オブジェクト
  • elem: type イベントを発生させる要素ノード(トリガー先とでも言うべきか)
  • donative: typeイベントによるブラウザのデフォルト動作を行わせるか(true)、行わせないか(false)を指定する真偽値
  • extra: trigger() メソッドによって type イベントを発生させた時に起動させる、イベントハンドラー関数とは別の、独自に指定する関数

を意味しています。

1. 第2引数 data の処理

data 引数を配列にし、data がなければ空の配列を作り data に代入する。data には trigger メソッドを起動させたイベントオブジェクトなどを記述する。

1962: trigger: function(type, data, elem, donative, extra) {
1963:  // Clone the incoming data, if any
1964:  data = jQuery.makeArray(data || []);
1965:
2. トリガー対象 (elem) が指定されていない場合の処理

第3引数の elem がない場合の処理です。この場合において、当該頁にイベントが登録されていれば、全てのノードを対象としてtrigger()メソッドを再帰呼び出しし、イベントが全く登録されていなければ何もしません。

1966:  // Handle a global trigger
1967:  if ( !elem ) { //elem が指定されていなければ
1968:   // Only trigger if we've ever bound an event for it
1969:   if ( this.global[type] ) //typeイベントが登録されていれば
      // 全てのノードを対象として trigger クラスメソッドを再帰呼び出しする。
1970:    jQuery("*").add([window, document]).trigger(type, data);
1971:
3. 1つの対象ノードに対する処理 (1) イベントハンドラー起動前の処理
1972:  // Handle triggering a single element
    // 1の要素ノードを trigger 対象とする。
1973:  } else {

 /* elem がテキストやコメントだった場合
  * 何もせずに undefined を返す。
  */ 
1974: // don't do events on text and comment nodes
1975: if ( elem.nodeType == 3 || elem.nodeType == 8 )
1976: return undefined;
1977:
 /* elem[type] が関数ならば fn = true、違えば fn = false とする。
  * この elem[type] は突然登場し、このメソッド以外では使われていない。
  * これはブラウザ固有の type メソッドが elem に指定されている場合に
  * 部分であり、2010-2017 行に連動する。
  */
1978:   var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),

 /* data 配列が空ならば、あるいは data 配列の最初の要素に preventDefault
  * プロパティがなければ(つまりそれがイベントオブジェクトでなければ)
  * evt = true とする。その他の場合には evt = false とする。
  * こうすることにより、イベントオブジェクトが第一引数にない場合において
  * var evt = true としてダミーイベントを用意する準備をしている。
  */
1979:   // Check to see if we need to provide a fake event, or not
1980:   evt = !data[0] || !data[0].preventDefault;
1981:

 // ダミーのイベントオブジェクトを作って data 配列の先頭要素とする。
 // その type プロパティは type、target プロパティは elem とする。
1982:   // Pass along a fake event
1983:   if ( evt )
1984:    data.unshift( this.fix({ type: type, target: elem }) );
1985:

 /* data の最初の要素としてユーザーが指示したイベントオブジェクト、
  * 又は 1721 行で作ったダミーのイベントオブジェクトの、type 
  * プロパティを type とする。
  * これは専らダミーイベントへの対応策であって、イベントオブジェクトの
  * type プロパティを与える目的のための行である。そうしないとダミーイベ
  * ントとして用を為さないから。
  */
1986:   // Enforce the right trigger type
1987:   data[0].type = type;
1988:
4. 1つの対象ノードに対する処理 (2) イベントハンドラー関数の起動その1

elem に対応する cache.id オブジェクトの "handle" プロパティ値が存在し、それが関数であれば、data を引数とする関数を elem のメソッドとして実行する。ここに data[0] はこれまでの処理でイベントオブジェクトとなっている。

これにより指定した type イベントに対応して登録されているイベントハンドラー関数が呼び出され、実行される。なお、当該関数の返値がvalに代入される。

1989:   // Trigger the event
1990:   if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
1991:    val = jQuery.data(elem, "handle").apply( elem, data );
1992:
5. 1つの対象ノードに対する処理 (3) イベントハンドラー関数の起動その2

(1)fn が存在せず、(2)elemに "on"+type 属性があり、(3)その属性値である関数を data を引数として実行して return 値が false ならばval に false を代入する。

これにより"on"+type 属性値である関数が励起・実行される。しかし、この行の起動を確認することは出来なかった。

1993:   // Handle triggering native .onfoo handlers
1994:   if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
1995:   val = false;
1996:
6. 1つの対象ノードに対する処理 (4) 固有に指定した関数 extra の起動
 // まずダミーイベントが設定されていれば、それを data 配列から削除する。
1997:   // Extra functions don't get the custom event object
1998:   if ( evt )
1999:    data.shift();
2000:

 /* 次の部分は ver 1.2.2で大きく変わった箇所です。
  * extra が既述されていてそれが関数の場合に、 val の値があれば data 配列に
  * その値を結合し、なければ data のままで、その配列を引数として当該関数を実
  * 行し、retに実行結果を返す。
  * この場合、1998-1999 行によりダミーイベントは削除されている一方、最初に
  * data にイベントオブジェクトが記述されていれば、それが引数として使われる。
  */
2001:   // Handle triggering of extra function
2002:   if ( extra && jQuery.isFunction( extra ) ) {
2003:    // call the extra function and tack the current return value on the end for possible inspection
2004:    ret = extra.apply( elem, val == null ? data : data.concat( val ) );

 /* もし何かが返されれば、それを優先的に val に代入してvalを上書きする。
2005:    // if anything is returned, give it precedence and have it overwrite the previous value
2006:    if (ret !== undefined)
2007:     val = ret;
2008:   }
7. 1つの対象ノードに対する処理 (5) ブラウザ固有のメソッドの扱い

(1)fn が存在し、(2)donative が trueで、(3)val も true で、(4)elem が a 要素でなく、(5)type が click でないならば、triggerd の値を true としてから、elem[type]()メソッドを実行する。

この部分は donative に関わる部分、つまりブラウザ固有の動きをさせるか、させないかを決める部分である。

trigger() インスタンスメソッドの場合には donative = true として jQuery.event.trigger() メソッドが起動されるので、elem[type]() が実行される。しかし、triggerHandler() メソッドの場合には donative = false として jQuery.event.trigger() メソッドが起動されるため、ブラウザ固有のメソッドすなわち elem[ type ]() は起動されない。

2010:   // Trigger the native events (except for clicks on links)
2011:    if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
      //次の行は1843行(in add() クラスメソッド)に関わる。
2012:     this.triggered = true;
2013:     try {
2014:	    elem[ type ]();
2015      // prevent IE from throwing an error for some hidden elements
2016      } catch (e) {}
2017:    }
2018:
2019:    this.triggered = false;
2020:  }
8. 1つの対象ノードに対する処理 (6) 終了処理
2021:
2022:  return val;
2023: },
2024:

 90%近いシェアを握っているインターネットエクスプローラの描画エンジンを利用したタブbrowser。沢山のタブbrowserがあるが、多機能、カスタマイズフリー、スクリプト利用等で一日の長がある。Gekkoエンジンへの対応も行われ、IEからの自立独立の方向に向かっている。2005年7月にはIE7が登場する見通しの中で、今後の発展が望まれる。

 多様なCSS作成支援機能を備えた、タグ入力式 HTML&CSS作成支援エディタ。スキンデザインもすっきりしている。テキストエディター上で作成するよりも確実で安全にタグ打ちが出来る。
文字コードを選べないのが欠点。

 StyleNote同様のタグ入力式 HTML&CSS 作成支援エディタ。長年使用してきたが現在StyleNoteに乗り換えつつある。

 クリップボード履歴情報を活用する為のソフト。画像まで履歴を取ってくれるのが嬉しい。このソフトを使わない日は絶対ない程に重宝し、愛用している。

 起動中のウィンドウの「コピーできない」説明文などの文字列を取得し、コピー可能な文字データにするツール。何かと便利。

 ストリーミングデータを保存することが出来るソフト。動画利用には不可欠なソフトだ。

 無料ながらレイヤー機能を有し、スクリプトによる拡張も可能な、sleipnir作者が提供している優れもの画像編集ソフト。

 画面キャプチャソフトと言えばこれに勝るものなし、ではないだろうか? 様々な取得方法を有しており、ブログ作成にもHomepage作成に不可欠だ。Jtrimと並んでWoodyBellsの作品。

 複数ファイルの同時編集は出来ないが、透過pngも作れる画像編集ソフト。
(以下当該サイトから抜粋)初心者にも簡単に操作が出来るフォトレタッチソフトです。多くの加工機能で画像に様々な効果を与えることができます。非常に軽快に動作するため、ストレスなく操作できます。

 Animation Gifファイルを作れる無料ソフト。

 キャプチャソフト。画面内にサイト全体が表示しきれない場合でも、これを使えば全体をキャプチャすることが出来る。

 画像処理。画像のフォーマット変換のみならず、色数やサイズ、圧縮率の変更まで一括処理できてしまう『BatchGOO!』は、大量の画像をまとめて処理したいときに大変便利なソフト。BMP, TIFF, JPEG, PCX, PNG の相互変換をはじめ、色数・サイズ・解像度の統一、JPEG圧縮率の調節など、ホームページ用の画像や携帯電話用の壁紙を揃えるのに抜群の相性を見せる。(Vectorの当該ソフト紹介頁より抜粋引用)

 名前から直ぐに想像が付くように画像のサイズを測るためのソフトだ。Homepage作成には欠かせない。2カラム、3カラムのレイアウトを行う場合に大変重宝する。

 ランチャーソフトは沢山あるが、中でもこれが一押しだ。2年以上使ってきたがその操作性には毎日満足している。これを使い始めてからデスクトップには一切のアイコンを表示することをやめてしまった。

 AdobeReader7によって、起動時間が長すぎるという長年のユーザーの不満はある程度解消した。そのためこの高速化ソフトは存在価値が低下してしまったかもしれない。AdobeReader6迄はこのソフトによる起動高速化で恩恵を受けてきた。

 IE専用が難点だが、様々なサイト内でIDやパスワードを入力するのに重宝するソフト。コンテキストメニューから簡単に起動できるのがGood! sleipnir等のIEの描画エンジンを利用しているブラウザでも使える。

 利用しているパソコンの諸元値を取得するには、このソフトがベストだ。インストール済みソフトの一覧が取得できるのも嬉しい。

 WMPは機能が豊富なだけ重い。RealPlayerも同様だ。そこでMedia Player Classicを使いたい。動作が軽快なだけではなく、対応しているファイル形式もすこぶる多く、これひとつで、wmvもrmも表示できてしまうのだから凄い! 数多あるMedia Playerの王様と言えるだろう。

 自宅でPCを起動しているときには必ず起動しているメディアプレーヤー。何かと過剰なWinampよりも、起動も速くスキンはシンプルだ。

 DivX, Xvid, Mov, Vob, Mpeg, Mpeg4, avi, wmv, dv, などの動画をDVD-Video形式に変換できるフリーソフト。クリックするとDVD関連ソフト紹介サイト=「DVDなToolたち」なるHomepageが開きます。