i'd like to include three image galleries on one page. one is running two are paused.
On event should the running gallery stop and the clicked one be running.
How do I bring the "return (function().." be stopped?
cheers
mate
var delay = 2500;
var start_frame = 0;
var container = "willkommen";
function fokus(container) {0.5
new Effect.Appear('willkommen', { duration:, to: 0.3 });
new Effect.Appear('eintreten', { duration:0.5, to: 0.3 });
new Effect.Appear('reservieren', { duration:0.5, to: 0.3 });
new Effect.Appear( container, { duration:1, to: 1 });
var lis = $(container).getElementsByTagName('li');
for( i=0; i < lis.length; i++){
if(i!=0){
lis[i].style.display = 'none';
}
}
end_frame = lis.length -1;
setTimeout(fadeInOut(container, start_frame, start_frame,end_frame, delay, lis), delay);
}
function fadeInOut(container, frame, start_frame, end_frame, delay, lis) {
return (function() {
lis = $(container).getElementsByTagName('li');
Effect.Fade(lis[frame]);
if (frame == end_frame) { frame = start_frame; } else { frame++; }
lisAppear = lis[frame];
setTimeout("Effect.Appear(lisAppear);", { duration:0.5, from:0.5, to:1 } );
setTimeout(fadeInOut(container, frame, start_frame, end_frame, delay), delay + 3500);
})
}
You need to store the timeout id returned from setTimeout and pass it into the clearTimeout function.
I'm not sure exacly how you're invoking the fokus function, but if you want it to encapsulate logic in multiple places on one page you should use it as a constructor function.
function Fokus (container) {
...
this.timeout_id = setTimeout(fadeInOut(container, start_frame, start_frame,end_frame, delay, lis), delay);
this.cancel = function () {
clearTimeout(this.timeout_id);
}
}
var gallery = new fokus("willkommen");
gallery.cancel();
There's not a whole lot of context given with your code, but it looks like you're using global variables for everything; I urge you to look into anonymous, self-executing closures to prevent global namespace pollution.
Related
I'm trying to cancel a requestAnimationFrame loop, but I can't do it because each time requestAnimationFrame is called, a new timer ID is returned, but I only have access to the return value of the first call to requestAnimationFrame.
Specifically, my code is like this, which I don't think is entirely uncommon:
function animate(elem) {
var step = function (timestamp) {
//Do some stuff here.
if (progressedTime < totalTime) {
return requestAnimationFrame(step); //This return value seems useless.
}
};
return requestAnimationFrame(step);
}
//Elsewhere in the code, not in the global namespace.
var timerId = animate(elem);
//A second or two later, before the animation is over.
cancelAnimationFrame(timerId); //Doesn't work!
Because all subsequent calls to requestAnimationFrame are within the step function, I don't have access to the returned timer ID in the event that I want to call cancelAnimationFrame.
Looking at the way Mozilla (and apparently others do it), it looks like they declare a global variable in their code (myReq in the Mozilla code), and then assign the return value of each call to requestAnimationFrame to that variable so that it can be used any time for cancelAnimationFrame.
Is there any way to do this without declaring a global variable?
Thank you.
It doesn't need to be a global variable; it just needs to have scope such that both animate and cancel can access it. I.e. you can encapsulate it. For example, something like this:
var Animation = function(elem) {
var timerID;
var step = function() {
// ...
timerID = requestAnimationFrame(step);
};
return {
start: function() {
timerID = requestAnimationFrame(step);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation = new Animation(elem);
animation.start();
animation.cancel();
timerID; // error, not global.
EDIT: You don't need to code it every time - that's why we are doing programming, after all, to abstract stuff that repeats so we don't need to do it ourselves. :)
var Animation = function(step) {
var timerID;
var innerStep = function(timestamp) {
step(timestamp);
timerID = requestAnimationFrame(innerStep);
};
return {
start: function() {
timerID = requestAnimationFrame(innerStep);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation1 = new Animation(function(timestamp) {
// do something with elem1
});
var animation2 = new Animation(function(timestamp) {
// do something with elem2
});
I'm trying to cancel a requestAnimationFrame loop, but I can't do it because each time requestAnimationFrame is called, a new timer ID is returned, but I only have access to the return value of the first call to requestAnimationFrame.
Specifically, my code is like this, which I don't think is entirely uncommon:
function animate(elem) {
var step = function (timestamp) {
//Do some stuff here.
if (progressedTime < totalTime) {
return requestAnimationFrame(step); //This return value seems useless.
}
};
return requestAnimationFrame(step);
}
//Elsewhere in the code, not in the global namespace.
var timerId = animate(elem);
//A second or two later, before the animation is over.
cancelAnimationFrame(timerId); //Doesn't work!
Because all subsequent calls to requestAnimationFrame are within the step function, I don't have access to the returned timer ID in the event that I want to call cancelAnimationFrame.
Looking at the way Mozilla (and apparently others do it), it looks like they declare a global variable in their code (myReq in the Mozilla code), and then assign the return value of each call to requestAnimationFrame to that variable so that it can be used any time for cancelAnimationFrame.
Is there any way to do this without declaring a global variable?
Thank you.
It doesn't need to be a global variable; it just needs to have scope such that both animate and cancel can access it. I.e. you can encapsulate it. For example, something like this:
var Animation = function(elem) {
var timerID;
var step = function() {
// ...
timerID = requestAnimationFrame(step);
};
return {
start: function() {
timerID = requestAnimationFrame(step);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation = new Animation(elem);
animation.start();
animation.cancel();
timerID; // error, not global.
EDIT: You don't need to code it every time - that's why we are doing programming, after all, to abstract stuff that repeats so we don't need to do it ourselves. :)
var Animation = function(step) {
var timerID;
var innerStep = function(timestamp) {
step(timestamp);
timerID = requestAnimationFrame(innerStep);
};
return {
start: function() {
timerID = requestAnimationFrame(innerStep);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation1 = new Animation(function(timestamp) {
// do something with elem1
});
var animation2 = new Animation(function(timestamp) {
// do something with elem2
});
I'm trying to work out how to make this counter work. After a certain amount of animations have played, I want to make the page refresh. I know my code sucks. I'm not educated in this and I'm very new, not to mention it being difficult to concentrate (to say the least) where I'm staying at the moment... so be nice. Here it is:
$(document).ready(function () {
function loop() {
var p = 0;
if (p = 3) {
location.reload(true);
} else {
$("#p3").delay("1000").fadeIn("slow");
$("#p3").delay("1000").fadeOut("slow", loop);
p + 1;
};
loop();
});
Your if (p = 3) statement is using the assignment operator = instead of the comparison operator === or ==. So p gets assigned to 3, the result of which is truthy, so the else statement is never executed.
Also your p variable is declared inside your loop() function, so it gets reset every time the function is called - you could move that declaration to just before the function (keep it inside the document ready handler: no need to make it global).
Also the line p + 1; doesn't do anything: it doesn't increment p because you'd need to assign the result back to p with p = p + 1, the shorthand for which is p += 1 or just p++.
Finally, your code as posted has a syntax error: you are missing the closing } from the loop() function. I would guess the intention is to end the function and then call it, so:
$(document).ready(function () {
var p = 0; // <--- moved outside function
function loop() {
if (p === 3) { // <-- changed = to ===
location.reload(true);
} else {
$("#p3").delay("1000").fadeIn("slow");
$("#p3").delay("1000").fadeOut("slow", loop);
p++; // <-- changed from p + 1
};
} // <--- this is the missing bracket
loop();
});
I've made some assumptions and written what I believe is what you want, code is un-tested.:
Change it to:
$(document).ready(function () {
var globalP = 0;
//this is called when fadeOut completes.
function fadeComplete() {
if (globalP == 3) {//if it is 3 reload..
location.reload(true);
} else {
globalP++;//increment counter
animate();//start animation again...
}
}
function animate() {
//start fading in...
$("#p3").delay("1000").fadeIn("slow", function() {
//start fading out when the fadeIn completes.
//should this happen? Since you're fading in the SAME element.
$("#p3").delay("1000").fadeOut("slow", fadeComplete);
});
};
animate();
});
First, I'm relatively new to both js and jQuery, so I apologize in advance if this is a really stupid question. That said, here it is:
I'm trying to create a cannon-like animation for a background that does a slow 'sweep-like' transition from one image to another.
The biggest issue I've been running into is ensuring that;
a. The increment counter is progressed and;
b. Each 'slice' of the image completes its fadeOut before the next begins.
If there's an easy (or obvious) way of doing this, I'd love to hear it. I've been pulling my hair out for a while now trying to figure out why these (and other similar variations) aren't working.
HTML:
img class="bg" (10 instances of this)
(function () {
// --- Variation 1 ---
function effect() {
var i = 0,
var current = $(".bg_1:eq(" + i + ")"),
arrLength = $(".bg_1").length;
while (i < arrLength) {
current.fadeOut(1000, 0);
i++;
}
}
effect();
// --- Variation 2 ---
function effect() {
var i = 0,
var current = $(".bg_1:eq(" + i + ")"),
arrLength = $(".bg_1").length;
while (i < arrLength) {
current.fadeOut(1000, 0, function () {
i++;
});
}
}
effect();
})();
I think it may be a problem with the scope of the 'i' variable, or a conflict in jQuery at that depth of scope. Any possible solutions would be GREATLY appreciated!
Thanks.
Without seeing your html, it's a bit hard to answer, but here's a general way to animate multiple elements in sequence:
(function _loop(idx) {
var $elements = $('#wrapper .bg'), idx = idx % $elements.length;
$elements.eq(idx).fadeIn('slow').delay(2500).fadeOut('slow', function () {
_loop(idx + 1);
});
}(0));
demo: http://jsfiddle.net/UU5AM/
Your var current will always be the same
try this:
function effect() {
var i = 0;
var arrLength = $(".bg_1").length;
while (i<arrLength) {
$(".bg_1:eq(" + i + ")").fadeOut(1000, 0);
i++;
}
}
effect();
Only now it will run as fast as the while loop goes. That means it will fade everything out almost immediately. You might want to run a setTimeout function for as long as the fadeOut goes:
var i = 0;
setTimeout(function(){
$(".bg_1:eq(" + i + ")").fadeOut(1000, 0);
i++;
}, 1000);
And ofcourse you will need to reset it when it reaches the end.
Edit:
Beat Richartz way, running the function again when the fadeOut is completed, is even better then the setTimeout.
You can use fadeOut's callback argument to provide it with a function which it will execute when the animation is completed. You can use this to raise the counter and (if necessary) animate the next element.
For example:
(function () {
function effect() {
var i = 0,
var current = $(".bg_1:eq(" + i + ")"),
arrLength = $(".bg_1").length;
var animateNext = function() {
current.fadeOut(1000, 0, function() {
i++;
if (i < arrLength) {
animateNext();
}
});
}
animateNext();
}
effect();
})();
As you can see, we've stored a reusable function in animateNext. We call it at the end of effect the first time to start the string of animation. After that, each next animation is started from the callback in fadeOut.
Your solutions are animating all the pictures at once. You have to install a recursive chain of events to do this:
// initial count value declared outside the function to not reinitialize
var count = 0;
function effect() {
// search the current image
var current = $(".bg_1:eq(" + count + ")");
// if there's an image, fade it out
if (current.length) {
current.fadeOut(1000, function() {
// increment the count;
count++;
// call the function recursively
effect();
});
}
}
// call the function
effect();
See it working with the JSFiddle here
I have this code which works ok but I would like to stop polling and clearInterval if the user is inactive (no mouse move) after say 5 iterations rather than be in a continuous loop.
var i, active = new Date, iter = 1;
$(window).on('mousemove', function(e){
active = new Date;
});
i = setInterval(function(){
if(new Date().getTime() - active.getTime() < 1000){
console.log("sending active event to server.....");
iter = 1;
else{
iter++;
if(iter >= 5){
clearInterval(i);
}
}
}, 2000);
right now it checks every two seconds in this example. I would like to check the active date say 5 times and if its expired 5 iterations in a row, call clearInterval(i)... so something inside the mousemove callback should reinitialize the setInterval only if it's currently not running. How can I accomplish this? Thanks for any tips and samples. I'd like to keep using an anonymous function if possible.
Seperate the Interval function
function intFunc(){
if(new Date().getTime() - active.getTime() < 1000){
console.log("sending active event to server.....");
iter = 1;
else{
iter++;
if(iter >= 5){
clearInterval(i);
}
}
};
Now, call them on the two places you need
var i;
$(window).on('mousemove', function(e){
active = new Date;
i = setInterval(intFunc, 2000);
});
i = setInterval(intFunc, 2000);
One simple way would just be to remove the clearInterval call, and instead only poll the server when iter < 5.
But that's still a little wasteful, as the handler is still being called when it has nothing to do, which is bad when you want your laptop/phone to stay in powersaving mode. So what I'd do is basically what you have, but after calling clearInterval, set up a one-time mousemove handler that restarts polling.
I'm not seeing a way to do that without naming a function (I'm presuming you don't want to get into Y-combinators and the like), but you can hide its name – and the others – from the outside world by using an anonymous function around the whole thing:
(function () {
var i, active = new Date, iter = 1;
$(window).on('mousemove', function(e) {
active = new Date;
});
function startPolling() {
i = setInterval(function() {
if (new Date().getTime() - active.getTime() < 1000) {
console.log("sending active event to server.....");
iter = 1;
}
else{
iter++;
if (iter >= 5) {
clearInterval(i);
$(window).one('mousemove', function () {
startPolling();
});
}
}
}, 2000);
}
startPolling();
})();