What is the best way to switch back and forth between showing and concealing JavaScript-generated images?

Though I've been gone for a while, I always find my way back, don't I (even if no one noticed)?

The Goal in Mind

All I really need are some images, grouped together with a main image.

This main image will always be visible and will also act as a link triggering an action upon clicking.

<a onclick="toggleHidden('ImageGroup1')"><img src="…"></a>

When this image is clicked, the function toggleHidden will be activated. The following images in the group will ideally be hidden by default and only shown when the main image is clicked. Only the images after the main image should toggle between being displayed or hidden.

The Challenge

I want the title attribute of the image to be dynamic, meaning it needs to have a number calculated based on the date. This seemed achievable only through JavaScript, where I create an image using const imgName = new Image() and then add attributes and classes. If I place these images within a <div> or <span> element, assign an id to it, and use element.getElementById in my function toggleHidden, the images still display. (By the way, I managed to make it work with "regular" images created using HTML code like <img src="">.)

In Practice

I attempted two functions. Firstly, all images in the same group share the same class (in this case ImageGroup1).

First function:

function showHiddenClassElements(myClassName) {
    var hidimg = document.getElementsByClassName(myClassName);
    if (hidimg.style.display === "none") {
        hidimg.style.display = "block";
    } else {
        hidimg.style.display = "none";
    }
}

I tried various iterations, including inversing the condition like !== "none" (and corresponding code adjustments) and using different attributes than initial or inline.

Second function:

function toggleHiddenClass(myClassName) {
    var element = document.getElementsByClassName(myClassName);
    element.classList.toggle("hiddenspan");
}

...where hiddenspan contains only display: none; - however, nothing seems to work.

My Implementation

<style>
    .Group2 { }

    .Group3 { }

    .basic {
        width:150px;
        height:225px;
    }

    .hiddenspan {
        display: none;
    }
</style>

<script>
    function myFunction(myDIVid) {
        var x = document.getElementById(myDIVid);
        if (x.style.display === "none") {
            x.style.display = "block";
        } else {
            x.style.display = "none";
        }
    }

    function showHiddenClassElements(myClassName) {
        var hidimg = document.getElementsByClassName(myClassName);
        if (hidimg.style.display === "none") {
            hidimg.style.display = "block";
        } else {
            hidimg.style.display = "none";
        }
    }

    function toggleHiddenClass(myClassName) {
        var element = document.getElementsByClassName(myClassName);
        element.classList.toggle("hiddenspan");
    }
</script>

<body>
    <h2>Group 1</h2>

    <a onclick="myFunction('Group1')"><img class="basic" src="01.gif" alt="01" title="01"></a>
    <span id="Group1" class="hiddenspan">
        <img class="basic" src="001.jpeg" alt="001" title="001">
        <img class="basic" src="002.jpeg" alt="002" title="002">
        <img class="basic" src="003.jpeg" alt="003" title="003">
    </span>

    <h2>Group 2</h2>

    <a onclick="showHiddenClassElements('Group2')">
      <img class="basic" src="02.gif" alt="02" title="02">
    </a>

    // Additional script content here...

</body>

It's clear that the code has been simplified, particularly the HTML part (no <h1> header, no HTML declaration), but the concept remains intact.

While the functionality works perfectly for Group 1 (almost, except for a line break after the main image which is manageable), the same approach with dynamically generated images using JavaScript (Group 4) results in displaying the images as if the <span> element with its assigned id and class were not present at all.

The other functions related to groups 2 and 3 do not seem to have any effect, as if getElementsByClassName is not functioning correctly. That's what I suspect.

What are your thoughts? Is there a method to toggle the display of these images effectively?

Update 1

Pursuant to Mike 'Pomax' Kamermans' suggestion, I included an event listener (hopefully correctly):

<script>
    document.getElementById("idGroup3").addEventListener("click", toggleHiddenClass("Group3"));
</script>

...and modified the code for Group 3 accordingly (as recommended):

<h2>Group 3</h2>

<button id="idGroup3">
    <img class="basic" src="03.gif" alt="03" title="03">
</button>

// Additional script content here...

</body>

Despite these updates, there appears to be no change in behavior.

Answer №1

My solution to the issue at hand:

After some thorough testing with Google Chrome DevTools, I realized that the problem did not lie in either the button or the event listener setups. The real challenge was how to iterate through the HTMLCollection returned by getElementsByClassName.

I found the initial clue on Stack Overflow here. Further insights came from a German website called mediaevent.de, with additional assistance from this source here for better code comprehension.

<html>

<head>

<style>
.basic {
width:150px;
height:225px;
}

.button {
  background-color: rgba(0, 0, 0, 0);
  border: none;
  color: rgba(0, 0, 0, 0);
  text-decoration: none;
  display: inline;
  padding: 0;
  cursor: pointer;
}

.hiddenspan {
  display: none;
}
</style>

<script>
function functionButton(className) {
    Array.from(document.getElementsByClassName(className))
    .forEach((element) => element.classList.toggle("hiddenspan"));
}
</script>

</head>
<body>

<h2>Group 1</h2>

<button class="button" id="buttonGroup1"><img class="basic" src="01.gif" alt="01" title="01"></button>
<img class="basic imgGroup1 hiddenspan" src="01/001.jpeg" alt="01: 001" title="01: 001">
<script>
        var d1 = new Date(1994,1,31);
        var d2 = new Date();
        var diff = d2.getTime() - d1.getTime();
        var daydiff = (diff / 31557600000);
        const img01_002 = new Image();
        img01_002.src = "01/002.jpeg"; 
        img01_002.classList.add("basic");
        img01_002.classList.add("imgGroup1");
        img01_002.classList.add("hiddenspan");
        img01_002.alt="01: 002";
        img01_002.title="01: 002 ("+Math.floor(daydiff)+" years old)";
        document.body.appendChild(img01_002);
    </script>

<script>
const elementButtonGroup1 = document.getElementById("buttonGroup1");
elementButtonGroup1.addEventListener("click", function() {
    functionButton("imgGroup1");
    }, false
    );
</script>

<h2>Group 2</h2>

<button class="button" id="buttonGroup2"><img class="basic" src="02.gif" alt="02" title="02"></button>
<img class="basic imgGroup2 hiddenspan" src="02/002.jpeg" alt="02: 001" title="02: 001">
<script>
        var d1 = new Date(2016,10,23);
        var d2 = new Date();
        var diff = d2.getTime() - d1.getTime();
        var daydiff = (diff / 31557600000);
        const img02_002 = new Image();
        img02_002.src = "02/002.jpeg"; 
        img02_002.classList.add("basic");
        img02_002.classList.add("imgGroup1");
        img02_002.classList.add("hiddenspan");
        img02_002.alt="02: 002";
        img02_002.title="02: 002 ("+Math.floor(daydiff)+" years old)";
        document.body.appendChild(img02_002);
    </script>

<script>
const elementButtonGroup2 = document.getElementById("buttonGroup2");
elementButtonGroup2.addEventListener("click", function() {
    functionButton("imgGroup2");
    }, false
    );
</script>

</body>
</html>

To simplify working with buttons, each specific script needs to be added for individual buttons and then an event listener must be attached to the respective button. The following revised code streamlines this process:

<script>
document.getElementById("buttonGroup1").addEventListener("click", function() {
    functionButton("imgGroup1");
    }, false
    );
</script>

This streamlined approach works effortlessly with both types of images, even when the images are initially hidden by default.

Moreover, despite the superiority of using a button, the functionality can still be achieved with

<a onclick="functionButton('imgGroup1')"><img class="basic" src="01.gif" alt="01" title="01"></a>
instead of
<button class="button" id="buttonGroup1"><img class="basic" src="01.gif" alt="01" title="01"></button>
(eliminating the need for scripting to add event listeners to buttons and avoiding additional button styling).

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

Why isn't the Full Calendar loading automatically within a Bootstrap Tab?

I have been working on a travel website and incorporated a bootstrap tab feature. In the first tab, I have some content, while in the second tab, I've added a full calendar with JavaScript. Everything seems to be functioning correctly when the full ca ...

I'm having trouble with Leetcode accepting my solution for the Rotate Array problem

Regarding the question about Rotating Arrays on a platform like Leetcode (array-646), I have encountered an issue. When I provide the answer as [5,6,7,1,2,3,4] and check it by using console.log(ans) in my VSCode editor, it displays the correct output. Ho ...

What strategies can I implement to stop Iframes from disrupting the browser's history when interacting with them?

In my particular situation, I utilize Iframes to display Grafana on my page, which showcases beautiful and user-friendly graphs. After examining, I noticed that interactions like zooming in or out on the graph using mouse clicks trigger a type of refresh ...

How can you effectively load shared header and panel HTML onto pages located in separate directories using jQuery Mobile?

I am currently developing a multi-page application utilizing jQuery Mobile and incorporating loadPage() to retrieve various pages. The overall structure is outlined below. landing.html /app-pages/page1.html /app-pages/page2.html /app-pages/page3.html ...

Is there a way to ensure the req.body retrieved from a form is not undefined?

Every time I submit a form with information, the response comes back as undefined. I have provided the code below for reference. If I include the (enctype="multipart/form-data") in the form, I do not receive any data in the body (req.body). However, if I e ...

Sliding Vertically in Ionic 5

I'm currently using Ionic 5 and I am looking to incorporate a vertical slide animation from bottom to top in my application. However, despite attempting to implement it, the functionality doesn't seem to work as expected. <ion-slides pager dir ...

How to choose the desired day within a specific month when creating a calendar from scratch?

Hi there! I need some assistance. I'm currently working on enhancing a calendar by adding an extra feature. The idea is that when the user selects one or more days, those specific day(s) should be highlighted. However, I'm facing an issue where s ...

Background image changing due to React re-render

I'm working on a React component that generates a random background image each time a user visits the page. However, I'm facing an issue where the background image updates every time a user types something into an input field. I've tried usi ...

Searching for a column fails to yield any results after altering the value in

Here is a snippet of code that I am working with: <!DOCTYPE HTML> <html lang="en"> <head> <title> Exact matches overview </title> <script type="text/javascript" src="/static/s ...

Having trouble getting CSS calc to work on a table cell? Wondering how to make two out of four columns the same width?

Is it possible that CSS calc doesn't work on a table cell? It seems that no matter what size I change 90px to, the result looks the same. Even after trying various calculations with calc, I cannot seem to achieve the desired number of 230. The goal i ...

Navigating through uncharted paths on Express

I am completely lost app.js app.use('/', userRoutes); app.use('/adminID', adminRoutes); app.all('*', (req, res, next) => { next(new AppError(`URL Not Found ${req.originalUrl}`, 404)); }) const ErrorHandler = require(' ...

What methods are available to load sections of a complex SVG shape asynchronously?

I'm currently in the process of creating a website with a geographic map built using SVG, pulling data from OpenStreetMap. Due to its large size and potential for transformations such as zooming and moving, only a portion of it will be visible on the ...

What are the implications of incorporating listeners in redux action creators?

While developing my app, I have a feature that involves constantly monitoring location changes and updating the store accordingly. One question that has arisen is whether it would be beneficial to keep the listeners inside the action creator rather than th ...

PHP unable to execute Javascript alert box

I am having trouble getting an alert to display when a user is redirected to the login-redirect page. Instead of showing the alert, it seems to bypass it and takes the user directly to the login-redirect page. Below is the code snippet: <script type=" ...

Canceling a window in JSP and navigating back to the previous page using JavaScript

Here is my Java class controller: public class Controller extends HttpServlet { private Chooser chooser = Chooser.INSTANCE; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOExcep ...

How can I create a React component that is accessible and controllable from external sources?

Attempting to create a Dialog component using React and Material-UI. Currently, the component behaves like a traditional Material-UI dialog with a button inside the class that opens the dialog. However, I aim to achieve the same behavior as the default Ma ...

Codepen fails to function properly after being uploaded to a server

I have encountered an issue with my code on CodePen. After exporting it as a .zip file and attempting to run it on a local server, it failed to work. I am unsure of the exact reason behind this. I made sure to include all the necessary dependencies in the ...

Develop a stylish HTML/CSS box featuring a trio of diagonal gradient colors

Trying to achieve a square with three colors inspired by the concept of a Two-tone background split by diagonal line using css, but with an additional color scheme similar to this example: https://i.sstatic.net/ci2Zv.png Seeking advice. Attempted the fol ...

Styling elements with CSS to create horizontal and vertical lines between them

Struggling to replicate the design elements from this image using CSS. Specifically, I need help creating a horizontal yellow line over the title "nossos numeros" and vertical blue lines between "Cursos", "Alunos", and "Aulas". I am working with Bootstrap ...

Creating a Custom Progress Bar with Bootstrap

I'm encountering an issue with aligning a Bootstrap 3 progress bar vertically within a table cell. While I have successfully aligned other cells to the middle, the progress bar still remains in its original position. How can I eliminate the excess spa ...