0

I'm currently working on a website that shows a visual representation of all the movies I watched. A Movie List if you will. I figured out how to filter the list based on button presses using JS, however, it only filters by 1 button at a time. I'd like the list to be filtered based on multiple buttons.

For example: "All completed movies with a rating of 3 and the action genre*".

Or: "All completed and watching movies"

I've never learned JS (though I plan to eventually) so I am kinda lost on how to do this.

Here's my current code:

filterSelection("all")
function filterSelection(c) {
    var eles = document.getElementsByClassName("flex-card");
    for(var i=0; i < eles.length; i++) {
        if (c === "all" || eles[i].classList.contains(c)) {
            eles[i].classList.remove("displayNone");
    		} 
        else {
    		    eles[i].classList.add("displayNone");
        }
    }
}
.card:hover .overlay {
    display: none;
}

.btn:hover {
    background-color: hsl(14,80%,70%);
}

.displayNone {
    display: none;
}

.yellow {
    color: hsl(14,80%,70%);
}

.heading {
    color: white;
}

.button-container {
    margin: 0px 0px 12px;
    text-align: center;
    padding-bottom: 12px;
}

.btn {
    color: hsl(14,80%,30%);
    background-color: hsl(43,83%,55%);
    border: 1px solid rgba(0, 0, 0, 0.94);
    border-radius: 10px;
    text-align: center;
    font-weight: 600;
    font-size: 10px;
    line-height: 20px;
    width: 80px;
    margin: 5px 0px 5px 5px;
    padding: 0px 12px;
}

.flex-container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    padding-left: 15%;
    padding-right: 15%;
}

/* I am using a 7:10 aspect ratio (width:height) */
.flex-card {
    position: relative;
    height: 265px;
    width: 185px;
    perspective: 1000px;
    margin-right: 1rem;
    margin-bottom: 1rem;
}

.a {
}

.card {
    position: relative;
    width: 100%;
    height: 100%;
    transition: transform 0.6s  0s;
    transform-style: preserve-3d;
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
}

.image {
    object-fit: cover;
    width: 100%;
    height: 100%;
}

.overlay {
    position: absolute;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.7);
    width: 100%;
    transition: .1s ease;
}

.title {
    text-align: center;
    color: white;
    font-size: 14px;
    font-weight: 600;
    margin: 8px;
}

.subtitle {
    margin: 8px;
    font-size: 12px;
    font-weight: 600;
    text-align: center;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>New page</title>
        <link href="css/new.css" rel="stylesheet" type="text/css">
    </head>
    <body style="background-color: rgb(19,23,29);">
        <div>
            <h1 style="text-align: center;" class="heading">Movie List</h1>
            <div class="button-container" data-pg-name="Buttons">
                <button class="btn" onclick="filterSelection('all')">All</button>
                <button class="btn" onclick="filterSelection('watching')">Watching</button>
                <button class="btn" onclick="filterSelection('planned')">Planned</button>
                <button class="btn" onclick="filterSelection('completed')">Completed</button>
                <button class="btn" onclick="filterSelection('dropped')">Dropped</button>
                <br>
                <button class="btn" onclick="filterSelection('five')">5</button>
                <button class="btn" onclick="filterSelection('four')">4</button>
                <button class="btn" onclick="filterSelection('three')">3</button>
                <button class="btn" onclick="filterSelection('two')">2</button>
                <button class="btn" onclick="filterSelection('one')">1</button>
                <br>
                <button class="btn" onclick="filterSelection('action')">Action</button>
                <button class="btn" onclick="filterSelection('horror')">Horror</button>
                <button class="btn" onclick="filterSelection('romance')">Romance</button>
                <button class="btn" onclick="filterSelection('etc')">etc.</button>
                <button class="btn" onclick="filterSelection('etc')">etc.</button>
            </div>
        </div>
        <div class="flex-container">
            <div class="watching five flex-card">
                <a href="#">
                    <div class="card">
                        <img src="https://via.placeholder.com/300" class="image">
                        <div class="overlay">
                            <p class="title">Title</p>
                            <p class="subtitle yellow">Studio</p>
                        </div>
                    </div>
                </a>
            </div>
            <div class="planned three flex-card">
                <a href="#">
                    <div class="card">
                        <img src="https://via.placeholder.com/300" class="image">
                        <div class="overlay">
                            <p class="title">Title</p>
                            <p class="subtitle yellow">Studio</p>
                        </div>
                    </div>
                </a>
            </div>
            <div class="completed two flex-card">
                <a href="#">
                    <div class="card">
                        <img src="https://via.placeholder.com/300" class="image">
                        <div class="overlay">
                            <p class="title">Title</p>
                            <p class="subtitle yellow">Studio</p>
                        </div>
                    </div>
                </a>
            </div>
        </div>
    </body>
</html>

also on jsfidle

1
  • Please add a minimal reproducible example. Don't put your LONG code when asking a question. Instead, just put the part when you find the problem. Commented Apr 26, 2020 at 12:56

1 Answer 1

1

It would be possible to store all clicked selectors in an array, and render cards based on the whole array's state, not just the last clicked button. Quick and dirty example could look like this:

const allCards = document.querySelectorAll(".flex-card");
var displayAll = true  // special value for displaying all - default true
var activeCards = []  // array holding all selected values

function toggleSelector(c) {
    if (c === 'all') {
    displayAll = !displayAll
    activeCards = []  // optional
    return
  }

  displayAll = false
  if (activeCards.includes(c)) {
    activeCards = activeCards.filter(card => card !== c)
  } else {
    activeCards.push(c)
  }
}

// quick dirty way to render cards
function renderCards() {
  if (displayAll) {
    allCards.forEach(card => showCard(card))
    return
  }

  allCards.forEach(card => hideCard(card))  
  
  for (let card of allCards) {
    for (let cardClass of card.classList) {
      if (activeCards.includes(cardClass)) {
      	showCard(card)
        break;
      }
    }
  }
}

// on each click toggle clicked selector and re-render cards
function filterSelection(c) {
  toggleSelector(c)
  renderCards()
}

function showCard(card) {
  card.classList.remove("displayNone");	
}

function hideCard(card) {
  card.classList.add("displayNone");
}

renderCards()
.card:hover .overlay {
    display: none;
}

.btn:hover {
    background-color: hsl(14,80%,70%);
}

.displayNone {
    display: none;
}

.yellow {
    color: hsl(14,80%,70%);
}

.heading {
    color: white;
}

.button-container {
    margin: 0px 0px 12px;
    text-align: center;
    padding-bottom: 12px;
}

.btn {
    color: hsl(14,80%,30%);
    background-color: hsl(43,83%,55%);
    border: 1px solid rgba(0, 0, 0, 0.94);
    border-radius: 10px;
    text-align: center;
    font-weight: 600;
    font-size: 10px;
    line-height: 20px;
    width: 80px;
    margin: 5px 0px 5px 5px;
    padding: 0px 12px;
}

.flex-container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    padding-left: 15%;
    padding-right: 15%;
}

/* I am using a 7:10 aspect ratio (width:height) */
.flex-card {
    position: relative;
    height: 265px;
    width: 185px;
    perspective: 1000px;
    margin-right: 1rem;
    margin-bottom: 1rem;
}

.a {
}

.card {
    position: relative;
    width: 100%;
    height: 100%;
    transition: transform 0.6s  0s;
    transform-style: preserve-3d;
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
}

.image {
    object-fit: cover;
    width: 100%;
    height: 100%;
}

.overlay {
    position: absolute;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.7);
    width: 100%;
    transition: .1s ease;
}

.title {
    text-align: center;
    color: white;
    font-size: 14px;
    font-weight: 600;
    margin: 8px;
}

.subtitle {
    margin: 8px;
    font-size: 12px;
    font-weight: 600;
    text-align: center;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>New page</title>
        <link href="css/new.css" rel="stylesheet" type="text/css">
    </head>
    <body style="background-color: rgb(19,23,29);">
        <div>
            <h1 style="text-align: center;" class="heading">Movie List</h1>
            <div class="button-container" data-pg-name="Buttons">
                <button class="btn" onclick="filterSelection('all')">All</button>
                <button class="btn" onclick="filterSelection('watching')">Watching</button>
                <button class="btn" onclick="filterSelection('planned')">Planned</button>
                <button class="btn" onclick="filterSelection('completed')">Completed</button>
                <button class="btn" onclick="filterSelection('dropped')">Dropped</button>
                <br>
                <button class="btn" onclick="filterSelection('five')">5</button>
                <button class="btn" onclick="filterSelection('four')">4</button>
                <button class="btn" onclick="filterSelection('three')">3</button>
                <button class="btn" onclick="filterSelection('two')">2</button>
                <button class="btn" onclick="filterSelection('one')">1</button>
                <br>
                <button class="btn" onclick="filterSelection('action')">Action</button>
                <button class="btn" onclick="filterSelection('horror')">Horror</button>
                <button class="btn" onclick="filterSelection('romance')">Romance</button>
                <button class="btn" onclick="filterSelection('etc')">etc.</button>
                <button class="btn" onclick="filterSelection('etc')">etc.</button>
            </div>
        </div>
        <div class="flex-container">
            <div class="watching five flex-card displayNone">
                <a href="#">
                    <div class="card">
                        <img src="https://via.placeholder.com/300" class="image">
                        <div class="overlay">
                            <p class="title">Title</p>
                            <p class="subtitle yellow">Studio</p>
                        </div>
                    </div>
                </a>
            </div>
            <div class="planned three flex-card displayNone action">
                <a href="#">
                    <div class="card">
                        <img src="https://via.placeholder.com/300" class="image">
                        <div class="overlay">
                            <p class="title">Title</p>
                            <p class="subtitle yellow">Studio</p>
                        </div>
                    </div>
                </a>
            </div>
            <div class="completed two flex-card displayNone action">
                <a href="#">
                    <div class="card">
                        <img src="https://via.placeholder.com/300" class="image">
                        <div class="overlay">
                            <p class="title">Title</p>
                            <p class="subtitle yellow">Studio</p>
                        </div>
                    </div>
                </a>
            </div>
        </div>
    </body>
</html>

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.