Infinite move object on mouseover - javascript

I'm trying to create a feature where when you mouseover an object, another object begins to move continuously until you mouseout. For some reason in my code it stops after the first 10 pixels, which is this,
http://jsfiddle.net/JoshuaWaheed/7df29/
$("a").mouseover(function(){
$("div").animate({
"margin-left": "+=" + 10 + "px"
});
});
How can I make it run continuously, while on mouseover only?

Try to do a clever recursion here,
$("a").mouseover(function () {
stop = false;
animate()
});
$("a").mouseout(function () {
stop = true;
$("div").stop();
});
function animate() {
if (stop) { return; }
$("div").animate({
"margin-left": "+=" + 10 + "px"
}, animate);
}
DEMO

Don't use .animate, because it's not designed for this. You can move it yourself by altering the CSS in a setInterval loop:
$("a").mouseover(function () {
// store the interval ID on the DOM element itself
$(this).data('tc', setInterval(function () {
$("div").css({
"margin-left": "+=1"
});
}, 20) // milliseconds
);
});
$("a").mouseout(function () {
// clear the interval ID
clearInterval($(this).data('tc'));
});
http://jsfiddle.net/mblase75/5QJTT/

Try if this works :
var over = false;
$("a").mouseover(function(){
over = true;
while(over == true)
{
$("div").animate({
"margin-left": "+=" + 10 + "px"
});
}
});
$("a").mouseout(function(){
over = false;
});

Related

Animating an image carousel

I am using and have modified an image slider/carousel and need some guidance one two things. I need to enable it to auto scroll through the images firstly. and secondly I need to have three words underneath that act as controls too. So if I click on one it will take me to that image in the slider with some text underneath?
Example Fiddle
(function() {
var first = $('.item').first(),
last = $('.item').last(),
itemWidth = first.width(),
carousel = $('.carousel');
carousel.prepend(last.clone()).append(first.clone());
carousel.width(itemWidth * $('.item').length);
carousel.css({left: -itemWidth});
$('.prev').on('click', function(e){
e.preventDefault();
carousel.animate({left: '+=' + itemWidth}, 300, function(){
if(Math.abs(carousel.position().left) < 2) {
carousel.css({left: -itemWidth * (carousel.children().length - 2)});
}
});
return false;
});
$('.next').on('click', function(e){
e.preventDefault();
carousel.animate({left: '-=' + itemWidth}, 300, function(){
if(Math.abs(carousel.position().left + itemWidth * (carousel.children().length - 1)) < 2) {
carousel.css({left: -itemWidth});
}
});
return false;
});
})();
so the image illustrates my aim.
Easiest way:
Create variable var autoplay=true;,
Wrap Your function binded to next button click in setInterval, so setInterval Function would be like this one:
setInterval(function(){
if(!autoplay)return;
carousel.animate({left: '-=' + itemWidth}, 300, function(){
if(Math.abs(carousel.position().left + itemWidth * (carousel.children().length - 1)) < 2) {
carousel.css({left: -itemWidth});
}
})
},1000)
and then just add autoPlay toggle handler
$('.autoplayControl').on('click',function(){
autoplay=!autoplay;
})
FIDDLE: http://jsfiddle.net/UWbrQ/197/
Since I hadn't seen the button for autoplay I thought of automatic solution.
In This fiddle the Gallery moves with automatic movement(ten second for image) when the user clicks on pre next buttons auto move stops to restart after 10 seconds of inactivity
For me this is a more elegant solution
<script type="text/javascript">
$(document).ready(function(){
var first = $('.item').first(),
last = $('.item').last(),
itemWidth = first.width(),
carousel = $('.carousel');
console.log(itemWidth)
carousel.prepend(last.clone()).append(first.clone());
carousel.width(itemWidth * $('.item').length);
carousel.css({left: -itemWidth});
//auto start
var giranews = setInterval(function(){move()},5000);
function move(){
carousel.animate({left: '-=' + itemWidth}, 300, function(){
if(Math.abs(carousel.position().left + itemWidth * (carousel.children().length - 1)) < 2) {
carousel.css({left: -itemWidth});
}
});
};
function stopx(){
clearInterval(giranews);
};
function countdown(a) {
var count = a;
timerId = setInterval(function() {
count--;
console.log(count);
if(count == 0) {
clearInterval(timerId);
giranews = setInterval(function(){move()},5000);
};
}, 1000);
};
$('.prev').on('click', function(e){
e.preventDefault();
stopx();
if(typeof timerId!=='undefined'){clearInterval(timerId);countdown(10)}else{countdown(10)}
carousel.animate({left: '+=' + itemWidth}, 300, function(){
if(Math.abs(carousel.position().left) < 2) {
carousel.css({left: -itemWidth * (carousel.children().length - 2)});
}
});
return false;
});
$('.next').on('click', function(e){
e.preventDefault();
stopx();
if(typeof timerId!=='undefined'){clearInterval(timerId);countdown(10)}else{countdown(10)}
carousel.animate({left: '-=' + itemWidth}, 300, function(){
if(Math.abs(carousel.position().left + itemWidth * (carousel.children().length - 1)) < 2) {
carousel.css({left: -itemWidth});
}
});
return false;
});
})
</script>
The Easiest Way Demo Based On your Code with Just Addition of few Lines
Periodically Call the auto function
This function is basically the content inside your click for next slide
Wrap this inside the function and call it with your required interval
setInterval(Auto,5000);
function Auto(){
carousel.animate({left: '-=' + itemWidth}, 300, function(){
if(Math.abs(carousel.position().left + itemWidth * (carousel.children().length - 1)) < 2) {
carousel.css({left: -itemWidth});
}
});
}
Although the aim of this community is not provide complete script to other people, but provide solutions to specific problems, given my love for web galleries in this fiddle there is a gallery with caption below the image with buttons that move images
To accomplish this i had to change the script logic and code is increased slightly
If you like this solution don't forget to flag in green my answer ;) thanks
<script type="text/javascript">
$(document).ready(function(){
var first = $('.item').first(),
last = $('.item').last(),
itemWidth = first.width(),
countx=1,
carousel = $('.carousel');
console.log(carousel.position().left)
carousel.width(itemWidth * $('.item').length);
//auto start
var giranews = setInterval(function(){move()},5000);
function move(){
var left=carousel.position().left
if(left<(itemWidth*($('li.item').length-2)*-1)){carousel.animate({'left':'0px'},300)}else{ carousel.animate({left: '-=' + itemWidth}, 300);}
if(countx===4){countx=1}else{countx++}
showCaption(countx)
};
function stopx(){
clearInterval(giranews);
};
function countdown(a) {
var count = a;
timerId = setInterval(function() {
count--;
console.log(count);
if(count == 0) {
clearInterval(timerId);
giranews = setInterval(function(){move()},5000);
};
}, 1000);
};
//show captions in caption div
function showCaption(countx){
var caption=$('li:eq('+(countx-1)+')').attr('data-caption')
$('#caption').text(caption)
}
showCaption(countx)
$('.prev').on('click', function(e){
e.preventDefault();
stopx();
if(typeof timerId!=='undefined'){clearInterval(timerId);countdown(10)}else{countdown(10)}
if(countx===1){countx=4}else{countx--}
showCaption(countx)
var left=carousel.position().left
if(left===0){carousel.animate({'left':(itemWidth*($('li.item').length-1)*-1)+'px'},300)}else{carousel.animate({left: '+=' + itemWidth}, 300);}
});
$('.next').on('click', function(e){
e.preventDefault();
stopx();
if(typeof timerId!=='undefined'){clearInterval(timerId);countdown(10)}else{countdown(10)}
if(countx===4){countx=1}else{countx++}
showCaption(countx)
var left=carousel.position().left
if(left<(itemWidth*($('li.item').length-2)*-1)){carousel.animate({'left':'0px'},300)}else{carousel.animate({left: '-=' + itemWidth}, 300);}
});
//insert buttons links to image
for(a=0;a<$('li.item').length;a++){
$('<a class="butt">'+(a+1)+'</a>').appendTo('div.buttons')
}
$('a.butt').click(function(e){
e.preventDefault();
stopx();
if(typeof timerId!=='undefined'){clearInterval(timerId);countdown(10)}else{countdown(10)}
var pos=carousel.position().left
carousel.animate({'left': (($(this).index()*itemWidth)*-1)+'px'})
showCaption($(this).index()+1)
countx=$(this).index()+1
})
})
</script>

Is it possible to cancel hover event based on condition while still hovering?

I need to make my hover event, which executes a function, to stop running that function based on the condition of margin-top.
Here is my fiddle - http://jsfiddle.net/Joe_Foster/LwrVv/
$(document).ready(function(){
function moveUp(){
$('#a').animate({
"margin-top" : "-=" + 30},200, "linear", moveUp);
};
/* $('.up').hover(function(){
if ($m =='0px'){
alert('stop');
}
else{
moveUp();
}
});
*/
$('.up').hover(function(){
moveUp();
},
function(){
$('#a').stop();
});
//---------------------------------------
function moveDown(){
$('#a').animate({
"margin-top" : "+=" + 30},200, "linear", moveDown);
};
$('.down').hover(function(){
moveDown();
},
function(){
$('#a').stop();
});
});
Please help me before I burst more blood vessels in my eyes :)
Thank you.
I was just looking at your JS Fiddle and while I'm not certain of what values you wished to stop at, here is the code I used to make it work:
JS:
var upperThreshold = -607;
var lowerThreshold = 0;
function moveUp()
{
if ($("#a").css("marginTop").replace(/px/,'') <= upperThreshold)
{
console.log($("#a").css("marginTop"));
$('#a').stop();
return false;
}
else
{
$('#a').animate({"margin-top" : "-=" + 30},200, "linear", moveUp);
}
}
function moveDown()
{
if ($("#a").css("marginTop").replace(/px/,'') >= lowerThreshold)
{
console.log($("#a").css("marginTop"));
$('#a').stop();
return false;
}
else
{
$('#a').animate({"margin-top" : "+=" + 30},200, "linear", moveDown);
}
}
$(document).ready(function()
{
$('.down').hover(function()
{
moveDown();
},
function()
{
$('#a').stop();
}
);
$('.up').hover(function()
{
moveUp();
},
function()
{
$('#a').stop();
}
);
});
JSFiddle: http://jsfiddle.net/irishgeek82/ePdE5/
Please let me know if this works for you! :)

Getting rid of the double click effect

Here's my fiddle. As you can see I've defined a simple click event handler:
$('#traveller > a').click(function(e) {
e.preventDefault();
var $ul = $('#traveller ul');
if($(this).hasClass('handle-next')) {
if(Math.abs($ul.position().top - parentPadding) < totalHeight - itemHeight) {
$ul.animate({top: '-=' + itemHeight});
}
}
else {
if($ul.position().top - parentPadding < 0) {
$ul.animate({top: '+=' + itemHeight});
}
}
});
I've noticed that when I make few double clicks quickly, pressing a.handle-next/a.handle-prev, ul position changes unexpectedly.
Howcome I avoid this behavior?
Just check if $ul is animated:
if($ul.is(':animated')) return;
DEMO
Check if an animation is occuring prior to executing the body of the event handler.
if(!$ul.is(":animated")){
if($(this).hasClass('handle-next')) {
if(Math.abs($ul.position().top - parentPadding) < totalHeight - itemHeight) {
$ul.animate({top: '-=' + itemHeight});
}
}
else {
if($ul.position().top - parentPadding < 0) {
$ul.animate({top: '+=' + itemHeight});
}
}
}
Working Example http://jsfiddle.net/A5u43/19/
You need to lock any action with your traveller, untill animation is finished. Here i used lock variable, but you can use any approach to lock it. For this purpose use callback on animate:
$ul.animate({top: '-=' + itemHeight}, 400, 'swing', function(){
lock = false;
});
Here is the jsfiddle like
You could just prevent it with a $ul.stop(); just before you define who $ul is
here's the fiddle
var $ul = $('#traveller ul');
$ul.stop(true,true);
http://jsfiddle.net/A5u43/23/

Stop timeOut and animation on mouseenter and continue on mouseleave

I wanted to get rid of a slider-plugin, so i tried to build my own,
everything works nice but i´m stuck to stop the whole thing on hover and restart it again on mouseleave,
here is my js :
function startPslider(val) {
if (!val) {
val = 0;
}
var holder = 'slideHolder';
var text = 'slideText';
startInterval(holder, text, val);
}
function startInterval(holder, text, val) {
var t;
var i = val;
if (i > 2) {
i = 0
}
$('#' + holder + i).animate({
opacity: 1,
}, function () {
$(this).addClass('active')
$('.' + text + i).animate({
opacity: 1,
left: 0
}, 1200);
t = setTimeout(function () {
$('.' + text + i).animate({
opacity: 0,
left: '-400px'
}, 1200);
$('#' + holder + i).animate({
opacity: 0,
}, 2200).removeClass('active');
startPslider(i + 1);
}, 4000)
});
// Here´s the not working hover-function
$('#hpCanvas').hover(function () {
clearTimeout(t);
}, function () {
var id = $('.active').attr('id');
var slide = id.substring(11, 22);
console.log(slide)
startPslider(slide);
});
}
$(function () {
startPslider();
});
tryed to solve this with adding class 'active' to the current holder and at hover-out try to catch the current-slide number (val) and restart it again, starting on the correct slide, but it´s not working as I wish,
have a look at this fiddle, http://jsfiddle.net/zDh76/ you will find html and css there, as you see everything works fine as long you do not hover.
Maybe anyone has a helping hint how to stop the animation, clear the timer and go on with the correct slide on mouseleave?
UPDATE
i separated start and end-interval
function startPslider(i) {
if(!i){
i=0;
}
if(i >2){
i=0
}
console.log('started Slider with slide:'+i)
var holder = 'slideHolder';
var text = 'slideText';
startInterval(holder, text, i);
}
function startInterval(holder,text,i) {
var t;
var v;
console.log('started Interval with slide:'+i);
$('#'+holder+i).animate({
opacity:1,
}, function(){
$('.'+text+i).animate({
opacity:1,
left:0
},1200);
t= setTimeout(function(){endInterval(holder,text,i); },4000);
});
}
function endInterval(holder,text,i,cont){
console.log('end Interval with slide:'+i);
$('.'+text+i).animate({
opacity:0,
left:'-400px'
},1200);
$('#'+holder+i).animate({
opacity:0,
},2200, function(){
$('.slideHolder').css('opacity',0);
i = i+1;
startPslider(i);
});
}
I found it out myself,
i needed to unbind the hover event on #hpCanvas inside the mouseleave function like
$('#hpCanvas').hover(function(){
$('.slideHolder, .slideText').stop(true,true);
clearTimeout(t)
},function(){
endInterval(holder,text,i);
$('#hpCanvas').unbind('mouseenter mouseleave')
})
as the next call to bind it with hover event is inside the mouseleave-part of the first hover event.
thanks anyway for everyone reading this

disable click until animation is finished

I want the animation to run before allowing clicking of the next button so the animation does not go out of sync. i don't know what would be better bind / unbind or something like a while not true loop.
function first_horizontal_slider() {
var $scroller = $('div#first_slider');
var counter = 0;
$('div#first_left_btn a').css({ 'background': 'url(img/left_arrow_bw.png) no-repeat' });
$('div#first_right_btn a').css({ 'background': 'url(img/right_arrow.png) no-repeat' });
$('div#first_left_btn a').click(function () {
if (counter != 0) {
$('div#first_right_btn a').css({ 'background': 'url(img/right_arrow.png) no-repeat' });
$scroller.stop().animate({
"left": "+=732px"
}, "slow");
counter--;
if (counter == 0) {
$('div#first_left_btn a').css({ 'background': 'url(img/left_arrow_bw.png) no-repeat' });
}
}
return false;
});
$('div#first_right_btn a').click(function () {
if (counter != 2) {
$('div#first_left_btn a').css({ 'background': 'url(img/left_arrow.png) no-repeat' });
$scroller.stop().animate({
"left": "-=732px"
}, "slow");
counter++;
if (counter == 2) {
$('div#first_right_btn a').css({ 'background': 'url(img/right_arrow_bw.png) no-repeat' });
}
}
return false;
});
}
If you used a button or input type="button" then you would be able to set .disabled to true before the animation, and back to false after.
on callback function of animate you can set button to enabled.
You could disable the button at the start of the animation and have a callback in the complete method of the animation to enable the button
//before animation starts
disableButton()
$scroller.stop().animate({
"left":"+=732px"
},"slow", 'swing', enableButton); //added default easing
function enableButton() {
$('#thebutton').removeAttr('disabled');
}
function disableButton() {
$('#thebutton').attr('disabled', 'disabled');
}
use jQuery end or check via jQuery animated

Categories