Ajaxで今よみがえる(^^;;-->[クロスブラウザ技術 ]DHTMLサンプル集
-- リスト --
【カテゴリー】 ActionScript ( 6 ) AIR ( 4 ) AjaSQL ( 10 ) Ajax ( 675 ) Arax ( 1 ) canvas ( 15 ) CSS ( 24 ) ( 9 ) DLNA ( 1 ) Dojo ( 25 ) DOM ( 51 ) ES4 ( 4 ) Ext JS ( 5 ) 反重力物質 ( 1 ) ffAdd-on ( 1 ) Flash ( 48 ) Flash Remoting ( 11 ) FTP ( 2 ) GAF ( 9 ) Google Maps ( 124 ) Google ガジェット ( 1 ) GPS ( 44 ) HTML ( 11 ) HTTPヘッダサンプル ( 10 ) IME ( 2 ) Internet ( 2 ) iPhone ( 49 ) IPv6 ( 1 ) 漫画 ( 4 ) Java ( 49 ) JavaScript ( 344 ) jKamo ( 8 ) jQchart ( 4 ) jQuery ( 207 ) jquery-ref ( 1 ) jsGadget ( 19 ) jslb_ ( 3 ) jslb_ajax ( 9 ) JSON ( 49 ) JSR223 ( 7 ) kjscmd ( 1 ) KNOPPIX ( 1 ) Linux ( 18 ) Mac ( 9 ) Memo ( 3 ) Microformats ( 2 ) Mini AJAX ( 2 ) MochiKit ( 2 ) mootools ( 10 ) Movable Type ( 58 ) MySQL ( 10 ) NewGameWeb ( 2 ) Nucleus ( 8 ) OpenAJAX ( 3 ) OpenDocument ( 1 ) OS ( 10 ) P2P ( 2 ) Perl ( 8 ) PHP ( 38 ) PostGIS ( 1 ) PostgreSQL ( 4 ) prototype.js ( 28 ) ROBOT ( 1 ) RSSリーダー ( 15 ) Ruby on Rails ( 7 ) SPDY ( 1 ) Spry ( 6 ) SQLite ( 17 ) SQLiteWorker ( 2 ) ssh ( 1 ) SSI ( 2 ) SVG ( 23 ) TRON ( 1 ) Ubiquity ( 7 ) Video ( 1 ) VML ( 1 ) Web Slice ( 1 ) Web Sockets ( 24 ) Webサービス ( 107 ) widget ( 6 ) Wii ( 1 ) Wiki ( 1 ) Win ( 6 ) WSH ( 1 ) X01HT ( 30 ) XML ( 32 ) XOOPS ( 1 ) XQuery ( 2 ) XUL ( 4 ) Yahoo! UI ( 74 ) 日付入力用カレンダー ( 1 ) 『Ajax実践テクニック』 ( 1 ) 『入門 Ajax』 ( 42 ) WinTips ( 2 ) こりゃすごい ( 7 ) チューニング ( 30 ) ダイナミックロード関数 ( 7 ) リファレンス ( 20 ) ライブラリ ( 210 ) レーダー雨量表示 ( 1 ) ハード ( 35 ) ペンギン ( 2 ) ブラウザ ( 108 ) ブログでBBS ( 1 ) アクセスグラフ ( 3 ) イベント ( 2 ) カレンダーによる日付入力スクリプト ( 4 ) クロスブラウザ ( 14 ) クロスブラウザ関数 ( 8 ) スポーツ ( 1 ) スマートフォン ( 8 ) セキュリティ ( 155 ) ソフトイーサ ( 1 ) マッシュアップ ( 23 ) 暗号 ( 4 ) 映画 ( 57 ) 河川の水位グラフ ( 3 ) 回線 ( 2 ) 開発ツール ( 38 ) 牛久大仏 ( 19 ) 携帯 ( 150 ) 言語 ( 19 ) 故障 ( 9 ) 高橋家の謎 ( 3 ) 広告とか ( 1 ) 洪水警報システム ( 2 ) 今日のひと言 ( 10 ) 仕様 ( 113 ) 雑談 ( 356 ) 実装 ( 2 ) 書籍 ( 20 ) 親子ウインドウ有無の確認関数 ( 3 ) 新海誠 ( 3 )
Web Sockets Domo

* サーバー側は、小松氏のこれをbloga.jp:80へ置いてあります。
* クライアント側はWS処理をjQueryプラグイン化してみました。これです。
* ちなみに、このDemoサンプルは、下記5行でローカルでも別ドメインでもどこにでも設置出来ます。
<script src="http://bloga.jp/ws/jq/js/jquery-1.3.2.min.js" type="text/javascript"></script> <script src="http://bloga.jp/ws/jq/js/jquery.ws-0.3-noenc-pre.js" type="text/javascript" charset="utf-8"></script> <script src="http://bloga.jp/ws/jq/conn/wschatdemo0.3.js" type="text/javascript"></script> <script>/*サポートしてない時のalertメッセージを抑止*/$.ws.wsSetup({nonosupportmsg:true});</script> <div id="wsdemos"></div>

【info】いつもいろいろなテストなどをページ内のあちこちでやっているので、重かったり、壊れていたりするf^^;ことも多いです。実験用ですので、カオス(混沌)をあえて意図したりもしますので、標準やValidとは無縁だったりしますが、何卒、ご了承ください ( _ _ b

【info】 最近はTwitterでぶつぶつ言ってることが多いです。
>http://twitter.com/toshirot

【info】 Chrome Extension [WebSocket Chat] もちろんChrome専用です
https://chrome.google.com/extensions/detail/fnoegeafibddabfhmpmhniphlcojkjli

2007年11月01日

【jQuery】イベントfixについて

jQuery , リファレンス ブックマークに追加する ブックマーク-- Hatena  / Livedoor track feed


JavaScriptのイベントはいまだにブラウザ間の非互換を大量に抱えた暗黒大陸です。addEventlistenerとattachEventが並立したままであるのは言わずもがな、eventで取得するwhichやbuttonなどのプロパティ群もNetscape4.xとIE4.xのブラウザ戦争時代の遺物をFirefoxとIEは引きずっています。

そこで、jQueryはどうしているのかと、試しに、handleメソッドを覗くと下記のようなfixメソッドでeventを作成しているのが見えます。引数のevent または、それが無ければwindow.event 、それもなければ空のオブジェクトを渡してプライベートなeventを作成しています。

つまり、handleメソッド内では、クロスブラウザなeventが使われることになります。
  handle: function(event) {
  // returned undefined or false
  var val;

  // Empty object is for triggered events with no data
  event = jQuery.event.fix( event || window.event || {} ); 
では、このfixメソッドは何をしているのでしょう?ざっくりいうとクローンeventを作成してeventのブラウザ間の非互換を吸収するいくつかのプロパティを作り返しています。
  fix: function(event) {
    // store a copy of the original event object 
    // and clone to set read-only properties
    var originalEvent = event;
    event = jQuery.extend({}, originalEvent);
    
    // add preventDefault and stopPropagation since 
    // they will not work on the clone

    //高橋注:イベントキャンセルをevent.preventDefault()に統一
    event.preventDefault = function() {
      // if preventDefault exists run it on the original event
      if (originalEvent.preventDefault)
        originalEvent.preventDefault();
      // otherwise set the returnValue property of the original event to false (IE)
      originalEvent.returnValue= false;
    };

    //高橋注:イベントバブルキャンセルをevent.stopPropagation()に統一
    event.stopPropagation = function() {
      // if stopPropagation exists run it on the original event
      if (originalEvent.stopPropagation)
        originalEvent.stopPropagation();
      // otherwise set the cancelBubble property of the original event to true (IE)
      originalEvent.cancelBubble = true;
    };

    //高橋注:イベント対象要素取得をevent.target に統一
    // Fix target property, if necessary
    if ( !event.target && event.srcElement )
      event.target = event.srcElement;       

    //高橋注:イベント対象要素取得でTEXTノード時のsafariフィックス 
    // check if target is a textnode (safari)
    if (jQuery.browser.safari && event.target.nodeType == 3)
      event.target = originalEvent.target.parentNode;

    //高橋注:イベント移動要素取得をrelatedTargetに統一
    // Add relatedTarget, if necessary
    if ( !event.relatedTarget && event.fromElement )
      event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;

    //高橋注:IEのDocType宣言により異なるDocument別にclientXへscrollLeft、
    // clientYへscrollTop を加えてevent.pageXevent.pageYを他のブラウザと統一
    // Calculate pageX/Y if missing and clientX/Y available
    if ( event.pageX == null && event.clientX != null ) {
      var e = document.documentElement, b = document.body;
      event.pageX = event.clientX + (e && e.scrollLeft || b.scrollLeft || 0);
      event.pageY = event.clientY + (e && e.scrollTop || b.scrollTop || 0);    }

    //高橋注:キーコード取得をevent.whichで統一
    // Add which for key events
    if ( !event.which && (event.charCode || event.keyCode) )
      event.which = event.charCode || event.keyCode;
    
    //高橋注:Mac以外のブラウザでもMacのevent.metaKey をevent.ctrlKey で動作させる
    // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
    if ( !event.metaKey && event.ctrlKey )
      event.metaKey = event.ctrlKey;

    //高橋注:マウスボタン押下番号IEのevent.button をevent.which と統一
    // Add which for click: 1 == left; 2 == middle; 3 == right
    // Note: button is not normalized, so don't use it
    if ( !event.which && event.button )
      event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
      
    return event;
  }

p.s. 再調査中 --寝る前にテストだけ

内部でクロスブラウザ化されたevent.whichがどのような場合に露出されるか?

テストソース

<script src="./jquery.js" type="text/javascript"></script>

<div id="div17831">1 インラインなレガシーeventをargument.whichで取得</div>
<div id="div17832">2 インラインなレガシーeventをargument.which経由jQueryで利用
</div>
<div id="div17833">3 jQueryイベント内のargumentsで渡されるevent.which</div>
<div id="div17834">4 jQueryイベント内でグローバルなevent.whichを取得</div>

入力してください<input type="input" id="input1783" onkeyup="k(event)">
<script>
function k(event){ 
    //test1
    document.getElementById('div17831').innerHTML='1:キーコードは、'+event.which +'です。'
    //test2
    $("#div17832").html( "2:キーコードは、"+event.which +"です。");
 }

$("#input1783").keyup(function(e){
    //test3
    $("#div17833").html("3:キーコードは、"+e.which +"です。");
    //test4
    $("#div17834").html("4:キーコードは、"+event.which +"です。");
})
</script>

テスト

1 インラインなレガシーeventをarguments.whichで取得
2 インラインなレガシーeventをarguments.which経由jQueryで利用
3 jQueryイベント内でargumentsで渡されるevent.which
4 jQueryイベント内でグローバルなevent.whichを取得

入力してください

結果





1 インラインなレガシーeventをarguments.whichで取得
2 インラインなレガシーeventをarguments.which経由jQueryで利用
3 jQueryイベント内のargumentsで渡されるevent.which ←これだけが全ブラウザででOK!
4 jQueryイベント内でグローバルなevent.whichを取得

たぶん結論

jQueryイベント内部でクロスブラウザ化された、jQueryの独自イベントは、
3のjQueryイベント内のargumentsで渡されるeventのwhichなど、
jQueryのイベントコールバック関数の引数としてのみ取得できますが、
グローバルなeventには影響しませんので、
他のライブラリなどと組み合わせても衝突などはありません。たぶん。

#(_ _b朝書いたサンプルは間違いでした(_ _b。 event.keyCode が書き代わっているわけではありません。ごめんなさい。


    Milly ( 2007年11月01日 18:26 )

    which に keyCode が格納されている場合があるだけで keyCode が変更されてるわけではないので、例が keyCode なのはよくないのでは。

    高橋 ( 2007年11月01日 19:20 )

    あ、本当だ、内部の話をしながら、途中からなぜか完全に勘違いしてました。Milly さんご指摘ありがとうございました。落ち込むなぁ、、、whichの条件式も頭の中で変になってたし。今日は朝からダメダメです。もう寝ようかな、、、。

    Milly ( 2007年11月01日 19:32 )

    なんだか落ち込ませてしまったみたいですが、いつも参考にさせていただいてます。これからも有用な記事を期待してます。:)

    高橋 ( 2007年11月01日 19:44 )

    ありがとうございます。中身は、少し不安になったので、再調査します。でも、今日はもう寝ます。ばた。

    高橋 ( 2007年11月01日 23:24 )

    寝ずにアバウトなテスト完了。ほぼスコープを推測(笑)できたような緩いような。。。最近、良いことが全然無くて、いまひとつ勢いが出ない状態です。今度こそ寝ます。


    【コメント】(←clickで入力欄open)

  

All About/JavaScript

All About のJavaScript関連記事を書いています。参考にしていただければ幸いです。