JavaScript - Looping image gallery does loop correctly - javascript

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.

Related

Deliver variable between two functions

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');
});

JQuery resize performance issue

I built a slider that moves left or right if some items are hidden. Obviously this needs to work responsively, so I am using a resize (smartresize) function to check when the browser is resized. It works, but after resizing when you click more (right arrow) it takes 2-5 seconds to actually calculate what is hidden and then execute.
Can anyone explain to me why this is happening, and how to possibly fix it?
Thanks!
$(window).smartresize(function () {
var cont = $('#nav-sub-menu-2 .container');
var ul = $('#nav-sub-menu-2 ul');
var li = $('#nav-sub-menu-2 ul li');
var amount = li.length;
var width = li.width();
var contWidth = cont.width();
var ulWidth = width * amount;
var remainder = ulWidth - contWidth;
ul.width(ulWidth);
if(remainder <= 0) {
$('.more, .less').fadeOut();
} else {
$('.more').fadeIn();
}
$('.more').click(function() {
ul.animate({ 'right' : remainder });
$(this).fadeOut();
$(".less").fadeIn();
});
$('.less').click(function() {
ul.animate({ 'right' : 0 });
$(this).fadeOut();
$(".more").fadeIn();
});
}).smartresize();
It could be because it is recalculating the screen size at every interval as you are resizing...
Try using a debouncer to delay the function calls until everything's settled.
/* Debounce Resize */
function debouncer( func , timeout ) {
var timeoutID , timeout = timeout || 200;
return function () {
var scope = this , args = arguments;
clearTimeout( timeoutID );
timeoutID = setTimeout( function () {
func.apply( scope , Array.prototype.slice.call( args ) );
} , timeout );
}
}
$( window ).resize( debouncer( function ( e ) {
/* Function */
}));

trigger a jquery effect when you scroll

Hey guys I'm back with another question. I'm using the code below to add a bouncing effect to a div on my site. It works fine right now but the div has to be clicked in order for the effect to start. I would like to modify it so that when the user is scrolling down the page and reaches that section it triggers the effect automatically. How can I modify the code below to trigger the effect when the user scroll's down and reaches that section of the site?
Here is the code I' using
$(".servi-block").click(function () {
doBounce($(this), 2, '10px', 150);
});
function doBounce(element, times, distance, speed) {
for (i = 0; i < times; i++) {
element.animate({
marginTop: '-=' + distance
}, speed)
.animate({
marginTop: '+=' + distance
}, speed);
}
}
$(window).scroll(function(event){
isElementVisible = inViewport($(".servi-block"));
if(isElementVisible)
{
doBounce($(this), 2, '10px', 150);
}
});
function inViewport (el)
{
var r, html;
if ( !el || 1 !== el.nodeType ) { return false; }
html = document.documentElement;
r = el.getBoundingClientRect();
return ( !!r
&& r.bottom >= 0
&& r.right >= 0
&& r.top <= html.clientHeight
&& r.left <= html.clientWidth
);
}
This should help you out: http://api.jquery.com/scroll/
$( "#target" ).scroll(function() {
$( "#log" ).append( "<div>Handler for .scroll() called.</div>" );
});
Also utilize this
$('#target').on("mousewheel", function() {
alert($(document).scrollTop());
});
Those two together should get you the ability to figure out you are scrolling, and when you reach position X, do something.
EDITED
Let's go at it this way -
var targetPos = "500px";
$( document ).scroll(function() {
if ($(document).scrollTop() == targetPos) {
doBounce($(this), 2, '10px', 150);
}
});
You can simply check to see when the element comes into view by taking the element's offset and subtracting that element's parent height and scrollTop value.
Here's an example:
$(document).ready(function() {
$(document).on('scroll', function() {
var offset = $('.element').offset().top,
scroll = $(document).scrollTop(),
height = $(document).height(),
inViewDown = ((offset - scroll - height) <= 0) ? true : false;
if (inViewDown) {
// Do some stuff
}
});
});
Here's a working example: http://jsfiddle.net/ughEe/

How to add if statements to loop the images around?

This code makes the 'li' move like I want to but when I get to the last 'li' and click next it keeps moving and the 'li' moves out of the users view. I want to know how to loop it so the first 'li' shows up again.
<script type="text/javascript">
$(document).ready(function() {
$('#right').click(function() {
$('.carousel-inner li').animate({
right: '+=292px'
}, 500);
});
$('#left').click(function() {
$('.carousel-inner li').animate({
right: '-=292px'
}, 500);
});
});
</script>
Here is a Fiddle to see an example
This should solve your problem:
$(document).ready(function () {
var inner = $('.carousel-inner'),
slides = inner.find('li'),
width = slides.eq(0).outerWidth(true),
max = (width * slides.length) - width;
$('#right, #left').on('click', function () {
var currRight = parseInt(inner.css('right'), 10), move;
if (this.id === 'right') {
move = currRight === max ? 0 : currRight+width;
} else {
move = currRight === 0 ? max : currRight-width;
}
inner.animate({ right: move }, 500);
});
});
The top four lines cache elements and set up a few basic variables such as the max right value that can used and the width of the slides.
I've then combined the click events to avoid repetition. The first line of the click event defines currRight as $('.carousel-inner')'s current CSS right value as well as move which is used later on.
if (this.id === 'right'){ /* #right */ }else{ /* #left */ } checks whether the id of the clicked element is right or left. The code inside the if statement just checks to see whether the slider is at zero (the beginning) or max (the end) and then sets the move variable to the correct value.
Here it is working: http://jsfiddle.net/mFxcq/10/
Update: To make the slides move on a timer add this after the click event is attached:
function setTimer(){
clearTimeout(window.slideTimer);
window.slideTimer = setTimeout(function(){ $('#right').trigger('click'); }, 5000);
};
setTimer();
Then add setTimer(); right after inner.animate({ right: move }, 500); and everything will work as expected.
Here it is working: http://jsfiddle.net/mFxcq/14/
Add a totalItems variable which will represent the total number of items in the carousel, and a currentItem variable which will represent the number of the current item being displayed (i.e. a number from 1 to totalItems). Then, simply check if it's the last item, and if it is, move the position back to the first one. Check out the revised fiddle, where it works in both directions. Here's example JavaScript, with everything written out for clarity.
var totalItems = $('.carousel-inner li').length;
var currentItem = 1;
$('#right').click(function () {
if (currentItem === totalItems) {
// We've reached the end -- go to the beginning again
$('.carousel-inner li').animate({
right: '-=' + 292 * (totalItems-1) + 'px'
}, 500);
currentItem = 1;
} else {
$('.carousel-inner li').animate({
right: '+=292px'
}, 500);
currentItem += 1;
}
});
$('#left').click(function () {
if (currentItem === 1) {
// We're at the beginning -- loop back to the end
$('.carousel-inner li').animate({
right: '+=' + 292 * (totalItems-1) + 'px'
}, 500);
currentItem = totalItems;
} else {
$('.carousel-inner li').animate({
right: '-=292px'
}, 500);
currentItem -= 1;
}
});
Take a look at this fiddle for a working approach. For the right click.
Basically, each time you click "Right", you'll test to compare the distance traveled by the items and compare that to the maximum distance allowed based on the total number of items.
var slideWidth = 292;
$('#right').click(function() {
if(parseInt($('.carousel-inner li').css('right')) == slideWidth*($('.carousel-inner li').length-1)) {
$('.carousel-inner li').animate({
right: '0px'
, 500);
}
else {
$('.carousel-inner li').animate({
right: '+=' + slideWidth + 'px'
}, 500);
}
});

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

Categories

Resources