0

I have a webpage with a grid of figures, when I contruct the page I add css classes to represent certain things such as has image/doesnt have image to an enclosing div. Then I have a select element that the user can use to filter the tiles (nofilter, no image, has image)

<div class="mb-2">
    <label for="selectArtistArtworkFilter" id="selectArtistArtworkFilterLabel">
        Artist Artwork Filter
    </label>
    <select id="selectArtistArtworkFilter" class="custom-select col-3" aria-labelledby="selectArtistArtworkFilterLabel" onchange="artworkFilter(&#x27;selectArtistArtworkFilter&#x27;);">
        <option value="1" selected="selected">
            No Filter
        </option>
        <option value="2">
            Without Artist Artwork
        </option>
        <option value="3">
            With Artist Artwork
        </option>
    </select>
    <span class="mx-2">
    </span>
</div>
<div style="display:grid;grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));grid-gap: 5px;">
    <div class="tile noimage albumimage">
        <figure class="figure" style="position:relative">
            <a href="StatusReport00108_byartistalbum00001.html">
                <img src="../style/images/folder.jpg" class="figure-img" width="200" height="200">
            </a>
        </figure>
    </div>
    <div class="tile image albumimage">
        <figure class="figure" style="position:relative">
            <a href="StatusReport00108_byartistalbum00002.html">
                <img src="../images/gb7iqGOT4duS062Nh2a3Xg==.jpg" class="figure-img" width="200" height="200">
            </a>
        </figure>
    </div>

by calling a javascript function

function artworkFilter(selectbox)
{
    var select   = document.getElementById(selectbox);
    var selected = select.options[select.selectedIndex].value;

    if(selected=="1")
    {
        var figures = document.getElementsByClassName("tile");
        for (i = 0; i < figures.length; i++)
        {
            figures[i].style.display = "block";
        }
    }
    else if(selected=="2")
    {
        var figures = document.getElementsByClassName("image");
        for (i = 0; i < figures.length; i++)
        {
            figures[i].style.display = "none";
        }

       figures = document.getElementsByClassName("noimage");
       for (i = 0; i < figures.length; i++)
       {
            figures[i].style.display = "block";
       }
    }
    else if(selected=="3")
    {
        var figures = document.getElementsByClassName("image");
        for (i = 0; i < figures.length; i++)
        {
            figures[i].style.display = "block";
        }

       figures = document.getElementsByClassName("noimage");
       for (i = 0; i < figures.length; i++)
       {
            figures[i].style.display = "none";
       }
    }
}

This works, but I then needed to add another filter (on albumartwork) so i added another select

<label for="selectCoverArtFilter" id="selectCoverArtFilterLabel">
        Cover Art Filter
    </label>
    <select id="selectCoverArtFilter" class="custom-select col-3" aria-labelledby="selectCoverArtFilterLabel" onchange="albumArtworkFilter(&#x27;selectCoverArtFilter&#x27;);">
        <option value="1" selected="selected">
            No Filter
        </option>
        <option value="2">
            Without Cover Art
        </option>
        <option value="3">
            With Cover Art
        </option>

and another javascript function

function albumArtworkFilter(selectbox)
{
    var select   = document.getElementById(selectbox);
    var selected = select.options[select.selectedIndex].value;

    if(selected=="1")
    {
        var figures = document.getElementsByClassName("tile");
        for (i = 0; i < figures.length; i++)
        {
            figures[i].style.display = "block";
        }
    }
    else if(selected=="2")
    {
        var figures = document.getElementsByClassName("albumimage");
        for (i = 0; i < figures.length; i++)
        {
            figures[i].style.display = "none";
        }

       figures = document.getElementsByClassName("noalbumimage");
       for (i = 0; i < figures.length; i++)
       {
            figures[i].style.display = "block";
       }
    }
    else if(selected=="3")
    {
        var figures = document.getElementsByClassName("albumimage");
        for (i = 0; i < figures.length; i++)
        {
            figures[i].style.display = "block";
        }

       figures = document.getElementsByClassName("noalbumimage");
       for (i = 0; i < figures.length; i++)
       {
            figures[i].style.display = "none";
       }
    }
} 

Now this ones work in isolation but doesnt take into account what the first filter is set to. So my next stage was to replace the two functions with a single function that took both selects into account in one go.

But then I remembered I needed a 3rd filter and it seems that this is very rapidly going to get very messy, and I think there must be a more elegant way to do this ?

1 Answer 1

1

Create a function that toggles the styles to save yourself the repetition..

function toggleDisplay(className, displayValue){
   var figures = document.getElementsByClassName(className);
   for (i = 0; i < figures.length; i++)
   {
      figures[i].style.display = displayValue;
   }
}

Now you can turn your jungle of if statements into:

function albumArtworkFilter(selectbox)
{
    var select   = document.getElementById(selectbox);
    var selected = select.options[select.selectedIndex].value;

    if(selected=="1")
    {
        toggleDisplay("tile", "block");
    }
    else if(selected=="2")
    {
       toggleDisplay("albumimage", "none");
       toggleDisplay("noalbumimage", "block");
    }
    else if(selected=="3")
    {
       toggleDisplay("albumimage", "block");
       toggleDisplay("noalbumimage", "none");
    }
}

Switch alternative:

switch(selected) {

  case "1":
    toggleDisplay("tile", "block");
    break;

  case "2":
    toggleDisplay("albumimage", "none");
    toggleDisplay("noalbumimage", "block");
    break;
    // .... etc

}

If you want to be able to pass multiple style properties for each elements.. modify the toggleDisplay function to the following:

function toggleDisplay(className, displayValue){
   var figures = document.getElementsByClassName(className);
   var keys = Object.keys(displayValue);

   for (i = 0; i < figures.length; i++)
   {
      for (var j = 0; j < keys.length; j++){
         figures[i].style[keys[j]] = displayValue[keys[j]];
      }
   }
}

Then you'd call that using

toggleDisplay("tile", {display: "block", color: "black" });

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

2 Comments

Thankyou that is very useful and I have rewrote to use toggle method and switch statement. However still unclear best mehtod for multiple filters, i,.e first filter says noartistimage and the use selects albumimage from 2nd filter it should only show tiles that have noartisatimage and an albumimge.
Okay I have figured out a satisfactory solution now (added to question), thanks for your help

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.