JavaScript Timer实现代码
程序员文章站
2022-03-23 13:32:41
ok,不废话了,实现一个javascript的timer吧 比起as3的timer类,功能上略有改动 timer2.src.js 复制代码 代码如下: /** * time...
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,明天换了。你又要从头开始了。
比起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,明天换了。你又要从头开始了。
上一篇: JS getMonth()日期函数的值域是0-11
下一篇: HDU 1412 {A} + {B}
推荐阅读