鼠标事件延时切换插件


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延时重复执行函数 lLoopRun.js
Jun 29 Javascript
setInterval 和 setTimeout会产生内存溢出
Feb 15 Javascript
Javascript 读后台cookie代码
Sep 15 Javascript
JS截取字符串常用方法整理及使用示例
Oct 18 Javascript
jQuery切换所有复选框选中状态的方法
Jul 02 Javascript
gameboy网页闯关游戏(riddle webgame)--仿微信聊天的前端页面设计和难点
Feb 21 Javascript
jQuery实现文字自动横移
Jan 08 Javascript
vue中如何引入jQuery和Bootstrap
Apr 10 jQuery
QRCode.js:基于JQuery的生成二维码JS库的使用
Jun 23 jQuery
js array数组对象操作方法汇总
Mar 18 Javascript
百度小程序自定义通用toast组件
Jul 17 Javascript
v-slot和slot、slot-scope之间相互替换实例
Sep 04 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
多数据表共用一个页的新闻发布
2006/10/09 PHP
学习php过程中的一些注意点的总结
2013/10/25 PHP
ThinkPHP上使用多说评论插件的方法
2014/10/31 PHP
PHP序列化操作方法分析
2016/09/28 PHP
Yii框架实现图片上传的方法详解
2017/05/20 PHP
Yii2第三方类库插件Imagine的安装和使用
2017/07/06 PHP
Yii框架响应组件用法实例分析
2019/09/04 PHP
Yii框架参数配置文件params用法实例分析
2019/09/11 PHP
javascript实现面向对象类的功能书写技巧
2010/03/07 Javascript
jQuery图片的展开和收缩实现代码
2013/04/16 Javascript
js 设置缓存及获取设置的缓存
2014/05/08 Javascript
使用JQuery实现的分页插件分享
2015/11/05 Javascript
AngularJS下对数组的对比分析
2016/08/24 Javascript
AngularJS 的$timeout服务示例代码
2017/09/21 Javascript
快速处理vue渲染前的显示问题
2018/03/05 Javascript
layui之select的option叠加问题的解决方法
2018/03/08 Javascript
jQuery实现带右侧索引功能的通讯录示例【附源码下载】
2018/04/17 jQuery
vue组件中iview的modal组件爬坑问题之modal的显示与否应该是使用v-show
2019/04/12 Javascript
JavaScript 变量,数据类型基础实例详解【变量、字符串、数组、对象等】
2020/01/04 Javascript
electron+vue实现div contenteditable截图功能
2020/01/07 Javascript
批处理与python代码混合编程的方法
2016/05/19 Python
Python实现Youku视频批量下载功能
2017/03/14 Python
今天 平安夜 Python 送你一顶圣诞帽 @微信官方
2017/12/25 Python
python urllib爬虫模块使用解析
2019/09/05 Python
python-视频分帧&多帧合成视频实例
2019/12/10 Python
python中property和setter装饰器用法
2019/12/19 Python
django列表筛选功能的实现代码
2020/03/27 Python
keras topN显示,自编写代码案例
2020/07/03 Python
俄罗斯女装店:12storeez
2019/10/25 全球购物
WINDOWS域的具体实现方式是什么
2014/02/20 面试题
英语专业推荐信
2013/11/16 职场文书
专业幼师实习生自我鉴定范文
2013/12/08 职场文书
财务管理职业生涯规划范文
2013/12/27 职场文书
小学体育教学反思
2014/01/31 职场文书
学习型班组申报材料
2014/05/31 职场文书
预备党员综合考察材料
2014/05/31 职场文书