setTimeout/pausing/ etc - javascript

I've tried a few different ways except the right one.
Trying this:
setTimeout( function() {
$('.historyTextBoxes p')
.bind('showText', function(e) {
$(this).fadeIn(800, function(){
$(this).next().length && $(this).next().trigger("showText");
});
}).eq(0).trigger('showText');
}, 4000);
Will wait for 4 seconds, then fade each paragraph in, one after another at the speed of .800 miliseconds.
What I want to do is fade a paragraph in at .800 ms, then wait for 4 seconds before the next paragraph fades in.
The basic set-up of:
$('.historyTextBoxes p')
.bind('showText', function(e) {
$(this).fadeIn(800, function(){
$(this).next().length && $(this).next().trigger("showText");
alert('pause here');
});
}).eq(0).trigger('showText');
works but I've yet to hit the right syntax to make it pause where the alert is.
I tried throwing a call to a function but I don't need to run anything except just to wait.
So in pseudo code, I'm trying to define something like:
function wait() {
pause(for 4 seconds);
}
Then I could just call that function instead of the alert above. My issues with setTimeout has been 'having' to define a function but I'm over thinking something.

Using setTimeout was correct, but you applied it in the wrong place.
$('.historyTextBoxes p').bind('showText',function(e) {
$(this).fadeIn(800,function(){
// this is the callback after the fadein
// here we want to wait (use a timeout)
var next = $(this).next();
if (next.length)
setTimeout(function() {
// before the next text is shown
next.trigger("showText");
}, 4000);
})
}).eq(0).trigger('showText');

This should do it:
function showAll() {
var p = $('.historyTextBoxes p').get(); // array of elements
(function loop() {
if (p.length) {
var el = p.shift();
$(el).fadeIn(800).delay(4000).promise().done(loop);
}
})();
}
demo at http://jsfiddle.net/4dNr3/2/
Note that this uses no explicit timers at all, and nor does it use any events to trigger the next phase - it relies on the animation queue for all timing. Note that it's not generally a good idea to mix timers and animation unless you can guarantee that they're interleaved rather than running in parallel. In this case that's OK, though.

Related

javascript/jquery loop execute function after every iteration

var dagaData = ['Manok', 'Pusa', 'Daga', 'Ibon', 'Aso'];
$('#clicktest').on('click', function() {
$.each(dagaData, function(index, item) {
executeData(item);
alert(item);
});
});
function executeData(item) {
var items = $("<div></div>").text(item);
$('#pangtest').append(items);
}
Is it possible to execute the function on every iteration?
Right now when I run the code above it finished all iteration before the append happen.
That why I've put alert to see if every alert append each iteration.
Output of code above: alert('Manok'), alert('Pusa') ,alert('Daga'), alert('Ibon'), alert('Aso') executed append.
What I'm trying to achieve is alert('manok') append, alert('Pusa') append, alert('Daga') append, alert('Ibon') append, alert('Aso') append.
Thanks in advance.
In a general sense, although the DOM is updated each time you call .append() the browser won't actually repaint the screen until after the entire JS function finishes. (Though some browsers will repaint at the point when an alert is open, which is why using alert() for debugging is a bad idea: it can subtly change the behaviour in a way that calling console.log() doesn't.)
You can work around this by using a setTimeout-based pseudo-loop - in between timeouts the browser then gets a chance to repaint:
var dagaData = ['Manok', 'Pusa', 'Daga', 'Ibon', 'Aso'];
$('#clicktest').on('click', function() {
var i = 0;
(function doNext() {
var item = dagaData[i];
executeData(item);
alert(item);
if (++i < dagaData.length)
setTimeout(doNext, 5);
})();
});
function executeData(item) {
var items = $("<div></div>").text(item);
$('#pangtest').append(items);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="clicktest">Test</button>
<div id="pangtest"></div>
Or just use your original $.each() loop with the contents of the loop wrapped in a timeout, as per Bnrdo's answer. But I prefer to wait to schedule each timeout only after the previous one is done because that way the order of execution is guaranteed.
Wrap them in setTimeout
$.each(dagaData, function(index, item) {
setTimeout(function() {
executeData(item);
alert(item);
}, 1);
});

clearInterval clearing two intervals

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.

Pausing function in javascript

I have a function which loops through rows in a table so that only one is shown at any given time.
I want to expand on this so that when I hover over the table, it shows all the rows, and then when I move away, it resumes showing one row at a time.
The Problem I have is that on hovering, the first function keeps going, is there a way to 'pause' the function. I've looked at various examples using ClearInterval(),but can't match them to my script.
//Calling The function that loops through the rows
function hideShow(time)
{
setInterval('showRows()',time);
};
//Set the time between each 'loop' and start looping
$(document).ready(function()
{
hideShow(2000);
}
);
//The hover function to show / hide all the rows
$(document).ready(function()
{
$('#dbTable1 tr').hover(function()
{
$('.Group td').removeClass('RoundBottom');
$('.Group').show();
},
function()
{
$('.Group td').addClass('RoundBottom');
$('.Group').hide();
}
);
}
);
Can anyone show me please how I can combine the two?
You need to keep track of the timer ID when you call setInterval:
var timerID;
function hideShow(time){
timerID = setInterval(showRows, time);
}
Then later on when you want to stop the repetition, call clearInterval and pass in that ID:
// ...
$('.Group td').removeClass('RoundBottom');
$('.Group').show();
clearInterval(timerID);
},
function()
{
hideShow(2000);
$('.Group td').addClass('RoundBottom');
// ...
You could just check the hovering state before doing anything else, like this:
function showRows() {
if (isHovering) {
return;
}
// ...
}
The isHovering variable is just a boolean with current hovering state, that could be set by your callback function.
With the above approach, you can set your timer only once and forget about it.

How to put a delay in loading of images in the same area to make it look like an animation?

Basically I have like 2 images, and I want to show one for 3 seconds, then replace it with another, in the same img tag.
This is what I have so far:
$(function(){
$("#image_area").hide();
$('#W40').click(function(){
$("#image_area img").remove();
show_image_area('40');
});
});
So the flow is first hide the #image_area, then when #W40 button is clicked, remove any current image in the area and run the show_image_area function, the function is as follows:
function show_image_area(world){
if (!$("#image_area img").length) { //only run if no current image exists
$('#image_area').show();
$('#image_area').prepend("<img id='tw_image' src='world+"/7.png' width=\"1000\" height=\"1030\" />");
setTimeout($("#tw_image").attr("src", "world+"/8.png"), 3000);
}
}
Right now, if I run these code, the 8.png shows almost immediately, and there are no 3 second delay that I wanted.
You have an extra " in the code: should be $("#tw_image").attr("src", world+"/8.png").
Also, I would put $("#tw_image").attr("src", world+"/8.png") in a function of it's own.
function SwapImage(world)
{
$("#tw_image").attr("src", world+"/8.png");
}
Then change your last line to setTimeout(SwapImage(world), 3000);
This isnt fully tested but gives you an idea:
$(function(){
$("#image_area").hide();
$('#W40').click(function(){
$("#image_area img").remove()
show_image_area('40');
});
});
function show_image_area(world){
var newImg = $('<img />').css({width: 1000, height: 1030}).attr({id: 'tw_image', src: world+'/7.png');
if ( !$("#image_area img").length ) { //only run if no current image exists
$('#image_area').prepend(newImg).show('fast');
setTimeout( function() {
$("#tw_image").attr("src", world+"/8.png");
}, 3000);
}
}
Basically yours was immediately firing the setTimeout function instead of passing in a function to be fired later
That's because the first parameter of setTimeout is not a function.
Also there is an extra quote on that line.
Also, the "world" variable might need closure (can't remember).
Try
function show_image_area(world){
if (!$("#image_area img").length) { //only run if no current image exists
$('#image_area').show();
$('#image_area').prepend("<img id='tw_image' src='world+"/7.png' width=\"1000\" height=\"1030\" />");
var myWorld = world;
setTimeout(function () {$("#tw_image").attr("src", myWorld+"/8.png");}, 3000);
}
}
Your setTimeout call is a bit off:
setTimeout($("#tw_image").attr("src", "world+"/8.png"), 3000);
The first argument should be the function to execute:
setTimeout(function() { $("#tw_image").attr("src", "world/8.png") }, 3000);
Also, I'm not sure what "world" is so I merged it into the new src path to fix a stray double quote.

How to block JQuery actions while a previous action is still taking place

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...

Categories