Question

I am trying to create a series of 3 chained selects where further selects are hidden until the previous one is chosen. I am using the plugin chained select and trying to add my own code for the hidden part.

Example:

3 chained selects

1 - visible 2 - hidden 3 - hidden

When I choose an option from 1, 2 is populated with the appropriate choices and is shown. The problem is that 3 is also being shown. 3 is set to be shown when 2 is changed. The plugin technically changes 2 when 1 is changed, because it populates the appropriate options (chain).

The plugin automatically disables the select boxes until the previous one has a selection made on it, so I tried to figure out something where disabled select boxes are hidden (so that I didn't have to use the onchange/div thing) but so far I've had no luck figuring that one out.

Is there are way to hide disabled elements (select box) and show them when they are enabled by the plugin?

Or is there any way of preventing the plugin from triggering the onchange event that shows the next div? (Allowing the plugin to populate the select without having that change trigger the onchange event.)

Here is the code. Thank you.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head> 
    <title>SoSleep: V1</title> 

<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />

    <script src="./code/jquery-1.10.2.min.js"></script>
    <script src="./code/jquery.mobile-1.3.1.min.js"></script>

    <script>

$(document).ready(function(){
    $(".2").hide();

  $(".destination").change(function(){
    $(".2").show();
  });
});

$(document).ready(function(){
    $(".3").hide();

  $(".guide").change(function(){
    $(".3").show();
  });
});

</script>

    </head>

<body>

<div id="sosleep">

<div class="1">
<h2>Destination</h2>
<select class="destination" name="Destination">
  <option value="" selected="selected">Destination</option>
  <option value="southern">Southern Sleep</option>
  <option value="city">City Sleep</option>
</select>
</div>

<div class="2">
<h2>Guide</h2>
<select class="guide" name="Guide">
  <option value="" selected="selected">Guide</option>
  <option value="jay" class="southern">Jay</option>
  <option value="annie" class="southern">Annie</option>
  <option value="aron" class="city">Aron</option>
  <option value="sally" class="city">Sally</option>
    <option value="none" class="southern city">None</option>
</select>
</div>

<div class="3">
<h2>Background</h2>
<select class="background" name="Background">
  <option value="" selected="selected">Background</option>
  <option value="Crickets" class="jay annie none">Crickets</option>
  <option value="Traffic" class="aron sally none">Traffic</option>
  <option value="Rain" class="jay annie aron sally none">Rain</option>
  <option value="None" class="jay annie aron sally">None</option>
</select>
</div>



</div>

  <xscript src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
  <script src="./code/jquery.chained.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript" charset="utf-8">

  $(function() {

    /* For jquery.chained.js */
    $(".guide").chained(".destination");
    $(".background").chained(".guide");

    });

  </script>

</body>

</html>

And here is the code for the plugin:

/* jshint -W098 */

/*
 * Chained - jQuery / Zepto chained selects plugin
 *
 * Copyright (c) 2010-2013 Mika Tuupola
 *
 * Licensed under the MIT license:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Project home:
 *   http://www.appelsiini.net/projects/chained
 *
 * Version: 0.9.8
 *
 */

;(function($, window, document, undefined) {
    "use strict";

    $.fn.chained = function(parent_selector, options) {

        var settings = $.extend( {}, $.fn.chained.defaults, options);

        return this.each(function() {

            /* Save this to self because this changes when scope changes. */
            var self   = this;
            var backup = $(self).clone();

            /* Handles maximum two parents now. */
            $(parent_selector).each(function() {

                $(this).bind("change", function() {
                    $(self).html(backup.html());

                    /* If multiple parents build classname like foo\bar. */
                    var selected = "";
                    $(parent_selector).each(function() {
                        if ($(":selected", this).val()) {
                            selected += "\\" + $(":selected", this).val();
                        }
                    });
                    selected = selected.substr(1);

                    /* Zepto class regexp dies with classes like foo\bar. */
                    if (window.Zepto) {
                        selected = selected.replace("\\", "\\\\");
                    }
                    /* Also check for first parent without subclassing. */
                    /* TODO: This should be dynamic and check for each parent */
                    /*       without subclassing. */
                    var first;
                    if ($.isArray(parent_selector)) {
                        first = $(parent_selector[0]).first();
                    } else {
                        first = $(parent_selector).first();
                    }
                    var selected_first = $(":selected", first).val();

                    $("option", self).each(function() {
                        /* Remove unneeded items but save the default value. */
                        if (!$(this).hasClass(selected) &&
                            !$(this).hasClass(selected_first) && $(this).val() !== "") {
                                $(this).remove();
                        }
                    });

                    /* If we have only the default value disable select. */
                    if (1 === $("option", self).size() && $(self).val() === "") {
                        $(self).attr("disabled", "disabled");
                    } else {
                        $(self).removeAttr("disabled");
                    }
                    $(self).trigger("change");
                });

                /* Force IE to see something selected on first page load, */
                /* unless something is already selected */
                if (!$("option:selected", this).length) {
                    $("option", this).first().attr("selected", "selected");
                }

                /* Force updating the children. */
                $(this).trigger("change");

            });
        });
    };

    /* Alias for those who like to use more English like syntax. */
    $.fn.chainedTo = $.fn.chained;

    /* Default settings for plugin. */
    $.fn.chained.defaults = {};

})(window.jQuery || window.Zepto, window, document);

EDIT: The selected answer works perfectly for me, with the following changes:

$(document).ready(function () {
    $(".2").hide();
    $(".destination").change(function () {
        if ($(".guide").is(":enabled")) {
            $(".2").show();
        }
    });
});

$(document).ready(function () {
    $(".3").hide();
    $(".guide").change(function () {
        if ($(".background").is(":enabled")) {
            $(".3").show();
        }
    });
});
Was it helpful?

Solution

You can check if the select is enabled during the change handler before showing the div...

$(document).ready(function () {
    $(".2").hide();
    $(".destination").change(function () {
        if ($(".2 select").is(":enabled")) {
            $(".2").show();
        }
    });
});

$(document).ready(function () {
    $(".3").hide();
    $(".guide").change(function () {
        if ($(".3 select").is(":enabled")) {
            $(".3").show();
        }
    });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top