jquery animation repeated several times - javascript

I have a problem with the animation. Here is my code:
<html>
<head>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.9.1.js'></script>
<title>title</title>
<style>
div{
width: 100px;
height: 100px;
background-color: green;
position:relative;
left: 0px;
}
</style>
</head>
<body>
<h1>Animation</h1>
<select id='text_1' type="text">
<option>100</option>
<option>200</option>
<option>300</option>
<option>400</option>
<option>500</option>
<option>600</option>
<option>700</option>
<option>800</option>
<option>900</option>
<option>1000</option>
</select>
<button>Animate Div</button><br/><br/>
<div></div>
<script>
$(document).ready(function(){
var number = 500;
$('#text_1').bind('change', function(){
var number_2 = $('#text_1').val() != '' ? $('#text_1').val() : 500;
animation(number_2);
});
animation(number);
});
function animation(num){
$('button').click(function(){
$('div').animate({
'left': num+'px',
}, 1000).animate({
'left': '0px',
}, 1000);;
});
}
</script>
</body>
</html>
When I change select option (example: 300) and click the button, then does a two animations.
when I change select option again, then does a tree animations.
What is wrong. Please help.

This isn't the most elegant solution, but if you modify your code to look like this:
function animation(num) {
$('button').unbind('click'); //this removes the old click event
$('button').click(function(){
....
}
}
then that should solve your problem.

Try
$(document).ready(function()
{
$('button').on('click',function()
{
var num = $('#text_1').val() != '' ? $('#text_1').val() : 500;
$('div').animate(
{
'left': num+'px',
}, 1000).animate(
{
'left': '0px',
}, 1000);
});
});

It might not matter for this, but you should learn how to use a Javascript debugger, like Firebug, if that might give you a clue.
If you used a debugger, and you set a breakpoint inside the "click" function, you'd see it getting hit multiple times, adding up to the number of times you've changed the option dropdown. I'm guessing that's because your "animation()" function is binding a NEW function to the "click" event every time it's called, and not removing the previous ones, so clicking the button will execute the "click" function multiple times.

This is what you probably meant
$(document).ready(function(){
var number = 500;
$('button').click(function(){
$('div').stop().animate({
'left': number+'px',
}, 1000).animate({
'left': '0px',
}, 1000);
});
$('#text_1').bind('change', function(){
number = $('#text_1').val() != '' ? $('#text_1').val() : 500;
});
});
otherwise you are binding the click event to the button every single time you animate which becomes the problem. The first time the click is binded once, so it animates once, then you animation binds to click again, so it animates twice. Also notice the stop() which causes the div to stop what it is doing and start a new animation to prevent stuff where you click the button multiple times and it keeps animating for several seconds.

You're binding the click event multiple times.
Change it to this:
$('button').off('click').on('click', function(){
$('div').animate({
'left': num+'px',
}, 1000).animate({
'left': '0px',
}, 1000);;
});
Keep in mind .off and .on replaced .bind and .unbind
Also, it's better for performance reasons to chain functions like this.

Related

Issue with .mouseleave() and .mouseenter()

I use .mouseenter() and .mouseleave() to make an animation to my button.The problem is that when I move my cursor across the button multiple times it keeps repeating the animation .For .mouseenter() I want it to complete the animation once the cursor keeps hovering over it till the animation time is complete and if it leaves the button before the animation is complete the animation should stop.For .mouseleave() the animation should stop if the cursor hovers over it before the animation is complete.
$(document).ready(function(){
$('#button').mouseenter(function(){
$(this).animate({backgroundColor:'#ffce00',width:'+=1em'},100);
});
$('#button').mouseleave(function(){
$(this).animate({backgroundColor:'#1e7989',width:'-=1em'},100);
});
});
#button{
width:100px;
height:50px;
background-color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//cdn.jsdelivr.net/jquery.color-animation/1/mainfile"></script>
<div id="button"></div>
You can use flags for entering and leaving. Then check the appropriate flag, and finish the current animation when an enter/leave event occurs, something like this:
$(document).ready(function () {
var isEntering = false, // Create flags
isLeaving = false;
$('#button').mouseenter(function () {
isEntering = true; // Set enter flag
if (isLeaving) { // Check, if leaving is on process
$(this).finish(); // If leaving, finish it
isLeaving = false; // Reset leaving flag
}
$(this).animate({
backgroundColor: '#ffce00',
width: '+=1em'
}, 100);
});
$('#button').mouseleave(function () {
isLeaving = true; // Set leave flag
if (isEntering) { // Check if entering is on process
$(this).finish(); // If it is, finish it
isEntering = false; // Reset enter flag
}
$(this).animate({
backgroundColor: '#1e7989',
width: '-=1em'
}, 100);
});
});
A live demo at jsFiddle.
Try adding .stop(), it will stop the animations from queueing.
$(document).ready(function(){
$('#button').mouseenter(function(){
$(this).stop().animate({backgroundColor:'#ffce00',width:'+=1em'},100);
});
$('#button').mouseleave(function(){
$(this).stop().animate({backgroundColor:'#1e7989',width:'-=1em'},100);
});
});
Regards,
Gados
If you only want it to run one time you can unbind it after the event fires:
$(document).ready(function(){
$('#button').mouseenter(function(){
$(this).animate({backgroundColor:'#ffce00',width:'+=1em'},100);
$(this).unbind('mouseenter');
});
$('#button').mouseleave(function(){
$(this).animate({backgroundColor:'#1e7989',width:'-=1em'},100);
$(this).unbind('mouseleave');
});
});

jquery click event lost after blur

I have a textarea field that I would like to have expand when it gains focus, and to contract back when it loses focus. Here is my test code:
$(function() {
var rows = parseInt(
$('textarea[name=details]').attr('rows')
);
$('textarea[name=details]').focus(function() {
$(this).animate({ rows: rows + 10 }, 250);
}).blur(function(e) {
$(this).animate({ rows: rows }, 250);
});
});
fiddle:
http://jsfiddle.net/p0t1pzh7/3/
The problem is when the textarea has focus, and the user clicks on another input element.
The textarea collapses back in this case, but the click event appears to be lost.
What I believe is happening, is the blur() handler is changing the page such that the target of the click changes position. Since blur runs before click, the click is in fact happening, but because the target has moved position, the click is no longer hitting an element. This is on Chrome 37.0.2062.120 under Linux.
The reason I think that, is if you comment out the resizing of the textarea in the blur handler, everything works as intended.
fiddle: http://jsfiddle.net/p0t1pzh7/4/
I've googled and searched SO for related issues and did find several discussions on the ordering of the blur and click events. Generally, solutions seemed to involve either adding a delay on the blur() action, or binding events on the other page element to keep track of what is occurring.
Both of those approaches seen rather fragile and error-prone. This behavior is really just a nicety, so if there's no "clean" way to do it, I'd rather just drop it altogether.
For reference, the delay approach does work, as can be seen in this fiddle:
http://jsfiddle.net/p0t1pzh7/5/
And I understand why blur is triggered before click, but found it surprising that the target of the click event isn't "set" prior to blur being triggered. Is that expected behavior or does this vary between browsers?
You may use setTimeout function:
$('textarea[name=details]').focus(function() {
$(this).animate({ rows: rows + 10 }, 250);
}).blur(function(e) {
setTimeout(function(){
$(this).animate({ rows: rows }, 250);
}.bind(this),400);
demo
Try this solution
$(window).load(function () {
$('textarea.expand').focus(function () {
$(this).addClass("expanding")
$(this).animate({
height: "10em"
}, 500);
});
$('textarea.expand').blur(function () {
$(this).animate({
height: "1em"
}, 500);
// $(this).removeClass("expanding")
});
});
<table>
<tr>
<td>
<textarea class="expand" rows="1" cols="10"></textarea>
</td>
</tr>
<tr>
<td>Here is some text just below. Does it move?</td>
</tr>
</table>
.expand {
height: 1em;
line-height: 1em;
width: 300px;
padding: 3px;
}
.expanding {
position: absolute;
z-index: 9;
}
textarea {
resize: none;
}
Here is a solution that works without using any timeouts. See http://jsfiddle.net/29sw1abb/
HTML:
<textarea name="details" rows="5"></textarea>
<p>
click me
</p>
JS
$(function() {
var target = undefined;
var rows = parseInt(
$('textarea[name=details]').attr('rows')
);
$('textarea[name=details]').focus(function() {
$(this).animate({ rows: rows + 10 }, 250);
}).blur(function(e) {
$(this).animate({ rows: rows }, 250);
});
$('.button').mousedown( function (e){
target = $(e.target).attr('class');
});
$(document).mouseup( function (e){
if (target) {
alert(target);
target = undefined;
}
});
});
I beleive you are correct in assuming the original click event is not firing because the target area moves out of position before the event can be evaluated. 'mousedown' seems to evaluate before the blur so we can capture the click target info with 'mousedown' and then action the event on 'mouseup'. Having larger targets, less dramatic animation and or slower animation also solves this issue.
Introducing a delay works:
$(function() {
var rows = parseInt(
$('textarea[name=details]').attr('rows')
);
$('textarea[name=details]').focus(function() {
if (typeof(toDetails) != "undefined") { clearTimeout(toDetails); }
$(this).animate({ rows: rows + 10 }, 250);
}).blur(function(e) {
toDetails = setTimeout(function() { $(this).animate({ rows: rows }, 250); }.bind(this), 250);
});
});

change jquery.animate depending on the value

When button.btn is clicked, div.img-box will move with animation.
I'd like to change the animation depending on the place of div.img-box.
First I click the button, it moves collectly.
Second I click, the image whose margin-right is now 10px does not move.
I have this code.
js
$(function(){
var mr = parseInt($('.img-box').css('margin-right'), 10);
$(".btn").click(function(){
if (mr == 10) {
$(".img-box").animate( { marginRight: '300px' }, 'slow' );
} else {
$(".img-box").animate( { marginRight: '10px' }, 'slow' );
};
});
});
html
<button class="btn"></button>
<div class="img-box"><img src="xxx.png"></div>
css
.img-box{
float: right;
width: 250px;
height: 350px;
margin: 200px 25%;
}
How do I fix it?
You need to put var mr = parseInt($('.img-box').css('margin-right'), 10); inside the click() function.
$(function(){
$(".btn").click(function(){
var mr = parseInt($('.img-box').css('margin-right'), 10);
if (mr == 10) {
$(".img-box").animate( { marginRight: '300px' }, 'slow' );
} else {
$(".img-box").animate( { marginRight: '10px' }, 'slow' );
};
});
});
JSFiddle
Your anonymous function is called only once, so that "mr" is only calculated once, so that when the function to attached to your button is called, it's using a global variable that was set to 200. even after it moves, the mr variable is still 200, because you never updated the variable.
imtheman seems to have answered this as i was typing this out, but he's right, put the mr variable definition in the function so that it's calculated every time the button is clicked, rather than one time when the javascript is run.

Jquery Timer Slide function

Right now I have a div that slides right to left and then vice versa back to its original place. But overall its not really how I want it to work. My main goal: is for the user to hover over the main div which will then pull out the sliding div. The part that gets tricky is the following: If the user forgets to slide the dive back, I want to give it time frame that will cause it to close automatically after a certain time has passed. Here is my working code so far: jsfiddle.net/eMsQr/14/.
My JavaScript function:
$(document).ready(function() {
$("#arrow").hover(
function(){
$("#inner").stop().animate({marginRight: "0px", opacity: "1px", height: "100px"}, 500 );
},
function(){}
);
});
$("#arrow").click(function(e){
$("#inner").stop().animate({marginRight: "-100px", opacity: "1px", height: "100px"}, 500 );
});
Try this: http://jsfiddle.net/vansimke/cJ5pf/
I hooked into the mouseleave event and added a setTimeout. You might need to catch the timeout if you need to cancel it later (i.e. they reenter the arrow)
Here's a jsFiddle example that sets a 3 second delay via the setTimeout function.:
jQuery
var cto;
$("#arrow").hover(
function() {
clearTimeout(cto);
$("#inner").stop().animate({
marginRight: "0px",
opacity: "1px",
height: "100px"
}, 500);
}, function() {
cto = setTimeout(function(){$('#arrow').trigger('click')}, 3000);
});
$("#arrow").click(function(e) {
$("#inner").stop().animate({
marginRight: "-100px",
opacity: "1px",
height: "100px"
}, 500);
});​
Note that if the user moves his mouse away and then returns it to the div, the box remains open again until they leave at which point the 3 second countdown timer begins.
You need to make sure you utilize the second function() in jQuery's hover method.
At the moment you're only animating your slide-out div when the user hovers over the main div. You want it to also animate on hover out.
Here's the updated jsFiddle.
Inside the hover function you can add an additional line to trigger the click event using the below line:
setTimeout(function() { $("#arrow").trigger('click'); }, 5000);
the 5000 is the number of milliseconds to wait before triggering the click.
see the fiddle here: http://jsfiddle.net/eMsQr/51/
it uses the mouseleave jquery and also delay. Change the value in the delay to get the time you want.
$("#arrow").mouseleave(function(){
$("#inner").stop().delay(500).animate({marginRight: "-100px", opacity: "1px", height: "100px"}, 500 );
});
You need to use setTimeout() to set the delay to closing the div. You also need to use clearTimeout() in the opening function to stop it auto closing if someone mousesout, then back over again:
var timeout;
$("#arrow").hover(
function() {
clearTimeout(timeout); // clear the timer which will close the div, as we now want it open
$("#inner").stop().animate({
marginRight: "0px",
opacity: "1px",
height: "100px"
}, 500);
}, function() {
timeout = setTimeout(function() {
$("#inner").stop().animate({
marginRight: "-100px",
opacity: "1px",
height: "100px"
}, 500);
}, 1000); // close the open div 1 second after mouseout.
}
);
Example fiddle

Simple example of a strange problem with jquery toggle

I'm trying to do a simple partial fade effect using toggle to toggle the opacity between two values, when an element is clicked. But the first click does nothing!
The html code:
<html>
<head>
<script type="text/javascript" src="../jquery-1.4.min.js"></script>
<script type="text/javascript" src="toggle.js"></script>
</head>
<body>
<div class="toggler" style="background:grey;width:300px;height:300px;"></div>
</body>
</html>
And the js code:
$(document).ready(function() {
$('div.toggler').click(function(event) {
$(this).unbind('click');
$('div.toggler').toggle(function(event) {
$('div.toggler').css({
'opacity': 0.5
});
alert('0.5');
return false;
}, function() {
$('div.toggler').css({
'opacity': 0.1
});
alert('0.1');
return false;
});
event.preventDefault();
});
});
To elaborate, it does "work", but only after the first click! So I need to click twice to begin with to get it working! I've tried this out in firefox and opera.
Edit: Went with the solution by Marcus Sá and steweb:
$('div.toggler').toggle(
function(event){
$(this).css({ 'opacity':0.5 });
alert('0.5');
return false;
},
function(){
$(this).css({ 'opacity':0.1 });
alert('0.1');
return false;
}
);
Try this, more simple:
$('div.toggler').toggle(
function(event){
$('div.toggler').css({ 'opacity':0.5 });
alert('0.5');
return false;
},
function(){
$('div.toggler').css({ 'opacity':0.1 });
alert('0.1');
return false;
}
);
See working here
Because you bind to click event once, then unbind, and bind to it again via toggle. What for ? Just use toggle. Here is working example.
Even easier without having to use toggle:
$('div.toggler').css('opacity', .5).click( function() {
$(this).css('opacity', $(this).css('opacity') == .5 ? .1 : .5);
});
Actually there is not enough info here, the problem COULD be that your CSS initially sets the opacity to 0.5 to start with, so when you click toggle first, it's already at 0.5 and so it switches from 0.5 to 0.5 and nothing happens.
What I would recommend doing instead is creating 2 css tags, then check which tag is already there and replace it with the other one.
i.e. you can create:
.fiftyPercent{ opacity:0.5; }
.tenPercent{ opacity:0.1; }
Then in your html start with
<div class="toggler fiftyPercent" style="background:grey;width:300px;height:300px;"></div>
Then all you have to do in your JS is toggleClass for both the classes on click.
$('.toggler').click(function(){
$('.toggler').toggleClass('fiftyPercent');
$('.toggler').toggleClass('tenPercent');
});
That's just my 2 cents.

Categories