Posted in Javascript onFebruary 17, 2010
ok,不废话了,实现一个javascript的Timer吧
比起as3的Timer类,功能上略有改动
timer2.src.js
/** * Timer 模型 * * @author rainsilence * @version 2.0 */ (function() { /** * TimerEvent constructor 构造器 * * @param type 事件类型 * @param bubbles 是否毛票 * @param cancelable 是否可取消 */ TimerEvent = function(type, bubbles, cancelable) { this.type = type; this.bubbles = bubbles; this.cancelable = cancelable; }; /** * Event 时间事件声明 * * @event TIMER * @event TIMER_COMPLETE */ extend(TimerEvent, { TIMER : "timer", TIMER_COMPLETE : "timerComplete" }); /** * Event 方法 * * @method toString */ extend(TimerEvent.prototype, { toString : function() { return "[TimerEvent type=" + this.type + " bubbles=" + this.bubbles + " cancelable=" + this.cancelable +"]"; } }); /** * Extend 扩展类,对象的属性或者方法 * * @param target 目标对象 * @param methods 这里改成param也许更合适,表示承载着对象,方法的对象,用于target的扩展 */ function extend(target, methods) { if (!target) { target = {}; } for (var prop in methods) { target[prop] = methods[prop]; } return target; } /** * Timer 构造器 * * @param delay 延时多少时间执行方法句柄 * @param repeatCount 重复多少次,如果不设置,代表重复无限次 */ Timer = function(delay, repeatCount) { var listenerMap = {}; listenerMap[TimerEvent.TIMER] = []; listenerMap[TimerEvent.TIMER_COMPLETE] = []; extend(this, { currentCount : 0, running : false, delay : delay, repeatCount : repeatCount, // true:Interval,false:Timeout repeatType : repeatCount == null || repeatCount < 1 ? true : false, handler : listenerMap, timerId : 0, isCompleted : false }); }; // 事件对象初始化(这部分未实现) var timerEvent = new TimerEvent(TimerEvent.TIMER, false, false); var timerCompleteEvent = new TimerEvent(TimerEvent.TIMER_COMPLETE, false, false); /** * Timer 计时器方法 * * @method addEventListener 增加一个方法句柄(前两个参数必须,后一个参数可选) * @method removeEventListener 移除一个方法句柄 * @method start 开始计时器 * @method stop 结束计时器 * @method reset 重置计时器 */ extend(Timer.prototype, { addEventListener : function(type, listener, useCapture) { if (type == TimerEvent.TIMER || type == TimerEvent.TIMER_COMPLETE) { if (!listener) { alert("Listener is null"); } if (useCapture == true) { this.handler[type].splice(0, 0, [listener]); } else { this.handler[type].push(listener); } } }, removeEventListener : function(type, listener) { if (type == TimerEvent.TIMER || type == TimerEvent.TIMER_COMPLETE) { if (!listener) { this.handler[type] = []; } else { var listeners = this.handler[type]; for (var index = 0; index < listeners.length; index++) { if (listeners[index] == listener) { listeners.splice(index, 1); break; } } } } }, start : function() { var timerThis = this; if (this.running == true || this.isCompleted) { return; } if (this.handler[TimerEvent.TIMER].length == 0 && this.handler[TimerEvent.TIMER_COMPLETE].length == 0) { alert("No Function"); return; } if (this.repeatType) { this.timerId = setInterval(function() { dispachListener(timerThis.handler[TimerEvent.TIMER], timerEvent); timerThis.currentCount++; }, this.delay); } else { this.timerId = setTimeout(function() {delayExecute(timerThis.handler[TimerEvent.TIMER]);}, this.delay); } this.running = true; function delayExecute(listeners) { dispachListener(listeners, timerEvent); timerThis.currentCount++; if (timerThis.currentCount < timerThis.repeatCount) { if (timerThis.running) { timerThis.timerId = setTimeout(function() {delayExecute(listeners);}, timerThis.delay); } } else { timerThis.running = false; } if (timerThis.running == false) { if (!timerThis.isCompleted) { dispachListener(timerThis.handler[TimerEvent.TIMER_COMPLETE], timerCompleteEvent); } timerThis.isCompleted = true; } } function dispachListener(listeners, event) { for (var prop in listeners) { listeners[prop](event); } } }, stop : function() { this.running = false; if (this.timerId == null) { return; } if (this.repeatType) { clearInterval(this.timerId); } else { clearTimeout(this.timerId); } if (!this.isCompleted) { var listeners = this.handler[TimerEvent.TIMER_COMPLETE]; for (var prop in listeners) { listeners[prop](timerCompleteEvent); } } this.isCompleted = true; }, reset : function() { this.currentCount = 0; this.isCompleted = false; } }); })();
接下来测试吧,大家见过新浪网上的滚动显示吗?用setTimeout写的,真叫牛叉。。。。。。换成Timer重构,简单易懂
timerTest.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-31j"> <title>Insert title here</title> <style type="text/css"> .rowLine { width: 400px; height: 80px; border-bottom-style: solid; border-width: 1px; } .barList { border-style: solid; border-width: 1px; width:400px; height: 80px; overflow: hidden; } </style> <script type="text/javascript" src="js/timer2.src.js"></script> <script type="text/javascript"> <!-- var timer = new Timer(50); var globalTimer = new Timer(10000); var bList; function init() { bList = document.getElementById("barList"); timer.addEventListener(TimerEvent.TIMER, calTime); timer.start(); globalTimer.addEventListener(TimerEvent.TIMER, controlTime); globalTimer.start(); } function controlTime() { if (!timer.running) { timer.reset(); timer.start(); } } function calTime() { bList.scrollTop += 1; if (bList.scrollTop > 80) { timer.stop(); var barNode = bList.firstChild; if (barNode.nodeType == 3) { bList.appendChild(barNode); bList.appendChild(bList.getElementsByTagName("div")[0]); } else { bList.appendChild(barNode); } bList.scrollTop = 0; } } window.onload = init; // --> </script> </head> <body> <div class="barList" id="barList"> <div class="rowLine" style="background-color: red" style="background-color: red">1</div> <div class="rowLine" style="background-color: pink" style="background-color: pink">2</div> <div class="rowLine" style="background-color: blue" style="background-color: blue">3</div> <div class="rowLine" style="background-color: gray" style="background-color: gray">4</div> </div> </body> </html>
addEventListener的useCapture参数本为捕获阶段触发之意,现在改成如果true,则在其他句柄之前触发,如果false,则在其他句柄之后触发。
后记:
现在貌似大家比较流行评论说明书的用法。。。比如struts+spring+hibernate。而忽略了编程的实质。希望大家多看源码,多讨论源码,那样才会有所谓的思想。否则人家今天用这个framework,明天换了。你又要从头开始了。
JavaScript Timer实现代码
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@