在开发一个应用程序的时候,不可避免要处理很多事件。对于如何处理标准的事件如鼠标,键盘事件是比较清楚的,但对于一个嵌入式项目而言,其实有很多自定义的事件,比如多媒体应用的usb insert/remove 事件,TV应用不可回避的搜索频道的事件,这些事件类型各不同,参数也各不同。那如何在javascript中自定这些事件和处理事件呢?这是本文要解决的问题。DOM level2定义了如何创建,初始化和发送这些事件,这里是基于jQuery-1.6.2库来实现。
本文的例子是关于频道搜索的,有一个开始搜索的按钮和一个停止搜索的按钮,当点击开始按钮将触发一个定时器模拟搜索进度,它将每秒发送一个事件,事件包含当前搜索到的电视频道数,广播频道数和搜索进度。下面是一个截图。
这里先定义一个html文件channelscan.html,在文件中定义上面图示中的文档结构
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html, charset=utf-8">
<title>Channel Scan</title>
<link rel="stylesheet" href="./css/channelscan.css" type="text/css" />
</head>
<body>
<div id = "channelScan">
<p id = "scanStatusNumber">搜索到 <span id="scanTvNum">0</span> 个电视和 <span id="scanBroadcastNum">0</span> 个广播 </p><br/>
<div id = "scanStatusProgressbarGroove"></div>
<div id="scanStatusProgressbarIndicator">0%</div>
<input type="button" id="buttonStartScan" value="Start Scan"></input>
<input type="button" id="buttonStopScan" value="Stop Scan"></input>
</div>
<script type="text/javascript" src="./js/jquery-1.6.2.js"></script>
<script type="text/javascript" src="./js/channelscan.js"></script>
</body>
</html>
再定义一个scanchannel.css的CSS文件定义文档的外观,关于css不多说
#channelScan
{
position:absolute;
top:200px;
left:30%;
}
#scanStatusProgressbarGroove
{
position:relative;
background-color:gray;
color:white;
width:200px;
height:30px;
}
#scanStatusProgressbarIndicator
{
position:relative;
background-color:green;
color:white;
top:-30px;
width:0px;
height:30px;
text-align:left;
}
下面定义一个channelscan.js的javascript文件,处理事件
var ChannelScan =
{
progress:0,
tvChannelNum:0,
tvBroadcastNum:0,
counter:0,
scanTimerId:null,
initialize:function()
{
/*bind the click handler for the two buttons*/
$("#buttonStartScan").bind("click",ChannelScan.startChannelScan);
$("#buttonStopScan").bind("click",ChannelScan.stopChannelScan);
/*definded a custom event 'eventScanProgress' and bind a handler to the custom event*/
$("#channelScan").bind("eventScanProgress",ChannelScan.handleScanEvent);
},
startChannelScan:function()
{
/*create and start a timer, bind a handler,trigger the event each 1 second*/
if(ChannelScan.scanTimerId == null)
ChannelScan.scanTimerId = setInterval(ChannelScan.dispathScanProgressEvent,1000);
},
stopChannelScan:function()
{
/*stop the timer and clear it.*/
if(ChannelScan.scanTimerId != null)
{
clearInterval(ChannelScan.scanTimerId);
ChannelScan.scanTimerId = null;
}
},
handleScanEvent:function(e)
{
/*receive the event and handle it*/
if(e.type == "eventScanProgress")
{
/* update the tv channel number*/
$("#scanTvNum").text(e.tvChannelNum);
/* update the broadcast channel number*/
$("#scanBroadcastNum").text(e.tvBroadcastNum);
/* update the scan progress bar and percent*/
$("#scanStatusProgressbarIndicator").width(e.progress*2);
$("div#scanStatusProgressbarIndicator").text(e.progress+"%");
return true;
}
return false;
},
dispathScanProgressEvent:function()
{
/* this function is triggered by the timer each 1 sec*/
ChannelScan.counter++;
if(ChannelScan.counter <= 100)
{
ChannelScan.tvChannelNum = ChannelScan.counter;
ChannelScan.tvBroadcastNum = ChannelScan.counter*2;
ChannelScan.progress = ChannelScan.counter;
/*create a event object named 'eventScanProgress'*/
var event = $.Event("eventScanProgress");
/*add the data to the event*/
event.progress = ChannelScan.progress;
event.tvChannelNum = ChannelScan.tvChannelNum;
event.tvBroadcastNum = ChannelScan.tvBroadcastNum;
/*trigger the event*/
$("#channelScan").trigger(event);
}
else
{
ChannelScan.stopChannelScan();
}
}
};
/*bind the intialize function*/
$(document).bind("ready",ChannelScan.initialize);
上面是基于jQuery库提供的接口实现自定义事件,DOM LEVEL2规范也定义了如何自定义事件。可以调用document的createEvent方法创建一个事件。
var evt = document.createEvent("Event");
var mevt = document.createEvent("MouseEvent");
....
createEvent的参数指定了事件的类型,DOM LEVEL2有如下几种类型:
UIEvent
: DOMFocusIn, DOMFocusOut & DOMActivate事件MouseEvent
: click, mousedown/up/over/move/outMutationEvent
: 所有的 DOMXX修改事件HTMLEvent
: load, unload, abort, error, select, change, submit, reset, focus, blur, resize, scroll事件Event
: 其它类型的事件
var evt = document.createEvent("Event");
evt.initEvent("myEvent",true,true);
...
var mevt = document.createEvent("MouseEvent");
mevt.initMouseEvent("click",true,true,...);
initEvent和initMouseEvent的第一个参数是事件的一个type属性,也可以认为是事件的名字,第二个参数表示是不是可以冒泡,第三个参数表示是不是可以阻止事件默认的行为。事件初始化后,也可以给事件添加任意的属性,这一点对自定义事件很有用,因为自定义事件可能有好几个属性,事件携带好几种信息。用dispatchEvent可以把事件发送出去。
var evt = document.createEvent("Event");
evt.initEvent("myEvent",true,true);
evt.progress = 10;
evt.tvNum = 2;
evt.broadcastNum = 1;
document.dispatchEvent(evt);
...
or
...
var target = document.getElementById("myTarget");
target.dispatchEvent(evt);
当然通常一个事件必定有一个对应的处理函数,addEventListener实现了一个函数与一个事件的捆绑
document.addEventListener("myEvent",myEventHandler,false);
...
or
...
var target = document.getElementById("myTarget");
target.addEventListener("myEvent",myEventHandler,false);
myEventHandler:function(e)
{
if(e.type == "myEvent")
{
alert("progress:"+ e.progress);
alert("tvNum:" + e.tvNum);
alert("broadcastNum:"+e.broadcastNum);
}
return true;
}