Deliver variable between two functions - javascript

I'm using this simple script to create some slider which is starting on mouseenter and which should stops on mouseleave:
$( ".grid-item" ).mouseenter(function() {
var slides = $(this).find( ".slide-image" ),
counter = 0;
var test = setInterval(function(){
slides.removeClass('active');
slides.eq(counter).addClass('active');
counter++;
if (counter > slides.length) {counter = 0;};
}, 600);
}).mouseleave(function() {
clearInterval(test);
// $( ".slide-image" ).removeClass('active');
});
The Slider starts quite fine but on the mouseleave-event I'm getting the console error "Uncaught ReferenceError: test is not defined". I think thats because the variable of the interval is not delivered in the second function. Is there any solution?
Check out my CodePen! (It works fine here)

Declare your variable test outside the function
var test;
$( ".grid-item" ).mouseenter(function() {
var slides = $(this).find( ".slide-image" ),
counter = 0;
test = setInterval(function(){
slides.removeClass('active');
slides.eq(counter).addClass('active');
counter++;
if (counter > slides.length) {counter = 0;};
}, 600);
}).mouseleave(function() {
clearInterval(test);
// $( ".slide-image" ).removeClass('active');
});

Related

Mouseover and mouseout not working on firefox?

I want to try image slide show on mouseover and stop on mouse out
Following is my code: but with mouse over mouse out is also calling..its working fine on chrome...
default_image = '';
timer = 0;
jQuery('.sales-product-images').on('mouseover',function(){
var counter = 0;
var selector = jQuery(this);
var pd_id = jQuery(this).attr('id');
var imageArray = jQuery.parseJSON(images);
var product_images= imageArray[pd_id];
default_image = jQuery(this).attr('data-image');
console.log('default-image= ' + default_image);
timer = setInterval(function(){selector.fadeOut("fast", function () {
console.log(counter);
if (counter === product_images.length) {
console.log('==');
counter = 0;
}
console.log('localhost/product/' + product_images[counter]);
selector.attr('src', 'localhost/product/' + product_images[counter]);
selector.fadeIn(2500);
counter = counter+ 1;
});
}, 2000)});
jQuery('.sales-product-images').on('mouseleave', function() {
console.log('now end');
// var counter = 0;
clearInterval(timer);
)};
problem is: "now end" is also printed on mouseover in firefox.Which should not be.
Try this :
jQuery('.sales-product-images').on('mouseout', function() {
console.log('now end');
// var counter = 0;
clearInterval(timer);
)};
The problem is likely caused by using mouseover with mouseleave, when it's paired event should be mouseout. The pairings can be seen below.
mouseover / mouseout
$( ".sales-product-images" )
.mouseover(function() {
console.log("mouse over");
})
.mouseout(function() {
console.log("mouse out");
});
mouseenter / mouseleave
$( ".sales-product-images" )
.mouseenter(function() {
console.log("mouse enter");
})
.mouseleave(function() {
console.log("mouse leave");
});
The above methods are shortcuts for the .on("", function(){}) method.
You could rewrite your javascript as follows:
default_image = '';
timer = 0;
jQuery('.sales-product-images').mouseover(function(){
var counter = 0;
var selector = jQuery(this);
var pd_id = jQuery(this).attr('id');
var imageArray = jQuery.parseJSON(images);
var product_images= imageArray[pd_id];
default_image = jQuery(this).attr('data-image');
console.log('default-image= ' + default_image);
timer = setInterval(function(){
selector.fadeOut("fast", function () {
console.log(counter);
if (counter === product_images.length) {
console.log('==');
counter = 0;
}
console.log('localhost/product/' + product_images[counter]);
selector.attr('src', 'localhost/product/' + product_images[counter]);
selector.fadeIn(2500);
counter = counter+ 1;
});
}, 2000);
}).mouseout(function() {
console.log('now end');
// var counter = 0;
clearInterval(timer);
});

JavaScript - Looping image gallery does loop correctly

I am trying to create an image gallery in HTML, CSS. And to use JavaScript to animate the transition. I've managed to get that working, so I decided I wanted a loop within it so that when it reached the last image (4th) it will loop - transition back to the first, and carry on with the sequence until it got to the end again.
Download to look at the site to get an idea of my problem - https://drive.google.com/folderview?id=0B8HDvQ3oZFi6MG5GLTBFWGNmZkU&usp=sharing
I've tried many ways of doing this, I've got it to loop back fine. My entire code:
var imagenum = 0;
var currentimg = 1;
var maxwidth = 0;
$(document).ready(function() {
var Div1 = $("#ip").offset().top;
var Div3 = $("#flash").offset().top;
$(window).scroll(function() {
if($(window).scrollTop() < Div3) {
$("#ip").fadeIn(400);
}
else if($(window).scrollTop() > Div3) {
$("#ip").fadeOut(400);
}});
});
$(document).ready(function() {
$( '.G-li' ).each(function() {
imagenum++;
maxwidth += 830;
});
$( '.G-ul' ).css('width' , maxwidth + 'px');
$( '.rightbtn-inner' ).click(function(){
moveLeft();
});
$( '.leftbtn-inner' ).click(function(){
moveRight();
});
timer();
loop();
});
function moveLeft() {
if( currentimg < imagenum ) {
$( '.G-ul' ).animate( {'marginLeft' : '-=820px' } , 1000 , 'swing' );
currentimg = currentimg + 1;
}
}
function moveRight() {
if( currentimg > 1 ) {
$( '.G-ul' ).animate( {'marginLeft' : '+=820px' } , 1000 , 'swing' );
currentimg = currentimg - 1;
}
}
function timer() {
setInterval(moveLeft, 10000);
}
function loop() {
if( currentimg = imagenum ) {
setInterval(loopbk, 10000);
currentimg = 1; // I did the reset here
}
function loopbk() {
$( '.G-ul' ).animate( {'marginLeft' : '+=2460px' } , 1000 , 'swing' );
/* currentimg = 1; // and tried reset here */
}
}
To make it carry on with the sequence as normal I have to reset the variable currentimg to 1 for this to work. But if i do currenting = 1 in the function loop() it goes to the last image and carries on for another until looping back.
Or if I place the reset in the function loopbk(), it loops perfectly until the 2nd image and then proceeds to do the loop resulting in going left too far.
Can someone play around with this and help me as from my eyes this should work, but it doesn't - and I've been trying to solve this for a very long time.
Thank you to anyone that can help.
Andy.

javascript - Need onclick to go full distance before click works again

I have this javascript function I use that when clicked goes a certain distance. This is used within a scroller going left to right that uses about 7 divs. My question is how do I get the click to go the full distance first before the click can be used again? The issue is if the user rapidly clicks on the arrow button it resets the distance and sometimes can end up in the middle of an image instead of right at the seam. What code am I missing to accomplish this?
$(function () {
$("#right, #left").click(function () {
var dir = this.id == "right" ? '+=' : '-=';
$(".outerwrapper").stop().animate({ scrollLeft: dir + '251' }, 1000);
});
});
I would've thought that the easiest way would be to have a boolean flag indicating whether or not the animation is taking place:
$(function () {
var animating = false,
outerwrap = $(".outerwrapper");
$("#right, #left").click(function () {
if (animating) {return;}
var dir = (this.id === "right") ? '+=' : '-=';
animating = true;
outerwrap.animate({
scrollLeft: dir + '251'
}, 1000, function () {
animating = false;
});
});
});
works for me: http://jsfiddle.net/BYossarian/vDtwy/4/
Use .off() to unbind the click as soon as it occurs, then re-bind it once the animation completes.
function go(elem){
$(elem).off('click'); console.log(elem);
var dir = elem.id == "right" ? '+=' : '-=';
$(".outerwrapper").stop().animate({ left: dir + '251' }, 3000, function(){
$("#right, #left").click(go);
});
}
$("#right, #left").click(function () {
go(this);
});
jsFiddle example
You can see in this simplified example that the click event is unbound immediately after clicking, and then rebound once the animation completes.
Use an automatic then call like this
var isMoving = false;
$(function () {
$("#right, #left").click(function () {
if (isMoving) return;
isMoving = true;
var dir = this.id == "right" ? '+=' : '-=';
$(".outerwrapper").stop().animate({ scrollLeft: dir + '251' }, 1000).then(function(){isMoving = false}());
});
});
I think that you miss the fact that when you make stop() you actually position the slider at some specific point. I.e. if your scroller is 1000px and you click left twice very quickly you will probably get
scrollLeft: 0 - 251
scrollLeft: -2 - 251
So, I think that you should use an index and not exactly these += and -= calculations. For example:
$(function () {
var numberOfDivs = 7;
var divWidth = 251;
var currentIndex = 0;
$("#right, #left").click(function () {
currentIndex = this.id == "right" ? currentIndex+1 : currentIndex-1;
currentIndex = currentIndex < 0 ? 0 : currentIndex;
currentIndex = currentIndex > numberOfDivs ? numberOfDivs : currentIndex;
$(".outerwrapper").stop().animate({ scrollLeft: (currentIndex * divWidth) + "px" }, 1000);
});
});
A big benefit of this approach is that you are not disabling the clicking. You may click as many times as you want and you can do that quickly. The script will still works.
This will work perfectly fine:
var userDisplaysPageCounter = 1;
$('#inventory_userdisplays_forward_button').bind('click.rightarrowiventory', function(event) {
_goForwardInInventory();
});
$('#inventory_userdisplays_back_button').bind('click.leftarrowiventory', function(event) {
_goBackInInventory();
});
function _goForwardInInventory()
{
//$('#inventory_userdisplays_forward_button').unbind('click.rightarrowiventory');
var totalPages = $('#userfooterdisplays_list_pagination_container div').length;
totalPages = Math.ceil(totalPages/4);
// alert(totalPages);
if(userDisplaysPageCounter < totalPages)
{
userDisplaysPageCounter++;
$( "#userfooterdisplays_list_pagination_container" ).animate({
left: "-=600",
}, 500, function() {
});
}
}
function _goBackInInventory()
{
//$('#inventory_userdisplays_back_button').unbind('click.leftarrowiventory');
if(userDisplaysPageCounter > 1)
{
userDisplaysPageCounter--;
$( "#userfooterdisplays_list_pagination_container" ).animate({
left: "+=600",
}, 500, function() {
});
}
}
I second BYossarian's answer.
Here is a variation on his demo, which "skips" the animation when the user clicks several times quickly on the buttons :
$(function () {
var targetScroll = 0,
outerwrap = $(".outerwrapper");
$("#right, #left").click(function () {
// stop the animation,
outerwrap.stop();
// hard set scrollLeft to its target position
outerwrap.scrollLeft(targetScroll*251);
if (this.id === "right"){
if (targetScroll < 6) targetScroll += 1;
dir = '+=251';
} else {
if (targetScroll > 0) targetScroll -=1;
dir = '-=251';
}
outerwrap.animate({ scrollLeft: dir }, 1000);
});
});
fiddle

Execute automatically in a loop a function

I have this slider where the gotoslide function changes the slide when the navigation links are pressed.
http://jsfiddle.net/AHYVr/
What is the way to make a loop where the gotoslide function autoruns from 0 to lastone and then goes back to start?
var num_slides;
var slides;
var current;
var sa_auto = true;
jQuery(document).ready(function() {
init_slide()
});
function init_slide(){
slides = jQuery('.slides_container div');
num_slides = (slides).length;
pagination = '<ul class="pagination">';
var i=1;
jQuery.each(slides, function() {
pagination += '<li>'+i+'</li>';
i++;
});
pagination += '</ul>';
jQuery(pagination).insertBefore('#slides');
}
function gotoslide(n){
sa_auto = false;
showslide(n);
}
function showslide(n){
current = n;
var leftpos = (1-n)*700;
pagination = jQuery('.pagination li')
pagination.removeClass('current');
jQuery(pagination[n-1]).addClass("current");
slides.removeClass('current');
jQuery(slides[n-1]).addClass("current");
jQuery('.slides_container').animate({
left: leftpos
}, 2000);
}
I've tried to make a function that increases the gotoslide parameter by 1 and then use it with a setInterval, but it fails. This is the code:
var t;
function time (){
if ( j < num_slides ) {
show_slide(j++);
}
};
t= setInterval(time, 2000);
clearInterval(t);
I'm still not sure I 100% understand your question, but I will say that your setInterval will do nothing, because the moment you create it, you cancel it. Calling clearInterval(t) is used when you want an interval to stop, and not fire again. So, by calling clearInterval the very next line after you create it, it will never fire.
If you want to switch slides once every 2 seconds, and start back over again once you reach the end, try something like this:
var currentSlide = 0;
var nextSlide = function(){
currentSlide++
if(currentSlide >= num_slides){
currentSlide = 0;
}
show_slide(currentSlide);
}
var interval = setInterval(nextSlide, 2000);
Have you tried:
function init_slide(){
slides = jQuery('.slides_container div');
num_slides = (slides).length;
pagination = '<ul class="pagination">';
var i=1;
jQuery.each(slides, function() {
pagination += '<li>'+i+'</li>';
i++;
});
pagination += '</ul>';
jQuery(pagination).insertBefore('#slides');
for ( var n=0;n <num_slides; n++ ){
gotoslide(n)
}
}
There we go:
for ( var n=1;n <= i; ++n ){
if(n == i) { gotoslide(1);}
else {
gotoslide(n);
}
}
I dont know why you are using var i = 1; imho it is kinda confusing.
I added functionality to start and stop the slideshow at whatever slide you want.
function initSlideshow( slides, duration, fadeDuration ) {
var slide = 0;
function nextSlide( ) {
if( slide >= slides.length ) slide = 0;
slides.hide();
$(slides[slide]).fadeIn( fadeDuration );
slide++;
setTimeout( nextSlide, duration );
}
function stopSlideshow( num ) {
slide = ( num >= 0 && num < slides.length ) ? num : 0;
window.clearTimeout( timer );
slides.hide();
$(slides[slide]).fadeIn( fadeDuration );
}
function startSlideshow( num ) {
if( timer ) window.clearTimeout( timer );
slide = ( num >= 0 && num < slides.length ) ? num : 0;
timer = setTimeout( nextSlide, 1 );
}
var timer = setTimeout( nextSlide, 1 );
return {
stop: stopSlideshow,
start: startSlideshow
};
}
// example usage
var controller = initSlideshow( $(".slides"), 3000 );
controller.stop( 3 );
controller.start( 1 );
Fiddle here

jquery stop image rotation on mouseover, start on mouseout / hover

I have built a jQuery rotator to rotate through 3 divs and loop them. I would like to add the functionality on mouse over to "freeze" the current div and then start again on mouse out.
I've thought about setting a variable to false at the start of the function and setting it true when it's on it's current frame but I've got my self a bit confused.
I've also tried to use the hover function but when using the in and out handlers, I'm confused as to how to stop, restart the animation.
function ImageRotate() {
var CurrentFeature = "#container" + featureNumber;
$(CurrentFeature).stop(false, true).delay(4500).animate({'top' : '330px'}, 3000);
var featureNumber2 = featureNumber+1;
if ( featureNumber == numberOfFeatures) {featureNumber2 = 1}
var NewFeature = "#container" + featureNumber2;
$(NewFeature).stop(false, true).delay(4500).animate({'top' : '0px'}, 3000);
var featureNumber3 = featureNumber-1;
if ( featureNumber == 1) {featureNumber3 = numberOfFeatures};
var OldFeature = "#container" + featureNumber3;
$(OldFeature).stop(false, true).delay(4500).css('top' , '-330px');
setTimeout('if (featureNumber == numberOfFeatures){featureNumber = 1} else {featureNumber++}; ImageRotate2()', 7500)};
Any help would be greatly appreciated!!
Thanks, Matt
If you were to add this code:
var timerId = null;
function startRotation() {
if (timerId) {
return;
}
timerId = setInterval('if (featureNumber == numberOfFeatures){featureNumber = 1} else {featureNumber++}; ImageRotate2()', 7500);
}
function stopRotation() {
if (!timerId) {
return;
}
clearInterval(timerId);
timerId = null;
}
and replace the last line of your code block with a simple call to startRotation();, then you could call stopRotation and startRotation when the mouse hovers over/leaves your element:
$('your-element-selector').hover(stopRotation, startRotation);
It's not clear what you are trying to do with the three divs without seeing the HTML and more code, so I think a basic example might help you better (demo).
HTML
<div class="test">image: <span></span></div>
Script
$(document).ready(function(){
var indx = 0, loop, numberOfFeatures = 5;
function imageRotate(){
indx++;
if (indx > numberOfFeatures) { indx = 1; }
$('.test span').text(indx);
loop = setTimeout( imageRotate , 1000 );
}
imageRotate();
$('.test').hover(function(){
clearTimeout(loop);
}, function(){
imageRotate();
});
})
changed things up a little bit, here is how I ended up doing it. `
var animRun = false;
var rotateHover = false;
function startRotation() {
rotateHover = false;
ImageRotate();
}
function stopRotation() {
rotateHover = true;
clearTimeout();
}
function ImageRotate() {
if (rotateHover == false){
animRun = true;
var CurrentFeature = "#container" + featureNumber;
$(CurrentFeature).stop(false, true).animate({'top' : '330px'}, featureDuration, function(){animRun = false;});
var featureNumber2 = featureNumber+1;
if ( featureNumber == numberOfFeatures) {featureNumber2 = 1}
var NewFeature = "#container" + featureNumber2;
$(NewFeature).stop(false, true).animate({'top' : '0px'}, featureDuration); /* rotate slide 2 into main frame */
var featureNumber3 = featureNumber-1;
if ( featureNumber == 1) {featureNumber3 = numberOfFeatures};
var OldFeature = "#container" + featureNumber3;
$(OldFeature).stop(false, true).css('top' , '-330px'); /*bring slide 3 to the top*/
//startRotation();
setTimeout('if (featureNumber == numberOfFeatures){featureNumber = 1} else {featureNumber++}; if (rotateHover == false){ImageRotate2()};', featureDelay);
};
};

Categories

Resources