public/app.js
// Define the function that fires when the fieldToDisplay selector changes.
Define the function that fires when the fieldToDisplay selector changes.
Define the function that fires when the fieldToDisplay selector changes .
function onChangeBehaviorForFieldToDisplaySelector (event)  
  {
    event.preventDefault();
    let selectorElementValues = [];
    document.querySelectorAll(".fieldToDisplay").forEach(function(element) 
    {
      if(element.value != "")
      {
        selectorElementValues.push(element.value);
      }
    });   
    document.querySelectorAll(".fieldToDisplay").forEach(function(element) 
    {
      let optionElements = element.querySelectorAll('option');  
      for (let optionElement of optionElements) 
      {
        if(selectorElementValues.indexOf(optionElement.innerHTML) > -1)
        {
          optionElement.style.display = "none";
        }    
        else
        {
          optionElement.style.display = "list-item";
        }  
      }
    }); 
    let selectorCount = document.querySelectorAll(".fieldToDisplay").length;     
    let optionsCount = document.querySelectorAll(".fieldToDisplay")[0].childElementCount;
    let fieldsCount = optionsCount - 1;
    let noBlanksExist = function ()
    {
      let foundBlank = false;
      document.querySelectorAll(".fieldToDisplay").forEach(function(element)      
      {
        if(element.value == "")
        {
          foundBlank = true;
        }
      });
      if(foundBlank)
      {
        return false;
      }
      else
      {
        return true;
      }
    };
    if(event.target.value == "" && selectorCount > 1)
    {
      event.target.parentNode.parentNode.removeChild(event.target.parentNode);
      selectorCount = selectorCount - 1;
    }    
    if(selectorCount < fieldsCount && noBlanksExist()) 
    {
      let elmnt = document.querySelectorAll(".fieldToDisplayInputWrapper")[selectorCount - 1];
      let cln = elmnt.cloneNode(true);
      document.querySelectorAll(".selectClauseWrapper")[0].appendChild(cln);     
      document.querySelectorAll(".fieldToDisplay")[selectorCount].addEventListener("change", onChangeBehaviorForFieldToDisplaySelector);                 
    }
  } 
function onChangeBehaviorForFieldToDisplaySelector ( event ) { event . preventDefault ( ) ; let selectorElementValues = [ ] ; document . querySelectorAll ( ".fieldToDisplay" ) . forEach ( function ( element ) { if ( element . value != "" ) { selectorElementValues . push ( element . value ) ; } } ) ; document . querySelectorAll ( ".fieldToDisplay" ) . forEach ( function ( element ) { let optionElements = element . querySelectorAll ( 'option' ) ; for ( let optionElement of optionElements ) { if ( selectorElementValues . indexOf ( optionElement . innerHTML ) > - 1 ) { optionElement . style . display = "none" ; } else { optionElement . style . display = "list-item" ; } } } ) ; let selectorCount = document . querySelectorAll ( ".fieldToDisplay" ) . length ; let optionsCount = document . querySelectorAll ( ".fieldToDisplay" ) [ 0 ] . childElementCount ; let fieldsCount = optionsCount - 1 ; let noBlanksExist = function ( ) { let foundBlank = false ; document . querySelectorAll ( ".fieldToDisplay" ) . forEach ( function ( element ) { if ( element . value == "" ) { foundBlank = true ; } } ) ; if ( foundBlank ) { return false ; } else { return true ; } } ; if ( event . target . value == "" && selectorCount > 1 ) { event . target . parentNode . parentNode . removeChild ( event . target . parentNode ) ; selectorCount = selectorCount - 1 ; } if ( selectorCount < fieldsCount && noBlanksExist ( ) ) { let elmnt = document . querySelectorAll ( ".fieldToDisplayInputWrapper" ) [ selectorCount - 1 ] ; let cln = elmnt . cloneNode ( true ) ; document . querySelectorAll ( ".selectClauseWrapper" ) [ 0 ] . appendChild ( cln ) ; document . querySelectorAll ( ".fieldToDisplay" ) [ selectorCount ] . addEventListener ( "change" , onChangeBehaviorForFieldToDisplaySelector ) ; } }
Define the function that fires when the fieldToDisplay selector changes.
Define the function that fires when the fieldToDisplay selector changes .
// Stop it from redirecting anywhere // Start of: Hide options which contain fields that are already displayed on select elements. // 1. Create an empty array to hold the values contained in the select elements. // 2. Look at each select element and store their values in the array. // if the select elements are not blank // Push the values onto the array. // 3. Examine the menu options of the selector having focus and hide any  //    options that exist in the selectElementValues array. //    So if an item has already been selected then it won't show in the  //    list of items to select. // End of: Hide options which contain fields that are already displayed on select elements. // Start of: Remove select elements when blanked out by user or add new blank select elements when needed. // Either of the two lines below will work.  // They both seem to return an array-like objects which are either an HTMLCollection or a NodeList // See the following page for a good explaination of the difference: // http://xahlee.info/js/js_array_vs_nodelist_vs_html_collection.html // querySelectorAll uses css selectors and it returns a NodeList that will respond to many array methods. // On the down side querySelectorAll is a bit slower and returns static elements which has advantages and disadvantages. // getElementsByClassName is a bit faster and it returns live elements but responds to fewer array methods. // See the following pages for a good explaination of what's the difference and how to work with these: // http://xahlee.info/js/js_get_elements.html or https://javascript.info/searching-elements-dom // let selectorCount = document.getElementsByClassName("fieldToDisplay").length;     // Get the amount of options contained in the select element. // Get the amount of fields contained in the select element. // This is the options count minus 1 because there is one option besides the fields. // The blank option is the extra option. // Define a function to check that no blank select elements exist. // Look at each select element to see if any are blank. // Note: getElementsByClassName does not work with .forEach() the way  // querySelectorAll does but it will work with a regular for loop // End of: Define a function that will check that no blank select elements exist. // if the user has selected the blank option and there is more than one select element showing: // Remove the selector and it's wrapper.  // Normally the following would work to remove the selector - event.target.remove; // But we have to go up two ancestors to remove the wrapper as well. // If there are still less selectors than there are fields avaliable for display and there are no blank select elements already: // Clone a new wrapper, the child select element, and children options from the previous and append it to the DOM // Create an event listener for the onchange event of the newly cloned select element and bind this function to it. // End of: Remove select elements when blanked out by user or add new blank select elements when needed. // End of: function onChangeBehaviorForFieldToDisplaySelector (event)