在开发一个应用程序的时候,不可避免要处理很多事件。对于如何处理标准的事件如鼠标,键盘事件是比较清楚的,但对于一个嵌入式项目而言,其实有很多自定义的事件,比如多媒体应用的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; }
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"); ....
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);
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; }