jquery continuous animation on mouseover - javascript

I am trying to have an animation run only when the mouse is over an object. I can get one iteration of the animation and then have it set back to normal on mouse out. But I'd like the animation to loop on mouseover. How would I do it, using setInterval? I'm a little stuck.

It could be done like this:
$.fn.loopingAnimation = function(props, dur, eas)
{
if (this.data('loop') == true)
{
this.animate( props, dur, eas, function() {
if( $(this).data('loop') == true ) $(this).loopingAnimation(props, dur, eas);
});
}
return this; // Don't break the chain
}
Now, you can do this:
$("div.animate").hover(function(){
$(this).data('loop', true).stop().loopingAnimation({ left: "+10px"}, 300);
}, function(){
$(this).data('loop', false);
// Now our animation will stop after fully completing its last cycle
});
If you wanted the animation immediately stop, you could change the hoverOut line to read:
$(this).data('loop', false).stop();

setInterval returns an id that can be passed to clearInterval to disable the timer.
You can write the following:
var timerId;
$(something).hover(
function() {
timerId = setInterval(function() { ... }, 100);
},
function() { clearInterval(timerId); }
);

I needed this to work for more then one object on the page so I modified a little Cletus's code :
var over = false;
$(function() {
$("#hovered-item").hover(function() {
$(this).css("position", "relative");
over = true;
swinger = this;
grow_anim();
}, function() {
over = false;
});
});
function grow_anim() {
if (over) {
$(swinger).animate({left: "5px"}, 200, 'linear', shrink_anim);
}
}
function shrink_anim() {
$(swinger).animate({left: "0"}, 200, 'linear', grow_anim);
}

Consider:
<div id="anim">This is a test</div>
with:
#anim { padding: 15px; background: yellow; }
and:
var over = false;
$(function() {
$("#anim").hover(function() {
over = true;
grow_anim();
}, function() {
over = false;
});
});
function grow_anim() {
if (over) {
$("#anim").animate({paddingLeft: "100px"}, 1000, shrink_anim);
}
}
function shrink_anim() {
$("#anim").animate({paddingLeft: "15px"}, 1000, grow_anim);
}
You can achieve this using timers too.

Related

How to know that which animation is currently running on an element using jquery or javascript

Please tell what should be code for know_anim() function to know the current animation executing on '#div' element.
jsFiddle link:https://jsfiddle.net/himavicii/bL0nsjeL/
function l()
{
$('#div').animate({'left':'20px'},10000);//1st animation queued after 1sec
}
function r()
{
$('#div').animate({'top':'100px'},10000);//after 2sec this animation queued
}
setTimeout(function(){l();},1000);
setTimeout(function(){r();},2000);
function know_anim()
{
//Code to detect which animation is currently executing at
the time of call to this function
}
Probably the easiest and most straightforward way would be to set a data attribute on your div when the animation starts and remove it when the animation ends. Then you can just check that attribute to see which animation is currently running on that div at any given time.
Check this updated jsfiddle: https://jsfiddle.net/bpursley/hq6bn1fs/
html:
<body>
<div id="div"></div>
<div id="output"></div>
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
</body>
and javascript:
$(function(){
function l()
{
$('#div').animate({ left: '200px' },
{
duration: 5000,
start: function() { $(this).data('animation', 1); },
complete: function() { $(this).removeData('animation'); }
});
}
function r()
{
$('#div').animate({ top: '100px' },
{
duration: 5000,
start: function() { $(this).data('animation', 2); },
complete: function() { $(this).removeData('animation'); }
});
}
function know_anim() {
return $('#div').data('animation');
}
setTimeout(function(){l();},1000);
setTimeout(function(){r();},2000);
setInterval(function() { $('#output').text('animation is currently ' + know_anim()); })
});
Here a solution which works for animations running concurrently too. The start and done callbacks you can set in the options are used to edit a global object (actualAnimations).
var actualAnimations = {};
function l()
{
$('#div').animate({'left':'20px'},
{
duration: 10000,
start: function(){actualAnimations['l'] = true;},
done: function(){delete actualAnimations['l'];},
queue: false
});//1st animation queued after 1sec
}
function r()
{
$('#div').animate({'top':'100px'},
{
duration: 10000,
start: function(){actualAnimations['r'] = true;},
done: function(){delete actualAnimations['r'];},
queue: false
});///after 2sec this animation queued
}
setTimeout(function(){l();},1);
setTimeout(function(){r();},3000);
function know_anim()
{
//Code to detect which animation is currently executing at
console.log(actualAnimations);
$('#anims').text(JSON.stringify(actualAnimations));
}
setInterval(know_anim, 100);
<script src="https://code.jquery.com/jquery-2.2.3.js"></script>
<div style="position: absolute; left: 50px; top:20px;">
<div id="div" style="position: relative; left: 50px;">animated div</div>
</div>
<div>
Actual animation: <span id="anims"></span>
</div>
You may have to declare a global function to check which animation is running.
check this updated fiddle https://jsfiddle.net/bL0nsjeL/3/
$(function() {
var anims = {
l: false,
r: false
}
function l() {
anims.l = true
$('#div').animate({
'left': '200px'
}, 5000, function() {
anims.l = false
}); //1st animation queued after 1sec
}
function r() {
anims.r = true
$('#div').animate({
'top': '100px'
}, 5000, function() {
anims.r = false
}); //after 2sec this animation queued
}
setTimeout(function() {
l();
}, 1000);
setTimeout(function() {
r();
}, 2000);
function know_anim() {
return anims;
}
});
when you fire know_anim() you will get an object which will have true for whichever or animation is currently running

Javascript blinking with setTimeouts

Helllo i am getting problem with blinking every 0.5 seconds. I start my code with #blink display= "inline" but it always stays inline. When starting my code, i call startBlinking.
function startBlinking() {
setInterval(function () {
blink();
}, 1000);
}
function blink() {
setTimeout(function () {
document.getElementById('blink').style.display = "none";
}, 500);
setTimeout(function () {
document.getElementById('blink').style.display = "inline";
}, 500);
}
Can you help me? Thanks.
The problem with your attemt is that you're setting the same timeout length for both hiding and showing the element, meaning it will hide and show again at the same time! Remove one and it should work:
function startBlinking() {
setInterval(function () {
blink();
}, 1000);
}
function blink() {
// note no timeout for the hiding part
document.getElementById('blink').style.display = "none";
setTimeout(function () {
document.getElementById('blink').style.display = "inline";
}, 500);
}
startBlinking();
<div id="blink">blink</div>
<p>some text following</p>
As you can tell, this causes the following content to jump. We are also fetching the element every time we're hiding or showing it. Better to swap to using visibility and make the function a bit more flexible:
function blink(element, time) {
// using visibility: hidden; instead of display: none;
// allows the element to keep its rendering space
element.style.visibility = "hidden";
setTimeout(function () {
element.style.visibility = "visible";
}, time);
setTimeout(function () {
blink(element, time); // recurse
}, time * 2);
}
// query the DOM for element once instead of every iteration
blink(document.getElementById("blink"), 500);
<div id="blink">blink</div>
<p>following content stays put</p>
You might also want to be able to stop the blinking at some point
function blink(element, time) {
function loop(){
element.style.visibility = "hidden";
setTimeout(function () {
element.style.visibility = "visible";
}, time);
timer = setTimeout(function () {
loop();
}, time * 2);
cleared = false;
}
var timer, cleared = true;
// expose methods
return {
start: function() {
if (cleared) loop();
},
stop: function() {
clearTimeout(timer);
cleared = true;
}
};
}
var blinking = blink(document.getElementById("blink"), 500);
document.getElementById("start").addEventListener("click", function(){
blinking.start();
});
document.getElementById("stop").addEventListener("click", function(){
blinking.stop();
});
<div id="blink">blink div</div>
<button id="start">start blinking</button><br />
<button id="stop">stop blinking</button>
you can make it simple by toggling a class
.hide{
display:none;
}
setInterval(function () {
$('.blink').toggleClass('hide')
}, 500);
JS Fiddle
Just call it once, setTimeout() is ripping it out of the thread so it gets set right back to inline.
function blink() {
setTimeout(function () {
if (document.getElementById('blink').style.display === 'inline') {
document.getElementById('blink').style.display = "none";
} else {
document.getElementById('blink').style.display = "inline";
}
}, 500);
}
you have messed up the event que of javascript, why dont you try this
function startBlinking() {
initial = 'inline';
index = 0;
setInterval(function () {
if(index==2){
initial = (initial=='none')?'block':'none';
document.getElementById('blink').style.display = initial;
index=0;
}
index++;
}, 1000);
}
For the jQuery fans:
you can use the 'pulsate' effect
http://jqueryui.com/effect/
This may or may not achieve the exact blinking you need but it's a lot simpler!

Why won't Javascript code work after moving it from html to an external js file?

I have this Javascript code that was working perfectly fine in my HTML. When I moved it to my main.js it suddenly stopped working.
Disclaimer: I am very new to jQuery and Javascript, so sorry if it is really obvious.
var infoVisible = false,
buyVisible = false;
function closeAllProductInfo() {
$('#info').css({visibility: 'hidden'});
$('#buy').css({visibility: 'hidden'});
$('#options.info a').removeClass('active');
$('#options.buy a').removeClass('active');
infoVisible = false;
buyVisible = false;
imagesVisible = false;
}
function openProductInfo() {
closeAllProductInfo();
$('#info').css({visibility: 'visible', opacity: 0});
$('#info').animate({opacity: 1}, 250);
$('#options.info a').addClass('active');
infoVisible = true;
}
function openProductBuy() {
closeAllProductInfo();
$('#buy').css({visibility: 'visible', opacity: 0});
$('#buy').animate({opacity: 1}, 250);
$('#options.buy a').addClass('active');
buyVisible = true;
}
$('.info').click(function() {
if (infoVisible) {
$('#info').animate({opacity: 0}, 250, function() {
closeAllProductInfo();
});
} else {
openProductInfo();
}
return false;
});
$('.buy').click(function() {
if (!$(this).hasClass('in-active')) {
if (buyVisible) {
$('#buy').animate({opacity: 0}, 250, function() {
closeAllProductInfo();
});
}
else {
openProductBuy();
}
}
return false;
});
$('#info').click(function() {
if (infoVisible) {
$('#info').animate({opacity:0}, 250, function() {
closeAllProductInfo();
});
}
});
$('#buy').click(function() {
if (!$(this).hasClass('in-active')) {
if (buyVisible) {
$('#buy').animate({opacity:0}, 250, function() {
closeAllProductInfo();
});
}
}
});
Probably because it used to execute after the document was loaded but now it executes when the script is loaded. Do you load main.js at the end of your HTML file or the start? Use this to get it to execute after the document is ready:
jQuery(document).ready(function($) {
// Code using $ as usual goes here.
});
Try to wrap all your code in :
$(document).ready(function(){
// Your code in here.
});

jQuery adding functions to the animation queue

The problem is that when I try doing multiple animations they all happen the same time.
Is there any way to have animations go one after another without using callbacks?
Here's what I want to do:
$('#a1').click(function() { $('#div1').hide(3000); });
$('#a2').click(function() { $('#div2').hide(3000); });
$('#a3').click(function() { $('#div3').show(3000); });
If you click on #a1 and then click on #a2 then #a3 before the first animation completes then it shouldn't start right away but instead wait until the animation queue is empty then start the next one.
Take this demo for example
I want to be able to click a1 then a2 then a3 one after the another and first have it hide the first div completely, then the second completely, and then show the third.
My example is overly simple and while this can be done with callbacks, my real problem can't so callbacks aren't an option.
In essence, if you click all three the animation should complete in 9 seconds.
This DEMO should alert ('took around 9 seconds to complete')
Use .queue() on a common jQuery object:
var q = $({}); // this could also be a common parent, e.g. $('body')
$('#a1').click(function() {
q.queue(function(next) {
$('#div1').hide(3000, next);
});
return false;
});
$('#a2').click(function() {
q.queue(function(next) {
$('#div2').hide(3000, next);
});
return false;
});
$('#a3').click(function() {
q.queue(function(next) {
$('#div3').show(3000, next);
});
return false;
});​
Demo
Use .promise() to sidestep callbacks on show and hide:
The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended.
By default, type is "fx", which means the returned Promise is resolved when all animations of the selected elements have completed
Use .queue() to limit the number of animations resolved per promise (See also jsFiddle):
var promises = $({});
$('#a1').click(function() {
promises.queue(function(next) {
$('div').promise().done(function() {
$('#div1').hide(3000);
next();
});
});
return false;
});
$('#a2').click(function() {
promises.queue(function(next) {
$('div').promise().done(function() {
$('#div2').hide(3000);
next();
});
});
return false;
});
$('#a3').click(function() {
promises.queue(function(next) {
$('div').promise().done(function() {
$('#div3').show(3000);
next();
});
});
return false;
});
Try to create some array with queue, and check if there is something in it, as callback for animation, and run it again if there is. I've played with your example a little.
check it out:
http://jsfiddle.net/acrashik/nqh6x/6/
var queue = {
q: [],
run: function(elem, type, time, recall) {
if (queue.isRunning && !recall) {
console.log('pushed: ' + elem + type + time);
queue.q.push({elem:elem, type:type, time:time});
} else {
console.log('running:' + elem);
queue.isRunning = true;
if (type=='hide') {
$(elem).hide(time, function(){
queue.recall();
})
} else {
$(elem).show(time, function(){
queue.recall();
})
}
}
},
recall: function(){
console.log(queue.q.length);
if (queue.q.length > 0) {
queue.run(queue.q[0].elem, queue.q[0].type, queue.q[0].time, true);
queue.q = queue.q.splice(1,queue.q.length);
} else {
queue.isRunning = false;
queue.q = [];
}
},
isRunning: false
}
$('#a1').click(function() { queue.run('#div1','hide',2200) });
$('#a2').click(function() { queue.run('#div2','hide',2200) });
$('#a3').click(function() { queue.run('#div3','show',2200) });
I would use the animate() function as it comes with a complete function which is called when the animation finishes http://api.jquery.com/animate/.
So to use the jQuery doc example:
$('#clickme').click(function() {
$('#book').animate({
opacity: 0.25,
left: '+=50',
height: 'toggle'
}, 5000, function() {
// Animation complete this is where you call the next animation...
});
});
function another_animation () {
$('xyz').animate({
opacity: 0.25,
left: '+=50',
}5000, function() {
// Animation complete this is where you call the next animation
I think that this is the cleanest way...
You could do something like this:
(function(){
var col=(function(){
var i=1;
return function(n){alert("you clicked link nr " + n + ", total clicks: "+i++)};
})();
$('#a1').click(function(){col(1)});
$('#a2').click(function(){col(2)});
$('#a3').click(function(){col(3)});
})();
Im not gona write the entire code for you but that should give you a good idea of how to do it.
Also none of the variables or functions are accessible from the global scope or any other.
Add stop() before the animation:
$('#a1').click(function() { $('#div1').stop().hide(3000); });
$('#a2').click(function() { $('#div2').stop().hide(3000); });
$('#a3').click(function() { $('#div3').stop().show(3000); });
Use this
$(element).promise().done(function () {...})
In your case
$('#a1').click(function () {
$('#div1').hide(3000);
});
$('#a2').click(function () {
$("#div1").promise().done(function () {
$('#div2').hide(3000);
});
});
$('#a3').click(function () {
$("#div2").promise().done(function () {
$('#div3').hide(3000);
});
});
The next animation will be performed only when the previous animation on selected element is complete.

Jquery stop animation on mouseover

A bit of JQuery taken from http://briancray.com/2009/05/06/twitter-style-alert-jquery-cs-php/ which should give a nice old-twitter style notification.
How do I edit the code below to stop the div hiding on a mouseover?
UPDATE: I still want the div to slideup after the mouseover has finished.
$(function () {
var $alert = $('#alert');
if($alert.length) {
var alerttimer = window.setTimeout(function () {
$alert.trigger('click');
}, 5000);
$alert.animate({height: $alert.css('line-height') || '50px'}, 200).click(function () {
window.clearTimeout(alerttimer);
$alert.animate({height: '0'}, 200);
});
}
});
If I'm understanding correctly (which I'm probably not), you want something like this:
var alerttimer, alertBox = $('#alert');
function resetTimeout() {
if (alerttimer) {
clearTimeout(alerttimer);
}
alerttimer = setTimeout(function() {
alertBox.trigger('click');
}, 5000);
}
$(function () {
if(alertBox.length) {
resetTimeout();
alertBox.animate({ height: alertBox.css('line-height') || '50px' }, 200).click(function () {
window.clearTimeout(alerttimer);
alertBox.animate({ height: '0px' }, 200);
}).mouseover(function () {
clearTimeout(alerttimer);
}).mouseout(function () {
resetTimeout();
});
}
});
It's important to note that the above is very much untested.

Categories

Resources