vxp has asked for the wisdom of the Perl Monks concerning the following question:


I am trying to do dynamic dropdown menu, of sorts. The idea is to have a dropdown menu like the one visible on nvidia drivers download page. You select the first choice, and then depending on what your first choice was, a second dropdown menu gets populated with possible choices/options that are 'related' to the first choice. Um. Yeah, I'm not being very articulate at describing this..Here's what I have now, which is pretty much a code snippet to generate a dropdown menu with choices in @distros. Basically I need some pointers, if possible, on what to do next to achieve the goal above. People choose "centos", for instance - so a second dropdown generates choices with centos versions. Somebody chooses "ubuntu" - a second dropdown gets generated with available ubuntu versions.. etc.


if ( !param() ) { print start_form(); print popup_menu( -name => 'distros_menu', -values => \@distros, -default => 'centos' ); print submit('which_distro_button'); print endform; } else { $which_radio_button = param('distros_menu'); print $which_radio_button; $q->end_html; }

Replies are listed 'Best First'.
Re: and dynamic dropdown menus
by Your Mother (Bishop) on Aug 15, 2009 at 20:43 UTC

    This is really a JavaScript question. You can indeed write the dropdowns in Perl and might want to depending on what you're doing but to dynamically update (reveal, hide, switch lists) the dropdowns you have to use JS.

    I highly recommend jQuery for this. It's ideal for this sort of DOM manipulation. You could write all the fields to the page in your CGI with Perl and hide them with CSS, then use JS to reveal/switch them as you need.

Re: and dynamic dropdown menus
by thunders (Priest) on Aug 16, 2009 at 02:57 UTC
    This is definitely something that requires Javascript. Here's a self-contained example to get you started. If you need to generate the values in the select boxes dynamically you could either dynamically generate the "osMap" data structure in your CGI, or better yet write a web service that returns just that structure as JSON via a XMLHttpRequest. If you need to do a lot of work like this, I highly recommend investing some time in learning a javascript toolkit like Dojo.
    <html> <body> Operating System: <select id="os" onchange="changeOS"> <option>--Choose OS--</option> </select><br/> Flavor:<select id="variant"></select> <script> var osMap = { "Windows":["95","98","NT","ME","2000","XP","Vista"], "Mac":["OS9","OSX(PPC)","OSX(x86)"], "Linux":["RedHat","Ubuntu","Debian","Slackware"] }; var osselect = document.getElementById('os'); var i=1; for (os in osMap){ osselect.options[i++] = new Option(os) } osselect.onchange = function(){ var variant = document.getElementById('variant'); var flavors = osMap[this.options[this.selectedIndex].value]; variant.length = 0; if(flavors){ for(i = 0; i<flavors.length;i++){ variant.options[i] = new Option(flavors[i]); } } } </script> </body> </html>
Re: and dynamic dropdown menus
by Trimbach (Curate) on Aug 16, 2009 at 03:20 UTC
    You can do this in pure Perl, too... you just have to refresh the screen following each selection. I might do it something like this:
    my %options = ( main => ["option1", "option2", "option3"], option1 => ["option1a", "option1b", "option1c"], option2 => ["option2a", "option2b", "option2c"], option3 => ["option3a", "option3b", "option3c"] ); if ( !param() ) { $values_ref = $options{'main'}; } else { $values_ref = $options{param('distros_menu')}; } print start_form(); print popup_menu( -name => 'distros_menu', -values => $values_ref, ); print submit('which_distro_button'); print endform;
    But that takes you down the road of outputting HTML via, which will eventually make you want to take your own life. Better would be to use a template like HTML::Template and just output different values to the template on each refresh. Best solution though is probably either a pure JS or an AJAX-style solution (as already suggested), as it presents a better experience for the user.

    Gary Blackburn
    Trained Killer