当容器具有选择框时,jQuery mouseleaf触发问题
Problem with jQuery mouseleave firing when container has select box
我有两个容器——一个嵌套在另一个容器中。当我将鼠标悬停在父容器上时,我希望子容器出现。当我将鼠标移出时,我希望子容器淡出。我遇到的问题是子容器有一个包含"选择框"的表单。当用户选择选择框时,mouseleave事件会意外触发。
如何阻止选择框触发mouseleave事件?
你可以在这里看到我的工作代码:http://jsfiddle.net/rsturim/9TZyh/3/
以下是我的脚本摘要:
$('#parent-container').live("mouseenter", function () {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().fadeTo('slow', 1.0);
}).live("mouseleave", function (e) {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().hide();
});
edit:在基于WebKit的浏览器中显示良好。在Firefox和IE7-IE9中失败。
在大多数情况下,您应该能够简单地检查事件目标是否是select元素,并且只有在不是的情况下才能继续。看起来比公认的解决方案干净得多,在我的情况下效果很好。
我修改了小提琴:http://jsfiddle.net/Dygerati/uj3ZC/5/
$('#parent-container').live("mouseenter", function() {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().fadeTo('slow', 1.0);
}).live("mouseleave", function(e) {
if(e.target.tagName.toLowerCase() != "select") {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().hide();
}
});
$('#parent-container').live("mouseenter", function () {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().fadeTo('slow', 1.0);
}).live("mouseleave", function (e) {
/* Solution */
if(e.relatedTarget == null) return;
/************/
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().hide();
});
由于mouseleave和mouseenter事件是非标准的,因此可以在各处获得这样的滞后。我唯一能建议的解决方法就是使用一些技巧。这是http://jsfiddle.net/mPDcu/1/代码的改进版本。
var selectOpened = false;
$('#select-grind-type').click(function(e){
selectOpened = !selectOpened;
e.stopPropagation();
});
$('body').click(function(){
if (selectOpened) {
selectOpened = false;
}
})
$('#parent-container').on("mouseenter", function() {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().fadeTo('slow', 1.0);
}).live("mouseleave", function(e) {
if (!selectOpened) {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().hide();
}
});
我在参与的一个项目中遇到了同样的问题,其他答案对我来说都不太好。我的棘手解决方案是检查事件对象中的鼠标位置是否在父容器中。效果不错!
var layer = $('#parent-container'),
layerPos = {};
$(layer).mouseenter(function () {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().fadeTo('slow', 1.0, function(){
layerPos.x = {
min: $(layer).offset().left,
max: $(layer).offset().left + $(layer).width()
};
layerPos.y = {
min: $(layer).offset().top,
max: $(layer).offset().top + $(layer).height()
};
});
})
$(layer).mouseleave(function(e) {
// check if event mouse position is inside parent container
var x_con = e.pageX >= layerPos.x.min && e.pageX <= layerPos.x.max;
var y_con = e.pageY >= layerPos.y.min && e.pageY <= layerPos.y.max;
if ( x_con && y_con ) {
return false;
}
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().hide();
});
您还可以检查导航器版本,以避免在Chrome等支持此功能的浏览器中执行此代码。
这部分解决了问题。当选择框获得焦点时取消绑定mouseleave
事件,当它失去焦点时再次绑定。
http://jsfiddle.net/9TZyh/5/
$('#parent-container').live("mouseenter", function() {
var $this = $(this);
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().fadeTo('slow', 1.0);
}).live("mouseleave",focusOut);
$("#select-grind-type").live("focus",function(){
$('#parent-container').die("mouseleave");
});
$("#select-grind-type").live("focusout change",function(){
$('#parent-container').live("mouseleave",focusOut);
});
function focusOut(e) {
var $this = $(this),
$selectOptionsContainer = $this.find('#child-container');
$selectOptionsContainer.stop().hide();
}
如果你不介意褪色在一些旧浏览器中不起作用,你可以用CSS快速完成:
#parent-container { }
#child-container {
opacity:0;
-webkit-transition:opacity 1s ease-in;
-moz-transition:opacity 1s ease-in;
}
#parent-container:hover #child-container {{
opacity:1;
-webkit-transition:opacity 1s ease-out;
-moz-transition:opacity 1s ease-out;
}
这些家伙给了你一个可行的替代方案,但它也有一些bug。例如,如果在组合框仍处于打开状态时退出外部框,则它不会淡出。我向您推荐一个更简单的替代方案,它也可以修复该错误。
与其在内部盒子的mouseleave事件中思考,为什么不换个角度思考呢?我的意思是,离开里面的盒子,也意味着进入另一个容器。所以你可以做outerContainer.mouseenter(function(){ hideInnerBox() });
:-)
显然,出于这个目的,innerbox不应该是outerbox的子代,即使在视觉上看起来是这样(可以使用css定位来实现)
所以我刚刚遇到了一个类似的问题,<select>
嵌套在一个容器中,并遇到了这个问题。以下是我最终做的事情。
$("#container").mouseover(function(e){
var t = $(this);
t.addClass('active');
var offset = t.offset();
var xMin = offset.left;
var yMin = offset.top;
var xMax = xMin + t.innerWidth();
var yMax = yMin + t.innerHeight();
t.parent().mousemove(function(e){
if(e.pageX < xMin || e.pageX > xMax-2 || e.pageY < yMin || e.pageY > yMax ){
t.removeClass('active');
// unbind this event
$(this).unbind('mousemove');
}
});
});
基本上,当您将鼠标悬停在容器上时,我们会收集它的边界并开始检查鼠标是否在元素上。当我们知道鼠标不在时,我们解除对mousemove
侦听器的绑定。
我愿意为你做一把小提琴,但今天跑得太慢了!
希望能有所帮助。
您应该只检查当前元素是否是容器的后代。
如果是,则中止处理程序。
参见:jquery后代
示例:
ContainerElement.mouseleave(function (e) {
if (ContainerElement.has(e.fromElement).length > 0) return;
// Do your Stuff
});
- 无法从 jQuery RSS Feed 中的 localStorage 动态替换类
- 如何使用jQuery自动打开页面上的所有链接
- 如何使用jquery在填充自动完成的值后使文本框只读
- jQuery:循环一个具有不同超时值的循环
- 用程序搜索JQuery数据表中的文本
- 使用 jQuery 的 .on 函数如何获取事件的原始元素
- jQuery匹配JSON对象的部分文本
- Jquery POST未填充数组
- JQuery使计数器每次更改时都会增加
- 如何在Angular2中使用jQuery插件
- 提高JQuery的性能
- 无法在通过jQuery的ajax加载的页面中执行javascript
- JQuery合并了keyup和focusout两个函数
- 如何使用jQuery选择下拉列表的值
- 将PHP变量传递给jQuery时遇到问题
- jQuery UI自动完成突然停止工作
- 剑道网格jQuery动画()问题
- 如何使jQuery插件函数可调用以供独立使用,而不在集合上操作
- 当选择了自动完成中的第一个项目时,jQuery mouseleaf将触发
- 当容器具有选择框时,jQuery mouseleaf触发问题