鼠標(biāo)事件延時(shí)切換插件
onmouseover、onmouseout執(zhí)行業(yè)務(wù)代碼時(shí)使用setTimeout進(jìn)行延時(shí),第二次觸發(fā)的時(shí)候先清除掉前面的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);
};
上述代碼可以看到,定時(shí)器返回值(唯一ID)由timer保存著,onmouseover與onmouserout都可以清除未執(zhí)行的定時(shí)器,防止重復(fù)執(zhí)行。這里timer讓onmouseover與onmouserout有了一個(gè)“組”的概念,我們還可以讓更多的元素能夠訪問(wèn)到“組”,例如插入式的下拉菜單與tips等觸發(fā)元素與彈出層都需要共用同一個(gè)timer,這樣不會(huì)因?yàn)槭髽?biāo)離開(kāi)導(dǎo)致層被關(guān)閉(只要指針還在層上)。
封裝事件
/*!
* 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負(fù)責(zé)保存著自定義的“組”,同一“組”下甚至可以暫停mouseout的回調(diào)函數(shù)執(zhí)行,這樣可以實(shí)現(xiàn)套嵌操作。
接口說(shuō)明
| 方法 | 參數(shù) | 作用 |
|---|---|---|
| hoverDelay (elem, over, out, group) | 元素, 鼠標(biāo)靠近時(shí)回調(diào)函數(shù), 鼠標(biāo)離開(kāi)時(shí)回調(diào)函數(shù), 設(shè)置延時(shí)分組名稱[可選] | 設(shè)置延時(shí)觸發(fā)效果 |
| hoverDelay (elem, group) | 元素, 延時(shí)分組名稱 | 停止鼠標(biāo)離開(kāi)執(zhí)行的回調(diào)函數(shù) |
| hoverDelay () | [無(wú)] | 獲取唯一延時(shí)分組名稱 |
我注意到j(luò)Query API中關(guān)于hover事件的說(shuō)明:
會(huì)伴隨著對(duì)鼠標(biāo)是否仍然處在特定元素中的檢測(cè)(例如,處在div中的圖像),如果是,則會(huì)繼續(xù)保持“懸停”狀態(tài),而不觸發(fā)移出事件(修正了使用mouseout事件的一個(gè)常見(jiàn)錯(cuò)誤)。
mouseout有BUG?這讓我想起了我曾經(jīng)工作中制作一個(gè)鼠標(biāo)觸發(fā)顯示名片(類(lèi)似騰訊微博的頭像名片)經(jīng)常被錯(cuò)誤的執(zhí)行了mouseout事件。于是我又查閱了jQuery的hover源碼如何解決這個(gè)問(wèn)題,發(fā)現(xiàn)它是使用“mouseenter”與“mouseleave”代替了“mouseover”與“mouseout”,“mouseenter”與“mouseleave”是IE(6、7、8)特有的的事件,標(biāo)準(zhǔn)瀏覽器并不支持,需要進(jìn)行模擬,最終版本:
/*!
* 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
新窗口打開(kāi)
下載
1、原生版1.1
2、jQuery插件版
相關(guān)文章
javascript實(shí)現(xiàn)的textarea運(yùn)行框效果代碼 不用指定id批量指定
今天在寫(xiě)一個(gè)網(wǎng)頁(yè)的時(shí)候用到了N多嵌套在textarea標(biāo)簽里的代碼,定義雙擊運(yùn)行其內(nèi)的代碼段。但是每次創(chuàng)建一個(gè)這樣的可運(yùn)行的實(shí)例都要給textarea元素自定義一個(gè)id值和寫(xiě)入雙擊事件,好不麻煩。2009-12-12
js實(shí)現(xiàn)提交前對(duì)列表數(shù)據(jù)的增刪改查
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)提交前對(duì)列表數(shù)據(jù)的增刪改查,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01
JavaScript頁(yè)面刷新與彈出窗口問(wèn)題的解決方法
解決JavaScript頁(yè)面刷新與彈出窗口問(wèn)題2010-03-03
javascript實(shí)現(xiàn)編寫(xiě)網(wǎng)頁(yè)版計(jì)算器
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)編寫(xiě)網(wǎng)頁(yè)版計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
javascript+css實(shí)現(xiàn)俄羅斯方塊小游戲
這篇文章主要為大家詳細(xì)介紹了javascript+css實(shí)現(xiàn)俄羅斯方塊小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
動(dòng)態(tài)創(chuàng)建script標(biāo)簽實(shí)現(xiàn)跨域資源訪問(wèn)的方法介紹
本篇文章主要是對(duì)動(dòng)態(tài)創(chuàng)建script標(biāo)簽實(shí)現(xiàn)跨域資源訪問(wèn)的方法進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-02-02
JS實(shí)現(xiàn)滑動(dòng)導(dǎo)航效果
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)滑動(dòng)導(dǎo)航效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01
javascript游戲開(kāi)發(fā)之《三國(guó)志曹操傳》零部件開(kāi)發(fā)(一)讓靜態(tài)人物動(dòng)起來(lái)
首先來(lái)說(shuō),讓一個(gè)游戲賦有可玩性必須要?jiǎng)屿o結(jié)合,我將要在下面告訴大家如何運(yùn)用Javascript將靜態(tài)圖片變?yōu)閯?dòng)態(tài)圖片,感興趣的朋友可以了解下,便當(dāng)鞏固js知識(shí)了2013-01-01

