skip to Main Content

I have a select field with the list of countries. And I want to show something ONLY for the US selection, and something else for !US selections. But I also want it to do something else when NOTHING is selected. The problem is, Nothing is also inclusive in a non-US selection.

Thanks in advance. Here’s the code:

var selectedCountry, selectAutograph

$('.country, .autograph').on('change', function() {

  selectedCountry = $('.country').find('option:selected').val();
  selectAutograph = $('.autograph').is(":checked")

  if (selectedCountry === "United States" && !selectAutograph) {
    console.log("Show US Only");
    $(".us").show();
    $(".int, .intauto, .usauto").hide();

  } else if (selectedCountry !== "United States" && !selectAutograph) {
    console.log("Show Int Only");
    $(".int").show();
    $(".us, .intauto, .usauto").hide();

  } else if (selectedCountry === "United States" && selectAutograph) {
    console.log("Show US and Autograph");
    $(".usauto").show();
    $(".intauto, .us, .int").hide();

  } else if (selectedCountry !== "United States" && selectAutograph) {
    console.log("Show Int and Autograph");
    $(".intauto").show();
    $(".usauto, .us, .int").hide();

  } else {
    console.log("Show Nothing");
    $(".intauto, .usauto, .us, .int").hide();
  }
});
.hide {
  display: none;
}
<form id="order-form" method="post" role="form">
  <select class="country" name="country" id="country">
    <option value="Select Country">Select Country</option>
    <option value="United States">United States</option>
    <option value="Canada">Canada</option>
    <option value="United Kingdom">United Kingdom</option>
    <!-- ... -->
    <option value="Zimbabwe">Zimbabwe</option>
  </select>

  <div class="form-check">
    <input class="autograph" type="checkbox" value="" id="autograph" name="autograph">
    <label class="form-check-label"> Add autograph </label>
  </div>
</form>

<div>
  <div class="us hide">
    US shipping
  </div>

  <div class="int hide">
    International shipping
  </div>

  <div class="usauto hide">
    US shipping + add autograph
  </div>

  <div class="intauto hide">
    International shipping + add autograph
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Here’s a JSFiddle as well.

2

Answers


  1. The else will never run because the Select Country country option will run in the selectedCountry !== "United States" && !selectAutograph or selectedCountry !== "United States" && selectAutograph condition, Also you can simplify the code, by adding data atttibutes.

    Please check this.

    var selectedCountry, selectAutograph
     var country = {
       "Select Country": "non",
       "United States": "us",
     }
          
          $('.country, .autograph').on('change', function() {   
    
            selectedCountry = $('.country').find('option:selected').val();     
            selectAutograph = $('.autograph').is(":checked")
            $('[data-autograpgh], [data-country="non-us"], [data-country="us"]').hide()
            if(country[selectedCountry] === "us" && !selectAutograph) {
              $('[data-country="us"]:not([data-autograpgh])').show()
            } else if(!country[selectedCountry] && !selectAutograph)   {
              $('[data-country="non-us"]:not([data-autograpgh])').show()
            } else if(country[selectedCountry] === "us" && selectAutograph)   {
              $('[data-country="us"][data-autograpgh]').show()
            } else if(!country[selectedCountry] && selectAutograph)   {
              $('[data-country="non-us"][data-autograpgh]').show()
            }
                            
          });
    .hide {
      display: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <form  id="order-form" method="post" role="form">
          <select  class="country"  name="country"  id="country" required="">
            <option value="Select Country">Select Country</option>
            <option value="United States">United States</option>
            <option value="Canada">Canada</option>
            <option value="United Kingdom">United Kingdom</option>
            <option value="Zimbabwe">Zimbabwe</option>
          </select>
    
          <div class="form-check">
            <input class="autograph" type="checkbox" value="" id="autograph" name="autograph">
            <label class="form-check-label"> Add autograph </label>
          </div>
        </form>
    
        <div>
          <div class="us hide" data-country="us">
            US shipping                   
          </div>
    
          <div class="int hide" data-country="non-us">
            International shipping                                    
          </div> 
    
          <div class="usauto hide" data-country="us" data-autograpgh>
            US shipping + add autograph
          </div>  
    
          <div class="intauto hide" data-country="non-us" data-autograpgh>
            International shipping + add autograph
          </div>
        </div>
    Login or Signup to reply.
  2. While you’ve already accepted an answer, I wanted to offer an alternative approach:

    // creating an Object in which we can access properties
    // of individual countries; the key of each object is
    // the value from the <select> element:
    const countries = {
      us: {
        country: 'United States',
        international: false,
      },
      canada: {
        country: 'Canada',
        international: true,
      },
      uk: {
        country: 'United Kingdom',
        international: true,
      },
      zimbabwe: {
        country: 'Zimbabwe',
        international: true,
      }
    };
    
    // caching the elements:
    let countrySelect = $('.country'),
      autograph = $('.autograph');
    
    // binding the anonymous function of the on() method as the event-handler
    // for the 'change' event:
    $('.country, .autograph').on('change', function() {
      // hiding the children of the '.details' element:
      $('.details > *').hide();
    
      // retrieving the selected <option> element:
      let selectedOption = countrySelect.find(':selected');
    
      // HTMLOptionElement.defaultSelected is a Boolean property which is
      // true if the <option> had the selected attribute on page-load, or
      // false if the <option> did not have the 'selected' attribute on
      // page-load:
      if (selectedOption.prop('defaultSelected')) {
        // all elements are now hidden by default in the function,
        // so no action taken except for logging a statement to the
        // console:
        console.log("No country selected.");
      } else {
        // here we retrieve the value of the selected <option>:
        let value = selectedOption.val(),
          // using destructuring to declare the variables that
          // are also property-names from the countries[value]
          // property-value:
          {
            country,
            international
          } = countries[value],
          // determining whether the checkbox is checked, the
          // .is() method returns a Boolean reflecting that
          // the collection matches the supplied selector:
          withAutograph = autograph.is(':checked'),
    
          // here we create the CSS selector, using a template-literal String;
          // the first conditional operator tests whether the 'international'
          // variable is true; if yes this returns the string 'int', otherwise
          // returning the string 'us'
          // the second conditional tests to see if 'withAutograph' is true,
          // if so returning the string 'auto', othewise an empty string:
          selector = `.${international ? 'int' : 'us'}${withAutograph ? 'auto' : ''}`;
    
        // we then use that selector, and call the show() method:
        $(selector).show();
      }
    });
    .hide {
      display: none;
    }
    <form id="order-form" method="post" role="form" action="#">
      <select class="country" name="country" id="country">
        <option value="Select Country" selected>Select Country</option>
        <!--
            Here I've changed the value to a lower-case single string, in
            order to reduce the chance of a mis-typed white-space character
            causing trouble elsewhere, and use an abbreviation where
            possible/obvious to do so:
        -->
        <option value="us">United States</option>
        <option value="canada">Canada</option>
        <option value="uk">United Kingdom</option>
        <option value="zimbabwe">Zimbabwe</option>
      </select>
    
      <div class="form-check">
        <input class="autograph" type="checkbox" value="" id="autograph" name="autograph">
        <label class="form-check-label"> Add autograph </label>
      </div>
    </form>
    
    <!--
        This element was given a class-name ('details') in order to easily hide
        the contents without having to refer to them individually:
    -->
    <div class="details">
      <div class="us hide">
        US shipping
      </div>
    
      <div class="int hide">
        International shipping
      </div>
    
      <div class="usauto hide">
        US shipping + add autograph
      </div>
    
      <div class="intauto hide">
        International shipping + add autograph
      </div>
    </div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    JS Fiddle demo.

    This is, of course, perfectly possible with plain JavaScript:

    // caching a reference to the document, along with some utility
    // helper functions to simplify life (and reduce typing):
    const D = document,
      // here we define an alias for querySelector(), which will use
      // either document.querySelector() or element.querySelector()
      // depending on whether a context is passed to the function;
      // if no context is passed document.querySelector() will be
      // used, otherwise with a context that Element will be used:
      get = (sel, context = D) => context.querySelector(sel),
      // as above, but here we call querySelectorAll() and return
      // the retrieved NodeList as an Array of Nodes in order to
      // utilise Array methods:
      getAll = (sel, context = D) => [...context.querySelectorAll(sel)],
      // creating an Object in which we can access properties
      // of individual countries; the key of each object is
      // the value from the <select> element:
      countries = {
        us: {
          country: 'United States',
          international: false,
        },
        canada: {
          country: 'Canada',
          international: true,
        },
        uk: {
          country: 'United Kingdom',
          international: true,
        },
        zimbabwe: {
          country: 'Zimbabwe',
          international: true,
        }
      };
    
    // caching the elements:
    let countrySelect = get('.country'),
      autograph = get('.autograph'),
      // the change-handling function:
      changeHandler = (evt) => {
        // hiding the children of the '.details' element:
        getAll('.details > *').forEach(
          (el) => el.classList.add('hide')
        );
    
        // retrieving the selected <option> element, with CSS
        // the selected <option> matches the :checked pseudo-
        // class, and we're looking within the context of the
        // countrySelect <select> element:
        let selectedOption = get(':checked', countrySelect);
    
        // HTMLOptionElement.defaultSelected is a Boolean property which is
        // true if the <option> had the selected attribute on page-load, or
        // false if the <option> did not have the 'selected' attribute on
        // page-load:
        if (selectedOption.defaultSelected) {
          // all elements are now hidden by default in the function,
          // so no action taken except for logging a statement to the
          // console:
          console.log("No country selected.");
        } else {
          // here we retrieve the value of the selected <option>:
          let value = selectedOption.value,
            // using destructuring to declare the variables that
            // are also property-names from the countries[value]
            // property-value:
            {
              country,
              international
            } = countries[value],
            // determining whether the checkbox is checked, the
            // property itself returns a Boolean indicating whether
            // the node is checked (true) or unchecked (false):
            withAutograph = autograph.checked,
    
            // here we create the CSS selector, using a template-literal String;
            // the first conditional operator tests whether the 'international'
            // variable is true; if yes this returns the string 'int', otherwise
            // returning the string 'us'
            // the second conditional tests to see if 'withAutograph' is true,
            // if so returning the string 'auto', othewise an empty string:
            selector = `.${international ? 'int' : 'us'}${withAutograph ? 'auto' : ''}`;
    
          // here we retreive all elements matching the selector, and then use
          // Array.prototype.forEach() to iterate over that Array of Nodes with
          // an Arrow function:
          getAll(selector).forEach(
            // here we pass in a reference to the current Node of the Array,
            // and we remove the 'hide' class-name from the Element's classList:
            (el) => el.classList.remove('hide')
          );
    
        }
      };
    
    // using Array.prototype.forEach() to iterate over the Array-literal which
    // contains both interactive elements with which the user interacts:
    [countrySelect, autograph].forEach(
      // binding the changeHandler function as the event-handler for the 'change' event:
      (el) => el.addEventListener('change', changeHandler)
    );
    .hide {
      display: none;
    }
    <form id="order-form" method="post" role="form" action="#">
      <select class="country" name="country" id="country">
        <option value="Select Country" selected>Select Country</option>
        <!--
            Here I've changed the value to a lower-case single string, in
            order to reduce the chance of a mis-typed white-space character
            causing trouble elsewhere, and use an abbreviation where
            possible/obvious to do so:
        -->
        <option value="us">United States</option>
        <option value="canada">Canada</option>
        <option value="uk">United Kingdom</option>
        <option value="zimbabwe">Zimbabwe</option>
      </select>
    
      <div class="form-check">
        <input class="autograph" type="checkbox" value="" id="autograph" name="autograph">
        <label class="form-check-label"> Add autograph </label>
      </div>
    </form>
    
    <!--
        This element was given a class-name ('details') in order to easily hide
        the contents without having to refer to them individually:
    -->
    <div class="details">
      <div class="us hide">
        US shipping
      </div>
    
      <div class="int hide">
        International shipping
      </div>
    
      <div class="usauto hide">
        US shipping + add autograph
      </div>
    
      <div class="intauto hide">
        International shipping + add autograph
      </div>
    </div>

    References:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search