Creating a Dropdown Filter using Vanilla JavaScript

I am currently working on a project for one of my college courses, which involves creating a dropdown list filter using pure JavaScript to filter a grid of images in HTML/CSS. The main challenge I am facing is that this filter needs to be able to work with three dropdown lists simultaneously. For instance, if I select "nature" and "people," it should display the grids corresponding to those categories, and when I choose "category," all the images should appear. Any help or guidance on how to achieve this would be greatly appreciated.

var element = document.getElementById("category1");
element.addEventListener("change", function() {
  var option = element.options[element.selectedIndex].text;
  var photos = document.getElementsByClassName("photo");
  
  for (var i = 0; i < photos.length; ++i) {
    if (!photos[i].classList.contains(option)) {
      photos[i].style.display = "none";
    } else {
      photos[i].style.display = 'block';
    }
  }
});
<div class="filter">
  <select id="category1">
    <option value="">category</option>
    <option value="people">people</option>
    <option value="nature">nature</option>
    <option value="landscapes">landscapes</option>
  </select>
  
  <select id="category2">
    <option value="">category</option>
    <option value="people">people</option>
    <option value="nature">nature</option>
    <option value="landscapes">landscapes</option>
  </select>
  
  <select id="category3">
    <option value="">category</option>
    <option value="people">people</option>
    <option value="nature">nature</option>
    <option value="landscapes">landscapes</option>
  </select>
</div>

<div class="gallery">
  <div class="photo nature people" style="background-image: url(https://picsum.photos/1000/1000?random=1);"></div>

  <div class="photo landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=2);"></div>

  <div class="photo nature" style="background-image: url(https://picsum.photos/1000/1000?random=3);"></div>

  <div class="photo people landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=4);"></div>

  <div class="photo people" style="background-image: url(https://picsum.photos/1000/1000?random=5);"></div>


  <div class="photo nature landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=6);"></div>

  <div class="photo people" style="background-image: url(https://picsum.photos/1000/1000?random=7);"></div>

  <div class="photo natureza landscapes people" style="background-image: url(https://picsum.photos/1000/1000?random=8);"></div>

  <div class="photo natureza landscapes people" style="background-image: url(https://picsum.photos/1000/1000?random=9);"></div>

  <div class="photo nature people" style="background-image: url(https://picsum.photos/1000/1000?random=10);"></div>

  <div class="photo landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=11);"></div>

  <div class="photo landscapes nature" style="background-image: url(https://picsum.photos/1000/1000?random=12);"></div>
</div>

Answer №1

Here is my initial attempt at solving this problem. If you have any questions or need further clarification, please don't hesitate to ask in the comments section below.

let activeFilters = [];
const images = [...document.querySelectorAll('.photo')];
const filters = [...document.querySelectorAll('.filter select')];

for (const filter of filters) {
  filter.addEventListener('change', function(event) {
    activeFilters = filters.map(filter => filter.value).filter(Boolean);
    console.log(activeFilters);
    for (const image of images) {
      image.classList[activeFilters.some(filter => image.classList.contains(filter)) 
        ? 'add'
        : 'remove']('visible');
    }
  })
}
.photo {
  color: #fff;
  height: 120px;
  width: 120px;
  background-size: cover;
  text-shadow: 0 0 2px #000;
  opacity: 0;
  overflow: hidden;
  transition: all .4s ease-in-out;
}

.gallery {
  display: flex;
}

.visible {
  height: 240px;
  width: 240px;
  opacity: 1;
}
<div class="filter">
  <select id="category1">
    <option value="">category</option>
    <option value="people">people</option>
    <option value="nature">nature</option>
    <option value="landscapes">landscapes</option>
  </select>
  <select id="category2">
    <option value="">category</option>
    <option value="people">people</option>
    <option value="nature">nature</option>
    <option value="landscapes">landscapes</option>
  </select>
  <select id="category3">
    <option value="">category</option>
    <option value="people">people</option>
    <option value="nature">nature</option>
    <option value="landscapes">landscapes</option>
  </select>
</div>

<div class="gallery">
  <div class="photo nature people" style="background-image: url(https://picsum.photos/1000/1000?random=1);">photo nature people</div>
  <div class="photo landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=2);">photo landscapes</div>
  <div class="photo nature" style="background-image: url(https://picsum.photos/1000/1000?random=3);">photo nature</div>
  <div class="photo people landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=4);">photo people landscapes</div>
  <div class="photo people" style="background-image: url(https://picsum.photos/1000/1000?random=5);">photo people</div>
  <div class="photo nature landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=6);">photo nature landscapes</div>
  <div class="photo people" style="background-image: url(https://picsum.photos/1000/1000?random=7);">photo people</div>
  <div class="photo nature landscapes people" style="background-image: url(https://picsum.photos/1000/1000?random=8);">photo nature landscapes people</div>
  <div class="photo nature landscapes people" style="background-image: url(https://picsum.photos/1000/1000?random=9);">photo nature landscapes people</div>
  <div class="photo nature people" style="background-image: url(https://picsum.photos/1000/1000?random=10);">photo nature people</div>
  <div class="photo landscapes" style="background-image: url(https://picsum.photos/1000/1000?random=11);">photo landscapes</div>
  <div class="photo landscapes nature" style="background-image: url(https://picsum.photos/1000/1000?random=12);">photo landscapes nature</div>
</div>

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

Is there a way to alphabetically sort V-Chips in Vuetify?

Hello, I'm currently attempting to organize multiple V-Chips alphabetically. Does anyone have any suggestions? Here is the code snippet I am working with. I want to display all my V-Chips in alphabetical order. Should I sort my array or is there a sp ...

Instant access to an interactive online platform

Is it feasible to create a shortcut from a webpage to my desktop for quick access? For instance, if a dynamic web page has 15 documents and I want to easily create shortcuts to them on my desktop by clicking on each one. I understand this is a brief quest ...

What is the best way to align content in the middle of a containing div?

I am struggling with centering text and images inside a div that is 190px x 190px. Despite searching on various platforms, including SO and Google, I have not found a simple solution. Can someone please provide guidance on the easiest way to achieve verti ...

Issue with joining tables in query on Cordova Mobile app

I have 2 queries that will return results which I plan to use in JSON format. The first query is $query = "SELECT * FROM info_location WHERE location_id=".$id.""; and the second query $query = "SELECT t1.location_id,t1.street,t1 ...

What could be causing the error "Unexpected identifier 'trytoCatch' while trying to minify?

I recently updated my script.js and now I'm looking to use "minify" in Node.js to compress it. When I type the command minify script.js > script.min.js into the terminal, I get an error message that says: /node_modules/bin/minify.js:3 import "tryTo ...

How can I adjust a number using a shifter in JavaScript?

Searching for an event handler where I can use a shifter to adjust the value of a number by moving it left or right. Would appreciate any links to documentation on how to achieve this. Many thanks UPDATE Thanks to the suggestions from other users, I hav ...

What is the most crucial element to focus on when initially building a website?

I have recently embarked on the journey of learning various programming languages for web development, and I strongly believe that the best way to enhance my skills is by brainstorming ideas and bringing them to life through coding. (Please feel free to co ...

Generate random div elements and insert them dynamically into a fixed-sized container using AngularJS. The number of div elements created can range anywhere from 0 to

Within a div of fixed size, dynamically generated div elements are displayed using ng-repeat. The inner divs should adjust their size to accommodate the number of child divs present - for example, if only one div is present, it should take up 100% of the s ...

Can you remind me of the specific CSS class used for Internet Explorer in Twitter Bootstrap?

Currently utilizing Twitter Bootstrap and curious if there is a specific CSS class to designate IE browsers within the BODY or HTML tags. Interested in writing CSS specifically for all IE browsers. Aware that Bootstrap offers some CSS classes for IE brows ...

Navigating through the properties of a JSON object and traversing the React state leads to encountering the error message 'state undefined'

Apologies if I seem a bit lost, but I'm attempting to assign a JSON object to a component's state for rendering purposes. This is the current setup within my component: render: function() { this.serverRequest = $.get(this.props.source, func ...

Vue.js <v-data-table> - Automatic sorting/ custom sorting options

I am trying to arrange the numerical data in a Vue.js data-table in descending order right from the start. I want it to look like the screenshot provided below. Screenshot of My Desired Result The data that needs to be arranged in descending order is the ...

Is it advisable to opt for window.webkitRequestAnimationFrame over setInterval?

Trying to figure out the best method for moving game characters in my JavaScript game - should I go with window.webkitRequestAnimationFrame or stick with setInterval? Any advice is appreciated! ...

Is there a way to verify a string before adding it to a MySQL database?

Recently, I encountered an issue with my database while storing input strings from users. It seems that someone tried to insert a WhatsApp smiley which resulted in an error. Although I do not recall the specific error message, it was clear that the value ...

What is the best way to calculate the combined total of radio button values using jQuery or JavaScript?

I recently came across a tutorial on how to sum radio button values using JavaScript or jQuery, and I decided to implement it in my code. However, I encountered some issues as it didn't work as expected. My goal was to offer users the option to downlo ...

The functionality of Anchor `<a>` tags is compromised in Chrome when using the hashtag symbol (#)

Below is the code I have implemented on my website: <li><a href="/explore/#Sound">Sound</a></li> (This menu is visible on all pages) <a id="Sound"><a> (This is on the specific page where I want to link to) I have at ...

What is the best way to position a tooltip near an element for optimal visibility?

One div is located on the page as follows: <div id="tip"> Text for tip goes here... </div> And another one can be found below: <div class="element"> Text for element goes here... </div> There is also a piece of JavaScript ...

"Triggering a JavaScript event when pasting text on

How can I capture a paste event on an iPhone using JavaScript and jQuery? I've already tried using jQuery's keyup and paste methods without success. Any suggestions? Here is the code I have attempted: $("#MyInputFields input").eq(0).b ...

Issue of displaying buttons based on sibling's height under certain conditions

OBJECTIVE I have undertaken a project to enhance my skills in React and TypeScript by developing a UI chat interface. The design requirement is that when a chat message has enough vertical space, its action buttons should appear stacked vertically to the ...

Most effective method for integrating a JS module across all browsers

I have created a robust library that I want to integrate into a different web project. This library handles all its dependencies and consists of js, css, and html files. My ideal scenario would be to package it as an npm module and simply use import to in ...

Disable a button during an AJAX request

Whenever a button is clicked, the record is saved to the database without refreshing the page using AJAX. I have implemented the AJAX code successfully. Now I need guidance on how to manage the state of the Submit button - enabling/disabling it dynamicall ...