Home > Blockchain >  Why does classList return an error: Uncaught TypeError: Cannot read properties of undefined (reading
Why does classList return an error: Uncaught TypeError: Cannot read properties of undefined (reading

Time:06-19

I don't understand why I get an error: Uncaught TypeError: Cannot read properties of undefined (reading 'classList') console.log(slid[numberArray].classList) - working, but slid[numberArray].classList.add('active') - not working I know that this is not a good code, but I'm still learning and I want to make a slider myself

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 >
  <div >
    <div > </div>
    <p >engine</p>
    <p >01</p>
  </div>
  <div >
    <div ></div>
    <p >exhaust</p>
    <p >02</p>
  </div>


  <div >
    <div ></div>
    <div ></div>
  </div>

</section>

CodePudding user response:

When you loop over your slid array, you define s as each element in that array:

slid.forEach(s => {

You then define numberArray as the index of that element in that array:

let numberArray = slid.indexOf(s);

Then you increment numberArray:

numberArray   ;

And then access the element at that new index:

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

So what will happen when s is the last element of the array? numberArray will be the index of that element, which you then increment to the index of the element after the last element. No such element exists, so at that time slid[numberArray] is undefined.

How do you want to handle it when you've reached the end of the array? However you want to handle it, that's where you'd implement that logic.

For example, if you want to start over at the beginning of the array when reaching the last element, you'd check if you're at the end of the array and reset to 0:

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

CodePudding user response:

Firstly, it's often a bad idea to use Array.forEach() in your scenario because it will go through the entire list even if your work was completed on the first element. So I highly suggest you use a loop you can break. Because After setting the next element.classList.active, there's no need for the list to continue.

Your Second Mistake was as David explained, not resetting back to position 0 when the last element of the list is reached.

Here's a working example. I've incorporated both arrows-right and arrows-left event behavior in one 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;
}

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

.slid.active {
    opacity: 1;
    display: block;
}

.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: green;
    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 >
  <div >
    <div > </div>
    <p >engine</p>
    <p >01</p>
  </div>
  <div >
    <div ></div>
    <p >exhaust</p>
    <p >02</p>
  </div>
  <div >
    <div ></div>
    <p >smoke</p>
    <p >03</p>
  </div>
  
  <div >
    <div ></div>
    <div ></div>
  </div>
</section>

  • Related