I have a link:
Here's my link
This is not a normal clickable link, it's coded in jQuery like this:
$("#link").hover(function(e) {
e.preventDefault();
$("#tv").stop().animate({marginLeft: "50px"});
$("#tv img)").animate({opacity: 1});
})
So after hovering unclickable link there's change of #tv's margin and opacity.
Is there any way of making this work only after the user hovers the link area with pointer for more than two seconds?
Because now everything happens in real time.
I know there's delay(), but it doesn't work because it just delays the animation and in this case I don't want any action if the pointer is over for less than two seconds.
Possible without a loop?
What you're after is called hoverIntent.
var animateTimeout;
$("#link").hover(function() {
if (animateTimeout != null) {
clearTimeout(animateTimeout);
}
animateTimeout = setTimeout(animate, 2000);
}, function() {
clearTimeout(animateTimeout);
});
function animate() {
//do animation
}
You just need a setTimeout() to delay the code, along with a clearTimeout() to clear it if the user leaves the link within 2 seconds.
Example: http://jsfiddle.net/mNWEq/2/
$("#link").hover(function(e) {
e.preventDefault();
$.data(this).timeout = setTimeout(function() {
$("#tv").stop().animate({marginLeft: "50px"});
$("#tv img)").animate({opacity: 1});
}, 2000);
}, function(e) {
clearTimeout($.data(this,'timeout'));
});
Related
I need some help making a sub-menu appear within 2s after the page loads instead of when the user clicks on it. I'm using JQuery. That file is the core of the website. I need it to stay opened.
Here's the code I have at the moment, I tried to change that on.Click event but it didn't work.
The handleSidenarAndContentHeight(); function resizes the menu items after the sub-menu appears.
jQuery('.page-sidebar li > a').on('click', function (e) {
if ($(this).next().hasClass('sub-menu') === false) {
return;
}
var parent = $(this).parent().parent();
parent.children('li.open').children('a').children('.arrow').removeClass('open');
parent.children('li.open').children('a').children('.arrow').removeClass('active');
parent.children('li.open').children('.sub-menu').slideUp(350);
parent.children('li').removeClass('open');
parent.children('li').removeClass('active');
var sub = jQuery(this).next();
if (sub.is(":visible")) {
jQuery('.arrow', jQuery(this)).removeClass("open");
jQuery(this).parent().removeClass("active");
sub.slideUp(350, function () {
handleSidenarAndContentHeight();
});
} else {
jQuery('.arrow', jQuery(this)).addClass("open");
jQuery(this).parent().addClass("open");
sub.slideDown(350, function () {
handleSidenarAndContentHeight();
});
}
e.preventDefault();
});
Working with a 2 second timeout should do the trick!
jQuery(document).ready(function(){
// Open Parent here
setTimeout(function(){
// Open Child here
}, 2000)
});
There is a simple javascript function you can use, the setTimeout function.
The code follows like this :
setTimeout(function() {yourFunctyion();}. delayTimeInMiliseconds);
This will call your function after the number of second(in ms).
There is also a plugin I've used. It has oneTime and everyTime methods.
jQuery timers plugin
I am making a results screen which toggles between showing the user their best time/score and their latest time/score. I found a solution using this site but after leaving the website open for a few hours I saw that the timings had gone out of sync. I know that this is hard to test so I thought I would see if any experts on here could help me to optimize or fix my code.
CODEPEN
JSFIDDLE
JS
$(document).ready(function() {
setInterval( function() { resultsTransition(); }, 4000);
function resultsTransition() {
$('.latest-transition').fadeOut(500).delay(3500).fadeIn(500).delay(3500);
$('.best-transition').fadeIn(500).delay(3500).fadeOut(500).delay(3500);
}
});
I think your design could be improved (and the out-of-sync problem solved) by simply toggling the opacity of the elements in your resultsTransition method instead of starting a new sequence, which could interfere unpredictably with the interval.
Something like:
var latestTransitionElementVisible = true; //the initial state of your elements
setInterval(resultsTransition, 4000); //note you can just pass the function name
function resultsTransition() {
$('.latest-transition').fadeTo(500, latestTransitionElementVisible ? 0 : 1);
$('.best-transition').fadeTo(500, latestTransitionElementVisible ? 1 : 0);
latestTransitionElementVisible = !latestTransitionElementVisible ;
}
I guess whatever problem/issue you are facing is because of varying animation times .Try the following:
$(document).ready(function() {
setTimeout( function() { resultsTransition(); }, 4000);
function resultsTransition() {
if(!$('.latest-transition').is(':animated') && !$('.best-transition').is(':animated'))
{
$('.latest-transition').fadeOut(500).delay(3500).fadeIn(500).delay(3500);
$('.best-transition').fadeIn(500).delay(3500).fadeOut(500).delay(3500);
setTimeout( function() { resultsTransition(); }, 4000);
}
}
});
I can't run clearInterval for my functions. I use them to scroll the window by firing setInterval with function that fires scrollLeft. The code:
function scrollSpan() {
$('nav#scrolling').children().css('width',config.windowWidth/10+'px');
var inter;
$('nav#scrolling').children('span').hover(function() {
var value;
if($(this).is('.scrollLeft')) {
value = '-=50'
} else {
value = '+=50'
}
inter = setInterval(function() {
$('body, html').animate({
scrollLeft: value
}, 50);
},0)
})
$('nav#scrolling').children('span').mouseleave(function() {
clearInterval(inter)
})
}
Problem is, when mouseleave is triggered, interval doesn't stop.
Fiddle: http://jsfiddle.net/FpX4M/
You are using hover where you should be using mouseenter. When only one handler is passed to hover that handler is called both on enter and leave. So your hover is called twice (once entering and once leaving) but your mouseleave is only called once. This is why even though one interval is cleared, the other remains.
See the documentation, in particular the signature added in v1.4 which takes only a single handler (scrolldown).
EDIT: Jsfiddles with proof:
http://jsfiddle.net/FpX4M/1/
Open your console and see that the handlers trigger twice and that interval continues.
http://jsfiddle.net/FpX4M/2/
In the console you will now see only one firing of the handler and then the intervals stop on leave.
Your whole scope is a little wonky. Try something like this:
var inter;
function scrollSpan() {
$('nav#scrolling').children().css('width',config.windowWidth/10+'px');
}
$('nav#scrolling').children('span').hover(function() {
var value;
if($(this).is('.scrollLeft')) {
value = '-=50'
} else {
value = '+=50'
}
inter = setInterval(function() {
$('body, html').animate({
scrollLeft: value
}, 50);
},0)
});
$('nav#scrolling').children('span').mouseleave(function() {
clearInterval(inter)
});
You need to make sure the inter variable is accessible outside of the function. Also, generally, state functions shouldn't be assigned within functions unless you're changing them rapidly - and it doesn't look like you're detaching them anywhere. The only things that need to be in the function are things that will be repeated. Maybe add a clearInterval(inter); right before your inter = setInterval... to make sure no old intervals persist.
I have a a div in a page that slides up on hover, and then back down on hover out. If you were then to hover in and out on the item, then all the actions will be queued and thus triggered, causing the object to keep sliding up and down even though you are no longer interacting with it.
You can see this in action on the site I am developing here. Simply hover over the large image in the center to see the information div to appear.
Ideally what should happen is that while an animation is taking place no further actions should be queued.
Here is my current code:
$(document).ready(function(){
$(".view-front-page-hero").hover(
function() {
$hero_hover = true;
$('.view-front-page-hero .views-field-title').slideDown('slow', function() {
// Animation complete.
});
},
function() {
$hero_hover = false;
$('.view-front-page-hero .views-field-title').slideUp('slow', function() {
// Animation complete.
});
}
);
});
Create a global variable. When the animation starts. Clear it when it completes. Set a condition to exit the function if this variable is set before calling the animation.
This is probably not the best solution, but if you run stop(true, true) before the animation, it should work.
Live demo: http://jsfiddle.net/TetVm/
$(document).ready(function(){
var continue=true;
$(".view-front-page-hero").hover(
function() {
if(continue){
$('.view-front-page-hero .views-field-title').slideDown('slow', function() {
continue=false;
});
}
},
function() {
if(continue!){
$('.view-front-page-hero .views-field-title').slideUp('slow', function() {
continue=true;
});
}
}
);
});
//this will make your code work correctly...
I am trying to delay the default event or events in a jQuery script. The context is that I want to display a message to users when they perform certain actions (click primarily) for a few seconds before the default action fires.
Pseudo-code:
- User clicks link/button/element
- User gets a popup message stating 'You are leaving site'
- Message remains on screen for X milliseconds
- Default action (can be other than href link too) fires
So far, my attempts look like this:
$(document).ready(function() {
var orgE = $("a").click();
$("a").click(function(event) {
var orgEvent = event;
event.preventDefault();
// Do stuff
doStuff(this);
setTimeout(function() {
// Hide message
hideMessage();
$(this).trigger(orgEvent);
}, 1000);
});
});
Of course, this doesn't work as expected, but may show what I'm trying to do.
I am unable to use plugins as ths is a hosted environment with no online access.
Any ideas?
I would probably do something like this.
$("a").click(function(event) {
event.preventDefault();
doStuff(this);
var url = $(this).attr("href");
setTimeout(function() {
hideMessage();
window.location = url;
}, 1000);
});
I'm not sure if url can be seen from inside the timed function. If not, you may need to declare it outside the click handler.
Edit: If you need to trigger the event from the timed function, you could use something similar to what karim79 suggested, although I'd make a few changes.
$(document).ready(function() {
var slept = false;
$("a").click(function(event) {
if(!slept) {
event.preventDefault();
doStuff(this);
var $element = $(this);
// allows us to access this object from inside the function
setTimeout(function() {
hideMessage();
slept = true;
$element.click(); //triggers the click event with slept = true
}, 1000);
// if we triggered the click event here, it would loop through
// this function recursively until slept was false. we don't want that.
} else {
slept = false; //re-initialize
}
});
});
Edit: After some testing and research, I'm not sure that it's actually possible to trigger the original click event of an <a> element. It appears to be possible for any element other than <a>.
Something like this should do the trick. Add a new class (presumably with a more sensible name than the one I've chosen) to all the links you want to be affected. Remove that class when you've shown your popup, so when you call .click() again your code will no longer run, and the default behavior will occur.
$("a").addClass("fancy-schmancy-popup-thing-not-yet-shown").click(function() {
if ($(this).hasClass("fancy-schmancy-popup-thing-not-yet-shown"))
return true;
doStuff();
$(this).removeClass("fancy-schmancy-popup-thing-not-yet-shown");
var link = this;
setTimeout(function() {
hideMessage();
$(link).click().addClass("fancy-schmancy-popup-thing-not-yet-shown";
}, 1000);
return false;
});
Probably the best way to do this is to use unbind. Something like:
$(document).ready(function() {
$("a").click(function(event) {
event.preventDefault();
// Do stuff
this.unbind(event).click();
});
})
This might work:
$(document).ready(function() {
$("a").click(function(event) {
event.preventDefault();
doStuff(this);
setTimeout(function() {
hideMessage();
$(this).click();
}, 1000);
});
});
Note: totally untested