Why are some elements undefined in my slider script? - javascript

I am creating an image slider for JavaScript. I have it so that my left and right arrows display the next image. I was thinking to add a setInterval method to just change the display image every few seconds. I was assuming it would be as easy as calling the function to click the right image every 3 seconds. But I get an error saying
index.js:26 Uncaught TypeError: Cannot read property 'style' of undefined
at slideRight (index.js:26)
Heres my code
let sliderImages = document.querySelectorAll('.slide');
let arrowLeft = document.getElementById('arrow-left');
let arrowRight = document.getElementById('arrow-right');
let current = 0;
function reset() {
for(let i = 0; i < sliderImages.length; i++) {
sliderImages[i].style.display = 'none';
}
}
function startSlider() {
reset();
sliderImages[0].style.display = 'block';
}
function slideLeft() {
reset();
sliderImages[current - 1].style.display = 'block';
current --;
}
function slideRight() {
reset();
sliderImages[current + 1].style.display = 'block';
console.log(current);
current ++;
console.log(current);
}
arrowLeft.addEventListener('click', function() {
reset()
if(current == 0) {
current = sliderImages.length;
}
slideLeft();
});
arrowRight.addEventListener('click', function () {
if(current == sliderImages.length -1 ) {
current = -1;
}
slideRight();
})
startSlider();
setInterval(slideRight, 3000);

Your problem seems to me to be that when you go too far right that index no longer exists in the array, so you need to use the modulus operator when going right:
sliderImages[(current + 1) % sliderImages.length].style.display = 'block';
And you need to wrap around to the right side when going left too far:
sliderImages[current - 1 >= 0 ?
current - 1 : sliderImages.length - 1].style.display = 'block';

The problem is in sliderImages[current + 1].
When you reach the lastest image current + 1 is an out of bound index and the cooresponding entry in sliderImages returns null.
You probably need to check something like
if (current < sliderImages.length) {
sliderImages[current + 1].style.display = 'block';
current++;
}

Related

Javascript function is working, but when I click the second time it doesn't work anymore

I have a slider on my website page, and I wanted to create a link that redirects to a specific slide of the slider, that contains 3 slides. Because I'm a beginner in javascript, I tried the easiest way that I could think, which is to click a certain number of times according to the current slide, so for example, if my current slide position is equal to 2[0,1,2], and I want to go to position 1, I can press the next button 2 times using a Javascript click() event. It's working like a charm, but when I click for the second time, it doesn't work. I would like to know why this is happening.
const mySlide = document.querySelectorAll('.mySlides');
let counter = 1;
slidefun(counter);
let timer = setInterval(autoSlide, 8100);
function autoSlide() {
counter += 1;
slidefun(counter);
}
function plusSlides(n) {
counter += n;
slidefun(counter);
resetTimer();
}
function currentSlide(n) {
counter = n;
slidefun(counter);
resetTimer();
}
function resetTimer() {
clearInterval(timer);
timer = setInterval(autoSlide, 8100);
}
function slidefun(n) {
let i;
for(i = 0;i<mySlide.length;i++){
mySlide[i].style.display = "none";
}
if(n > mySlide.length){
counter = 1;
}
if(n < 1){
counter = mySlide.length;
}
mySlide[counter - 1].style.display = "block";
}
const slide2 = document.getElementById('slide2');
var slideButton = document.getElementById('myButton');
slideButton.addEventListener('click', openSlide);
nextButton = document.getElementsByClassName('next');
nextButton.addEventListener('click', slideSelected);
function slideSelected(){
if(currentSlide == currentSlide(0)){
nextButton.click()
}else if(currentSlide == currentSlide(2)){
nextButton.click();
nextButton.click();
}
}

Could you explain this simple image slider code line by line?

Are you able explain this simple image slider code line by line?
I'm particularly interested in where the n and no values come from in currentSlide(no) + plusSlides(n).
var slideIndex = 0;
var slides = document.getElementsByClassName("mySlides");
var interval;
var pauseButton = document.getElementById("pause");
showSlides();
playSlideshow();
function showSlides() {
var i;
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1;
}
slides[slideIndex - 1].style.display = "block";
}
// Manual control
function currentSlide(no) {
var i;
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex = no;
slides[no - 1].style.display = "block";
}
function plusSlides(n) {
var newslideIndex = slideIndex + n;
if (newslideIndex < 6 && newslideIndex > 0) {
currentSlide(newslideIndex);
}
}
Edited to add rest of the code.
// Pause
var playing = true;
function pauseSlideshow() {
var pauseButton = document.getElementById("pause");
pauseButton.innerHTML = "▸";
playing = false;
clearInterval(interval);
}
function playSlideshow() {
pauseButton.innerHTML = "⏸";
playing = true;
interval = setInterval(showSlides, 5000);
}
pauseButton.onclick = function () {
if (playing) {
pauseSlideshow();
} else {
playSlideshow();
}
};
As per the comments, I have added additional code.
Yes, can do!
The first function showSlides is called. It first makes every element with the mySlides class invisible (basically hides all your slides). Then it increments the slide index and checks to see if the index is over the total amount of slides so it can start from the beginning again. Finally it shows the slide that the index is referring to.
The currentSlide function sets the active slide to the index provided in the no argument. First it hides all the slides and then sets the new slide index to what no is and then shows that slide.
Finally plusSlides goes forward (or backwards if using a negative number) n slides. The if statement checks if the index is between 1 and 5. If it is the slide that corresponds with the new index is shown.
A few notes
for loops can be written without a variable declaration preceding it like this
for(let x = 0; x < 100; x++){
console.log(x);
}
In your plusSides function, you check for a specific range, but you could base it off of the amount of slides with slides.length like in showSlides. Also, I would recommend making sure that if the index does happen to fall out of this range to set the index to a default value.
if (newslideIndex < slides.length && newslideIndex > 0) {
currentSlide(newslideIndex);
} else {
currentSlide(1);
}
That is all!

How to change status when clicking on a specific node

I'm trying to create a gallery. Most of it already works thanks to some online tutorials.
On the final page there should be a slider and also some thumbnails to click on which will effect the slider. I tried to achieve this by working with status. The problem I'm facing right now is to change the status when clicking on the matching img.
const imgs = document.querySelectorAll('.imgs img');
let status = 0;
var num = document.querySelectorAll('.profile_pics img').length;
let maxstatus = status + num;
imgs.forEach(img => img.addEventListener('click', imgClick));
function imgClick(){
for(let f = 0; f < imgs.length; f++){
if(imgs[f].click == true){
status = [f];
}
}
}
// Rest of the code (is working)
function reset(){
for(let i = 0; i < maxstatus; i++){
slides[i].style.display = 'none';
slides[i].style.opacity = 0;
slides[i].classList.add('fade_in');
imgs[i].style.opacity = 1;
}
}
function focus(){
imgs[status].style.opacity = opacity;
}
function startSlide(){
reset();
slides[0].style.display = 'block';
}
function slideLeft(){
reset();
slides[status - 1].style.display = 'block';
status--;
focus()
console.log(status);
}
function slideRight(){
reset();
slides[status + 1].style.display = 'block';
status++;
focus()
console.log(status);
}
prevBtn.addEventListener('click', function(){
if(status === 0){
status = maxstatus;
}
slideLeft();
});
nextBtn.addEventListener('click', function(){
if(status === maxstatus - 1){
status = -1;
}
slideRight();
});
startSlide();
I've tried now for a couple of hours but can't find a solution. Worked with console.log of course but simply can't get the status update working when clicking of one of those images.
Help would be appreciated - Thanks a lot
Full Code Can Be Found Here: Paste Bin Link
Update:
// Global Variable
let status = -1;
let imgs = [
$('#img0'),
$('#img1'),
$('#img2'),
$('#img3'),
$('#img4'),
$('#img5'),
]
// Functions
function imgClick(elm){
status = imgs.indexOf(elm); // This will set the status variable to the element index, using indexOf function. it will check inside of imgs variable which element index it is, if it cant be found status will return a -1 value
}
// Execute
imgs.forEach(img => img.on('click', () => {
imgClick(img);
}));

Dont figure what s the role of the counter in javascript

I want to create a fullscreen image slider in js so I watched a tutorial and I understand most of it beside the 'counter'.I know that its representing the current image but I don't know how it doing that, how is assigned.
HERE IS THE CODE
let sliderImages = document.querySelectorAll(".slide"),
arrowLeft = document.querySelector("#arrow-left"),
arrowRight = document.querySelector("#arrow-right"),
current = 0; (!!!!THIS ONE I DON`T UNDERSTAND HOW IT S REPRESENTING THE CURRENT IMAGE!!!
// Clear all images
function reset() {
for (let i = 0; i < sliderImages.length; i++) {
sliderImages[i].style.display = "none";
}
}
// Init slider
function startSlide() {
reset();
sliderImages[0].style.display = "block";
}
// Show prev
function slideLeft() {
reset();
sliderImages[current - 1].style.display = "block";
current--;
}
// Left arrow click
arrowLeft.addEventListener("click", function () {
if (current === 0) {
current = sliderImages.length;
}
slideLeft();
});
// Show next
function slideRight() {
reset();
sliderImages[current + 1].style.display = "block";
current++;
}
// Right arrow click
arrowRight.addEventListener("click", function () {
if (current === sliderImages.length - 1) {
current = -1;
}
slideRight();
});
startSlide();
!! HERE IS THE LINK FROM TUTORIAL https://youtu.be/7ZO2RTMNSAY
Current is being used for the index of the array that contains all the elements with the class name of slide.
It might be beneficial for you to read more about arrays: https://www.w3schools.com/js/js_arrays.asp

Sliding through a gallery of photos on a timer

I am currently creating a website for a friend and I'm having an issue I can't seem to figure out. I am sure its a simple method call to what I already have. So the problem seems to be that after the slider reaches the end of the photos it just shows a blank screen and doesn't reset to the start again. what would I need to call or what method would I need to make in order to get this to work correctly. It already works when using the arrows themselves but not the auto slide. Thank you in advance.
let sliderImages = document.querySelectorAll(".slide"),
arrowLeft = document.querySelector("#arrow-left"),
arrowRight = document.querySelector("#arrow-right"),
current = 0;
// Clear all images
function reset() {
for (let i = 0; i < sliderImages.length; i++) {
sliderImages[i].style.display = "none";
}
}
//Slides after aprrox 10 seconds
function startTimer() {
setInterval(slideRight, 10000);
}
// Init slider
function startSlide() {
startTimer();
reset();
sliderImages[0].style.display = "block";
}
// Show prev
function slideLeft() {
reset();
sliderImages[current - 1].style.display = "block";
current--;
}
// Show next
function slideRight() {
reset();
sliderImages[current + 1].style.display = "block";
current++;
}
// Left arrow click
arrowLeft.addEventListener("click", function() {
if (current === 0) {
current = sliderImages.length;
}
slideLeft();
});
// Right arrow click
arrowRight.addEventListener("click", function() {
if (current === sliderImages.length - 1) {
current = -1;
}
slideRight();
});
startSlide();
When you click the right arrow, you use this code:
if (current === sliderImages.length - 1) {
current = -1;
}
...to make sure you stop and the end of the images and don't try to go too far. But your setInterval() calls slideRight() directly, which has no protection against going too far.
Probably, current should be reset to zero as you call slideRight() and fall off the end of the array.
// Show next
function slideRight() {
reset();
if (current > sliderImages.length -1) {
current = 0;
}
sliderImages[current].style.display = "block";
current++;
}
Incidentally, you might want to take a look at bootstrap carousel feature https://getbootstrap.com/docs/4.0/components/carousel/
Ended up fixing it by using carousol type function here is the code I used to replace the startSlide function, Thank you all for the help!
function carousel(){
reset();
current++;
if (current > sliderImages.length){
current = 1
}
sliderImages[current-1].style.display = "block";
setTimeout(carousel, 7000);
}

Categories

Resources