JavaScript Slider Effect Not Consistant - javascript

I have created a slider so that when you click a button a section of content will appear from the side, the next click the section will come from the top and so on so on, however the first few slides are not consistant and all slide the same way (The side).
If someone could have a look and find out why this is happening it would be great:
<div id="slider">
<section class="horizontal-gallery">
<img src="images/pekapeka/peka1.jpg" class="init-hidden" id="1-slide" rel="right"/>
<p id="1-text" class="horizontal-gallery-text">This is the first image in the gallery </p>
</section>
<section class="vertical-gallery">
<img src="images/pekapeka/peka2.jpg" class="picture2 init-hidden" id="2-slide" rel="right" />
<p id="2-text" class="vertical-gallery-text init-hidden">This is the second image in the gallery, it should be sliding down</p>
</section>
<section class="horizontal-gallery">
<img src="images/pekapeka/peka3.jpg" class="picture3 init-hidden" id="3-slide" rel="up" />
<p id="3-text" class="horizontal-gallery-text text-3 init-hidden">This is the third image in the gallery it should be sliding in from the side </p>
</section>
JS:
var totalslides = '5';
var slidenum = 0;
var slidenext = 0;
var slideType = '';
$(function(){
$('#gallery-next').data('counter', 0);
$('#gallery-next').click(function() {
slidenum = parseInt($('#gallery-next').data('counter'));
slidenext = slidenum+1
slideType = $('#'+slidenum+'-slide').attr('rel')
//alert('Next slideType is: ' + slideType)
//hide(slide) is a jQueryUI function, so ensure you include that lib
$('#'+slidenext+'-slide').show('slide',{direction:slideType}, 1000);
$('#'+slidenum+'-slide').delay(600).fadeOut(600);
$('#'+slidenext+'-text').delay(1200).fadeIn();
$('#'+slidenum+'-text').fadeOut(400);
slidenum = slidenum % totalslides + 1;
$('#gallery-next').data('counter',slidenum);
console.log(slideType);
});
});
And a link: http://luvly.co.nz/space/te-horo-beach-house.html

I took the liberty of fixing the entire script, reproduced here: http://jsfiddle.net/samliew/waTDr/31/
var totalslides = 6;
var slidenum = 0;
var slidenext = 0;
$(function () {
var $slider = $('#slider');
var $slides = $slider.find('img');
var $slideTexts = $slider.find('p');
// hide all except first slide
$slides.hide().eq(0).show();
$slideTexts.hide().eq(0).show();
$('#gallery-next').data('counter', 0);
$('#gallery-next').click(function () {
slidenext = slidenum + 1;
if(slidenext >= totalslides) slidenext = 0;
var slideType = $slides.eq(slidenext).attr('rel');
console.log(slidenum + ', ' + slidenext + ': ' + slideType);
// hide(slide) is a jQueryUI function, so ensure you include that lib
$slides.eq(slidenext).show('slide', {
direction: slideType
}, 1000);
$slides.eq(slidenum).delay(600).fadeOut(600);
$slideTexts.eq(slidenext).delay(1200).fadeIn();
$slideTexts.eq(slidenum).fadeOut(400);
slidenum++;
if(slidenum >= totalslides) slidenum = 0;
console.log(slidenum + ', ' + slidenext);
});
});
Also, there is something wrong with the CSS positioning of text-6, you might want to look into that.

its broken because the first time the thing executes, slidenum is 0. so when it trys to find
slideType = $('#'+slidenum+'-slide').attr('rel')
slideType is undefined because $('#0-slide') doesn't exist. so when you try to pass {direction:undefined} to your show() function, i'm assuming its defaulting to some direction you don't expect.
try initializing your slideNum variable to 1.

Related

Javascript: slideshow not slide when click

I have simple code where is slideshow which automatic slides every 5000ms.
Now I tried to make button which when I click on this button next image will not slide every 5000ms but when I click.
When I make code like this browser giving me errors.
Is there any solutions or I need make ned slideshow?
This is original code:
function cycleBackgrounds() {
var index = 0;
$imageEls = $('.container .slide');
setInterval(function () {
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}, 5000);
};
$(function () {
cycleBackgrounds();
});
This is added code:
function rightSlide() {
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}
EDIT added HTML
<section class="slide show" style="background-image: url('https://s7img.ftdi.com/is/image/ProvideCommerce/FTD_19_EDAY_19M3_HP_HEROBANNER?$ftd-product-banner-lv$');">
<div class="slide-content-wrapper">
<div class="slide-content">
<h2>02</h2>
</div>
</div>
</section>
<section class="slide" style="background-image: url('https://s7img.ftdi.com/is/image/ProvideCommerce/FTD_19_EDAY_19M3_HP_HEROBANNER?$ftd-product-banner-lv$');">
<div class="slide-content-wrapper right">
<div class="slide-content">
<h2>01</h2>
</div>
</div>
</section>
The problem is that you are creating an interval and then never clearing it. This means that once the interval is created it will keep going on forever (currently). You can read more about intervals here.
To briefly explain how to solve it:
You need to assign the interval to a variable
When you want to manually change images then clear the interval
Code snippet from the site:
var myVar = setInterval(myTimer, 1000);
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
function myStopFunction() {
clearInterval(myVar);
}
Inside of your code, when creating the interval you need to assign it into a variable and inside of the function rightSlide() you would need to clear it clearInterval(<yourIntervalHere>);
var intervalVariable = setInterval(function () {
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}, 5000);
function rightSlide() {
clearInterval(intervalVariable);
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}
You need to clear the interval but that's not the only problem:
Probably, the $imageEls and index variables are not in the scope of your custom click handler. It is definitely not the cleanest solution, but for now we will add them to the global window object
This is how I would write it (untested):
function cycleBackgrounds() {
window.index = (window.index + 1 < window.$imageEls.length) ? window.index + 1 : 0;
window.$imageEls.eq(index).addClass('show');
window.$imageEls.eq(index - 1).removeClass('show');
}
$(function () {
// add the new variables to window so they are globally accessible
window.index = 0;
window.$imageEls = $('.container .slide');
// start sliding images
window.slideshow_interval = setInterval(cycleBackgrounds, 5000);
// register onClick handler for the button with id "myButton"
$('#myButton').on('click', function(){
if (window.slideshow_interval != -1){
clearInterval(window.slideshow_interval);
window.slideshow_interval = -1;
}
cycleBackgrounds();
});
});

Click event on a slider goes at the end of the array

I am trying to create a simple slider using javascript.
So far, here is my code :
html:
<div class="carousel-container">
<div class="slides-container">
<div class="slide">
<img src="assets/images/image-1.jpg" alt="">
</div>
<div class="slide">
<img src="assets/images/image-3.jpg" alt="">
</div>
<div class="slide">
<img src="assets/images/image-2.jpg" alt="">
</div>
<div class="slide">
<img src="assets/images/image-3.jpg" alt="">
</div>
</div>
</div>
<div class="carousel-nav">
<button class="button-previous">Previous</button>
<button class="button-next">Next</button>
</div>
Js :
const slides = document.querySelectorAll('.slide')
const slidesContainer = document.querySelector('.slides-container')
const slidesCount = slides.length
const slideWidth = slides[0].clientWidth
const prevButton = document.querySelector('.button-previous')
const nextButton = document.querySelector('.button-next')
function nextSlide(slide) {
for (slide = 0; slide < slidesCount; slide++) {
slidesContainer.style.transform = 'translateX(-' + (slide * slideWidth) + 'px)'
}
}
nextButton.addEventListener('click', function() {
nextSlide()
})
The issue I have is that when I click on the next button, the slider goes all the way at the end of my array, thus skipping all the images in between.
What would be the best way to have my for loop stop at each image and go again when the button is clicked?
The reason it is skipping to the end with each click is: the for() loop. You are cycling through all of the slides — generating a new translateX coordinate with each pass – on every click. Leaving you with the last value every time.
The answer CheapGamer gave defines a pattern to avoid the for() loop trap by keeping track of the current “slide” index outside of the nextSlide() handler.
let current = 0; // <- independent index reference
function nextSlide(slide) {
if (current < slidesCount) {
slidesContainer.style.transform = 'translateX(-' + (current * slideWidth) + 'px)';
current++; // <- increment the index
}
}
// I changed the `slide` reference in `(slide * slideWidth)` to `current` to reflect the intent of the code
This takes care of incrementing you through the carousel until current equals 3. (The slide argument in nextSlide(slide) isn’t necessary.)
let current = 0;
function nextSlide(slide) {
if (current < slidesCount) {
slidesContainer.style.transform = 'translateX(-' + (slide * slideWidth) + 'px)';
current++;
}
}
I might not exactly understand what you try to do or why you intend to use a for loop but if it's just about selecting the next slide you may go with this:
var currentSlide = 0;
function nextSlide() {
//make sure currentSlide is in range
currentSlide = (currentSlide >= slidesCount) ? 0 : ++currentSlide;
slidesContainer.style.transform = 'translateX(-' + (currentSlide * slideWidth) + 'px)';
}
nextButton.addEventListener('click', nextSlide);
or a little bit more flexible:
var currentSlide = 0;
function nextSlide(direction /* Number */) {
if(!direction) direction = 1; //default
setSlide(currentSlide + direction % slidesCount);
}
function setSlide(index) {
if(index === currentSlide) return;
//make sure index is in range
while(index >= slidesCount) index -= slidesCount;
while(index < 0) index += slidesCount;
slidesContainer.style.transform = 'translateX(-' + (index * slideWidth) + 'px)';
currentSlide = index;
}
nextButton.addEventListener('click', function() {
nextSlide(this.dataset["direction"]); //by using data you don't need two different button classes
});
But if you insist on using a loop I'm afraid to tell that it's inappropriate in this case since the calculation of translateX is based on a given value.

jQuery nicescroll is not working with dynamic content and other JavaScript function that makes random effect

So here is the thing, I have a sidebar that has big height due the lots of navigation links. And I'm using jQuery nicescroll plugin to make it look fine. In the sidebar I also have h3 tag which makes a random effect of showing letters (see the code) every 4 seconds. So, when it's on - scroll is not working at all for these 4 seconds and you can't do any scrolling. I tried to use $("#sidebar").getNiceScroll().resize() but it doesn't work either. Is there any way to make it work?
<div id="sidebar">
<h3 id="output">Random</h3>
</div>
//Calling for nicescroll function for my sidebar
$(function(){
$("#sidebar").niceScroll({ cursorcolor:"#66aee9", cursorfixedheight: 400 });
})
//Random effect for my h3 tag
setInterval(function(){
$(document).ready(function(){
var theLetters = "abcdefghijklmnopqrstuvwxyz#%&^+=-"; //You can customize what letters it will cycle through
var ctnt = "Random"; // Your text goes here
var speed = 50; // ms per frame
var increment = 8; // frames per step. Must be >2
var clen = ctnt.length;
var si = 0;
var stri = 0;
var block = "";
var fixed = "";
//Call self x times, whole function wrapped in setTimeout
(function rustle (i) {
setTimeout(function () {
if (--i){rustle(i);}
nextFrame(i);
si = si + 1;
}, speed);
})(clen*increment+1);
function nextFrame(pos){
for (var i=0; i<clen-stri; i++) {
//Random number
var num = Math.floor(theLetters.length * Math.random());
//Get random letter
var letter = theLetters.charAt(num);
block = block + letter;
}
if (si == (increment-1)){
stri++;
}
if (si == increment){
// Add a letter;
// every speed*10 ms
fixed = fixed + ctnt.charAt(stri - 1);
si = 0;
}
$("#output").html(fixed + block);
block = "";
}
});
}, 4000);
I change to rows and check it in jsfiddle, looks like working scroll fine.
Before:
setInterval(function(){
$(document).ready(function(){
...
});
}, 4000);
After:
$(document).ready(function(){
setInterval(function(){
...
}, 4000);
});

Fading Image Slider

I'm trying to fade images in and out of each other. I'm not sure if it's better to preload the image before hand or not. Pretty much what's happening is that fade is hitting completely white background before fading in the next image, but I want it to fade immediatly instead of showing the white background - if that makes sense:
$(document).ready(function () {
var $next,
cycle;
var i = 0;
var imgArr = ['1.jpg', '2.jpg', '3.jpg'];
$activeLi = $("#slideshow li");
$activeLi.html('<img src="images/' + imgArr[i] + '" />');
cycle = setInterval(change_img, 1000);
function change_img(){
clearInterval(cycle);
$activeLi.find('img').fadeOut('slow', function(){
$activeLi.html('<img src="images/' + imgArr[i] + '" />').fadeIn('slow');
});
i = (i == (imgArr.length - 1)) ? 0 : ++i;
cycle = setInterval(change_img, 1000);
}
});
Also is it better to prealod my images before fading them in?
JSFiddle
My Solution (Which is jaded sinced I started the question...)
$(document).ready(function () {
var $next,
cycle;
var i = 0;
var durTimer = 2000;
var imgArr = ['1.jpg', '2.jpg', '3.jpg', '4.jpg'];
$activeLi = $("#slideshow li");
$activeLi.first().html('<img src="images/' + imgArr[0] + '" />');
cycle = setInterval(change_img, durTimer);
function change_img(){
clearInterval(cycle);
var nxtImg = (i == imgArr.length) ? 1 : i;
$activeLi.last().html('<img src="images/' + imgArr[nxtImg] + '" />');
$activeLi.find('img').animate({opacity:0}, {duration: durTimer});
i = (i == (imgArr.length - 1)) ? 0 : ++i;
$activeLi.first().html('<img src="images/' + imgArr[i] + '" />');
cycle = setInterval(change_img, durTimer);
}
});
If you have limited number of images, it is better to load all of them on page load.
In the given example, you are using only one img tag and changing the source of that to another image after some time.
So, when the image is faded out, definitely we can see the white background. Also it will take some time to load the new image.
Instead of a single img tag, add three img tags (from your code, there are three images).
Start both the fadeOut and fadeIn animations at a time.
fadeOut for current image and fadeIn for next image.
This will not show any white background.
I already created a small demo for this.
Check this out : http://db.tt/q8VPb03U

Update counter in slider

I have a slider that I've built myself, which is a carousel that infinitely loops. I'm wanting to create a counter (1 of 4, 2 of 4) etc, with the last number being the total number of slides present and the 1/2/3/4 displays which slide you are viewing.
This is what I have so far for my counter:
var $tota = $('.past-project-container').find('span.total');
var $curr = $('.past-project-container').find('span.current');
function changeCurr(){
$tota.text(numberOfProjects);
$curr.text(1);
}
changeCurr();
HTML:
<span class="slide-count-container">
<span class="current">1</span> of <span class="total">1</span>
</span>
And this is my JS for the carousel if it helps
var $carousel = $('.past-project-slider'), carW = $carousel.outerWidth(), intv;
$carousel.wrapInner('<div id="slider" />');
var $slider = $('#slider');
numberOfProjects = $('.past-project-each').length;
$slider.css({position:'absolute',left:0, width:carW*numberOfProjects}).find('.past-project-each').css({'float':'left'});
function move(cb){
if(!$slider.is(':animated')){
if(cb=='next'){
$slider.animate({left:-carW},800,function(){
$slider.append($('.past-project-each:first'));
$slider.css({left:0});
});
}else{
$slider.prepend($('.past-project-each:last'));
$slider.css({left:-carW});
$slider.animate({left:0},800);
}
}
}
$('#next-past-project, #prev-past-project').click(function(){
var btn = this.id=='next-past-project' ? move('next') : move('prev');
});
Many thanks,
R
Rather than constantly reading and converting the contents of the $curr element its probably better to keep track in another variable, like so:
var $tota = $('.past-project-container').find('span.total');
var $curr = $('.past-project-container').find('span.current');
var currentIndex = 0;
function changeCurr(){
$tota.text(numberOfProjects);
// If we've not reached the final index, add one, else return to the start
currentIndex = (currentIndex == numberOfProjects) ? 1 : currentIndex + 1;
$curr.text(currentIndex);
}
changeCurr();
This will count up until the last slide. Be sure to call changeCurr() on each slide transition.

Categories