鼠标事件延时切换插件

 更新时间:2011年03月12日 19:10:06   作者:  
为了防止误操作,很多时候需要对鼠标滑过触发的事件进行延时处理。网易首页的选项卡好几年之前就添加了这个特性,当时我记得是采用150毫秒作为触发基准
原理很简单:
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.jb51.net/js/2011/hover/index.htm
新窗口打开

下载

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

相关文章

  • 微信小程序实现渐入渐出动画效果

    微信小程序实现渐入渐出动画效果

    这篇文章主要给大家介绍了关于微信小程序实现渐入渐出动画效果的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用微信小程序具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 微信小程序实现录音功能

    微信小程序实现录音功能

    这篇文章主要为大家详细介绍了微信小程序实现录音功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • bootstrap multiselect 多选功能实现方法

    bootstrap multiselect 多选功能实现方法

    这篇文章主要介绍了bootstrap multiselect 多选功能实现方法,需要的朋友可以参考下
    2017-06-06
  • JS中的Date()使用小结

    JS中的Date()使用小结

    Date() 日期对象是一个构造函数必须使用new来调用创建我们的日期对象,本文给大家介绍JS中的Date()使用小结,感兴趣的朋友一起看看吧
    2024-01-01
  • 使用js实现一个可编辑的select下拉列表

    使用js实现一个可编辑的select下拉列表

    这篇文章主要介绍了使用js实现一个可编辑的select下拉列表,个人感觉还不错,需要的朋友可以参考下
    2014-02-02
  • 百度地图API之本地搜索与范围搜索

    百度地图API之本地搜索与范围搜索

    地图服务是指可以提供数据信息的接口,比如说本地搜索/路线规划等,下面介绍下百度地图API之本地搜索与范围搜索的相关知识,有需要的小伙伴可以来学习下
    2015-07-07
  • js实现滑动到页面底部自动加载更多功能

    js实现滑动到页面底部自动加载更多功能

    本文主要分享了js实现滑动到页面底部自动加载更多功能的代码。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • 从零搭一个自用的前端脚手架的方法步骤

    从零搭一个自用的前端脚手架的方法步骤

    这篇文章主要介绍了从零搭一个自用的前端脚手架的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • XP折叠菜单&仿QQ2006菜单

    XP折叠菜单&仿QQ2006菜单

    XP折叠菜单&仿QQ2006菜单...
    2006-12-12
  • 基于JS实现移动端左滑删除功能

    基于JS实现移动端左滑删除功能

    最近做个项目,需要实现移动端左滑删除功能,当时js代码将网上找的进行删减优化,下面通过本文给大家分享基于JS实现移动端左滑删除功能,感兴趣的朋友一起看看
    2017-07-07

最新评论