2

Based on post here on StackOverflow, I am trying to make a drop down menu, which contents depends on the selection of another drop down menu.

Fortunately the solution I found, is very applicable to my problem, although I originally do get my drop down menu options from a database. Less fortunately however, is that I cannot seem to get the solution to work.

Both menus are correctly read from the database, and converted to the correct HTML-code. So what seems to fail is the JavaScript which is used to filter the options in the second drop down menu. My code is as following:

<div id="selection">
    <?php
        // Top level part selection
        echo "<select name='firstLevelParts' id='select1'>";
        foreach ($category_primary as $category_item):
            echo "<option value = '".$category_item['cat_primary_id']."'>".$category_item['cat_primary_name']."</option>";
        endforeach;
        echo "</select>";


        // Second level part selection (This should be updated, based on selection in top level menu)
        echo "<select name='secondLevelParts' id='select2'>";
        foreach ($category_secondary as $cat_sec_item):
             echo "<option value='".$cat_sec_item['cat_secondary_code']."'>".$cat_sec_item['cat_secondary_name']."</option>"; 
        endforeach;
        echo "</select>";
    ?>

</div>


<script>
    $("#select1").change(function() { 
        if(typeof $(this).data('options') === "undefined")){
            /*Taking an array of all options-2 and kind of embedding it on the select1*/
            $(this).data('options',$('#select2 option').clone());
            } 
        var id = $(this).val();
        var options = $(this).data('options').filter('[value=' + id + ']');
        $('#select2').html(options);
    });
</script>

I really hope you can help me locating the flaw in my code, I really annoys the heck out of me...

Update - Per request, here is the resulting HTML-code, I can't really give you the page url, as it lies behind password protection:

<div id="selection">
<select name='firstLevelParts' id='select1'>
 <option value = '1'>Terræn</option>
 <option value = '2'>Fundamentsystem</option>
 <option value = '3'>Vægsystem</option>
 <option value = '4'>Dæksystem</option>
 <option value = '5'>Tagsystem</option>
</select>

<select name='secondLevelParts' id='select2'>
 <option value='1'>Jordprofil</option>
 <option value='2'>Befæstet Areal</option>
 <option value='3'>Beplantning</option>
 <option value='1'>Fundamentkonstruktion</option>
 <option value='2'>Bærelag</option>
 <option value='3'>Åbning</option>
 <option value='4'>Lukning</option>
 <option value='5'>Inddækning</option>
 <option value='6'>Afslutning</option>
 <option value='7'>Afskærmning</option>
 <option value='8'>Fuge</option>
 <option value='9'>Samling</option>
 <option value='10'>Overflade</option>
</select>  
</div>

<script>
    $("#select1").change(function() { 
        if(typeof $(this).data('options') === "undefined")){
            /*Taking an array of all options-2 and kind of embedding it on the select1*/
            $(this).data('options',$('#select2 option').clone());
            } 
        var id = $(this).val();
        var options = $(this).data('options').filter('[value=' + id + ']');
        $('#select2').html(options);
    });
</script> 
Community
  • 1
  • 1
Jakob Busk Sørensen
  • 5,599
  • 7
  • 44
  • 96

3 Answers3

2

Adapted from this solution to a similar problem the below should do what you want:

$(function() {
  $('#select').filterByValues( $('.filterElements') );
  $('.filterElements').change();
});  


jQuery.fn.filterByValues = function(masterSelects) {
  return this.each(function() {
    var select = this;
    var options = [];
    $(select).find('option').each(function() {
      options.push({value: $(this).val(), text: $(this).text()});
    });
    $(select).data('options', options);
    
    masterSelects.bind('change', function() {
      var options = $(select).empty().scrollTop(0).data('options');
      var vals=[];
      $(masterSelects).each(function(i,e){
        vals.push('^'+$.trim($(e).val())+'$' );
       });
      var search = vals.join('|');
      var regex = new RegExp(search,'gi');

      $.each(options, function(i) {
        var option = options[i];
        if(option.value.match(regex) !== null) {
          $(select).append(
             $('<option>').text(option.text).val(option.value)
          );
        }
      });
    });
    
  });
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="selection">
<select name='firstLevelParts' class='filterElements'>
 <option value = '0'>(Select category)</option> <!-- added -->
 <option value = '1'>Terræn</option>
 <option value = '2'>Fundamentsystem</option>
 <option value = '3'>Vægsystem</option>
 <option value = '4'>Dæksystem</option>
 <option value = '5'>Tagsystem</option>
</select>
  
<select name='firstLevelPartsB'  class='filterElements'>
 <option value = '0'>(Select category)</option> <!-- added -->
 <option value = '1'>Terræn</option>
 <option value = '2'>Fundamentsystem</option>
 <option value = '3'>Vægsystem</option>
 <option value = '4'>Dæksystem</option>
 <option value = '5'>Tagsystem</option>
</select>

<select name='secondLevelParts' id='select'>
 <option value='1'>Jordprofil</option>
 <option value='2'>Befæstet Areal</option>
 <option value='3'>Beplantning</option>
 <option value='1'>Fundamentkonstruktion</option>
 <option value='2'>Bærelag</option>
 <option value='3'>Åbning</option>
 <option value='4'>Lukning</option>
 <option value='5'>Inddækning</option>
 <option value='6'>Afslutning</option>
 <option value='7'>Afskærmning</option>
 <option value='8'>Fuge</option>
 <option value='9'>Samling</option>
 <option value='10'>Overflade</option>
</select>  
</div>
Wesley Smith
  • 19,401
  • 22
  • 85
  • 133
  • This actually seems to work. Does it have any advangtes/disadvantages compared to my original solution? (Besides the obvious fact that it actually works...) – Jakob Busk Sørensen Feb 08 '15 at 12:18
  • @Noceo it should be more efficient and it's basically a plug-in so it's extremely re-usable, just call `$('#select2').filterByValue($('#select1'), true);` and supply the elements to filter by and on. – Wesley Smith Feb 08 '15 at 12:22
  • Thanks, one last question if I might... I am trying to add an option called "(Select category)" in menu one, which have value zero, and should allow only one option (of the same name) to be shown in menu two. Should this not be possible just by having them use value="0" ? – Jakob Busk Sørensen Feb 08 '15 at 12:43
  • 1
    Yes, you can do this, just make sure to call `$('#select1').change();` right after you call the plugin, that way it will clear the options that are visible when the page loads, I updated my answer to show this – Wesley Smith Feb 08 '15 at 12:48
  • More problems :-). Is it possible to have two set of values for menu two? One which matches menu one values (as in what you posted) and a second set of values which is related to a third menu? – Jakob Busk Sørensen Feb 08 '15 at 13:03
  • Edited to allow any number of select boxes to be used to filter the final select box. Just give any select box you want to act as a filter the `filterElements` class then call `$('#select').filterByValues( $('.filterElements') );` – Wesley Smith Feb 08 '15 at 13:23
0

I think, that problem is in simple error in your syntax - you have extra ")" in your condition if(typeof $(this).data('options') === "undefined")){

Here is your jsfiddle without this error - it works: http://jsfiddle.net/dn7fLny5/

EDIT: You can attach your hanlders after DOM ready like this:

<script>
    $(document).ready(function() {
        $("#select1").change(function() { 
            // your code
        });
    });
</script>
rakhmanoff
  • 349
  • 1
  • 3
  • 13
  • Just noticed that myself, however removing it did not seem to change anything, which makes me wonder if it even tries to run the script... – Jakob Busk Sørensen Feb 08 '15 at 12:00
  • Did you use $(document).ready(function() {...}) for attach your handlers? – rakhmanoff Feb 08 '15 at 12:08
  • No, and now I have the feeling that I should have... Where does this go? Found something about in on this page: http://learn.jquery.com/using-jquery-core/document-ready/ - but I am still kinda new to JavaScript. – Jakob Busk Sørensen Feb 08 '15 at 12:11
0

I hope I'm understanding your question correctly, but it sounds like what you want is actually a use case supported by the Select3 library, though it presents the choices in nested dropdowns rather than separated select boxes.

Just take a look at the fourth example on that page (titled 'Select a city by timezone') and see if it does what you want. If you have any other questions on how to set it up, I'm open for questions!

arendjr
  • 679
  • 6
  • 12
  • Not sure if it is exactly what I was looking for, but its definitely something I can use for other parts of the projects, so thanks. The issue right now is that I have a 3 layer category system, where you first need to select the top category, then the middle and then the bottom. And the options of the middle category depends on top and the options of bottom depends on the middle. So its sort of like a 3 layer dependency system... – Jakob Busk Sørensen Feb 16 '15 at 06:59