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>