-3

Soo, I'm a complete beginner to javascript and I've got this code for a carousel(from this tutorial:https://www.youtube.com/watch?v=gor5BvT2z88) which is existing only on one of the pages. What do I need to add to the code, so that when I'm on other pages which don't contain this carousel I don't get this error: Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') ?

let slidePosition = 0;
const slides = document.getElementsByClassName('carousel__item');
const totalSlides = slides.length;

document.
getElementById('carousel__button--next')
    .addEventListener("click", function () {
        moveToNextSlide();
    });
document.
getElementById('carousel__button--prev')
    .addEventListener("click", function () {
        moveToPrevSlide();
    });

function updateSlidePosition() {
    for (let slide of slides) {
        slide.classList.remove('carousel__item--visible');
        slide.classList.add('carousel__item--hidden');
    }

    slides[slidePosition].classList.add('carousel__item--visible');
}

function moveToNextSlide() {
    if (slidePosition === totalSlides - 1) {
        slidePosition = 0;
    } else {
        slidePosition++;
    }

    updateSlidePosition();
}

function moveToPrevSlide() {
    if (slidePosition === 0) {
        slidePosition = totalSlides - 1;
    } else {
        slidePosition--;
    }

    updateSlidePosition();
}
<section id="carousel-section">
      <div class="carousel">
        <h2 class="carousel-header">FEATURED WORK</h2>
        <div class="carousel__item carousel__item--visible"><img
            src="./carousel pictures/slide show pictures/slide1.jpg" alt=""></div>
        <div class="carousel__item"><img src="./carousel pictures/slide show pictures/slide2.JPG" alt=""></div>
        <div class="carousel__item"><img src="./carousel pictures/slide show pictures/slide3.JPEG" alt=""></div>
        <div class="carousel__item"><img src="./carousel pictures/slide show pictures/slide4.JPG" alt=""></div>
        <div class="carousel__item"><img src="./carousel pictures/slide show pictures/slide5.JPG" alt=""></div>
        <div class="carousel__actions">
          <button id="carousel__button--prev" aria-label="previous slide">
            < </button> <button id="carousel__button--next" aria-label="next slide"> >
          </button>
        </div>
    </section>
  • 2
    Why include the carousel code on a page that doesn’t make use of it in the first place…? This is a hugely unnecessary bandwidth strain as is. – esqew Sep 27 '21 at 15:45
  • Does this answer your question? [$(document).ready equivalent without jQuery](https://stackoverflow.com/questions/799981/document-ready-equivalent-without-jquery) – Jared Smith Sep 27 '21 at 15:46
  • You can move this javascript code piece directly inside a `script` tag in that page. And remove the code from the `javascript` file which you are using. – Agil Atakishiyev Sep 27 '21 at 15:47
  • @esqew because when you are working with students you see this all the time. And i am pretty familiar with this kind of error. I get the first idea because OP's question contains a phrase 'so that when I'm on other pages'. And on top of that idea when from another page you try to find an element which is not in the DOM you get `null` and then you try to use its methods like `addEventListener` or properties like `className` you get that error. Now you get the idea that where i get those ideas from??? – Agil Atakishiyev Sep 27 '21 at 15:55
  • I have one js file connected to all pages and in it this carousel (which is only on the main page) and a hamburger menu that is available on all pages. Because from what I was told I thought I was supposed to use a separate file for js instead of making it inline – Julia Woś Sep 27 '21 at 16:21
  • @JuliaWoś It's arguably a bit easier to maintain when segmented neatly into their own files (you'll realize this is more opinion-based than most like to let on); the core of the clarifying questions here are regarding *why* you've elected to include this JavaScript in a file that's ostensibly being included on every page? Arguably best practice would be to segment this page-specific JavaScript into its own `.js` file and reference it only in the HTML page(s) in which you're using this specific carousel functionality. – esqew Sep 27 '21 at 16:27
  • @esqew Thanks, I moved it to a separate file and linked it only to that one page and the error is gone. :) I haven't even thought about making more than one file and just guessed that I should rather keep it all together, I'm really new to JavaScript and still struggle with how to write it in most efficient ways etc – Julia Woś Sep 27 '21 at 16:50
  • @JuliaWoś These things come with experience - here alone you’ve just learned about how to ensure your files are modular (can be swapped in/out as necessary) and what benefits and trade-offs this might come with. You seem to be on the right path, though. – esqew Sep 27 '21 at 16:56
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Oct 05 '21 at 11:25

3 Answers3

1

The error in question is being thrown as a result of this code looking for carousel-related DOM elements on pages where the functionality isn’t in use. While the current answers do assist in the resolution of the issue, I feel there is a better way to resolution that can also be of use in many other scenarios where page-specific functionality can be included/excluded as necessary:

As discussed in the comments on the original question, the clean way to resolve this is to move all carousel-related code to a separate .js file, and reference that new file only on pages where you explicitly need this carousel functionality.

This way, you’ll be segmenting your JavaScript code more neatly, reduce unnecessary networking, memory, and processing overhead, and avoid script errors on pages that don’t leverage this functionality.

esqew
  • 42,425
  • 27
  • 92
  • 132
0

You can check if the element exists before adding listeners to it. So instead of

document.getElementById('carousel__button--next')
   .addEventListener("click", function () {
       moveToNextSlide();
   });

You could do

let nextButton = document.getElementById('carousel__button--next')

And then check if it exists

if(nextButton) {
     netxtButton.addEventListener("click", function () {
        moveToNextSlide();
     });
}

To be totally sure you can also to this in updateSlidePosition

if(totalSlides > 0) {

    for (let slide of slides) {
        slide.classList.remove('carousel__item--visible');
        slide.classList.add('carousel__item--hidden');
    }

}

slides[slidePosition].classList.add('carousel__item--visible');
Kokodoko
  • 26,167
  • 33
  • 120
  • 197
  • I mean that's cool and all, but unless I'm missing something OP's problem is *probably* related to trying to run the js before the DOM is loaded. – Jared Smith Sep 27 '21 at 15:47
  • 1
    I thought the problem was that the carousel only exists on some HTML pages, but the javascript exists on all HTML pages. But yes, the whole thing should be executed after the DOM has finished loading. – Kokodoko Sep 27 '21 at 15:48
  • 1
    @JaredSmith i think he is just referring to same javascript file from every html document he creates. If it was the case you mentioned he would get `Uncaught TypeError: Cannot read properties of undefined (reading 'addEventListener')` not null – Agil Atakishiyev Sep 27 '21 at 15:50
0

When your code depends upon the existence of a particular element, it's prudent to add a "existence guard" at the top of any function that uses it, like this:

// Look the element up somehow...using ids is usually a good strategy for convenience and speed

const requiredElement = document.getElementById('someId');
if (requiredElement !== undefined) {
   // Do all the things that work on that element
   requiredElement.addEventListener('someEvent', someHandler);
}


sh0rtwave
  • 1
  • 1