这篇文章发布于 2010年07月1日,星期四,21:24,归类于 jQuery相关。 阅读 250615 次, 今日 7 次 33 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=906
一、关于鼠标hover事件及延时
鼠标经过事件为web页面上非常常见的事件之一。简单的hover可以用CSS :hover
伪类实现,复杂点的用js。
一般情况下,我们是不对鼠标hover事件进行延时处理。但是,有时候,为了避免不必要的干扰,常会对鼠标hover事件进行延时处理。所谓干扰,就是当用户鼠标不经意划过摸个链接,选项卡,或是其他区域时,本没有显示隐藏层,或是选项卡切换,但是由于这些元素上绑定了hover事件(或是mouseover事件),且无延时,这些时间就会立即触发,反而会对用户进行干扰。
例如,在腾讯网首页,几乎对所有的鼠标经过事件进行了延时处理,例如其选项卡:
或是其顶部的搜搜导航条,见下图:
二、实例及演示
本文的主要内容就是展示我前几天写的鼠标延迟的方法,jQuery下的方法,水平拙劣,仅供参考。本文就以腾讯网首页搜搜搜索栏的一些鼠标经过效果为实例,演示jQuery下的延时处理。下图为demo页面的效果截图:
您可以狠狠地点击这里:腾讯搜搜搜索框延迟demo
三、代码与实现
说到延时,离不开window下的setTimeout方法,本实例的jQuery方法的核心也是setTimeout。代码不长,完整如下:
(function($){ $.fn.hoverDelay = function(options){ var defaults = { hoverDuring: 200, outDuring: 200, hoverEvent: function(){ $.noop(); }, outEvent: function(){ $.noop(); } }; var sets = $.extend(defaults,options || {}); var hoverTimer, outTimer; return $(this).each(function(){ $(this).hover(function(){ clearTimeout(outTimer); hoverTimer = setTimeout(sets.hoverEvent, sets.hoverDuring); },function(){ clearTimeout(hoverTimer); outTimer = setTimeout(sets.outEvent, sets.outDuring); }); }); } })(jQuery);
这段代码的目的在于让鼠标经过事件和延时分离的出来,延时以及延迟的清除都已经由此方法解决了。您所要做的,就是设定延时的时间大小,以及相应的鼠标经过或是移除事件即可。举个简单的例子吧,如下代码:
$("#test").hoverDelay({ hoverEvent: function(){ alert("经过我!"); } });
表示的含义是id
为"test"
的元素在鼠标经过后200毫秒后弹出含有“经过我!”文字字样的弹出框。
关于此js,您可以狠狠地点击这里:jquery.hoverdelay.js(725字节)
ok,现在应用到本文的实例上。
腾讯网的首页的搜索框上面除了鼠标经过延时,其换肤也是值得一提的,关于换肤我之前也提过,在jQuery-马化腾产品设计与用户体验的一些技术实现一文中,相应的demo页面您可以狠狠地点击这里:腾讯首页个性化换肤demo页面
首先,展示下腾讯首页搜索栏的主要HTML结构域代码:
<div id="sosoFod"> <h3 id="sosoweb" class="s1">网页</h3> <h3 id="sosoimg" class="s2">图片</h3> <h3 id="sosovid" class="s2">视频</h3> <h3 id="sosomus" class="s2">音乐</h3> <h3 id="sososoba" class="s2">搜吧</h3> <h3 id="sosowenwen" class="s2">问问</h3> <h3 id="sosoqz" class="s2">博客</h3> <h3 style="cursor:pointer;" class="s2">更多▼ <div style="display:none;" class="more" id="tm"> <ul> <li><a href="#">综合</a></li> <li><a href="#">新闻</a></li> <li><a href="#">词典</a></li> <li><a href="#">生活</a></li> <li><a href="#">百科</a></li> <li style="border-top:1px solid rgb(178, 208, 234);"><a href="#">所有产品</a></li> </ul> </div> </h3> </div>
与先首页代码几乎一致,如假包换。应用了本文没什么技术含量的延迟方法后,可以应用如下的代码实现延迟执行。
$(".s2").each(function(){$("#sosoFod h3").each(function(){ var that = $(this); var id = that.attr("id"); if(id){ that.hoverDelay({ hoverEvent: function(){ $(".s1").attr("class","s2");that.attr("class","s1");//感谢“type23”提供了绑定对象方法 $(this).attr("class","s1"); } }); }else{ that.hoverDelay({ outDuring: 1000, hoverEvent: function(){ $("#tm").show(); }, outEvent: function(){ $("#tm").hide(); } }); } });
唉,惭愧,代码就这样,没什么技术含量的,希望对有用的有用吧。“更多”的下拉鼠标移出后1000毫秒后下拉框隐藏。
基本上都是代码在撑页面,说点有用的东西吧。
hoverDelay
方法共四个参数,表示意思如下:
- hoverDuring
- 鼠标经过的延时时间
- outDuring
- 鼠标移出的延时时间
- hoverEvent
- 鼠标经过执行的方法
- outEvent
- 鼠标移出执行的方法
四、我嚓,结语
月光大人曾说过与下面主要意思一样的话:写博客三五天写一篇重量级的文章,隔个一天两天写个简单,价值度偏低的文章,是比较不错滴。本文就属于有凑篇数之嫌的价值相对偏低的文章。加上本身js还很稚嫩,所以本文内容的方法一般般,仅供参考。
对了,我是抱有疑问的,如何在写jQuery插件组件这类公共方法时将当前对象传到设置的默认的方法中。例如本实例中,如果将当前$(this)
对象传到hoverEvent
或是outEvent
方法中呢,希望有高人不吝赐教。
本文为原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=906
(本篇完)
- JavaScript实现最简单的拖拽效果 (0.337)
- 小tip: transition与visibility (0.210)
- URL锚点HTML定位技术机制、应用与问题 (0.210)
- MooTools和jQuery库继承实现class切换对比 (0.187)
- 团购类网站倒计时的js实现 (0.186)
- JavaScript实现图片幻灯片滚动播放动画效果 (0.166)
- web上渐进使用jQuery Mobile中animate相关CSS (0.158)
- jQuery-火焰灯效果导航菜单 (0.139)
- js下拉菜单实现与可访问性问题的一些思考 (0.110)
- 文章文档标题自动生成导航jQuery小插件titleNav.js (0.104)
- 代码精简 - 常见JavaScript代码缩写举例 (RANDOM - 0.028)
$(“#test”).hoverDelay({
hoverEvent: function(){
alert(“经过我!”);
$(this)失效!!!!!!!!!!!
}
});
鼠标放在更多上,从更多移到子菜单上这期间,子菜单要一直显示;
但是在更多和子菜单之间移动时,子菜单会消失;
有一个解决办法是把更多的元素区域高度加长,这样更多的作用域会到子菜单,但是这种办法不能用,请问还有别的解决办法吗?
hoverTimer = setTimeout(sets.hoverEvent, sets.hoverDuring);你确定这样写,定时器里面的那个sets.hoverEvent会执行!!!
这段代码的 bug 还挺不少,包括 this 指针的处理, timer 的作用域等等。。。
分享一个 web(互联网)开发学习交流群;301909232,欢迎大家踊跃参与,网页设计,php、linux,等等;请收到的,继续传下去,谢谢
假如是是用onclik 那该怎么写呢?因为最近刚刚学JS,所以还不是很懂耶,谢谢啦
为什么要用onclik呢
1、用户也许根本不懂这导航是点击还是滑动的,假如他的思维就是按照按键触发才可以实现,那么200微秒,似乎有点反应迟钝;
2、假如把时间调到快一点的话,就会像你开头说的一样,对用户造成干扰
this 参数传递错误,
$(this).hover(function(){
clearTimeout(outTimer);
that = this;
hoverTimer = setTimeout(function(){sets.hoverEvent.apply(that)}, sets.hoverDuring);
},function(){
clearTimeout(hoverTimer);
that = this;
outTimer = setTimeout(function(){sets.outEvent.apply(that)}, sets.outDuring);
});
应该把that复制提到函数里面,我是针对里面的js评价的。。
解决了this的问题,厉害。
弱弱的问一下
18楼的 sets.hoverEvent.apply(that)
和22楼的sets.hoverEvent.apply(that)
怎么理解啊,这里的that不是指向当前触发Jquery对象吗?
为什么把“更多”下面的子块复制到其他项目下就不行了呢。。。
//修改绑定live事件
$.fn.hoverDelay = function(options) {
var defaults = {
hoverDuring: 200,
outDuring: 200,
hoverEvent: $.noop,
outEvent: $.noop
};
var sets = $.extend(defaults, options || {});
return $(this).live(“hover”,function(event) {
var that = this;
if(event.type == “mouseenter”){
clearTimeout(that.outTimer);
that.hoverTimer = setTimeout(
function(){sets.hoverEvent.apply(that)},
sets.hoverDuring
);
}else {
clearTimeout(that.hoverTimer);
that.outTimer = setTimeout(
function(){sets.outEvent.apply(that)},
sets.outDuring
);
}
});
}
太感谢了,真的很好用,没有这个JS的话真的会浪费很多流量,会多很多次请求,现在我用了这个0.5秒鼠标移动才求请,减清了服务器压力,非常不错。。谢谢
这个很好用!
插件一如既往的好
to:麦子 的确有时候不能正常关闭,你的解决办法帮了我大忙了,谢谢
感谢楼主,做一个菜单时发现发现,有时移到相邻的项时,之前展开的子项没有关闭。
把var hoverTimer, outTimer; 放在更下一层的闭包函数可以解决。
return $(this).each(function(){
var that = this;
var hoverTimer, outTimer;
$(this).hover(
function(){
clearTimeout(outTimer);
hoverTimer = setTimeout(
function(){sets.hoverEvent.apply(that)},
sets.hoverDuring
);
},
function(){
clearTimeout(hoverTimer);
outTimer = setTimeout(
function(){sets.outEvent.apply(that)},
sets.outDuring
);
}
);
});
确实有这种问题 多个元素的就会出现BUG
非常感谢,你帮了我大忙
你好,我新插入的html结构 ,无法使用激活事件,怎么把live()加入呢?QQ314724012
多谢,目前用了这个效果.
关于this的传递问题我解决了,参数也简化了一下.
$.fn.hoverDelay = function(hoverEvent, outEvent){
var hoverTimer, outTimer;
return $(this).each(function(){
$(this).hover(function(){
var t = this;
clearTimeout(outTimer);
hoverTimer = setTimeout(function (){
hoverEvent.call(t);
}, 200);
},function(){
var t = this;
clearTimeout(hoverTimer);
outTimer = setTimeout(function (){
outEvent.call(t);
}, 200);
});
});
}
(function($){
$.fn.hoverDelay = function(options){
var defaults = {
hoverDuring: 200,
outDuring: 200,
//hoverEvent: function(){
// $.noop();
//},
hoverEvent: $.noop,
//outEvent: function(){
// $.noop();
//}
outEvent: $.noop
};
var sets = $.extend(defaults,options || {});
var hoverTimer, outTimer;
//return $(this).each(function(){
return $(this).hover(function(){
clearTimeout(outTimer);
hoverTimer = setTimeout(sets.hoverEvent, sets.hoverDuring);
},function(){
clearTimeout(hoverTimer);
outTimer = setTimeout(sets.outEvent, sets.outDuring);
});
//});
}
})(jQuery);
看了好多博主的文章。非常喜欢。我提一点个人看法,供参考:
hoverDelay现在只接收一个动作参数,可以把动作的所有者也用有参数传进去。
有理,我可以试试。
实际用到了,就有用了。
感谢分享。
问题解决了,我在li标签里加了个和子元素同级的透明a标签盖住了下面的li,然后鼠标放到导航上的话其实是放在了a标签上,于是导航就可以点击了。
但是我不明白的是,假如a的hover事件是通过继承li的hover来完成显示子菜单的话,那为什么a的click事件没有继承li呢?也许讨论这个根本没有用,但是如果您知道的话还请不吝赐教咯。
很感激你能这么耐心的看我问题,没有你就没有这个导航的现在,谢谢!
jQuery的hover方法是有别于mouseover与mouseout方法,例如,鼠标移动到div内部的一个的图片上,如果是使用mouseover与mouseout方法,当鼠标“悬停”在图片上时会触发mouseout事件,这是不合理的。而jQuery的hover方法则修正了这个问题。mouseover以及mouseout方法似乎更符合您的“事件继承”的理解,而hover不然。
http://2009.jqdd.com/yytest/
想要的结果是:点击导航也可以链接到其它页面。
因为a标签下放一个div不符合嵌套规则而且会导致很多问题,所以我在尝试了很多次之后只能无奈的用li标签做了导航,当鼠标放到品牌专区的时候可以显示下方的区域,但是怎么给导航加链接让我很纠结。
我先试着给li加了onclick事件,结果他包裹的子元素全部都执行了这个事件,如果我把子元素的onclick事件return false,又导致点击子元素的链接没有反应.
我这里发现了一个问题,就是:如果“更多”这个按钮需要添加一个指向的话,这样的结构好像很难做到,可是如果把“更多”按钮下包含的块移出来,鼠标离开“更多”按钮的话又会触发mouseout事件…
怎么样才能在“更多”按钮上添加一个onclick事件呢?
此方法主要就是针对鼠标移出移入事件的,如果您想应用点击事件,可以修改hover方法为click方法~~
在函数外围:var self = this;
然后改这句:
hoverTimer = setTimeout(function(){sets.hoverEvent.apply(this, [$(self)])}, sets.hoverDuring);
apply的第一个参数是this还是self你自己决定。
对不起,我只是怕说不明白,我没那么迂腐,只是不善于沟通。
那个js文件我借用了,谢谢啊!
$(“.s2”).each(function(){
var that = $(this);
var id = that.attr(“id”);
if(id){
这里有一个问题需要探讨一下,还有一个问题需要请教一下:
1. 虽然我依然看不懂jquery.hoverdelay.js这个文件,不过在测试的时候发现第一个项【网页】在取消激活之后,无论鼠标如何hover都无法再次激活了。
然后我逼迫自己去一行一行的看代码,在我所引用的这段代码中,第一行的意思应该是将class=”s2″的元素遍历并赋予hover事件…吧~,但在这个时候页面的第一个项【网页】的class=”s1″,所以没有被XX。
我觉得应该可以这样解决:$(“#sosoFod h3”).each(function(){ … }
2.为什么我不那么确定说可以这样解决,而加了“应该可以”,是因为我还有一个问题需要请教*^^*
第二行:var that = $(this);
①这里的this指的是当前调用hover事件的标签h3么?
②然后 var id… 这句就是把当前h3标签的id值取到对吧?
③最后 根据是否有id值执行相应的函数是吗?
我不大确定,所以如果您没有太多时间的话,就请只用回答“1.是2.对3.嗯”就可以了,如果错了就请尽量解释下吧。
如果撇开一些咬文嚼字,全部都对!
更惭愧,这么简单都看不懂,希望上午能自己用这个js做个菜单出来。
唉,其实做出来了又能怎么样呢~
还是不会…