• 鼠标事件(onmouseover、onmouseout)延时切换插件


    原理很简单:
    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,这样不会因为鼠标离开导致层被关闭(只要指针还在层上)。
    封装事件

    复制代码 代码如下:

     (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 () [无] 获取唯一延时分组名称

    我注意到JQuery API中关于hover事件的说明:
    会伴随着对鼠标是否仍然处在特定元素中的检测(例如,处在div中的图像),如果是,则会继续保持“悬停”状态,而不触发移出事件(修正了使用mouseout事件的一个常见错误)。
    mouseout有BUG?这让我想起了我曾经工作中制作一个鼠标触发显示名片(类似腾讯微博的头像名片)经常被错误的执行了mouseout事件。于是 我又查阅了jQuery的hover源码如何解决这个问题,发现它是使用“mouseenter”与“mouseleave”代替了 “mouseover”与“mouseout”,“mouseenter”与“mouseleave”是IE(6、7、8)特有的的事件,标准浏览器并不支持,需要进行模拟,最终版本:

    代码如下:

     (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');

  • 相关阅读:
    jQuery实现图片前进后退
    jQuery写日历
    python列表模拟栈
    python 列表去重
    Linux的文件系统
    新建vss数据库
    关于业务用例和系统用例
    从零开始使用Linux命令
    svn的安装与配置
    数塔 动态规划
  • 原文地址:https://www.cnblogs.com/piuba/p/2619815.html
Copyright © 2020-2023  润新知