I am not sure what is wrong with my code here, I've set the variable global but the clear timeout is still not working here.
Thank you,
Kelvin
var myslide = null;
$(document).ready(function () {
var current = null;
$('ul#panel li a').click(function () {
stopAuto();
$('ul#panel li a').removeClass('active');
$(this).addClass('active');
current = $(this).attr('href');
$('#wrapperSlide').clearQueue();
$('#wrapperSlide').scrollTo($(current), 800);
return false;
});
if (current==null)
{
$("ul#panel li").each(function(i){
var counter1 = i+1;
var timer1 = counter1 * 5000;
myslide = setTimeout(function(){
setLoop1(counter1);
},timer1);
});
} else {
$('#wrapperSlide').clearQueue();
return false;
}
});
these are the functions for looping the slide images and stop auto
function setLoop1(counter)
{
var counter4 = counter;
var myID = $('a#'+counter4).attr('href');
$('ul#panel li a').removeClass('active');
$('a#'+counter4).addClass('active');
$('#wrapperSlide').scrollTo($(myID), 800);
}
//function to stop the auto slide
function stopAuto() {
clearTimeout(myslide);
}
You're starting those two timers for each separate <li> element:
$("ul#panel li").each(function (i) {
var counter1 = i + 1;
var myID = $('a#' + counter1).attr('href');
setLoop1(counter1, myID);
});
However, that setLoop1() function uses the same two variables. Each timer is distinct from the others, and the return value from setTimeout() is a distinct value each time you call it. You can't store a bunch of different numbers in a single simple variable.
What you should be doing is storing the timer in a jQuery "data" property on each <li> element. Then your "click" handler can cancel the timeout from that. Or, perhaps you don't need a separate pair of timer functions for each list item.
Two cases are here possible as I see, either the stopAuto() function is not being called or if its is being called, the stopAuto() function is undefined when it is called. So I would suggest to define the stopAuto() function before it is being called and use some debugger tool to see the console.
Related
var start = $('#start_img');
start.on('click', function(){
var piano = $('.piano');
piano.each(function(index){
$(this).hide().delay(700 * index).fadeIn(700*index);
start.off('click');
})
});
You can see that I have used the start.off('click') method, to stop the Event Listener from running again once it has been called. But the thing is, I only want the Event listener to be off during the time that the event is running. So that it cannot be called again while the event is still running. But once the event has finished, I want it to be 'callable' again. Does anyone know how t do this?
other way of doing this (doesn't work neither). Can anyone help me here. The other one is now clear.
var start = $('#start_img');
start.on('click', function() {
var q = 0;
var piano = $('.piano');
if (q === 1) {
return; // don't do animations
}
else{
piano.each(function(index) {
q = 1;
$(this).hide()
.delay(700 * index)
.fadeIn(700 * index, function() {
// remove from each instance when animation completes
q = 0
});
});}
});
You could toggle a class on active elements as well and then you can check for that class and not do anything if it exists
start.on('click', function() {
var piano = $('.piano');
if (piano.hasClass('active')) {
return; // don't do animations
}
piano.each(function(index) {
$(this).addClass('active')
.hide()
.delay(700 * index)
.fadeIn(700 * index, function() {
// remove from each instance when animation completes
$(this).removeClass('active')
});
});
});
For only one object, you could use a global variable for this, in my case, I'll be using isRunning:
var start = $('#start_img');
var isRunning = false;
start.on('click', function(){
if (!isRunning){
isRunning = true;
var piano = $('.piano');
piano.each(function(index){
$(this).hide().delay(700 * index).fadeIn(700*index, function(){
isRunning = false;
});
start.off('click');
});
}
});
This way your app shouldn't run the code until isRunning == false, which should happen after fadeIn is completed.
Syntaxes:
.fadeIn([duration] [,complete]);
.fadeIn(options);
.fadeIn([duration] [,easing] [,complete]);
For two or more objects, Charlietfl's answer should work perfectly.
Thank you in advance for your help with this.
I'm writing a click event that sets an active state on an element, and then after a couple seconds, removes the active state. This is working fine with the exception that there is some weird behavior happening if you click on the link a few times quickly in a row (menu opens and closes quickly, or doesn't show fully before closing again after a subsequent click). My guess is that clearTimeout really isn't clearing the timer quick enough (or not at all) the way I wrote this. The function is firing though so not sure what's going on with the odd behavior. Any help would be appreciated. My code is below. -Chris
$(document).on('click', '.toggle-edit-panel', function () {
var toggleEditPanelTimeout;
// resets timeout function
function resetEditPanelTimeout() {
clearTimeout(toggleEditPanelTimeout);
}
resetEditPanelTimeout();
// declares what this is and toggles active class
var $this = $(this);
var thisParent = $this.parent();
thisParent.find('.edit-panel').toggleClass('active');
$this.toggleClass('active');
toggleEditPanelTimeout = setTimeout(toggleEditPanelTimeoutFired($this), 2000);
// sets initial timeout function
function toggleEditPanelTimeoutFired(thisLinkClicked) {
toggleEditPanelTimeout = setTimeout(function(){
thisParent.find('.edit-panel').removeClass('active');
$(thisLinkClicked).removeClass('active');
},2000);
}
});
Solution below (Thanks Aroth!):
var toggleEditPanelTimeout;
$(document).on('click', '.toggle-edit-panel', function () {
// resets timeout function
clearTimeout(window.toggleEditPanelTimeout);
// declares what this is and toggles active class
var $this = $(this);
var thisParent = $this.parent();
thisParent.find('.edit-panel').toggleClass('active');
$this.toggleClass('active');
// sets initial timeout function
var theLink = $(this);
window.toggleEditPanelTimeout = setTimeout(function(){
$(theLink).parent().find('.edit-panel').removeClass('active');
$(theLink).removeClass('active');
},2000);
});
You've got a definite order-or-operations problem going on here (among other things):
var toggleEditPanelTimeout; //value set to 'undefined'; happens first
// resets timeout function
function resetEditPanelTimeout() {
clearTimeout(toggleEditPanelTimeout); //still undefined; happens third
}
resetEditPanelTimeout(); //value *still* undefined; happens second
// declares what this is and toggles active class
//...
//the value is assigned when this happens; happens fourth:
toggleEditPanelTimeout = setTimeout(toggleEditPanelTimeoutFired($this), 2000);
As a quick fix, you can simply make the variable global, and revise the code along the lines of:
clearTimeout(window.toggleEditPanelTimeout); //clear the previous timeout
// declares what this is and toggles active class
//...
//schedule a new timeout
window.toggleEditPanelTimeout = setTimeout(toggleEditPanelTimeoutFired($this), 2000);
You'll also likely want to remove that intermediate toggleEditPanelTimeoutFired(thisLinkClicked) function that you're using in order to get the code fully working. For instance:
//schedule a new timeout
var theLink = $(this);
window.toggleEditPanelTimeout = setTimeout(function(){
$(theLink).parent().find('.edit-panel').removeClass('active');
$(theLink).removeClass('active');
}, 2000);
I have a series of links with a class "bloglink".
They have a click event associated with them - but that is irrelevant at this point. I am trying to cycle through them and trigger the click event every X seconds. This is where I'm at:
$('a.bloglink').each(function(){
var $bl = $(this);
setInterval(function(){
$bl.trigger('click')
},2000);
})
But it just triggers the click event for all of them at once.
Any tips?
You could do something like this:
(function Loop(){
var arry = $("a.bloglink").get();
var traverse = function(){
$(arry.shift()).trigger('click');
if (arry.length)
setTimeout(traverse, 2000);
};
setTimeout(traverse,2000);
})();
You can see it in action here: http://jsfiddle.net/Shmiddty/B7Hpf/
To start it over again, you can just add an else case:
(function Loop(){
var arry = $("a.bloglink").get();
var traverse = function(){
$(arry.shift()).trigger('click');
if (arry.length)
setTimeout(traverse, 2000);
else
Loop(); // Do the whole thing again
};
setTimeout(traverse,2000);
})();
See here: http://jsfiddle.net/Shmiddty/B7Hpf/1/
Create a function that sets the timer to run your code, clears the timer, then calls itself on the next element...
function processNext($current)
{
$h = setInterval(function() {
$current.css('color', 'green');//do your business here
clearTimeout($h);
if ($current.next('a.blah').size()>0)
{
processNext($current.next('a.blah'));
}
}, 750);
}
processNext($('a.blah').eq(0));
See here: http://jsfiddle.net/skeelsave/6xqWd/2/
I was wondering if there is a function to be run after an element (e.g. div class="myiv") is hovered and check every X milliseconds if it's still hovered, and if it is, run another function.
EDIT: This did the trick for me:
http://jsfiddle.net/z8yaB/
For most purposes in simple interfaces, you may use jquery's hover function and simply store in a boolean somewhere if the mouse is hover. And then you may use a simple setInterval loop to check every ms this state. You yet could see in the first comment this answer in the linked duplicate (edit : and now in the other answers here).
But there are cases, especially when you have objects moving "between" the mouse and your object when hover generate false alarms.
For those cases, I made this function that checks if an event is really hover an element when jquery calls my handler :
var bubbling = {};
bubbling.eventIsOver = function(event, o) {
if ((!o) || o==null) return false;
var pos = o.offset();
var ex = event.pageX;
var ey = event.pageY;
if (
ex>=pos.left
&& ex<=pos.left+o.width()
&& ey>=pos.top
&& ey<=pos.top+o.height()
) {
return true;
}
return false;
};
I use this function to check that the mouse really leaved when I received the mouseout event :
$('body').delegate(' myselector ', 'mouseenter', function(event) {
bubbling.bubbleTarget = $(this);
// store somewhere that the mouse is in the object
}).live('mouseout', function(event) {
if (bubbling.eventIsOver(event, bubbling.bubbleTarget)) return;
// store somewhere that the mouse leaved the object
});
You can use variablename = setInterval(...) to initiate a function repeatedly on mouseover, and clearInterval(variablename) to stop it on mouseout.
http://jsfiddle.net/XE8sK/
var marker;
$('#test').on('mouseover', function() {
marker = setInterval(function() {
$('#siren').show().fadeOut('slow');
}, 500);
}).on('mouseout', function() {
clearInterval(marker);
});
jQuery has the hover() method which gives you this functionality out of the box:
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
},
function () {
// the element is no longer hovered... do stuff
}
);
To check every x milliseconds if the element is still hovered and respond adjust to the following:
var x = 10; // number of milliseconds
var intervalId;
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
intervalId = window.setInterval(someFunction, x);
},
function () {
// the element is no longer hovered... do stuff
window.clearInterval(intervalId);
}
);
DEMO - http://jsfiddle.net/z8yaB/
var interval = 0;
$('.myiv').hover(
function () {
interval = setInterval(function(){
console.log('still hovering');
},1000);
},
function () {
clearInterval(interval);
}
);
So I have an interval I create for each of my posts, the issue is that I load new posts and remove the old ones, so obviously I'd like to stop the interval for the previous posts. However I can't seem to figure out how to do this. Could someone explain to me how to properly go about doing this? I'm completely lost.
$(".post").each(function(){
myInterval = setInterval("postStats('"+$(this).attr('id')+"')", 500);
});
function postStats(pid) {
//do some stuff
}
$(".button").click(function(){
clearInterval(myInterval);
});
You can store the interval ID in a data attribute:
$(".post").each(function () {
var that = this;
var myInterval = setInterval(function () {
postStats(that.id);
}, 500);
$(this).data("i", myInterval);
});
and clear the interval specific to each .post like so:
$(".button").click(function () {
// assuming the button is inside a post
clearInterval($(this).closest(".post").data("i"));
});
and like SiGanteng said, you should pass a function object to setInterval rather than a string, which only gets eval'd.
You need to keep one handle for each interval that you start:
var myIntervals = [];
$(".post").each(function(){
var id = $(this).attr('id');
var handle = window.setInterval(function(){
postStats(id);
}, 500);
myIntervals.push(handle);
});
function postStats(pid) {
//do some stuff
}
$(".button").click(function(){
$.each(myIntervals, function(i, val){
window.clearInterval(val);
});
myIntervals = [];
});