鼠标事件延时切换插件


Posted in Javascript onMarch 12, 2011

原理很简单:
onmouseover、onmouseout执行业务代码时使用setTimeout进行延时,第二次触发的时候先清除掉前面的setTimeout。
原理

var timer; 
document.getElementById('test').onmouseover = function () { 
clearTimeout(timer); 
timer = setTimeout(function () { 
alert('over') 
}, 150); 
}; 
document.getElementById('test').onmouseout = function () { 
clearTimeout(timer); 
timer = setTimeout(function () { 
alert('out') 
}, 150); 
};

上述代码可以看到,定时器返回值(唯一ID)由timer保存着,onmouseover与onmouserout都可以清除未执行的定时器,防止重复执行。这里timer让onmouseover与onmouserout有了一个“组”的概念,我们还可以让更多的元素能够访问到“组”,例如插入式的下拉菜单与tips等触发元素与弹出层都需要共用同一个timer,这样不会因为鼠标离开导致层被关闭(只要指针还在层上)。
封装事件
/*! 
* hoverDelay.js 
* http://www.planeArt.cn 
* Copyright 2011, TangBin 
* Dual licensed under the MIT or GPL Version 2 licenses. 
*/ 
(function (pluginName) { 
var id = 0, data = {}, 
addEvent = function (elem, type, callback) { 
if (elem.addEventListener) { 
elem.addEventListener(type, callback, false); 
} else { 
elem.attachEvent('on' + type, function () {callback.call(elem)}); 
}; 
}; 
this[pluginName] = function (elem, over, out, group, speed) { 
id ++; 
if (arguments.length === 0) return id; 
if (typeof arguments[1] !== 'function') return clearTimeout(data[arguments[1]]); 
if (typeof elem === 'string') elem = document.getElementById(elem); 
group = group || elem[pluginName] || id; 
speed = speed || 150; 
elem[pluginName] = group; 
addEvent(elem, 'mouseover', function () { 
var elem = this, 
fn = function () {over.call(elem)}; 
clearTimeout(data[group]); 
data[group] = setTimeout(fn, speed); 
}); 
addEvent(elem, 'mouseout', function () { 
var elem = this, 
fn = function () {out.call(elem)}; 
clearTimeout(data[group]); 
data[group] = setTimeout(fn, speed); 
}); 
}; 
})('hoverDelay');

data负责保存着自定义的“组”,同一“组”下甚至可以暂停mouseout的回调函数执行,这样可以实现套嵌操作。

接口说明

方法 参数 作用
hoverDelay (elem, over, out, group) 元素, 鼠标靠近时回调函数, 鼠标离开时回调函数, 设置延时分组名称[可选] 设置延时触发效果
hoverDelay (elem, group) 元素, 延时分组名称 停止鼠标离开执行的回调函数
hoverDelay () [无] 获取唯一延时分组名称
2011-01-22更新
我注意到jQuery API中关于hover事件的说明:
会伴随着对鼠标是否仍然处在特定元素中的检测(例如,处在div中的图像),如果是,则会继续保持“悬停”状态,而不触发移出事件(修正了使用mouseout事件的一个常见错误)。
mouseout有BUG?这让我想起了我曾经工作中制作一个鼠标触发显示名片(类似腾讯微博的头像名片)经常被错误的执行了mouseout事件。于是我又查阅了jQuery的hover源码如何解决这个问题,发现它是使用“mouseenter”与“mouseleave”代替了“mouseover”与“mouseout”,“mouseenter”与“mouseleave”是IE(6、7、8)特有的的事件,标准浏览器并不支持,需要进行模拟,最终版本:
/*! 
* hoverDelay.js v1.1 
* http://www.planeArt.cn 
* Copyright 2011, TangBin 
* Dual licensed under the MIT or GPL Version 2 licenses. 
*/ 
(function (pluginName) { 
var id = 0, data = {}, 
addEvent = function (elem, type, callback) { 
if (elem.addEventListener) { 
if (type === 'mouseenter') { 
elem.addEventListener('mouseover', withinElement(callback), false); 
} else if (type === 'mouseleave') { 
elem.addEventListener('mouseout', withinElement(callback), false); 
} else { 
elem.addEventListener(type, callback, false); 
}; 
} else { 
elem.attachEvent('on' + type, function () {callback.call(elem, window.event)}); 
}; 
}, 
withinElement = function(callback) { 
return function (event) { 
var parent = event.relatedTarget; 
try { 
while (parent && parent !== this) parent = parent.parentNode; 
if (parent !== this) callback.apply(this, arguments); 
} catch(e) {}; 
}; 
}; 
this[pluginName] = function (elem, over, out, group, speed) { 
id ++; 
if (arguments.length === 0) return id; 
if (typeof arguments[1] !== 'function') return clearTimeout(data[arguments[1]]); 
if (typeof elem === 'string') elem = document.getElementById(elem); 
group = group || elem[pluginName] || id; 
speed = speed || 150; 
elem[pluginName] = group; 
addEvent(elem, 'mouseenter', function () { 
var elem = this, 
fn = function () {over.call(elem)}; 
clearTimeout(data[group]); 
data[group] = setTimeout(fn, speed); 
}); 
addEvent(elem, 'mouseleave', function () { 
var elem = this, 
fn = function () {out.call(elem)}; 
clearTimeout(data[group]); 
data[group] = setTimeout(fn, speed); 
}); 
}; 
})('hoverDelay');

查看1.1版演示
http://demo.3water.com/js/2011/hover/index.htm
新窗口打开

下载

1、原生版1.1
2、jQuery插件版

Javascript 相关文章推荐
javascript中的绑定与解绑函数应用示例
Jun 24 Javascript
5分钟理解JavaScript中this用法分享
Nov 09 Javascript
jquery查找父元素、子元素(个人经验总结)
Apr 09 Javascript
javascript实现阻止iOS APP中的链接打开Safari浏览器
Jun 12 Javascript
JQuery动画与特效实例分析
Feb 02 Javascript
JavaScript驾驭网页-获取网页元素
Mar 24 Javascript
js+html5实现canvas绘制网页时钟的方法
May 21 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
Dec 26 Javascript
Angular企业级开发——MVC之控制器详解
Feb 20 Javascript
JS canvas绘制五子棋的棋盘
May 28 Javascript
解决layer.confirm选择完之后消息框不消失的问题
Sep 16 Javascript
Vue实现计算器计算效果
Aug 17 Javascript
autoIMG 基于jquery的图片自适应插件代码
Mar 12 #Javascript
再谈javascript图片预加载技术(详细演示)
Mar 12 #Javascript
在jQuery1.5中使用deferred对象 着放大镜看Promise
Mar 12 #Javascript
使用jquery插件实现图片延迟加载技术详细说明
Mar 12 #Javascript
Jquery.LazyLoad.js修正版下载,实现图片延迟加载插件
Mar 12 #Javascript
javascript textarea光标定位方法(兼容IE和FF)
Mar 12 #Javascript
JavaScript全局函数使用简单说明
Mar 11 #Javascript
You might like
document.compatMode介绍
2009/05/21 Javascript
基于jquery的仿百度搜索框效果代码
2011/04/11 Javascript
zTree插件之单选下拉菜单实例代码
2013/11/07 Javascript
使用js写的一个简易的投票
2013/11/27 Javascript
用console.table()调试javascript
2014/09/04 Javascript
jQuery插件Validation快速完成表单验证的方式
2016/07/28 Javascript
jQuery数组处理函数整理
2016/08/03 Javascript
jQueryUI 拖放排序遇到滚动条时有可能无法执行排序的小bug及解决方案
2016/12/19 Javascript
微信小程序 解析网页内容详解及实例
2017/02/22 Javascript
jquery.masonry瀑布流效果
2017/05/25 jQuery
vue-ajax小封装实例
2017/09/18 Javascript
详解刷新页面vuex数据不消失和不跳转页面的解决
2018/01/30 Javascript
js实现简单模态框实例
2018/11/16 Javascript
实例讲解vue源码架构
2019/01/24 Javascript
Vue3 的响应式和以前有什么区别,Proxy 无敌?
2020/05/20 Javascript
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
基于javascript canvas实现五子棋游戏
2020/07/08 Javascript
vue:el-input输入时限制输入的类型操作
2020/08/05 Javascript
区分vue-router的hash和history模式
2020/10/03 Javascript
Python中统计函数运行耗时的方法
2015/05/05 Python
Python爬虫框架Scrapy实战之批量抓取招聘信息
2015/08/07 Python
python3实现磁盘空间监控
2018/06/21 Python
浅析python 中大括号中括号小括号的区分
2019/07/29 Python
django 链接多个数据库 并使用原生sql实现
2020/03/28 Python
Keras自定义IOU方式
2020/06/10 Python
python利用后缀表达式实现计算器功能
2021/02/22 Python
电信营业员自我评价分享
2014/01/17 职场文书
外贸专业求职信
2014/03/09 职场文书
建筑投标担保书
2014/05/20 职场文书
公司运动会策划方案
2014/05/25 职场文书
党支部创先争优活动总结
2014/08/28 职场文书
2014年幼师工作总结
2014/11/22 职场文书
入党介绍人意见范文
2015/06/01 职场文书
2016年度创先争优活动总结
2016/04/05 职场文书
2019员工保密协议书(3篇)
2019/09/23 职场文书
java.util.NoSuchElementException原因及两种解决方法
2022/06/28 Java/Android