Dapoxetine manufacturer's approved product information from DapPremium you can view video goodrx.com. For France use http://edfromparis.com website to help buy priligy in Paris. GiveUpAlready.com - jQuery: Dependant Selects Tutorial
  • Top Authors

    Username Articles Kudos


    Gary Upton-Abbott View Articles 1,477

    Shards View Articles 1,377

    Sr Gregor View Articles 69

    ChaosLight View Articles 22

    I Am View Articles 14

    TheEvilGenius View Articles 9

    eth View Articles 7

    RazoR_ View Articles 6

    LT3 View Articles 6

    Sailor Moon View Articles 6

  • jQuery: Dependant Selects Tutorial

    In the preivious article, we learned how to create a plug-in. In this article we're going to use that pattern to create a dependent selects plug-in.

    A dependent select is when a form select box's options depend on the values of a previous form select box. Two examples of this would be a USA State selector, which then filled the next box with cities from that state. Another example would be a car make selector (ie. Ford) which then displayed models (ie. Taurus, Bronco, F-150).
    Why would you want to do this? Primarily for useability. In the case of car make/model, there are about 130 makes, but there are over 2000 models. If you didn't use javascript, you'd have a model select that was 2279 items long! That's pretty unwieldy.

    Remember the source code for this project is attached at the end! (Both a sample HTML document, and the javascript)


    01: Pick A Data Source

    In making a plug-in like this, your first decision has to be about how it's going to work. Where is the data for the 2nd select going to come from? There are two options:

    * Load Data via AJAX request
    * Store all the data on page in javascript arrays

    In many cases you want your web pages to work without javascript, relying on script to only enhance the user experience. If we use AJAX to load the data, then users without javascript won't see any data in the second or subsequent selects. All 2000+ options is better then no options.



    02: Design the API

    API means "application programming interface" -- or in more simple terms, we mean "how will the plug-in be used?". The first thing I'm going to do is create a call to the mythical plug-in.

    Code:
        $('#master_select').dependent({
            chain : ['#slave_select', '#slave_to_slave_select']
        });
    This syntax makes sense; it allows us to specify a dependent select, and additional selects that would fire in a chain if there's more then one. For example, Country >> State >> City would look like this:

    Code:
        #('#country').dependent({
            chain : ['#state', '#city']
        });


    03: Other Assumptions

    We're going to assume that slaved selects are already pre-populated with data because we want the page to work without javascript.

    We're also going to assume the code for the selects has been set up properly, so our script can know what information is related to what options. To make that happen, we're going to use optgroups. Optgroups are part of HTML that allows you to put a non-selectable label above a group of options in a select. The label of each optgroup will identify which options belong with the choice from the previous select. Here's an example to help make it more clear:

    HTML Code:
        <select id="country">
            <option value="USA">USA</option>
            <option value="Australia">Australia</option>
        </select>
     
        <select id="state">
            <optgroup label="USA">
                <option value="IL">IL</option>
                <option value="TX">TX</option>
            </optgroup>
            <optgroup label="Australia">
                <option value="New South Wales">New South Wales</option>
                <option value="Western Australia">Western Australia</option>
            </optgroup>
        </select>
     
        <select id="city">
            <optgroup label="IL">
                <option value="Chicago">Chicago</option>
                <option value="Springfield">Springfield</option>
            </optgroup>
            <optgroup label="TX">
                <option value="Houston">Houston</option>
                <option value="Dallas">Dallas</option>
            </optgroup>
            <optgroup label="New South Wales">
                <option value="Sydney">Sydney</option>
                <option value="Taree">Taree</option>
            </optgroup>
            <optgroup label="Western Australia">
                <option value="Perth">Perth</option>
                <option value="Albany">Albany</option>
            </optgroup>
        </select>
    Now, imagine that with thirty countries, each with many states/provinces - the number of cities could easily be in the thousands. There could also be duplicate cities - Albany, NY, USA and Albany, Western Australia. This HTML is the format our plug-in will expect the selects to be in.



    04: Processing the Selects

    When the plug-in is called on a select there's not going to be much to do outside of the main this.each loop (see the previous article for the general plug-in architecture). However once we get into the loop, we have to parse the select options and stuff them into an array for later use. The array we're going to put everything in will be stored as opts.data.

    The first thing we're going to process is the selects listed in the chain option. Here's the beginning of our main loop:

    Code:
        this.each(function() {
            $.each(opts.chain, function(index, selectID) {
    In our example, this means we'll be looping over both the #state and #city selects. The data for each select will be stored as an array indexed by the optgroup label for those selects. Imagine it something like this:

    Code:
        array['TX'] = "<option>Dallas</option><option>Houston</option>";
    Each option is not stored separately -- it doesn't have to be. They are stored as option groups since they will be loaded as option groups. Our next few lines of code will help readability, and create the array:

    Code:
        // substr is used to strip off the # at the start of the string
        var ident = selectID.substr(1);
        var selectHTML = $(selectID).html();
     
        opts.data[indent] = {};
    Now we need another loop to move through the select's option groups. Because the variable selectHTML only stores the inside of the select, we're going to wrap it in a select tag when we work with it, for traversal reasons.

    Code:
        $('<select>'+selectHTML+'</select>').find('optgroup').each(function() {
    The previous line will iterate through each optgroup contained in the select we're working on. The next step is to fetch the HTML for the complete optgroup -- including the optgroup tag -- and the optgroup's label. We'll need the label for our array key.

    Code:
        var optGroup = $('<div>').append( $(this).eq(0).clone() ).html();
        var group = $(this).attr('label');
    That first line may seem a bit confusing. Remember there's no "outerHTML" function so we get a little tricky by cloning the tag we wish to extract, put it inside a newly created div, and then extract that div's HTML. This gets us the entire optgroup HTML.

    Then, store optgroup HTML in our data array:

    Code:
        // an example is: opts.data[city][IL] = optGroup's HTML
        opts.data[ident][group] = optGroup;


    05: Binding the events

    Next we need to create some event bindings. If we are linking more then two selects, then the chain will be at least two values. In fact, we need to keep binding selects until the select we're working on doesn't have one following it. Here’s how we'll check for that:

    Code:
        if(opts.chain[index+1]) {
    Within that if statement, we'll bind the select, because we've determined there's a select further down the chain.

    Code:
        $(opts.chain[index]).bind('change', function() {
            // returns the bare ID like "state"
            var next =  opts.chain[index+1].substr(1);
     
            $('#'+next).html(opts.data[next][$(this).val()]);
            $('#'+next).trigger('change');
        });
    If you think back to how we stored the data in our array, it becomes pretty obvious what's going on in this code. The first line gets the name of the next select, which is the 'ident' of our data array - that's the ID we want to change.

    The next line changes the contents of the 'next' select to the optgroup we want. Here's a more readable version of that array value, for clarity:

    Code:
        opts.data[the-next-selects-name][the-current-select-value]
    This pulls up the related optgroup to the selection that was just made.

    The final line triggers the change event in the select because programmatically changing the values of the select does not fire this event. This means when you make a change on any select, it filters all the selects following it in the chain. You can see this pretty clearly in the attached example files, because that code includes 4 dependent selects.



    06: The Last Step

    There's one last step in the main $.each loop -- and outside the loop created for the values of opts.chain. Can you guess what that is? We need to bind the original select passed into the plug-in!

    Code:
        $(this).bind('change', function() {
            var next = opts.chain[0].substr(1);
            $('#'+next).html(opts.data[next][$(this).val()]);
            $('#'+next).trigger('change');
        });


    Conclusion

    Now that you've read the tutorial, have a look at the source code file attached to see the complete code in one place. Because it's packaged as a plug-in you can put the javascript in its own file and include it in any page, and then use it just like any other jQuery plug-in.

    dependent-selects.zip

    In our next jQuery article, we're going to explore turning your standard forms into AJAX submitted forms. We'll continue with the theme of putting our custom code into a reusable plug-in so we can write once and reuse.