-1

I’ve been away awhile, but we always come back, won’t we (even if no one missed us;)?

What Am I Trying to Achieve

Basically just images, grouped with a primary image.

This primary will always be shown and also serves as the content for link with a OnClick action.

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

Clicking the image will then trigger the function toggleHidden. This image will be followed by several images that ideally are hidden by default and can be shown when clicking on the primary image of the group. Naturally, only the images following the primary image shall toggle between being displayed or hidden.

What Makes It Harder

I want the title attribute of the image to be dynamic, i.e. has a number that has to be calculated based on the date. I only found this feasible by using JavaScript, meaning I create an image using const imgName = new Image() and then add the attributes and classes. If I put these images into a <div> or <span> element, give it an id and use element.getElementById in my function toggleHidden, then the images are still shown. (Btw, I made it work with ordinary images, that is images that a created using HTML code like <img src="">.)

In Theory

I tried two functions. First, all images in the same group have the same class (here ImageGroup1).

1st 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 several variations, using an inversion like !== "none" (and corresponding changes in the code) and different attributes than initial or inline.

2nd function:

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

…where hiddenspan contains only display: none; - nothing works.

My Code

<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>

    <script>
        var d1 = new Date(1994,1,31);
        var d2 = new Date();
        var diff = d2.getTime() - d1.getTime();
        var daydiff = (diff / 31557600000);
        const img02_001 = new Image();
        img02_001.src = "02/001.jpeg"; 
        img02_001.classList.add("basic"); 
        img02_001.classList.add("Group2");
        img02_001.alt="001";
        img02_001.title="001 ("+Math.floor(daydiff)+" years old)";
        document.body.appendChild(img02_001);
    </script>

    <script>
        var d1 = new Date(2006,7,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("Group2");
        img02_002.alt="002";
        img02_002.title="002 ("+Math.floor(daydiff)+" years old)"; 
        document.body.appendChild(img02_002);
    </script>

    <h2>Group 3</h2>

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

    <script>
        var d1 = new Date(1997,3,31);
        var d2 = new Date();
        var diff = d2.getTime() - d1.getTime();
        var daydiff = (diff / 31557600000);
        const img03_001 = new Image();
        img03_001.src = "03/001.jpeg"; 
        img03_001.classList.add("basic"); 
        img03_001.classList.add("Group3");
        img03_001.alt="001";
        img03_001.title="001 ("+Math.floor(daydiff)+" years old)"; 
        document.body.appendChild(img03_001);
    </script>

    <script>
        var d1 = new Date(2016,10,23);
        var d2 = new Date();
        var diff = d2.getTime() - d1.getTime();
        var daydiff = (diff / 31557600000);
        const img03_002 = new Image();
        img03_002.src = "03/002.jpeg"; 
        img03_002.classList.add("basic"); 
        img03_002.classList.add("Group3");
        img03_002.alt="002";
        img03_002.title="002 ("+Math.floor(daydiff)+" years old)"; 
        document.body.appendChild(img03_002);
    </script>

    <h2>Group 4</h2>

    <a onclick="myFunction('Group4')">
        <img class="basic" src="03.gif" alt="03" title="03">
    </a>

    <span id="Group4" class="hiddenspan">

        <script>
            var d1 = new Date(1997,3,31);
            var d2 = new Date();
            var diff = d2.getTime() - d1.getTime();
            var daydiff = (diff / 31557600000);
            const img03_001 = new Image();
            img03_001.src = "03/001.jpeg"; 
            img03_001.classList.add("basic"); 
            img03_001.classList.add("Group3");
            img03_001.alt="001";
            img03_001.title="001 ("+Math.floor(daydiff)+" years old)";
            document.body.appendChild(img03_001);
        </script>

        <script>
            var d1 = new Date(2016,10,23);
            var d2 = new Date();
            var diff = d2.getTime() - d1.getTime();
            var daydiff = (diff / 31557600000);
            const img03_002 = new Image();
            img03_002.src = "03/002.jpeg"; 
            img03_002.classList.add("basic"); 
            img03_002.classList.add("Group3");
            img03_002.alt="002";
            img03_002.title="002 ("+Math.floor(daydiff)+" years old)";
            document.body.appendChild(img03_002);
        </script>
    </span>
</body>

Obviously the code has been simplified, especially the HTML part (no <h1> header, no HTML declaration), but you should get the idea.

For Group 1 the code works flawlessly (almost, except for a line break after the primary image, but I could live with that), the same function with images generated with JavaScript (Group 4) will display the images, as if the <span> element with its id and class weren’t even there.

The other functions for group 2 and 3 do not work at all, as if getElementsByClassName doesn’t work at all. That's what I believe.

So what do you think? Is there a way to toggle the display of these images?

Edit 1

As Mike 'Pomax' Kamermans suggested, I added an event listener (hopefully the right way):

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

…and changed the code for Group 3 like this (per suggestion):

<h2>Group 3</h2>

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

<script>
    var d1 = new Date(1997,3,31);
    var d2 = new Date();
    var diff = d2.getTime() - d1.getTime();
    var daydiff = (diff / 31557600000);
    const img03_001 = new Image();
    img03_001.src = "03/001.jpeg"; 
    img03_001.classList.add("basic"); 
    img03_001.classList.add("Group3");
    img03_001.alt="001";
    img03_001.title="001 ("+Math.floor(daydiff)+" years old)";
    document.body.appendChild(img03_001);
</script>

<script>
    var d1 = new Date(2016,10,23);
    var d2 = new Date();
    var diff = d2.getTime() - d1.getTime();
    var daydiff = (diff / 31557600000);
    const img03_002 = new Image();
    img03_002.src = "03/002.jpeg"; 
    img03_002.classList.add("basic"); 
    img03_002.classList.add("Group3");
    img03_002.alt="002";
    img03_002.title="002 ("+Math.floor(daydiff)+" years old)"; 
    document.body.appendChild(img03_002);
</script>

Still no effect.

14
  • Don't use the HTML onclick attribute. Write proper JS that adds normal event listeners based on query selecting (or directly selecting by id or tagname etc) the element(s) you need. Also, don't set style values, use element.classList.add and element.classList.remove to add and remove classes - the only direct manipulation your JS should be doing with style is setting/updating CSS variables so that CSS takes care of the rest. Commented Jul 28, 2023 at 21:49
  • Thanks, Mike, for answering. Commented Jul 28, 2023 at 22:04
  • Unfortunately, your link uses buttons (which I don’t want to use), and my knowledge in JS is very, very rusty. And you meant the style manipulation in the function showHiddenClassElements? I did not create it, I’ not yet that good in JS. :) Let’s try and find some better info on event handling using a link, shall we (I)? Commented Jul 28, 2023 at 22:10
  • I didn't, nothing I've said is an answer, it's just a comment. As for button or a, that's irrelevant, the link explains event handling in "modern" JS (as in, ever since HTML5 replaced HTML4.01, about a decade ago). Commented Jul 28, 2023 at 22:10
  • Use a button when it triggers an action on the page. buttoncheatsheet.com Commented Jul 28, 2023 at 22:16

1 Answer 1

1

Here's my solution.

The problem was neither button nor the event listener (though it certainly is a more proper solution with both) but the question how to iterate the HTMLCollection returned by getElementsByClassName.

Identifying this as the cause of my problem took some testing (thanks to the Google Chrome DevTools). And the first step to the full solution can be found here. The second part came from the German website mediaevent.de, with some help from here for a better understanding of the code.

<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>

Working with buttons, you need to add a specific script for each button, then add an event listener to the aforementioned button. And this code can be simplified like this:

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

It works on both kinds of images. In this example, the images are hidden by default.

By the way, even if a button is the better solution, it does worked 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> (and without the script to add an event listener to each button and without the need to style the button).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.