04 | 2017/05 |  06

  1. 無料サーバー

User forum-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut

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

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

 

jQuery()の挙動を解読する(23) $.event.special オブジェクト ──jQuery解読(35)

jQuery.event.special オブジェクトの働き

special オブジェクトは bind( elem ,fn ) 又は unbind( elem ,fn ) メソッドを使って、reaady、maouenter 及び mouseleave イベントタイプとそのハンドラー関数を elem に登録し、あるいはこれを解除する為に ver1.2.2 で新設されました。それは、(un)bind('ready',fn)、(un)bind('mouseenter', fn) 又は (un)bind('mouseleave', fn) の6つのインスタンスメソッドが起動された場合にだけ、jQuery.event.add() 又は jQuery.event.remove() メソッド内で呼び出されます。

special オブジェクトは ready、mouseenter 及び mouseleave の3つのプロパティを持っています。ready は setup と teardown の2つの関数オブジェクトで構成され、他の2つのプロパティは setup、teardown 及び handler の3つの関数オブジェクトから構成されています。(下図参照)

 special = {
  ready      : { setup : fn11, teardown : fn12 },
  mouseenter : { setup : fn21, teardown ; fn22, handler : fn23 },
  mouseenter : { setup : fn31, teardown ; fn32, handler : fn33 }
 }

ここに、それぞれの関数の役割は setup はイベントの登録用、teardown は登録済みイベント解除用、handler は各タイプのイベントに対するハンドラー関数です。

hover()メソッドと mouseover/out イベント、そしてIEへの「配慮」?

hover()メソッドは jQuery ver1.2.1 では mouseover/out イベントを扱うためのトグルメソッドでした。ところが、1.2.2 ではコードを一見すると hover()メソッドは、mouseenter/leave を扱うように変更されたように見えます。mouseover/out は hover()メソッドから切り離されてしまったような印象を受けます。

しかし、コードを詳細に見てみるとそうではないことが直ぐに分かります。hover()メソッドは IE においては mouseenter/leave イベントをサポートし、その他のブラウザにおいては mouseover/out イベントを扱うように拡張されたのです。

この拡張が何故もたらされたか、その理由は判然としませんが、過去の hover() にバグはないようですから、市場占有率が相変わらず高い IE に配慮したと理解すればよいのかも知れません。mouseenter/leave イベントが IE だけのイベントであって他のブラウザでは存在しないのに、敢えてこれらのイベントをサポートする理由は、まだ IE を無視する訳にはいかないためとしか考えられません。

関連して、それでは $(args).eventtype() 形式のイベント発動メソッドにおいて、eventtype として利用できるイベントの種類はどう変わったのか確認してみました。すると、こちらは 1.2.1 と 1.2.2 で全く同一でした。つまり、mouseenter/leave イベントは hover() メソッドだけで利用可能なのに対して、mouseover/out イベントは hover() メソッドでの利用だけではなく、それぞれを単独で利用することも想定した仕様となっています。

勿論、bind メソッドを使って mouseenter/leave イベントを単独使用することは可能でしょうが、IE だけでしか動かないコードを作る意味はありません。

▲ToTop

jQuery.event.special["type"]["setup/teardown/handler"]()メソッドの解読

specialオブジェクトは、jQuery.evemt.add() メソッド又は jQuery.evemt.remove() メソッドから呼ばれます。前者は当該イベントをバインドする際に、後者はそのイベントの登録を解除する時に、です。

type == ready の時
2126: special: {
2127:  ready: {
2128:   setup: function() {
2129:    // Make sure the ready event is setup
2130:    bindReady();
2131:    return;
2132:   },
2133:
2134:   teardown: function() { return; }
2135:  },
2136:
  • jQuery.event.special.ready.setup()
    1. $(document).bind("ready",fn) メソッドが起動されると、add()メソッドを介して special.ready.setup() メソッドが呼び出されます。この special.ready.setup() は bindReady() メソッドを呼び出して、 jQuery.ready() メソッドを DOM 読み込み完了イベントハンドラーとして登録し、DOM 読み込み完了後にこれを起動させます。
      しかし、これらの動きのどこにも第2引数の fn 関数が登場しません。正確に言えば jQuery.ready() メソッドの最後の行に至って初めて fn が起動されます。jQuery(document).triggerHandler("ready"); です。これにより fn 関数が起動されます。
    2. 次に、special.ready()メソッドの最後(2131行)には返値なしの return がありますから、未定義値が呼出し元に返されます。この結果 1875-1878 行の Listner 等のバインダー関数は起動されません。
  • jQuery.event.special.ready.teardown()

    これは単に未定義値を return するだけです。何もしません。呼出し元に戻った際には return により返された undefined は !== false ですから、1875-1878 行の Listner 等のバインダー関数は起動されません。

▲ToTop

type == mouseenter の時
2137:  mouseenter: {
2138:   setup: function() {
2139:    if ( jQuery.browser.msie ) return false;
2140:    jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
2141:    return true;
2142:   },
2143:
2144:   teardown: function() {
2145:    if ( jQuery.browser.msie ) return false;
2146:    jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
2147:    return true;
2148:   },
2149:
2150:   handler: function(event) {
2151:    // If we actually just moused on to a sub-element, ignore it
2152:    if ( withinElement(event, this) ) return true;
2153:    // Execute the right handlers by setting the event type to mouseenter
2154:    arguments[0].type = "mouseenter";
2155:    return jQuery.event.handle.apply(this, arguments);
2156:   }
2157:  },
2158:
  • jQuery.event.special.mouseenter.setup()
    1. IE の場合、何もせずに呼出し元に false を return します。この結果 attachEvent() メソッド( 1878 行 )が実行されます。
    2. IE 以外のブラウザの場合、イベントタイプ名を mouseover に変え、ハンドラー関数にjQuery.event.special.mouseenter.handler を指定して bind()メソッドを再帰呼び出しします。
      再帰呼び出しされた bind() メソッドによって、更に add() メソッドも再帰呼び出しされ、その中で mouseover名の jQuery.event.special.mouseenter.handler を関数とするイベントがバインドされます。そして実は、この moueenter.handler 関数には、mouseenterイベント名と連動している fn 関数が入るようになっています。こうして、mouseenter 名で登録された fn ハンドラー関数が、mouseover 名のハンドラー関数として機能することになります。
      それが終わると再帰先から呼出し元の 2140 行に戻りますが、2141 行で true を return させることにより、呼出し元で再び addEventListner ()メソッドが実行させることはありません。
  • jQuery.event.special.mouseenter.teardown()
    1. IE の場合、何もせずに呼出し元に false を return します。この結果 detachEvent() メソッド( 1942 行 )が実行されます。
    2. IE 以外のブラウザの場合、イベントタイプ名を mouseover に変え、ハンドラー関数にjQuery.event.special.mouseenter.handler を指定して unbind()メソッドを再帰呼び出しします。
      再帰呼び出しされた unbind() メソッドによって、更に remove() メソッドも再帰呼び出しされ、その中で mouseover名の jQuery.event.special.mouseenter.handler を関数とするイベントがアンバインド( removeEventistner() メソッド起動 )されます。
      その後再帰先から呼出し元の 2146 行に戻った後には 2147行で true を return させることにより、呼出し元で再び removeEventistner() メソッドを実行させることはありません。
  • jQuery.event.special.mouseenter.handler()

    ※ この関数は IE からは呼び出されません。

    1. 内包されている要素にマウスが移動した時に、mouseout したとブラウザに判断させないために、withinElement 関数を起動させて、要素の「先祖/子孫」関係をチェックさせます。内包されている要素内にマウスがある場合には新たにイベントを発生させません。
    2. event.typeプロパティ値を mouseenter に戻した上で、mouseenter 名で登録されているイベントハンドラー関数がイベントハンドラー関数となるようにセットします。

上の説明ではもちろんのこと、special["type"].setup()メソッドは大変分かりにくいので、IE 以外のブラウザで mouseenter イベントをバインドする時の、スクリプトの進行過程を辿るフローチャート的資料を作ってみましたので、以下に掲載します。

$(elem).bind('mouseenter',fn)  process Analyze

左図をクリックすると原寸画像が別窓で開きます。mouseenter イベントタイプ名から、どのようにして mouseover イベントの登録に至るのか、その経過を分かりやすく説明したつもりです。

▲ToTop

type == mouseleave の時
2159:  mouseleave: {
2160:   setup: function() {
2161:    if ( jQuery.browser.msie ) return false;
2162:    jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
2163:    return true;
2164:   },
2165:
2166:   teardown: function() {
2167:    if ( jQuery.browser.msie ) return false;
2168:    jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
2169:    return true;
2170:   },
2171:
2172:   handler: function(event) {
2173:    // If we actually just moused on to a sub-element, ignore it
2174:    if ( withinElement(event, this) ) return true;
2175:    // Execute the right handlers by setting the event type to mouseleave
2176:    arguments[0].type = "mouseleave";
2177:    return jQuery.event.handle.apply(this, arguments);
2178:   }
2179:  }
2180: }

mouseleave が mouseout に、jQuery.event.special.mouseenter.handler が jQuery.event.special.mouseleave.handler に変わる以外は、上の mouseenter の場合と全く同様ですので記述を省略します。

jQuery.event.special ["type"] の難解さについて

上に見たように、special オブジェクトはまさに「 特別に 」難解です。

特に type 名が mouseenter/leaveの場合の setup/teardown メソッドは、bind メソッドと add メソッドの再帰呼び出しを含み、しかも途中でイベント名を変更しつつ、ブラウザ毎に不必要なイベントは登録しないという「 裏技的 」技法を用いて mouseover/out イベントにも同時対応させており、難解を極めます。

このエントリイ作成に当たり、沢山の時間を要してコード進行を図示したり、何度も FireBug で追跡したり、色々チャレンジしてやっと「 理解できた 」のですが、この一連の Event 関連コード解読作業において、この箇所が最も苦労させられました。

上の記述でこれらの挙動を的確に表現できた自信はありませんし、読むだけで分かる表現になっているとも思えません。(書いておきながら、失礼なことですが...)

本来、もっと分かりやすい説明・解読文章を書ければ、と悔やまれます。

'eType'は 'mouseenter' 又は 'mouseleave' を表すものとします。 'fType'は 'mouseover' 又は 'mouseout' を表すものとします。 gn は $.event.special['eType'].handler メソッドを表します。  $(elem).bind('eType',fn)   → add( elem, 'eType', fn )     → $.event.special['eType'].setup.call(elem)       → $(elem).bind( 'fType', gn)         → add( elem, 'fType', gn ) jQuery.event.handle には special オブジェクトが呼び出されるより前の段階で、fn が登録されている。 そして gn では、add() メソッドによって既に登録されたこの fn を呼び出している。 例えば、既に jsファイルの読み込みが終わり、&(fn(){})が実行されてイベントのバインドを行う場合の、mouseenterイベントのバインド過程を綴ってみます。 >>> console.log(jQuery.cache[2]["events"]["mouseenter"][3].toString()) function () { $(this).css("background-color", "white"); } >>> console.log(jQuery.cache[2]["events"]["mouseover"][4].toString()) function (event) { if (withinElement(event, this)) { return true; } arguments[0].type = "mouseenter"; return jQuery.event.handle.apply(this, arguments); }

 

● コメント ●

コメントありがとうございました。 (hkom)

 ご指摘感謝します。
> innerHTML、ime-modeやcontentEditableなど、今までもFirefoxはIEを除外することなく、有用と判断される機能は追加されています。
 Firefoxでも mouseenter/leave がサポートされれば、ちらつき対応コードを書く必要がなくなるわけですね。 mouseenter/leave に関する知見が極めて不十分だったことを初めて認識しました。
 ありがとうございました。

● コメント ●

mouseenter/leaveについて (あきら)

mouseenter/leaveは優れたイベントであり、主にFirefoxで開発を行っているものとしては、早くFirefoxでもサポートして欲しい機能です。
mouseover/outイベントは、子要素に移動した場合にもイベントが発生してしまうため、表示がちらついたり動作が安定しない原因となります。
結局、mouseenter/leave同等の処理をコーディングする事になってしまいます。
この点、mouseenter/leaveは子要素に関係ないイベントなので、直観的であり、問題が起きにくいのです。
innerHTML、ime-modeやcontentEditableなど、今までもFirefoxはIEを除外することなく、有用と判断される機能は追加されています。

■ コメントの投稿 ■

管理者にだけ表示を許可する

●トラックバック●

■トラックバックURLはこちら■
http://hkom.blog1.fc2.com/tb.php/618-82edb182

久々にjQueryを触る

1.1が出たころから触ってなかったので1.2.2を仕事で使ってみたらハマった。 ...

●参照元一覧●

<provided Fc2>
<provided i2i>

▲ToTop

 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が開きます。

----------
200801230043
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。