Reputation: 33
I'm having a little problem with the setTimeout-function.
$(this) is every DOM-Element with a specific class.
When the mouse enters an elememt, and then leave it, there is no problem. But when the mouse leaves an element directly to another (within the 500ms timeout) the first element (that one, the mouse left from) never fades out.
So the new mouseenter-Event kind of prevent the timeOut to call the function. Without the setTimeout-wrapper everything is just working fine.
Here's my code:
$(this).hover(methods['mouseenterManager'], methods['mouseleaveManager']);
/**
* manage mouseenter events
*/
mouseenterManager: function() {
clearTimeout(timer);
//create toolbar, if no toolbar is in dom
if ($(this).data("layouter").toolbar == undefined) {
//get bottom center of this element
pos_left = ($(this).width() / 2) + $(this).offset().left;
pos_top = $(this).height() + $(this).offset().top;
//create toolbar element
toolbar = $('<div style="display:none; left:' + parseInt(pos_left) + 'px; top:' + parseInt(pos_top) + 'px;" class="layouter_bar"><ul><li><a class="edit" href="javascript:;">Edit</a></li><li><a class="copy" href="javascript:;">Edit</a></li><li><a class="remove" href="javascript:;">Edit</a></li></ul></div>');
//bind this element to toolbar
toolbar.data("layouter", {
parent: $(this),
});
//bind toolbar to this element
data = $(this).data("layouter");
data.toolbar = toolbar;
$(this).data("layouter", data);
//bind this element to toolbar
data = toolbar.data("layouter");
data.parent = $(this);
toolbar.data("layouter", data);
element = $(this);
toolbar.mouseleave(function() {
toolbar = $(this);
timer = setTimeout(function() {
if (!toolbar.is(":hover") && !element.is(":hover")) {
toolbar.fadeOut("fast", function() {
$(this).remove();
});
data = element.data("layouter");
data.toolbar = undefined;
element.data("layouter", data);
}
}, 500);
});
//display the toolbar
$("body").append(toolbar);
toolbar.fadeIn("fast");
}
},
/**
* manage mouseleave events
*/
mouseleaveManager: function() {
toolbar = $(this).data("layouter").toolbar;
element = $(this);
if (toolbar != undefined) {
timer = setTimeout(function() {
if (!toolbar.is(":hover")) {
toolbar.fadeOut("fast", function() {
$(this).remove();
});
data = element.data("layouter");
data.toolbar = undefined;
element.data("layouter", data);
}
}, 500);
}
},
};
Any ideas?
thank you!
Upvotes: 0
Views: 255
Reputation: 707876
It looks to me like you're using a lot of global variables and when you go into another element, the value of all those global variables gets changed. Your timeout function is referencing those global variables so it doesn't work properly when they've been changed by entering another element.
It also looks to me like as soon as you enter another element, you clear the timer to prevent it from running and since it's a global timer, there is only one so you have killed the timer that you want to fire.
For the global variable problem, put var
in front of all variables that should be local like this:
var toolbar = $(this).data("layouter").toolbar;
var element = $(this);
and
//get bottom center of this element
var pos_left = ($(this).width() / 2) + $(this).offset().left;
var pos_top = $(this).height() + $(this).offset().top;
For the timer issue, it appears to me like you need to NOT have a single global timer, but need a timer for each element. That is a bit more complicated. Without something I can run and test, I can't be sure if this works without any other changes, but this is steps in the right direction to fix the variables to be local and to make the timer be local for each element:
$(this).hover(methods['mouseenterManager'], methods['mouseleaveManager']);
/**
* manage mouseenter events
*/
mouseenterManager: function() {
var self = $(this);
var timer = self.data("timer");
if (timer) {
clearTimeout(timer);
}
//create toolbar, if no toolbar is in dom
if (self.data("layouter").toolbar == undefined) {
//get bottom center of this element
var pos_left = ($(this).width() / 2) + $(this).offset().left;
var pos_top = $(this).height() + $(this).offset().top;
//create toolbar element
var toolbar = $('<div style="display:none; left:' + parseInt(pos_left) + 'px; top:' + parseInt(pos_top) + 'px;" class="layouter_bar"><ul><li><a class="edit" href="javascript:;">Edit</a></li><li><a class="copy" href="javascript:;">Edit</a></li><li><a class="remove" href="javascript:;">Edit</a></li></ul></div>');
//bind this element to toolbar
toolbar.data("layouter", {
parent: self,
});
//bind toolbar to this element
var data = self.data("layouter");
data.toolbar = toolbar;
self.data("layouter", data);
//bind this element to toolbar
data = toolbar.data("layouter");
data.parent = self;
toolbar.data("layouter", data);
var element = self;
toolbar.mouseleave(function() {
toolbar = self;
timer = setTimeout(function() {
self.data("timer", null);
if (!toolbar.is(":hover") && !element.is(":hover")) {
toolbar.fadeOut("fast", function() {
$(this).remove();
});
data = element.data("layouter");
data.toolbar = undefined;
element.data("layouter", data);
}
}, 500);
self.data("timer", timer);
});
//display the toolbar
$("body").append(toolbar);
toolbar.fadeIn("fast");
}
},
/**
* manage mouseleave events
*/
mouseleaveManager: function() {
var toolbar = $(this).data("layouter").toolbar;
var element = $(this);
var timer = element.data("timer");
if (toolbar != undefined && !timer) {
timer = setTimeout(function() {
element.data("timer", null);
if (!toolbar.is(":hover")) {
toolbar.fadeOut("fast", function() {
$(this).remove();
});
var data = element.data("layouter");
data.toolbar = undefined;
element.data("layouter", data);
}
}, 500);
element.data("timer", timer);
}
},
};
Upvotes: 0
Reputation: 1515
Pass the elements you want to edit to the function of the timer.
For example:
timer = setTimeout(function(toolbar, element) {
if (!toolbar.is(":hover")) {
toolbar.fadeOut("fast", function() {
toolbar.remove();
});
data = element.data("layouter");
data.toolbar = undefined;
element.data("layouter", data);
}
}, 500)
Upvotes: 0