Prevent other functions running after selected function - javascript

I have a div #imageSwap and three buttons #button1, #button2, #button3. The first two buttons change the HTML of the div to hold a specific image, the third starts a rotation of multiple images.
For some reason, when the third (rotating) button is clicked it runs fine, but when the first or second button is clicked after the third, the animation runs when it shouldn't.
<script language="javascript" type="text/javascript">
$(document).ready(function () {
setImageOne();
$('#button1').addClass('selected');
$("a#button1").click(function() {
setImageOne();
$(this).addClass('selected');
$('#button2').removeClass('selected');
$('#button3').removeClass('selected');
});
$("a#button2").click(function() {
commObj();
$(this).addClass('selected');
$('#button1').removeClass('selected');
$('#button3').removeClass('selected');
});
$("a#button3").click(function() {
comProg();
$(this).addClass('selected');
$('#button1').removeClass('selected');
$('#button2').removeClass('selected');
});
});
function setImageOne() {
$('#imageSwap').fadeIn(500).html('<img src="slide1.png" />');
}
function commObj() {
$('#imageSwap').fadeIn(500).html('<img src="co.png" />');
}
function comProg() {
$('#imageSwap').fadeIn(500).html('<img src="bo2.png" />').delay(2000).fadeOut(500, function () { comProg2(); });
}
function comProg2() {
$('#imageSwap').fadeIn(500).html('<img src="bo2.png" />').delay(2000).fadeOut(500, function () { comProg3(); });
}
function comProg3() {
$('#imageSwap').fadeIn(500).html('<img src="bo2.png" />').delay(2000).fadeOut(500, function () { comProg4(); });
}
function comProg4() {
$('#imageSwap').fadeIn(500).html('<img src="bo2.png" />').delay(2000).fadeOut(500, function () { comProg(); });
}
</script>

That is because all your comProg functions have a callback function that calls a comProg function and because of that the animation will run every 2 seconds.
And btw you can write comProg2 instead of function () { comProg2(); } although all your comProg functions are same you could just use one function and use a callback that would call the same function instead of the next function which does the same thing...

check out jquery animation queue http://api.jquery.com/queue/

Add something like
$('#imageSwap').clearQueue();
in the callback handlers for button 1 and button 2 to stop the endless animation.
See http://api.jquery.com/clearQueue/

Related

Make a Testimonial Scroller Stay on the Screen Before Fading Out

I have a testimonial scroller that shows one testimonial, fades out, shows the next, fades out, and returns to the first.
My issue is that after the fade in animation, the fade out animation begins immediately. It doesn't give enough time for someone to read it.
$(document).ready(function() {
function doFade() {
$("#one").fadeIn(6000,function() {
$("#one").fadeOut(6000).delay(3000);
setTimeout(fadeTwo,6000);
});
}
function fadeTwo() {
$("#two").fadeIn(6000,function() {
$("#two").fadeOut(6000).delay(3000);
setTimeout(fadeThree,6000);
});
}
function fadeThree() {
$("#three").fadeIn(4000,function() {
$("#three").fadeOut(6000).delay(3000);
setTimeout(doFade,6000);
});
}
doFade();
});
jQuery's delay function will only delay functions that are called after it in the chain, so it is having no effect on your code. Delay docs
You need to use it before the call to fadeOut, e.g.
$(document).ready(function() {
function doFade() {
$("#one").fadeIn(6000,function() {
setTimeout(fadeTwo,6000);
})
.delay(3000)
.fadeOut(6000);
}
function fadeTwo() {
$("#two").fadeIn(6000,function() {
setTimeout(fadeThree,6000);
})
.delay(3000)
.fadeOut(6000);
}
function fadeThree() {
$("#three").fadeIn(6000,function() {
setTimeout(doFade,6000);
})
.delay(3000)
.fadeOut(6000);
}
doFade();
});
Edit:
You are currently setting a timeout to execute the next function, within the complete callback of fadeIn. This is a bit confusing to my mind, and I think it is simpler and clearer to do something like the following. In addition, there is no reason to define the three functions within the ready function - it is personal preference but I like to keep the amount of code within a callback to a minimum, such as...
$(document).ready(function() {
doFade();
});
function doFade() {
setTimeout(fadeTwo,12000);
$("#one").fadeIn(6000).delay(3000).fadeOut(6000);
}
function fadeTwo() {
setTimeout(fadeThree,12000);
$("#two").fadeIn(6000).delay(3000).fadeOut(6000);
}
function fadeThree() {
setTimeout(doFade,12000);
$("#three").fadeIn(6000).delay(3000).fadeOut(6000);
}
Edit 2:
In further effort to reduce the amount we repeat ourselves, we can extract the whole animation sequence into a function:
$(document).ready(function() {
doFade();
});
function fadeInThenOut(element) {
element.fadeIn(6000).delay(3000).fadeOut(6000);
}
function doFade() {
setTimeout(fadeTwo,12000);
fadeInThenOut($("#one"));
}
function fadeTwo() {
setTimeout(fadeThree,12000);
fadeInThenOut($("#two"));
}
function fadeThree() {
setTimeout(doFade,12000);
fadeInThenOut($("#three"));
}
Edit 3:
At this point we probably notice how similar our three functions are, and want some way to reduce that repetitiveness. So we could use recursion, and just change which element we pass in each time.
$(document).ready(function() {
doFade();
});
function doFade(elementNumber) {
const elementNumber = elementNumber < testimonialElements.length ? elementNumber : 0;
setTimeout(doFade(elementNumber + 1),12000);
$('#' + testimonialElements[elementNumber]).fadeIn(6000).delay(3000).fadeOut(6000);
}
var testimonialElements = ["one","two","three"];
While this solution may lose something in readability and simplicity, the great advantage is that when you add a fourth testimonial, you don't need to write a function to handle it. All you would do is change the testimonialElements array to include the new element id.

jQuery not hiding element before handler returns

I have some code that executes when a user clicks on a button. The first thing I want to do is hide the button and then run a function that takes a long time to run. The problem is that the button gets hidden only after the blocking function runs. There's a jsFiddle here and here's the code:
$(document).ready(function () {
$('#Test').click(function () {
$(this).hide();
console.log('button should be hidden');
LotsOfWork();
});
});
function LotsOfWork() {
for (var i = 0; i < 1000000000; i++) {}
}
As you can see in the Fiddle, the console shows the string but the button is still visible and only gets hidden after LotsOfWork() is done.
How can I change this so that the button gets hidden first?
That's a common issue, when you call hide() before the browser renders the changes applied to the DOM you have to wait for it to complete the js execution.
One solution is to use a setTimeout(myfunc,0); to delay the call of your slow function to the next cycle.
In this way the browser have the time to complete js execution, render the changes and execute your function on the next iteration.
$('#Test').click(function () {
$(this).hide();
console.log('button should be hidden');
setTimeout(LotsOfWork, 0);
});
Another solution is to use JQuery callback to handle it.
Use default callback in jquery it hides the button quickly and after callback the function LotsOfWork
$(this).hide('fast', function() { LotsOfWork() });
Fiddle
You should use .hiddens() "complete" option for this. Here I updated your code...
$(document).ready(function () {
$('#Test').click(function () {
$(this).hide({
complete: function () {
LotsOfWork();
}
});
console.log('button should be hidden');
});
});
function LotsOfWork() {
for (var i = 0; i < 1000000000; i++) {}
}
http://jsfiddle.net/g77Lyysp/2/
You could use .on() instead of click. This will allow you to manipulate dynamically generated elements.
$(document).ready(function () {
$('#Test').on('click', function() {
$(this).hide();
LotsOfWork();
});
});
function LotsOfWork() {
for (var i = 0; i < 1000000000; i++) {}
}
jsfiddle - http://jsfiddle.net/g77Lyysp/6/ - I've used setTimeout instead of a for loop to demonstrate lag between click and alert.

Alert button's inner content after clicking it

Please, help fix bug: the code currently alerts undefined instead of button's inner contents
function registerClickHandler() {
$('#clickme').click(function() {
setTimeout(function() {
alert(this.innerHTML);
}, 200);
});
}
this inside the timeout handler is not the button
function registerClickHandler() {
$('#clickme').click(function (e) {
setTimeout(function () {
alert(e.currentTarget.innerHTML);
}, 200);
});
}
Try to get the value before setTimeout
function registerClickHandler() {
$('#clickme').click(function () {
var value=this.innerHTML;
setTimeout(function () {
alert(value);
}, 200);
});
}
In java script this points to the last function and inside the timeout handler is not the button, thats why you are getting the error.
Also it's a good practice implement this kind of functions or onclicks using on.('click', function(){...})
below you can see my example:
$(document).ready(function(){
$('#clickme').on('click', function (e) {
setTimeout(function() {
alert(e.currentTarget.innerHTML);
}, 200);
});
});
You can take a look and run it here: http://jsfiddle.net/gon250/6qwk0g1t/1/
Try putting the click eventhandler outside the function. Also pass the value of 'this' to a variable before calling setTimout. Later use this variable inside setTimout. Read more about Javascrpt prototypes here
$(document).ready(function(){
$('#clickme').click(function() {
var me = this;
setTimeout(function() {
alert(me.innerHTML);
}, 200);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="clickme">click me</div>

Function becomes undefined after first trigger

I have a block of code like so:
function doSomething() {
someVar.on("event_name", function() {
$('#elementId').click(function(e) {
doSomething();
});
});
}
// and on document ready
$(function () {
$('#anotherElemId').click(function () {
doSomething();
});
});
The problem that I'm encountering is that when I call doSomething() from anotherElemId click event(that is binded on document ready) it works as expected, but calling it recursively from elementId click doesn't work.
Any ideas? Thinking is something trivial that I'm missing.
Is someVar an actual jQuery reference to a dom element? (e.g. $('#someitem'))
The second problem is you cant put a .click event inside a function that you would like to instantiate later on. If you are trying to only allow #elementId to have a click event AFTER some previous event, try testing if a tester variable is true:
var activated = false;
$(function () {
$('#anotherElemId').click(function () {
activated = true;
});
$('#secondElemId').on("event_name", function() {
if (activated) {
// code that happens only after #anotherElemId was clicked.
}
});
});

Using Jquery calling different functions with a singe link

I would like to use single a href link to call different functions .
On first click it should call first_function() and on second click it should call second_function. Like toggling between two functions using same link. Suggest the best way to be done.
Jquery Code :
$(function() {
var IntervalId;
function first_function() {
//code goes here
};
function second_function(){
//code goes here
}
$("#link2").click((function(){
second_function();
}));
$("#link1").click((function(){
first_function();
}));
});
Html Code :
Call function2
Call function1
"Like toggling between two functions using same link."
$("#link1").toggle(
function first_function() {
// Code goes here
},
function second_function(){
// Code goes here
}
);
From the jQuery docs on toggle(fn1, fn2, [fn3, [fn4, [...]]]):
Toggle among two or more function calls every other click.
Javascript:
$(document).ready(function() {
function first_function() {
// Code goes here
};
function second_function(){
// Code goes here
}
$("#link").toggle(first_function, second_function);
});
HTML:
<!-- I'm pretty sure that <a> isn't the right tag for this. -->
<button id="link">Toggle between the two functions.</button>
the easiest way would be
var performFirstAction = true;
$(function() {
function first_function() {
// Code goes here
}
function second_function(){
// Code goes here
}
$("#link1").click(function(){
if(performFirstAction) {
first_function(); performFirstAction = false; }
else {
second_function(); performFirstAction = true; }
});
});
or using toggle as Tomalak mention and well,
$(function() {
function first_function() {
// Code goes here
}
function second_function(){
// Code goes here
}
$("#link1").toggle(
first_function,
second_function
);
});

Categories

Resources