jQuery mousemove fade in/out element cancel fade on element mouseover - javascript

I have written this code which fades out the navigation menu to 50% opacity when the mouse is dormant:
var hidden, fadenav, dimNav = function () {
hidden = true;
$('#main-nav').animate({'opacity': 0.5}, 200);
};
$('document').ready(function () {
dimNav();
$('body').on('mousemove', function (e) {
if (hidden) {
$('#main-nav').animate({'opacity': 1}, 200);
hidden = false;
}
if (fadenav !== null) {
clearTimeout(fadenav);
}
fadenav = setTimeout(dimNav, 500);
});
});
What I want to do is make it so that it doesn't fade when the user has their mouse over the #main-nav element.
I have tried this to no avail:
$('#main-nav').on('mouseover mouseout', function (e) {
if (e.type === 'mouseover') {
clearTimeout(fadenav);
} else {
fadenav = setTimeout(dimNav, 500);
}
});
does anyone have any idea how to do this?

Well this certainly is not less code but it may be a bit more straight forward:
​$('#main-nav').on('mousemove',function(e){
if(hidden){
$('#main-nav').animate({'opacity': 1}, 200);
hidden = false;
}
clearTimeout(fadenav);
e.stopPropagation();
});
add that instead of:
$('#main-nav').on('mouseover mouseout', function (e) {
if (e.type === 'mouseover') {
clearTimeout(fadenav);
} else {
fadenav = setTimeout(dimNav, 500);
}
});
you don't have to play with classes at all.
Here is my working sample: http://jsfiddle.net/TbwSA/1
EDIT: I realized that you don't even need the mouseout event.

I discovered the solution myself and thought it might be worth other people knowing:
first, you need to do something similar to this:
$('#main-nav').on('mouseover', function (e) {
if (!$('#main-nav').hasClass('hovered')) {
$('#main-nav').addClass('hovered');
}
}).on('mouseout', function () {
if ($('#main-nav').hasClass('hovered')) {
$('#main-nav').removeClass('hovered');
}
});
and then change the dimNav() function to this:
dimNav = function() {
if (!$('#main-nav').hasClass('hovered')) {
hidden = true;
$('#main-nav').css('opacity', '0.5');
}
};
If anyone can think of a better method than this, please contribute!

Related

Make JQuery event available after a certain amount of time

I'm trying to make one of those annoying popups when leaving your browser. However, I want the event to be available after a certain amount of time. The event should be allowed to trigger after a certain amount of time. I've seen stuff such as delay and setTimeout, but I have no idea how to implement it on my code.
JavaScript:
$(document).on("mouseleave", function (event) {
if (event.pageY < 0) {
$(".leavemodal").fadeIn(600);
}
});
This is not tested but maybe you can try this.
$(document).ready(function() {
canRun = false;
waitPeriod = 1000;// waiting time
setTimeout(function() { canRun = true; }, waitPeriod);
$(document).on("mouseleave", function (event) {
if (!canRun) {
return false;
}
if (event.pageY < 0) {
$(".leavemodal").fadeIn(600);
}
});
});
If you want to use setTimeout() you can do something like this. Click event will be allowed 2 seconds after you mouseleave the element.
var click = false;
$('.el').mouseleave(function() {
if (click == false) {
setTimeout(function() {
console.log('You can click now')
click = true;
$(this).click(function() {
console.log('click')
})
}, 2000)
}
})
.el {
width: 200px;
height: 200px;
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="el"></div>

mouseenter bubbling when mousehover multiple times

how to prevent bubbling or "out of control" when user hover(mouseenter) multiple times . When user hover i'm using slideDown and slideUp for mouseleave and delay i set 250. I can only fix this if delay i set to 1 ms. Below is my script :
$("#nav li").mouseenter(function (e) {
e.stopPropagation();
if (!is_opened) {
var left = $(this).position().left;
$(this).children('div').css('left', '-' + left + 'px');
$(this).children('div').slideDown(delay, function () {
// Animation complete.
is_opened = true;
});
}
return false;
});
$("#nav li").mouseleave(function () {
if (is_opened) {
$(this).children('div').slideUp(delay, function () {
// Animation complete.
is_opened = false;
});
} else {
setTimeout(function () {
if (is_opened) {
$('#nav li:first-child').children('div').slideUp(delay, function () {
// Animation complete.
is_opened = false;
});
}
}, 1000);
}
return false;
});
You can check my JsFiddle here
Reproduce a Problem
Hover Catalogue multiple times and stop hover(but point your cursor at Catalogue), you will see the dropdown will hide but actually it should slide down.
I think your issue is caused by the is_opened flag and then the animation being run along side changing the left css property
If you change your mouse enter and leave js to the following
$("#nav li").each(function() {
//cache vars for better performance
var li = $(this);
var left = $(this).position().left;
var divs = li.children('div');
//change div left first so it only changes once
divs.css('left', '-' + left + 'px');
//do mouse enter and leave stuff
li.mouseenter(function (e) {
e.stopPropagation();
divs.stop(true, true).slideDown(delay);
});
li.mouseleave(function () {
divs.stop().slideUp(delay);
return false;
});
});
it should work: Example

Prevent function running for lots of clicks

Sorry for the misleading title its hard to explain!
Basically I have a function that when you click left/right a div moves X pixels either way.
// Upcoming events slide
$('.nextEvent').click(function(e){
e.preventDefault();
if($('.newsColWrap').offset().left == '597.5'){
} else {
$('.newsColWrap').stop(true,true).animate({'left' : "-=435px"},500)
}
});
$('.prevEvent').click(function(e){
e.preventDefault();
if($('.newsColWrap').offset().left == '1032.5'){
} else {
$('.newsColWrap').stop(true,true).animate({'left' : "+=435px"},500);
}
});
The function works fine, but if the animations is happening and you click again, because the if statement doesn't return my div moves too far, does this make sense?
You can check if the element is being animated using :animated before animating it again.
$('.nextEvent').click(function(e){
e.preventDefault();
if($(this).is(':animated')) return; // check if currently being animated
// ... animate
});
$('.prevEvent').click(function(e){
e.preventDefault();
if($(this).is(':animated')) return; // check if currently being animated
// ... animate
});
The problem could be that you are reading the offset before the previous animation is completed so try
$('.nextEvent').click(function (e) {
e.preventDefault();
var $newsColWrap = $('.newsColWrap').stop(true, true);
if ($newsColWrap.offset().left == '597.5') {
} else {
$newsColWrap.animate({
'left': "-=435px"
}, 500)
}
});
$('.prevEvent').click(function (e) {
e.preventDefault();
var $newsColWrap = $('.newsColWrap').stop(true, true);
if ($newsColWrap.offset().left == '1032.5') {
} else {
$newsColWrap.stop(true, true).animate({
'left': "+=435px"
}, 500);
}
});
You could use a simple setTimeout function running for 500.

jQuery - when clicking on elements too fast animations get buggy

I've been working on this jQuery effect heres the fiddle:
http://jsfiddle.net/abtPH/26/
Everything's pretty good so far, however when I click on the elements too fast it seems to get buggy and get weird behavior. If you take your time and click on the elements it works fine.
I've tried using :animate
stuff to make sure the animation ends before the user can click on the next one. I do not like this approach though because from a end user it seems like the effects are laggy. I want the user to be able to click on the elements fast and have the desired effect.
Here's my jQuery so far:
$('li').on('click', function (e) {
e.preventDefault();
var active = $(this).siblings('.active');
var posTop = ($(this).position()).top;
if (active.length > 0) {
var activeTop = (active.position()).top;
if (activeTop == posTop) {
$(this).find('.outer').fadeIn('medium', function () {
active.toggleClass('active', 400).find('.outer').fadeOut('medium');
});
} else {
$(this).siblings('.active').toggleClass('active', 400).find('.outer').slideToggle();
$(this).find('.outer').slideToggle();
}
} else {
$(this).find('.outer').slideToggle();
}
$(this).toggleClass('active', 400);
});
$('.outer').on('click', function (e) {
return false;
});
Use .finish() complete all the queued animation before beginning a new one
$('li').on('click', function(e){
e.preventDefault();
var active = $(this).siblings('.active');
var posTop = ($(this).position()).top;
if (active.length > 0) {
var activeTop = (active.position()).top;
if (activeTop == posTop) {
$(this).find('.outer').finish().fadeIn('medium', function(){
active.finish().toggleClass('active', 400).find('.outer').finish().fadeOut('medium');
});
} else {
$(this).siblings('.active').finish().toggleClass('active', 400).find('.outer').finish().slideToggle();
$(this).find('.outer').finish().slideToggle();
}
} else {
$(this).find('.outer').finish().slideToggle();
}
$(this).finish().toggleClass('active', 400);
});
$('.outer').on('click', function(e){
return false;
});
Demo: Fiddle

jQuery hover on the same element

With jQuery hover how do you check if you've just hovered on the same element again? Say I have two boxes and hover on box 1, then left, then come back and hover on that same box. I'd like to store the value of the initial hovered element (box 1) and then compare if it's the same when hovering back.
Thanks!!
Try something like below,
var lastHovered = '';
$('#box1').hover(function () {
if (lastHovered == 'box1') {
alert('You have hovered on this already');
}
lastHovered = 'box1';
//Your stuff
}, function () {
//mouse out stuff
});
$('#box2').hover(function () {
if (lastHovered == 'box2') {
alert('You have hovered on this already');
}
lastHovered = 'box2';
//Your stuff
}, function () {
//mouse out stuff
});
Note: I have used 2 functions assuming that box1 hover and box2 hover has totally different functionalities... If not you can have it inside same function and use this.id to group them.. see below.
var lastHovered = '';
$('#box1, #box2').hover(function () {
if (lastHovered == this.id) { //<-- used this.id instead of hard-coded value
alert('You have hovered on ' + this.id + ' already');
}
lastHovered = this.id; //<-- used this.id instead of hard-coded value
//Your stuff
}, function () {
//mouse out stuff
});
Use .data() http://api.jquery.com/data/ so on first hover in the callback do something like
if (!$(this).data('var')) {
$(this).data('var','value');
} else {
console.log($(this).data('var'));
};
var lastHovered = null;
$('#selector1,#selector2,#selector3').hover(function (evt) {
if(lastHovered && lastHovered === $(this).attr("id")){
//code for 're-hovering'
}else{
//code for 'new hover'
}
}, function (evt) {
//mouse out stuff
lastHovered = $(this).attr("id");
});

Categories