Home > Software design >  Uncaught TypeError: Cannot read properties of undefined (reading 'classList') while trying
Uncaught TypeError: Cannot read properties of undefined (reading 'classList') while trying

Time:04-20

Hello!
first, I know the question title seems like a duplicate but, it's not.
I'm a beginner at Javascript and I'm trying to build a portfolio section that shows a couple of projects, if you click on an icon it will show you the project's picture in a bigger way. Anyway I wrote a couple of js lines but, I keep getting this error:

Uncaught TypeError: Cannot read properties of undefined (reading 'classList')
    at changeImage (index.js:168:19)
    at HTMLSpanElement.<anonymous> (index.js:139:9)

The first image is showing and nothing wrong with it, but the other pictures, show it in a strange order and some of the pictures don't even show! I tried several solutions including getting the items using getElementByClassName and so on.
If you can help me I would appreciate it and tell me how it can be done!

HTML:

<section  id="portfolio">
    <div >
        <div ></div>
        <div >
            <div >
                <i ></i>
            </div>
            <div >
                <img  src="./assets/images/port1.jpg" alt="">
                <img src="./assets/images/port2.png" alt="">
                <img src="./assets/images/port3.jpg" alt="">
                <img src="./assets/images/port4.png" alt="">
                <img src="./assets/images/port5.png" alt="">
                <img src="./assets/images/port6.jpg" alt="">
            </div>
            <div >
                <i ></i>
            </div>
        </div>
    </div>
    <div >
        <div >
            <div >
                <h3 >Portfolio</h3>
                <h1 >Latest projects</h1>
            </div>
            <div >
                <button  data-filter="all">All</button>
                <button  data-filter=".product">Product</button>
                <button  data-filter=".interaction">Interacting</button>
                <button  data-filter=".webapps">Web apps</button>
            </div>
        </div>
        <div >
            <div >
                <div >
                    <img src="./assets/images/port1.jpg">
                    <div >
                        <span  style="--i: 0s">
                            <i ></i>
                        </span>
                        <a href="#"  style="--i: .15s">
                            <i ></i>
                        </a>
                    </div>
                </div>
                <div >
                    <h3>Olido interaction</h3>
                    <a href="#" >Read more</a>
                </div>
            </div>
            <div >
                <div >
                    <img src="./assets/images/port2.png">
                    <div >
                        <span  style="--i: 0s">
                            <i ></i>
                        </span>
                        <a href="#"  style="--i: .15s">
                            <i ></i>
                        </a>
                    </div>
                </div>
                <div >
                    <h3>Olido interaction</h3>
                    <a href="#" >Read more</a>
                </div>
            </div>
            <div >
                <div >
                    <img src="./assets/images/port3.jpg">
                    <div >
                        <span  style="--i: 0s">
                            <i ></i>
                        </span>
                        <a href="#"  style="--i: .15s">
                            <i ></i>
                        </a>
                    </div>
                </div>
                <div >
                    <h3>Olido interaction</h3>
                    <a href="#" >Read more</a>
                </div>
            </div>
            <div >
                <div >
                    <img src="./assets/images/port4.png">
                    <div >
                        <span  style="--i: 0s">
                            <i ></i>
                        </span>
                        <a href="#"  style="--i: .15s">
                            <i ></i>
                        </a>
                    </div>
                </div>
                <div >
                    <h3>Olido interaction</h3>
                    <a href="#" >Read more</a>
                </div>
            </div>
            <div >
                <div >
                    <img src="./assets/images/port5.png">
                    <div >
                        <span  style="--i: 0s">
                            <i ></i>
                        </span>
                        <a href="#"  style="--i: .15s">
                            <i ></i>
                        </a>
                    </div>
                </div>
                <div >
                    <h3>Olido interaction</h3>
                    <a href="#" >Read more</a>
                </div>
            </div>
            <div >
                <div >
                    <img src="./assets/images/port6.jpg">
                    <div >
                        <span  style="--i: 0s">
                            <i ></i>
                        </span>
                        <a href="#"  style="--i: .15s">
                            <i ></i>
                        </a>
                    </div>
                </div>
                <div >
                    <h3>Olido interaction</h3>
                    <a href="#" >Read more</a>
                </div>
            </div>
        </div>
    </div>
</section>

And here is the Javascript code:

const prt_section = document.querySelector(".portfolio");
const zoom_icon = document.querySelectorAll(".zoom-icon");
const modal_overlay = document.querySelector('.modal-overlay');
const images = document.querySelectorAll(".images img");

let currentIndex = 0;

zoom_icon.forEach((icn, i) =>
    icn.addEventListener("click", () => {
        prt_section.classList.add("open");
        document.body.classList.add("stopScrolling");
        currentIndex = i;
        changeImage(currentIndex);
    })
);

modal_overlay.addEventListener("click", () => {
    prt_section.classList.remove("open");
    document.body.classList.remove("stopScrolling");
});

function changeImage(index) {
    images.forEach((img) => img.classList.remove("showImage"));
    images[index].classList.add("showImage");
}

NOTE: When I navigate throughout the images with the mixer there is nothing wrong and it's showing me all the images in the correct order.

Here is the mixer js code if you're interested:

const prev_btn = document.querySelector(".prev-btn");
const next_btn = document.querySelector(".next-btn");

let mixer = mixitup(".portfolio-gallery", {
    selectors: {
        target: ".prt-card",
    },
    animation: {
        duration: 500,
    },
});

prev_btn.addEventListener("click", () => {
    if (currentIndex === 0) {
        currentIndex = 5; //NOTE: (5) is the number of the last image.
    } else {
        currentIndex--;
    }
    changeImage(currentIndex);
});

next_btn.addEventListener("click", () => {
    if (currentIndex === 5) {
        currentIndex = 0;
    } else {
        currentIndex  ;
    }
    changeImage(currentIndex);
});

CodePudding user response:

function changeImage(index) {
    images.forEach((img) => img.classList.remove("showImage"));
    images[index].classList.add("showImage");
}

Error states it's in the last line of this function if I'm correct.

In your HTML you have 12 elements with class "zoom-icon". (on span and anchor).

You only have 6 images in you DIV.images.

So eventually this will break: at the 7th "zoom-icon":

zoom_icon.forEach((icn, i) =>
    icn.addEventListener("click", () => {
        prt_section.classList.add("open");
        document.body.classList.add("stopScrolling");
        currentIndex = i;
        changeImage(currentIndex); // will break when i > 6
    })
);

CodePudding user response:

Thanks to @ColinT, the problem was in my HTML code. I put zoom-icon on both the search icon and the link icon which is wrong. My code was completely correct.

  • Related