Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

alborz
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
alborz
Full Stack JavaScript Techdegree Graduate 30,885 Points

Can't hide options when previous select option is selected

I have an interactive form. When the user selects a type of design for a shirt, I want the next select menu to only display the colors that match the previous design selected. I want to show and hide the appropriate colors.

Below is my code:

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register for Full Stack Conf</title>
  <link href="https://fonts.googleapis.com/css?family=Roboto:400,500,700" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div class="container">

    <header>
      <span>Register for</span>
      <h1>Full Stack Conf</h1>
    </header>

    <form action="index.html" method="post">

      <fieldset class="basicinfo">         
        <legend>Basic Info</legend>

        <label for="name">Name:</label>
        <input type="text" id="name" name="user_name">

        <label for="mail">Email:</label>
        <input type="email" id="mail" name="user_email">

        <label for="title">Job Role</label>
        <select id="title" name="user_title">
          <option value="full-stack js developer">Full Stack JavaScript Developer</option>
          <option value="front-end developer">Front End Developer</option>
          <option value="back-end developer">Back End Developer</option>
          <option value="designer">Designer</option>          
          <option value="student">Student</option>
          <option value="other">Other</option>  
        </select>           
      </fieldset>

      <fieldset class="shirt">
        <legend>T-Shirt Info</legend>

        <div>
          <label for="size">Size:</label>
          <select id="size" name="user_size">
            <option value="small">S</option>
            <option value="medium" selected>M</option>
            <option value="large">L</option>
            <option value="extra large">XL</option>
          </select>
        </div>

        <div class="design-section">
          <label for="design">Design:</label>
          <select id="design" name="user_design">
            <option>Select Theme</option>
            <option value="js puns">Theme - JS Puns</option>
            <option value="heart js">Theme - I &#9829; JS</option>
          </select>
        </div>

        <div id="colors-js-puns" class="">
          <label for="color">Color:</label>
          <select id="color">
            <option value="cornflowerblue">Cornflower Blue (JS Puns shirt only)</option>
            <option value="darkslategrey">Dark Slate Grey (JS Puns shirt only)</option> 
            <option value="gold">Gold (JS Puns shirt only)</option> 
            <option value="tomato">Tomato (I &#9829; JS shirt only)</option>
            <option value="steelblue">Steel Blue (I &#9829; JS shirt only)</option> 
            <option value="dimgrey">Dim Grey (I &#9829; JS shirt only)</option> 
          </select>
        </div>                
      </fieldset>

      <fieldset class="activities">
        <legend>Register for Activities</legend>
        <label><input type="checkbox" name="all"> Main Conference — $200</label>
        <label><input type="checkbox" name="js-frameworks"> JavaScript Frameworks Workshop — Tuesday 9am-12pm, $100</label>
        <label><input type="checkbox" name="js-libs"> JavaScript Libraries Workshop — Tuesday 1pm-4pm, $100</label>
        <label><input type="checkbox" name="express"> Express Workshop — Tuesday 9am-12pm, $100</label>
        <label><input type="checkbox" name="node"> Node.js Workshop — Tuesday 1pm-4pm, $100</label>          
        <label><input type="checkbox" name="build-tools"> Build tools Workshop — Wednesday 9am-12pm, $100</label>
        <label><input type="checkbox" name="npm"> npm Workshop — Wednesday 1pm-4pm, $100</label>

      </fieldset>
      <fieldset>
        <legend>Payment Info</legend>

        <label for="payment">I'm going to pay with:</label>
        <select id="payment" name="user_payment">
          <option value="select_method">Select Payment Method</option>
          <option value="credit card">Credit Card</option>
          <option value="paypal">PayPal</option>
          <option value="bitcoin">Bitcoin</option>
        </select>

        <div id="credit-card" class="credit-card">

          <div class="col-6 col">
            <label for="cc-num">Card Number:</label>
              <input id="cc-num" name="user_cc-num" type="text">
          </div>

          <div class="col-3 col">
            <label for="zip">Zip Code:</label>
            <input id="zip" name="user_zip" type="text"> 
          </div>

          <div class="col-3 col">
            <label for="cvv">CVV:</label>
            <input id="cvv" name="user_cvv" type="text"> 
          </div>

          <label for="exp-month">Expiration Date:</label>
          <select id="exp-month" name="user_exp-month">
            <option value="1">1 - January</option>
            <option value="2">2 - February</option>
            <option value="3">3 - March</option>
            <option value="4">4 - April</option>
            <option value="5">5 - May</option>
            <option value="6">6 - June</option>
            <option value="7">7 - July</option>
            <option value="8">8 - August</option>
            <option value="9">9 - September</option>
            <option value="10">10 - October</option>
            <option value="11">11 - November</option>   
            <option value="12">12 - December</option>                         
          </select>
          <label for="exp-year">Expiration Year:</label>
          <select id="exp-year" name="user_exp-year">
            <option value="2016">2016</option>
            <option value="2017">2017</option>
            <option value="2018">2018</option>
            <option value="2019">2019</option>
            <option value="2020">2020</option>                        
          </select>                                  
        </div>

        <div>
            <p>If you selected the PayPal option we'll take you to Paypal's site to set up your billing information, when you click “Register” below.</p>
        </div> 

        <div>
            <p>If you selected the Bitcoin option we'll take you to the Coinbase site to set up your billing information. Due to the nature of exchanging Bitcoin, all Bitcoin transactions will be final.</p>
        </div>                  

      </fieldset>        

      <button type="submit">Register</button>

    </form>

    </div>
  <script src="js/script.js"></script>
</body>
</html>

JavaScript:

// When the page loads, give focus to the first text field.
window.onload = function() {
    document.getElementById("name").focus();
}

// Global variabls
var jobRoleSelection = document.getElementById("title");
var basicInfoSection = document.getElementsByClassName("basicinfo")[0];
var designSelection = document.getElementById("design");
var colorSelection = document.getElementById("color");
var hiddenColorOptions = [];
console.log(jobRoleSelection);
console.log(basicInfoSection);
console.log(designSelection);
console.log(colorSelection);

// "Job Role" section of the form: reveal a text field when the "Other" option is selected from the "Job Role" drop down menu
document.getElementById("title").addEventListener("change", function () {

    // Variable containing the selecting job role from the job role dropdown
    var selectedJobRole = jobRoleSelection.options[jobRoleSelection.selectedIndex].value;
    console.log(selectedJobRole);

    // If the "other" option is selected, display a text field
    if (selectedJobRole === "other") {
        var otherTextField = document.createElement('input');
        otherTextField.setAttribute('id', 'other-title');
        otherTextField.setAttribute('placeholder', 'Your Title');
        otherTextField.setAttribute('type', 'text');

        basicInfoSection.appendChild(otherTextField);
    }

});

// For the T-Shirt color menu, only display the options that match the design selected in the "Design" menu
document.getElementById("design").addEventListener("change", function () {

    // Variable containing the selected option from design
    var selectedDesign = designSelection.options[designSelection.selectedIndex].value;
    console.log(selectedDesign);

    // Variables holding the specific custom design options
    var jsPuns = document.getElementById("design").options[value="js puns"];
    var iHeartJs = document.getElementById("design").options[value="heart js"];
    console.log(jsPuns);
    console.log(iHeartJs);

    // Depending on which design is selected, display the matching colors and hide the colors that do not match design
   if (selectedDesign === jsPuns) {
       // variable containing the color options to show
       //document.getElementById("color").options[value="cornflowerblue, darkslategrey, gold"].style.display = 'block';
       // revision of line 53
       var showColors = document.querySelector("select#color option[value=cornflowerblue, darkslategrey, gold]");
       showColors.style.display = 'block';
       // variable containing the color options to hide
       //document.getElementById("color").options[value="tomato, steelblue, dimgrey"].style.display = 'none';
       // revision of line 57
       var hideColors = document.querySelector("select#color option[value=tomato, steelblue, dimgrey]");
       hideColors.style.display = 'none';
   }

});

So far the colors are not filtering based off of the design selected.

Can you throw up the styles to.

If you create you color options dynamically as a function outside of your listener. When you call the function to populate the selector you can simply pass the shirt value and filter which ones display according to the input. It would also give you more freedom down the road to make changes.

I would write it for you but that would defeat the learning.

Also, I am not seeing an identifiers that would destinigush the colors in groups, ie. tshirtOne or thrtTwo

alborz
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
alborz
Full Stack JavaScript Techdegree Graduate 30,885 Points

Jonathan Ankiewicz Here you go:

/* ================================= 
  Base Element Styles
==================================== */

* {
  box-sizing: border-box;
}

body,
input,
button {
 font-family: 'Roboto', sans-serif;
}

body {
  font: 1em/1.5;
  color: #184f68;
    background: #accbd9;
}

header {
    text-align: center;  
}

h1 {
    font-size: 2.5em;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.45);
    margin: 0;
}

a {
  text-decoration: none;
}

/* ================================= 
  Form Element Styles
==================================== */

form {
    padding: .875em 1.875em 1.875em;
    background: #85b5ca;
}

fieldset,
legend,
button {
    padding: 0;
    border: none;
}

fieldset {
    margin-top: 1.5em;
}

legend,
button {
    font-size: 1.25em;  
}

legend {
    font-weight: 500;
    padding-top: .5em;
    border-top: 2px solid #679cb3;
    margin-bottom: 1.125em;
}

input[type="text"],
input[type="email"],
legend {
    width: 100%;
}

label {
    color: #000;
    display: block;
    margin-bottom: .5em;
}

input,
select {
    margin-bottom: 1.125em; 
}

input {
    font-size: 1em;
    font-weight: 500;
    padding: .8em;
    background: #c1deeb;
    border: 2px solid #c1deeb;
    outline: none;
}

input:focus {
    background: #fff;
    border-color: #5e97b0;
    transition: border-color .4s, background-color .4s;
}

input[type="checkbox"],
input[type="radio"] {
    display: inline-block;
}

button {
    color: #fff;
    padding: .55em 1.25em;
    background: #22627e;
    margin: 1.25em 0 .5em;
    cursor: pointer;
}

button:hover {
    background: #184c62;
}

/* ================================= 
  Page Styles
==================================== */

.container {
    margin: auto;
    max-width: 680px;
}

.shirt div {
    float: left;
    margin-right: .85em;
}

.interests input {
    margin-bottom: 0;
}

.credit-card {
    margin-top: 1.25em;
}

/* ================================= 
  Helper Classes
==================================== */

.is-hidden {
    display: none;
}

.clearfix::after {
  content: " ";
  display: table;
  clear: both;
}

/* ================================= 
  Media Queries
==================================== */

@media (min-width: 0) and (max-width: 679px) {
    header {
        padding: 2em 0;
    }
    button {
        width: 100%;
    }
}

@media (min-width: 680px) {
    header {
        padding: 4.65em 0 2.5em;
    }
    .col {
        float: left;
    }
    .col + .col {
        margin-left: 2.5%;
    }
    .col-3 {
        width: 23%;
    }
    .col-6 {
        width: 49%;
    }
}

3 Answers

You could add a class to each color option and then hide all color options that did not have that class?

<select id="color">
    <option class="puns-op" value="cornflowerblue">Cornflower Blue (JS Puns shirt only)</option>
    <option class="puns-op" value="darkslategrey">Dark Slate Grey (JS Puns shirt only)</option> 
    <option class="puns-op" value="gold">Gold (JS Puns shirt only)</option> 
    <option class="js-op" value="tomato">Tomato (I &#9829; JS shirt only)</option>
    <option class="js-op" value="steelblue">Steel Blue (I &#9829; JS shirt only)</option> 
    <option class="js-op" value="dimgrey">Dim Grey (I &#9829; JS shirt only)</option> 
</select>
if (selectedDesign === jsPuns) {
    var unavailableColors = document.getElementsByClassName("js-op");
    hideColors.style.display = 'none';
}
alborz
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
alborz
Full Stack JavaScript Techdegree Graduate 30,885 Points

Sebastian Haviland I tried but it's still not changing anything. Here's what I have

<div id="colors-js-puns" class="">
          <label for="color">Color:</label>
          <select id="color">
            <option class="puns" value="cornflowerblue">Cornflower Blue (JS Puns shirt only)</option>
            <option class="puns" value="darkslategrey">Dark Slate Grey (JS Puns shirt only)</option> 
            <option class="puns" value="gold">Gold (JS Puns shirt only)</option> 
            <option class="heart" value="tomato">Tomato (I &#9829; JS shirt only)</option>
            <option class="heart" value="steelblue">Steel Blue (I &#9829; JS shirt only)</option> 
            <option class="heart" value="dimgrey">Dim Grey (I &#9829; JS shirt only)</option> 
          </select>
        </div>   
 // Variables holding the specific custom design options
    var jsPuns = document.getElementById("design").options[value="js puns"];
    var iHeartJs = document.getElementById("design").options[value="heart js"];
    console.log(jsPuns);
    console.log(iHeartJs);

    // Depending on which design is selected, display the matching colors and hide the colors that do not match design
   if (selectedDesign === jsPuns) {
       // variable containing the color options to show
       //document.getElementById("color").options[value="cornflowerblue, darkslategrey, gold"].style.display = 'block';
       // revision of line 53
       /*var showColors = document.getElementsByClassName("puns");
       showColors.style.display = 'block';*/
       // variable containing the color options to hide
       //document.getElementById("color").options[value="tomato, steelblue, dimgrey"].style.display = 'none';
       // revision of line 57
       var hideColors = document.getElementsByClassName("heart");
       hideColors.style.display = 'none';
   }

Alborz I'm not sure what else to suggest without looking at the code myself. I'm happy to have a look and help further if you link me to a workspace or codepen.

alborz
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
alborz
Full Stack JavaScript Techdegree Graduate 30,885 Points

Sebastian Haviland Here's my GitHub https://github.com/amesbahi/interactive-form

I've managed to filter the color options, however there's a new problem: when I filter the color options, the default selected option for the color still remains displayed, but when you select the color menu it displays as options the filtered colors -- click the dropdown again and the options disappear but the default color option remains as selected despite which ever design option is selected.

Sorry wish I had more time to work on this for you.

``` var selectedDesign = designSelection.options[designSelection.selectedIndex].value; console.log(selectedDesign);

    // Variables holding the specific custom design options

// Your method of grabbing the value originally wasn't work. This one should work better var jsPuns = document.getElementById("design").value;

//Your if statement comparing jspuns to selectedDesign, these are the same results, this will always render true