What is causing the classList function to throw an error: Uncaught TypeError: Cannot read properties of undefined (reading 'classList')?

There's an error that I can't figure out: Uncaught TypeError: Cannot read properties of undefined (reading 'classList') console.log(slid[numberArray].classList) is working fine, but slid[numberArray].classList.add('active') is not working. I know my code isn't great, but I'm still learning and trying to build a slider from scratch.

const slid = [...document.querySelectorAll('.slid')];
const arrows = document.querySelectorAll('.arrows-slider .arrow');

slid.forEach(s => {
    if( s.classList.contains('active') == false){
         s.style.opacity = '0';
    }
 });

arrows.forEach( arrow =>{
    arrow.addEventListener('click', function(){
        if(this.classList.contains('arrows-right')){
            slid.forEach(s => {
                if( s.classList.contains('active')){
                    s.classList.remove('active');
                    let numberArray = slid.indexOf(s);
                    numberArray ++;
                    slid[numberArray].classList.add('active');
                    console.log(slid[numberArray].classList);
                }
             });
        }else if( this.classList.contains('arrows-left')){

        }

    });
});
.slider {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    background-image: url('../img/mirrored_squares.png');
    height: 100vh;
}

.slid {
    position: absolute;
    width: 100%;
    height: 100vh;
    opacity: 0;
}

.active {
    opacity: 1 !important;
}

.img-slid {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 35%;
    height: 50%;
    background-size: cover;
}

.engine {
    background-image: url("../img/silnik.jpg");
}

.exhaust {
    background-image: url("../img/wydech.jpg");
}



.slid-text {
    position: absolute;
    top: 50%;
    left: 11%;
    transform: translateY(-50%);
    font-size: 8rem;
    text-transform: uppercase;
    color: #fff;
    font-family: 'Black Ops One', cursive;

}

.number-slaid {
    position: absolute;
    bottom: 8%;
    right: 8%;
    font-size: 2rem;
    color: #fff;
    font-family: 'Black Ops One', cursive;
}

/* .arrows-left {
    position: absolute;
    top: 50%;
    left: 5%;
    transform: translateY(-50%);
}

.line-arrow {
    width: 2px;
    height: 70px;
    background-color: black;
}

.top-line {
    transform: rotate(48deg) translateY(25%);
}

.bottom-line {
    transform: rotate(-48deg) translateY(-25%);
} */

.arrows-left {
    position: absolute;
    top: 50%;
    left: 5%;
    transform: translateY(-50%) rotate(45deg);
}

.arrows-right {
    position: absolute;
    top: 50%;
    right: 5%;
    transform: translateY(-50%) rotate(-135deg);
}

.arrow {
    width: 80px;
    height: 80px;
    border-left: 2px solid #000;
    border-bottom: 2px solid #000;
    cursor: pointer;
}
<section class="slider">
  <div class="slid slid1 active">
    <div class="engine img-slid"> </div>
    <p class="slid-text">engine</p>
    <p class="number-slaid">01</p>
  </div>
  <div class="slid slid2 ">
    <div class="exhaust img-slid"></div>
    <p class="slid-text">exhaust</p>
    <p class="number-slaid">02</p>
  </div>


  <div class="arrows-slider">
    <div class="arrows-left arrow"></div>
    <div class="arrows-right arrow"></div>
  </div>

</section>

Answer №1

It's not advisable to use Array.forEach() in your situation because it will iterate through the entire list even if the task is completed on the first element. I recommend using a loop that can be terminated. Once you have set the next element.classList.active, there is no need to continue looping.

Your second mistake, as mentioned by David, was failing to reset back to position 0 when reaching the last element of the list.

Below is a functional example that combines both arrows-right and arrows-left event behaviors into one block of code:

const slid = [...document.querySelectorAll('.slid')];
const arrows = document.querySelectorAll('.arrows-slider .arrow');

arrows.forEach( arrow =>
{
    arrow.addEventListener('click', function(clickEvent)
    {
        var target = clickEvent.currentTarget;
        for(let i = 0; i < slid.length; i++)
        {
            if( slid[i].classList.contains('active'))
            {
                slid[i].classList.remove('active'); 
                let numberArray;
                
                if(target.classList.contains("arrows-right")) 
                {
                  numberArray = 0;
                  i++;  
                } else 
                {
                  numberArray = slid.length - 1;
                  i--;  
                } 
                
                if(slid[i] === undefined)
                  slid[numberArray].classList.add('active');
                else
                  slid[i].classList.add('active');
                  
                break;
            }
        }
    });
});
.slider {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    background-image: url('../img/mirrored_squares.png');
    height: 100vh;
}

// More CSS rules here...

.arrows-right {
    position: absolute;
    top: 50%;
    right: 5%;
    transform: translateY(-50%) rotate(-135deg);
}

.arrow {
    width: 80px;
    height: 80px;
    border-left: 2px solid #000;
    border-bottom: 2px solid #000;
    cursor: pointer;
}
<section class="slider">
    // HTML content including slider elements and arrows goes here
</section>

Answer №2

As you iterate through the slid array, assigning each element to the variable s:

slid.forEach(s => {

You then determine the index of that element in the array and assign it to numberArray:

let numberArray = slid.indexOf(s);

Next, you increment the value of numberArray:

numberArray ++;

Afterward, you access the element at this updated index:

slid[numberArray].classList.add('active');

If s happens to be the last element in the array, what occurs? The variable numberArray will hold the index of that element, which gets incremented to the non-existent index after the last element. Consequently, slid[numberArray] will return undefined.

How should this scenario be handled when reaching the end of the array? This is where you would incorporate the necessary logic based on your requirements.

For instance, if you wish to restart from the beginning of the array upon reaching the last element, you can add a check to reset the index to 0 when necessary:

let numberArray = slid.indexOf(s);
numberArray ++;
if (numberArray >= slid.length) {
  numberArray = 0;
}
slid[numberArray].classList.add('active');

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Emphasize sections of text within a chart

Looking for a Specific Solution: I've encountered similar problems before, but this one has a unique twist. What I'm trying to achieve is to search for a substring within a table, highlight that substring, and hide all other rows (tr's) th ...

Calculating the sum of table columns with the help of knockout.js

Is there a way to calculate the table columns using knockout.js? I am familiar with jQuery but new to knockout.js and unsure how to approach this. Instead of generating the table data using JSON, I would like to directly create it in the HTML table itself. ...

The JavaScript code appears to have malfunctioned as it abruptly terminates with an exit code of 1

When running the code, it reports that prompt-sync cannot be found and exits with error code 1 const input = require('prompt-sync')(); var firstName = input("Enter your first name:"); var lastName = input("Enter your last name:"); console.log(" ...

Convert the background image (specified in the CSS with background-image) into a PHP variable

I am looking to create a product gallery featuring 5 products, each with its own background image attribute. I am using a loop to insert the product images and I want each loop to display a different background-image. One approach I have considered is usi ...

The jQuery code does not execute following the use of window.location.replace( url ) command

I'm facing an issue with my code that involves redirecting the page to the index page after clicking on a specific link ('#versionPageFromProdLink'). The index page contains certain content within a div, which I want to hide once the redirec ...

Sideways movement of a single line within a table

Would you please help with a challenge I'm facing? I want to create a horizontally scrollable row that spans 100% of the page width without overflowing on top of the background image and while keeping the header text in focus. This is what I have att ...

Is it possible to include choices in the number option for slash commands in discord.js v13?

I am currently working on creating a custom slash command that includes a numerical option. Utilizing the .addNumberOption() method for this purpose. Is there a method to restrict users from inputting numbers outside the range of 0-5 after entering the Di ...

Creating a stand-alone JavaScript file for generating Bootstrap-vue Toast notifications

After a few days of learning vue.js, I decided to implement a custom toast function based on the official bootstrap-vue documentation: . I successfully created toasts using component instance injection and custom components in Vue. However, my goal now is ...

How can I use try-catch in JavaScript to call the same function again in the catch block

When encountering a scenario in JavaScript where a Try Catch block fails due to some issue, what is the best approach to handle this and retry the same operation until it is successful? For example: const getMyDetails = async()=>{ try{ await ge ...

Learn the method of showcasing a JavaScript variable value within an HTML href tag

Currently, I am in the process of rewriting my URL and category name to be passed into the URL. For this purpose, I am creating a URL friendly string using the following JavaScript function: function getUrlFriendlyString(str) { // convert spaces to &ap ...

How can I omit extra fields when using express-validator?

Currently, I am integrating express-validator into my express application and facing an issue with preventing extra fields from being included in POST requests. The main reason for this restriction is that I pass the value of req.body to my ORM for databas ...

Exploring the Intersection of jQuery and Rails in Dynamic Form Development

I am currently working on an interactive form for a Rails project and need some assistance with listing multiple jQuery functions in the same file. Whenever I try to add a second set of code language, it seems to break the entire file. Below is the Rails ...

Avoiding cheating in a JavaScript game

I am in the process of creating a JavaScript/JQuery game that resembles a classic brick breaker. The game includes features such as scoring, levels, and more. I have plans to add a leaderboard where users can submit their final scores. However, my concer ...

Achieving Dynamic Center Alignment of Filtered Node in SVG Using D3

I am currently implementing filter functionality for my d3 graph. The goal is to allow users to search for a specific node by label or ID, then re-render the graph to display the entire structure with the filtered node positioned at the center of the SVG e ...

The callback function in jQuery does not function properly in a custom class or object

Hello, I am new to the world of programming so bear with me if this question seems basic. I am currently working on creating a simple wave effect to give the illusion of moving water. Initially, I achieved this using a straightforward jQuery function which ...

Disable the shadow on the focused state of Safari and Chrome dropdown selects

I'm attempting to eliminate the shadow that appears on a select element when it is in focus: https://i.sstatic.net/5kDKE.png I have tried the following CSS styles: select { border: none; box-shadow: none; -webkit-box-shadow: none; o ...

The search results fail to show the required information

I am trying to retrieve data from an API based on a search query. When the user enters the name of the film they are looking for and hits enter to submit the form, the matching films should be displayed on the screen. However, my console is showing errors ...

Moving from the end to the beginning with a jQuery slider transition

Instead of relying on external plugins, I built this slider from scratch: function customSlider(selector, interval, index) { var slider = this; this.ind = index; this.selector = selector; this.slides = []; this.activeSlide = 0; this.amount; ...

Looping through and printing JSON strings

Currently, I am dealing with a JSON string of this specific format: {"prey":["{\"distance\": 8.686924173343307, \"signal\": \"-59\", \"frequency\": 2447, \"mac\": \"00:00:00:00:00:00\", \"ip ...

Locking Bootstrap 4.3 Navbar at the Page's Summit with a See-Through Effect

I have extensively researched and searched online for information before reaching out here. I hope my question is not redundant. My challenge lies in creating a static navbar at the top of my Bootstrap 4.3 page. Despite multiple attempts, it seems to elud ...