| |
HTML4.0 では殆ど全てのタグにイベントが指定できます。
そのため、W3C DOM Level 2 ではイベントは大雑把に言って EventTarget と
Event と呼ばれる独立したオブジェクトで管理されます。
この EventTarget は全ての Node 及び Node のサブクラスのオブジェクトに
実装されていることになっています。
#> 回りくどい表現ですが、これはチョット胡散臭い気がするので...
#> 特に TextNode あたりなんか... ( 調査中ですけどね ^^; )
#> M18(と NN6正版)からは WindowEventOwner なんてのもあります。 f(^^;
イベントハンドリングを行う方法としては、 W3C HTML4.0 で規定されているタグ内で記述する方法 と W3C DOM Level 2 で規定されているスクリプトで指定する方法 の 2種類が存在するワケです。
タグ内で記述する方法について
タグ内で記述する方法は、従来のように onmouseover, onclick など をタグに記述すればよく、IE4,5 のように殆どのタグで記述できることを除いては 従来と殆ど同じ指定方法と言えます。
考えようによっては、これは便利で比較的安全な方法と言えます。
例えば、hover のようにマウスが文字の上に来たら文字の色を変更すると言ったことが
したい場合
<SPAN onmouseover="this.style.color='red'" onmouseout="this.style.color='black'">Hover</SPAN>
#> この例は CSS2 に疑似要素として :hover があるので全く意味がないですけど
のように、NN でイベント指定できないタグに記述する限り、 無視されるので、クロスな環境でも問題が発生しにくい特徴があります。
#> このスクリプトは IE4,5 及び Mozilla では動作して、 NN4 では動作しませんがエラーも出ません。
また、逆に言えばクロスな環境で、どのブラウザでも同様に何らかの効果を演出したい場合には、 従来通り INPUT や A タグなどどこでも通用するタグで指定しなければなりません。
#> まあ、これは Mozilla に限った話じゃないですけどね。 f(^^;
スクリプトで指定する方法について
クロスなイベントハンドリング方法の紹介の前に、 先ず、Mozilla における実装について少し説明しておく必要があるでしょう。
#> 実はこのあたりは Undocumented な部分が結構あるような気がします。
W3C DOM Level2 - Document Object Model Events ではイベントの登録は
addEventListener メソッドで行うことになっています。
つまり、以下のように記述するわけです。
var div=document.getElementById('div1'); div.addEventListener('mousedown',mousedown,true);
これを見て、「ああなるほど」と思った人は多いと思いますが、
「ちょっと待てよ」と思った人もいると思います。
ここで、 div は getElementById で取得した HTMLDivElement オブジェクトで、
addEventListener は EventTarget オブジェクトのメソッドです。
また、 HTMLDivElement オブジェクトを for(prop in div) でプロパティを取り出しても
EventTarget の要素は出ませんし、 IDL を覗いても該当するメソッドやオブジェクトは
見あたりません。
つまり、Node と EventTarget は仲良し( friendly )な関係だけど、他人の関係にあるようです。
では、タグで記述した場合の onmouseover などのイベントはどうでしょう。
これも、該当するオブジェクトを for(prop in div) などで見ても、 IDL にも該当する
属性はありません。
div.setAttribute('onmouseover',mousedown);なんて記述をしてもなんの効果も得られません。
#> この意味不明なオブジェクトに管理されるイベントは、
M18 からは WindowEventOwner と呼ばれるオブジェクトとして明示的な存在になったようです。
( だからといって、何かがわかったワケではないですけど... ^^; )
そこで、次にレイアをドラッグ操作で移動するスクリプトを例に 手法を研究してみましょう。
レイアのドラッグ操作 - DOM2 な方法
W3C DOM Level 2 で規定されている addEventListener や removeEventListener を 使用すると、レイア( id="t1" - DIV タグ )をドラッグ操作で移動するスクリプトは 次のようになります。
function drag(){ // ドラッグ操作の登録 var div=document.getElementById('t1'); div.addEventListener('mousedown',mdownMz,true); div.addEventListener('mouseup', mupMz, true); } function mdownMz(e){ // mouse down 処理 // 現在のマウス位置を記憶 e.target.eX=window.scrollX+e.clientX; e.target.eY=window.scrollY+e.clientY; // mousemove イベントハンドラを登録 e.target.addEventListener('mousemove',mmoveMz,true); e.cancelBubble=true; } function mmoveMz(e){ // mouse move 処理 var ex=window.scrollX+e.clientX; var ey=window.scrollY+e.clientY; // レイアを移動 e.target.style.left=parseInt(e.target.style.left)+ex-e.target.eX; e.target.style.top =parseInt(e.target.style.top )+ey-e.target.eY; e.target.eX=ex; e.target.eY=ey; e.cancelBubble=true; } function mupMz(e){ // mouse up 処理 // mousemove イベントハンドラを削除 e.target.removeEventListener('mousemove',mmoveMz0,true); e.cancelBubble=true; }
然し、現在の Mozilla(M13,M14) では
1. addEventListener の caputure 指定が有効にならない(?)
2. removeEventListener が何故か機能しない
ので、次のようにします。
grabObj=null; // ドラッグ操作中オブジェクトのメモ function drag(){ // ドラッグ操作の登録 var div=document.getElementById('t1'); div.addEventListener('mousedown',mdownMz,true); } function mdownMz(e){ // mouse down 処理 grabObj=e.target; grabObj.eX=window.scrollX+e.clientX; grabObj.eY=window.scrollY+e.clientY; document.addEventListener('mousemove',mmoveMz,true); document.addEventListener('mouseup', mupMz, true); e.cancelBubble=true; } function mmoveMz(e){ // mouse move 処理 if(grabObj==null) return; var ex=window.scrollX+e.clientX; var ey=window.scrollY+e.clientY; grabObj.style.left=parseInt(grabObj.style.left)+ex-grabObj.eX; grabObj.style.top =parseInt(grabObj.style.top )+ey-grabObj.eY; grabObj.eX=ex; grabObj.eY=ey; e.cancelBubble=true; } function mupMz(e){ // mouse up 処理 if(grabObj==null) return; document.removeEventListener('mousemove',mmoveMz,false); document.removeEventListener('mouseup', mupMz, false); e.cancelBubble=true; grabObj=null; }
レイアのドラッグ操作 - Mozilla な方法
Mozilla には addEventListener でイベントハンドラを登録する方法以外に
従来のように( 互換のためか? )、 onmousedown プロパティ等にハンドラを登録する
方法も機能するようです。
#> これは調べた限り、記述されていませんでしたが... f(^^;;
grabObj=null; // ドラッグ操作中オブジェクトのメモ function drag(){ // ドラッグ操作の登録 var div=document.getElementById('t1'); div.onmousedown=mdownMz; } function mdownMz(e){ // mouse down 処理 grabObj=e.target; grabObj.eX=window.scrollX+e.clientX; grabObj.eY=window.scrollY+e.clientY; document.onmousemove=mmoveMz; document.onmouseup =mupMz; e.cancelBubble=true; } function mmoveMz(e){ // mouse move 処理 if(grabObj==null) return; var ex=window.scrollX+e.clientX; var ey=window.scrollY+e.clientY; grabObj.style.left=parseInt(grabObj.style.left)+ex-grabObj.eX; grabObj.style.top =parseInt(grabObj.style.top )+ey-grabObj.eY; grabObj.eX=ex; grabObj.eY=ey; e.cancelBubble=true; } function mupMz(e){ // mouse up 処理 if(grabObj==null) return; document.onmousemove=null; document.onmouseup =null; e.cancelBubble=true; grabObj=null; }
まあ、 DOM2 な方法と比べてそれほど変わるわけではありませんが、 removeEventListener でハンドラが削除できないよりはマシってとこですか(笑)。
レイアのドラッグ操作 - クロスでちょっと汎用
こんどは、ドラッグ操作を行うためのクロスな関数を作ってみましょう。
関数の I/F はとりあえず
setDrag(div,dStart,dStartData,dIng,dIngData,dEnd,dEndData); div : レイア dStart : ドラッグ開始時の通知関数 dStartData : dStart で指定した関数に付けるデータ dIng : ドラッグ中の通知関数 dIngData : dIng で指定した関数に付けるデータ dEnd : ドラッグ終了時の通知関数 dEndData : dEnd で指定した関数に付けるデータ dStart,dIng,dEnd 各ハンドラの呼出形式は handler(div,x,y,data); div : レイア x,y : マウスの位置 data : setDrag で指定したデータ
にでもすると以下のようになります。
_dom=(document.all?3:(document.getElementById?1:(document.layers?2:0))); _ie5=(navigator.appVersion.indexOf('MSIE 5')>=0); grabObj=null; // ドラッグ操作中オブジェクトのメモ // 登録関数 function setDrag(div,dStart,dStartData,dIng,dIngData,dEnd,dEndData){ var targetObj=null; if(_dom==1){ // Mozilla div.onmousedown=mdownMz; targetObj=div; } else if(_dom==2){ // NN4 div.document.onmousedown=mdownNN; div.document.captureEvents(Event.MOUSEDOWN); targetObj=div.document; } else if(_dom==3){ // IE4,IE5 div.onmousedown=mdownIE; targetObj=div; } if(targetObj) targetObj.objctrl=new ObjCtrl(div, dStart,dStartData,dIng,dIngData,dEnd,dEndData); } // イベント制御用オブジェクト function ObjCtrl(div,dStart,dStartData,dIng,dIngData,dEnd,dEndData){ this.div =div; this.dragStart=dStart; this.dragStartData=dStartData; this.dragging =dIng; this.draggingData =dIngData; this.dragEnd =dEnd; this.dragEndData =dEndData; } // ============= Mozilla用イベントハンドラ ============ function mdownMz(e){ // mousedownハンドラ if(e.target.objctrl==null) return; grabObj=e.target.objctrl; var div = grabObj.div; if(grabObj.dragging) document.onmousemove=mmoveMz; document.onmouseup=mupMz; if(grabObj.dragStart) grabObj.dragStart(div, window.scrollX+e.clientX,window.scrollY+e.clientY, grabObj.dragStartData); e.cancelBubble=true; } function mmoveMz(e){ // mousemoveハンドラ if(grabObj==null) return; if(grabObj.dragging) grabObj.dragging(grabObj.div, window.scrollX+e.clientX,window.scrollY+e.clientY, grabObj.draggingData); e.cancelBubble=true; } function mupMz(e){ // mouseupハンドラ if(grabObj==null) return; var div=grabObj.div; if(grabObj.dragEnd) grabObj.dragEnd(div, window.scrollX+e.clientX,window.scrollY+e.clientY, grabObj.dragEndData); if(grabObj.dragging) document.onmousemove=null; document.onmouseup=null; grabObj=null; e.cancelBubble=true; } // ============= NN用イベントハンドラ ============ function mdownNN(e){ // mousedownハンドラ if(e.target.objctrl==null) return; grabObj=e.target.objctrl; var div = grabObj.div; if(grabObj.dragging){ div.document.onmousemove=mmoveNN; div.document.captureEvents(Event.MOUSEMOVE); } div.document.onmouseup=mupNN; div.document.captureEvents(Event.MOUSEUP); if(grabObj.dragStart) grabObj.dragStart(div,e.pageX,e.pageY,grabObj.dragStartData); return false; } function mmoveNN(e){ // mousemoveハンドラ if(grabObj==null) return; if(grabObj.dragging) grabObj.dragging(grabObj.div,e.pageX,e.pageY,grabObj.draggingData); return false; } function mupNN(e){ // mouseupハンドラ if(grabObj==null) return; var div=grabObj.div; if(grabObj.dragEnd) grabObj.dragEnd(div,e.pageX,e.pageY,grabObj.dragEndData); if(grabObj.dragging){ div.document.onmousemove=null; } div.document.onmouseup=null; grabObj=null; return false; } // ============= IE用イベントハンドラ ============ function mdownIE(){ // mousedownハンドラ if(window.event.srcElement.objctrl==null) return; grabObj=window.event.srcElement.objctrl; var div = grabObj.div; if(grabObj.dragging) document.onmousemove=mmoveIE; document.onmouseup=mupIE; if(grabObj.dragStart) grabObj.dragStart(div, (_ie5?document.body.scrollLeft:0)+window.event.clientX, (_ie5?document.body.scrollTop :0)+window.event.clientY, grabObj.dragStartData); window.event.returnValue=false; } function mmoveIE(){ // mousemoveハンドラ if(grabObj==null) return; if(grabObj.dragging) grabObj.dragging(grabObj.div, (_ie5?document.body.scrollLeft:0)+window.event.clientX, (_ie5?document.body.scrollTop :0)+window.event.clientY, grabObj.draggingData); window.event.returnValue=false; } function mupIE(){ // mouseupハンドラ if(grabObj==null) return; var div=grabObj.div; if(grabObj.dragEnd) grabObj.dragEnd(div, (_ie5?document.body.scrollLeft:0)+window.event.clientX, (_ie5?document.body.scrollTop :0)+window.event.clientY, grabObj.dragEndData); if(grabObj.dragging) document.onmousemove=null; document.onmouseup=null; window.event.returnValue=false; window.event.cancelBubble=true; grabObj=null; }
戻る | Copyright(c) 2000 ShinSoft. All rights reserved. |