2011年12月12日 星期一

JavaScript的滑鼠事件

這篇來介紹一些最基本的事件--滑鼠事件。雖然說很簡單,但只要IE插一腳任何事情都會變的很複雜......

先上範例,再來上Code︰http://eight04.zapto.org/js_3.html

<p id="control1"></p> 
<div style="position: relative;">
    <p id="control2"></p>
</div>
<p id="control3"></p>

這次的HTML很簡單,只有三個P,也就是要做三個測試。第一個是什麼事都不做的練習註冊事件︰

function start(){ 
    var control=document.getElementById("control1");
    registEvent(control,"mouseover",mouseover);
    registEvent(control,"mouseout",mouseout);
    registEvent(control,"mousedown",mousedown);
    registEvent(control,"mouseup",mouseup);
    var control=document.getElementById("control2");
    registEvent(control,"mousemove",mousemove);
    var control=document.getElementById("control3");
    registEvent(control,"mousedown",mousedown3);
    registEvent(control,"mouseup",mouseup3);
}
window.onload=start;
function registEvent(target,event,func){
    if(document.addEventListener)   //FF
        target.addEventListener(event,func,false);
    else{                            //IE
        target.attachEvent("on"+event,func);
    }
}

註冊事件的核心,可以看出對IE與其它主流瀏覽器採用了不同的方式...IE的事件關鍵字前面有加"on",而且註冊用的函數是attachEvent。

function mouseover(e){ 
    if(!e.target)e.target=e.srcElement;
    e.target.className="over";
}
function mouseout(e){
    if(!e.target)e.target=e.srcElement;
    e.target.className="out";
}
function mousedown(e){
    if(!e.target)e.target=e.srcElement;
    e.target.className="down";
}
function mouseup(e){
    if(!e.target)e.target=e.srcElement;
    e.target.className="up";
}

可以看到...綁到Control One的都是些改變className的函式,反正只是區別用。比較特別的是IE(又是IE)沒有event.target,IE把事件目標(P元素)存在srcElement內。

function mousemove(e){ 
    if(!e.target)e.target=e.srcElement;
    e.target.innerHTML=
    "e.x,e.y<br />&nbsp;&nbsp;&nbsp;"+
    e.x+","+e.y+
    "<br />e.pageX,e.pageY<br />&nbsp;&nbsp;&nbsp;"+
    e.pageX+","+e.pageY+
    "<br />e.layerX,e.layerY<br />&nbsp;&nbsp;&nbsp;"+
    e.layerX+","+e.layerY+
    "<br />e.offsetX,e.offsetY<br />&nbsp;&nbsp;&nbsp;"+
    e.offsetX+","+e.offsetY;
}

Control Two是用來測試事件的各種座標成員,這部份可以自己玩玩看,下面是各大瀏覽器的整理(x軸)︰

由此表看來,最好的做法是不設border用offset,再針對沒有offset的瀏覽器做layer就好了。

Control Three是最複雜的東西了,它是用來測試滑鼠的動作是點一下或按住不放。這個的應用會在下次提到。

function mousedown3(e){ 
    if(!e.target)e.target=e.srcElement;
    window.delayId=setTimeout(delay,200,window.t=e.target); 
    //IE不能在settimeout傳值 就丟給window了XD
}

(由setTimeoue再次證明了IE的無能...)在滑鼠按下的瞬間建立一個delay函數,預計在200毫秒後執行。

function mouseup3(e){ 
    if(!e.target)e.target=e.srcElement;
    clearTimeout(window.delayId);
    if(window.delayflag){
        window.delayflag=0;
        return;
    }
    e.target.innerHTML="click<br />"+e.target.innerHTML;
}

在滑鼠放開的瞬間取消delay函式(在200毫秒之內放開的話),且如果delayflag為true(delayflag會在delay函式中看到,若超過200毫秒,delay函式執行,delayflag就會設成true),就將delayflag恢復原始狀態,並return;否則就在P元素中加入"click"字樣(表示滑鼠在200毫秒內放開)。

function delay(t){ 
    if(!t)t=window.t;
    t.innerHTML="hold<br />"+t.innerHTML;
    window.delayflag=1;
}

delay函式,在P元素內加入"hold"並將delayflag設成true。

以下是完整的code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type"
            content="text/html; charset=utf-8" />
<title>JavaScript範例 - 滑鼠事件</title>
<script type="text/javascript"><!--
function registEvent(target,event,func){
    if(document.addEventListener)   //FF
        target.addEventListener(event,func,false);
    else{                           //IE
        target.attachEvent("on"+event,func);
   }
}
function mouseover(e){
   if(!e.target)e.target=e.srcElement;
   e.target.className="over";
}
function mouseout(e){
   if(!e.target)e.target=e.srcElement;
   e.target.className="out";
}
function mousedown(e){
   if(!e.target)e.target=e.srcElement;
   e.target.className="down";
}
function mouseup(e){
   if(!e.target)e.target=e.srcElement;
   e.target.className="up";
}
function mousemove(e){
   if(!e.target)e.target=e.srcElement;
   e.target.innerHTML=
   "e.x,e.y<br />&nbsp;&nbsp;&nbsp;"+
   e.x+","+e.y+
   "<br />e.pageX,e.pageY<br />&nbsp;&nbsp;&nbsp;"+
   e.pageX+","+e.pageY+
   "<br />e.layerX,e.layerY<br />&nbsp;&nbsp;&nbsp;"+
   e.layerX+","+e.layerY+
   "<br />e.offsetX,e.offsetY<br />&nbsp;&nbsp;&nbsp;"+
   e.offsetX+","+e.offsetY;
}
function mousedown3(e){
   if(!e.target)e.target=e.srcElement;
   window.delayId=setTimeout(delay,200,window.t=e.target);
   //IE不能在settimeout傳值 就丟給window了XD
}
function mouseup3(e){
   if(!e.target)e.target=e.srcElement;
   clearTimeout(window.delayId);
   if(window.delayflag){
      window.delayflag=0;
      return;
   }
   e.target.innerHTML="click<br />"+e.target.innerHTML;
}
function delay(t){
   if(!t)t=window.t;
   t.innerHTML="hold<br />"+t.innerHTML;
   window.delayflag=1;
}
function start(){
   var control=document.getElementById("control1");
   registEvent(control,"mouseover",mouseover);
   registEvent(control,"mouseout",mouseout);
   registEvent(control,"mousedown",mousedown);
   registEvent(control,"mouseup",mouseup);
   var control=document.getElementById("control2");
   registEvent(control,"mousemove",mousemove);
   var control=document.getElementById("control3");
   registEvent(control,"mousedown",mousedown3);
   registEvent(control,"mouseup",mouseup3);
}
window.onload=start;
--></script>
<style type="text/css">
#control1,#control2,#control3{
   width: 200px;
   height: 150px;
   border: 1px solid black;
   overflow: auto;
   font-family: courier new;
   font-size: 12px;
}
.over{
   background-color: pink;
}
.out{
   background-color: white;
}
.down{
   background-color: red;
}
.up{
   background-color: pink;
}
</style>
</head>
<body>
<div id="container">
   <a href="home.html">上一頁</a>
   <p>以下的矩形大小都是200*150,並有寬度1的邊框。</p>
   <p id="control1"></p>
   <p>這是對事件座標的觀察!各位請開各種瀏覽器來玩玩看XD</p>
   <div style="position: relative;">
      <p id="control2"></p>
   </div>
   <p>下面的方法可以分辨出點擊與按住不放~</p>
   <p id="control3"></p>
</div>
</body>
</html>

沒有留言:

張貼留言