I have a two containers -- one is nested inside of another. When I hover over the parent, I want the child container to appear. When I mouseout, I want the child container to f
Since mouseleave and mouseenter events are non-standard you can get such lags here and there. The only method I can suggest to fix that is using some hacks. Here is http://jsfiddle.net/mPDcu/1/ improved version of you code.
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();
}
});
Those guys give you a working alternative, but it also has some bugs. For example, if you quit the outer box while the combobox is still opened, it won't fade out. I recommend you a much easier alternative that will also fix that bug.
Instead of thinking in the mouseleave event of the inner box, why don't you swap your mind to think in the other way around? I mean, leaving the inner box, also means entering in another container. So you can do outerContainer.mouseenter(function(){ hideInnerBox() });
:-)
Obviously for that purpose innerbox should not be a child of outerbox, even if visually it seems so (css positioning can be used to achieve it)
I had the same problem in a project in which I am contributing, and the other answers didn't work fine for me. My tricky solution was to check if the mouse position inside the event object is inside the parent container. Works pretty good!
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();
});
You can also check the navigator version to avoid this code to execute in browsers that support this functionality like Chrome.
$('#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();
});
If you don't mind having the fade not working in some old browsers, you could do it with CSS quickly:
#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;
}
In most cases you should simply be able to check to see if the event target was a select element, and only continue in the case that it wasn't. Seems much cleaner than the accepted solution, and worked well in my case.
I've modified the fiddle: 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();
}
});