Firefoxでの擬似window.event

category-icon

Follow-Up 2006-7-6

 Firefoxでもwindow.eventを有効にするやり方のエントリーはこちらLink  

 Gecko系のブラウザでは、これはNetscape4.x時代からずっとそうなんだけど、イベントは、イベントハンドラーにargumentとして渡されるので、この手の記述には必ず引数(ひきすう)を書く必要がある。一方、IEでは(Operaもか?)、イベントモデルには、最後に生じたイベントをキャプチャーするwindow.eventという属性があり、これはどこからでも自由にアクセスすることが出来る。以上のことをまとめると、イベントに関してクロスブラウザーな記述をしようと思えば、例えば以下のような感じになる。

function getEventType(e){
 var e = e || window.event;
 alert("Event Type is:" + e.type);
}

 で、ここで引数に使用している"e" であるが、これはGecko系のためだけに必須である。window.event であれば、この引数は不要だ。で、自分は常々、この"e"を追放できないかなと思っていた。何しろ、イベントを絡ませるような関数に必ずついて回るからだ。スクリプトの記述はシンプルなのが良いのに、この"e" のために余計に引数が増えてしまう。

 ppBlogでは数箇所に、この"e" が出てくるので、こいつを追放してやろうと決心した。そして色々弄った結果、これならOKかなというのを見つけたのでメモしておく。もちろん、ppBlogにも反映される。

 まず、最初にやったことは、ppBlogのjs/lib.jsに記述してある、ページ内でのマウスイベントX座標をゲットする以下の関数において、Firefoxでイベントがどんな風に呼び出されるのかだ。

function getEventPageX(e){
 var e = e ||window.event;
 if(e.pageX){
  return e.pageX;
 } else if(e.clientX){
  if(d.documentElement && typeof d.documentElement.scrollLeft != "undefined"){
   return d.documentElement.scrollLeft + e.clientX;
  } else if(d.body && typeof d.body.scrollLeft != "undefined"){
   return d.body.scrollLeft + e.clientX;
  }
 }
 return 0;
}

 実行している関数自身は、arguments.calleeで参照出来る。そして、この関数が何によって呼び出されているかは、callerプロパティーを参照すればいい。これらを使って、上の関数に、

 alert(arguments.callee.caller);

を付け足してみると、Firefoxでは、

function onclick(event){
  getEventPageX(event);
}

というのが返ってくる。→デモ1。Link ほほう。ちなみにIEでは

function anonymous()
{
  getEventPageX(event);
}

という匿名関数が返ってくる。Firefoxでは、引数のeventonclick関数によってキャプチャーされていることが分かる。じゃ、このonclick関数のeventって何だろう。これは次のようにして調べることが出来る。

 alert(arguments.callee.caller.arguments[0]);

すると次の答えが返ってくる。→デモ2Link

[object MouseEvent]

ほうほう。イベントは、マウスイベントオブジェクトとしてonclick関数に組み込まれているらしい。ならば、これを呼び出して、"e" に渡してやれば、"e" の束縛から逃れられるのではと推察する。なので次のようにして、"e" なしのやつを走らせてみる。→デモ3Link

function getEventPageX(){
 var e = arguments.callee.caller.arguments[0] || window.event;
 if(e.pageX){
  return e.pageX;
 } else if(e.clientX){
  if(d.documentElement && typeof d.documentElement.scrollLeft != "undefined"){
   return d.documentElement.scrollLeft + e.clientX;
  } else if(d.body && typeof d.body.scrollLeft != "undefined"){
   return d.body.scrollLeft + e.clientX;
  }
 }
 return 0;
}

 おおぉー、上手く行った:) 3つ目のデモでは、もはや引数のeは必要なく、getEventPageX()だけで座標を取得していることに着目。

 こりゃいいやと、js/lib.jsjs/editor.jsに出てくる引数"e"をとりあえず、全部なしにしてブロッグを見てみると、意図したように動かない。何でかなと、デバッグダイアログを見てみると、これまでのデモでは、マウスクリックによって直接getEventPageX()を呼び出していたのに対して、実際のスクリプトでは、getEventPageX()などは、別の関数の中で呼び出されている。なので、

arguments.callee.caller.arguments[0]

だと、getEventPageX()を含んだ関数の第一引数を返してしまうのである。初歩的ミス。。それならば、

arguments.callee.caller

を次々に呼び出していけば、そのうち、マウスイベントオブジェクトに到達するはずである。イメージ的には、sourceに向かって遡っていくイベントバブリングですね。これは次のような記述でいい。

var caller = arguments.callee.caller;
while(caller){
 var ob = caller.arguments[0];
 if(ob == '[object MouseEvent]') return ob;
 caller = caller.caller; // 次の呼び出し元にセット
}

ただ、ob == "[object MouseEvent]" というのは何となく「カッコ悪い」。この部分はコンストラクタを用いて次のようにも書ける。

ob.constructor == MouseEvent

 以上をまとめて、IEでも使えるようなクロスな記述にすると以下のような感じ。

function windowEvent(){
 if(window.event) return window.event;
 var caller = arguments.callee.caller;
 while(caller){
  var ob = caller.arguments[0];
  if(ob && ob.constructor == MouseEvent) return ob;
  caller = caller.caller;
 }
 return null;
}

 windowEvent()がそのままIEのwindow.eventに相当する。これを用いればイベント関連の記述に必須であったeからめでたく解放される訳である。最初に出てきたgetEventPageX()関数は、最終的には次のように記述できる。

function getEventPageX(){
 var e = windowEvent();
 if(e.pageX){
  return e.pageX;
 } else if(e.clientX){
  if(d.documentElement && typeof d.documentElement.scrollLeft != "undefined"){
   return d.documentElement.scrollLeft + e.clientX;
  } else if(d.body && typeof d.body.scrollLeft != "undefined"){
   return d.body.scrollLeft + e.clientX;
  }
 }
 return 0;
}

 もはやイベントのキャプチャーのためだけに引数は必要ない。最終的なデモをあげておきます。 →http://p2b.jp/demos/windowEvent.htmlLink  なお、イベント座標取得関数とは別に、イベントが起こった要素の座標を返す、getElementPosition()という関数も新たに定義しています。これは、JavaScriptマスターであるppk氏Link のサイトにある"Find PositionLink " という記事に紹介されている関数をmodifyしたやつです。こんなやつ。

function getElementPosition(){
 var _x = _y = 0;
 var ob = windowEvent().target || windowEvent().srcElement;
 if(ob.offsetParent){
  while (ob.offsetParent){
   _x += ob.offsetLeft; _y += ob.offsetTop;
   ob = ob.offsetParent;
  }
 }
 return [_x, _y];
}

 とりあえず

— posted by martin at 06:10 pm   commentComment [14]  pingTrackBack [0]

この記事に対するコメント・トラックバック [14件]

scrollUp1. angler — 2009/05/22@13:24:25

大変為になります。

2. レプリカ腕時計販売 Website — 2017/03/07@12:19:25

唯一の正しいURL:JpSuperGreat7.CoM_スーパーコピー時計,レプリカ腕時計販売[日本人気店]JpSuperGreat7「15% OFFセール開催中!」。スーパーコピー時計直営店.会員登録頂くだけで2000ポイント 取得できます!
唯一の正しいURL:www.jpsupergreat7.com/
レプリカ時計 http://www.jpsupergreat7.com/Link

3. ロレックススーパーコピー腕時計 Website — 2017/03/08@14:55:49

ロレックススーパーコピー腕時計_レプリカロレックス(N級) JPwatch365.CoM 責任者:山田!当店は【1~8万円】スーパーコピー全商品一覧ロレックスのみを取り扱っていますので、品質も2年間保証しています!
ロレックスコピー http://www.jpwatch365.com/iowares/watches-io1/Link
ロレックス エクスプローラー http://www.jpwatch365.com/iowares/watches-small-io3/Link

4. スーパーコピー Website — 2017/03/09@14:18:53

唯一の正しいURL:www.JPwatch365.CoM!!スーパーコピー時計,人気ロレックスコピー時計大特価通販JPwatch365.CoM!!!ロレックススーパーコピー時計,Hublotコピーなどのスーパーコピー品を扱っております。世界のブランド腕時計スーパーコピーが大特価!
スーパーコピー http://www.jpwatch365.com/Link
ロレックススーパーコピー http://www.jpwatch365.com/iowares/watches-io1/Link

5. スーパーコピーパネライ Website — 2017/03/10@14:32:55

パネライスーパーコピー腕時計_レプリカパネライ(N級) JPwatch365.CoM
スーパーコピーパネライ http://www.jpwatch365.com/iowares/watches-io2/Link

scrollUp6. スーパーコピー全商品一覧ウブロ Website — 2017/03/11@18:17:47

ウブロスーパーコピー腕時計_レプリカウブロ(N級),責任者:山田!当店は【1~8万円】スーパーコピー全商品一覧ウブロのみを取り扱っていますので、品質も2年間保証しています!
スーパーコピーウブロ http://www.jpwatch365.com/iowares/watches-io4/Link

7. ロレックススーパーコピー Website — 2017/03/13@14:36:06

スーパーコピーロレックス代引き専売店NO.1!
ロレックススーパーコピー http://www.keepgoing365.com/tokei/b1/Link
ロレックス サブマリーナ http://www.keepgoing365.com/tokei/s5/Link

8. スーパーコピー偽物時計 Website — 2017/03/14@17:54:28

スーパーコピー時計,スーパーコピー代引き専売店NO.1!
偽物時計 http://www.keepgoing365.com/Link

9. パネライコピー品の販売専門 Website — 2017/03/16@11:35:08

スーパーコピーパネライ代引き専売店NO.1!世界大人気 激安パネライスーパーコピーの新作品を探していますか。パネライコピー品の販売専門ショップです.
パネライコピー http://www.keepgoing365.com/tokei/b2/Link
時計コピー http://www.keepgoing365.com/Link

10. スーパーコピーガガミラノ Website — 2017/03/16@15:51:44

スーパーコピーガガミラノ代引き専売店NO.1!.
スーパーコピーガガミラノ http://www.keepgoing365.com/tokei/b11/Link

scrollUp11. スーパーコピーロレックス Website — 2017/03/17@17:11:23

ロレックススーパーコピー腕時計_レプリカロレックス(N級) JPwatch365.CoM 責任者:山田!当店は【1~8万円】スーパーコピー全商品一覧ロレックスのみを取り扱っていますので、品質も2年間保証しています!
スーパーコピーロレックス http://www.jpwatch365.com/iowares/watches-io1/Link

12. レプリカ腕時計販売 Website — 2017/03/20@18:39:37

スーパーコピー時計,レプリカ腕時計販売[日本人気店]JpSuperGreat7
スーパーコピー http://www.jpsupergreat7.com/Link
ロレックスコピー販売 http://www.jpsupergreat7.com/pewares/watches-pe1/Link

13. 人気スーパーコピーブランド時計 Website — 2017/03/22@11:48:18

スーパーコピー時計通販、人気スーパーコピーブランド時計一覧! 世界大人気激安時計スーパーコピーの新作品を探していますか。ブランド時計コピー品の販売専門ショップです
レプリカ時計 http://www.always777.com/Link

14. 代引き専売店 Website — 2017/03/24@12:41:31

スーパーコピー時計,スーパーコピー代引き専売店NO.1! 世界大人気 激安時計スーパーコピーの新作品を探していますか。ブランド時計コピーの販売専門ショップです スーパーコピー時計
http://www.keepgoing365.com/Link

この記事に対する TrackBack URL:

設定によりTB元のページに、こちらの記事への言及(この記事へのリンク)がなければ、TB受付不可となりますのであらかじめご了承下さい。

コメントをどうぞ。 名前(ペンネーム)と画像認証のひらがな4文字は必須で、ウェブサイトURLはオプションです。

ウェブサイト (U):

タグは使えません。http://・・・ は自動的にリンク表示となります

:) :D 8-) ;-) :P :E :o :( (TT) ):T (--) (++!) ?;w) (-o-) (**!) ;v) f(--; :B l_P~

     
T: Y: ALL: Online:
Created in 0.0314 sec.
prev
2017.7
next
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31