Chained Selects
Keywords: dhtml, javascript, menu, select, selection, list, select list, selection list, dropdown, drop-down

Chained Selects Copyright 2004 Xin Yang
Select a vehicle:
Chained Selects lets you "chain" multiple form select lists together so that the selection in a "parent" list can tailor the options available in a "child" list. Chained Selects supports unlimited number of form select lists in a "chain", as well as unlimited number of "chains" in a page. Click [ here ] to download Chained Selects. To implement Chained Selects, you will need to: define the structure of your select options, which would be referred to as a list group include the Chained Selects function script (chainedselects.js) in the page embed the definitions of list groups in the page, or include it if put in a JS file set up the form select lists as usual (or just set up some empty select lists) bind the form select lists to a list group when the page is loaded A list group is like a folder tree. Imagine that you want to "chain" three select lists and you would prepare options for them. It's just like mapping a three-level folder tree to three select lists, the folders/items at top-level will populate the first select list, and when a top-level folder is selected, its sub-folders/sub-items will populate the second select list, and same goes for the third select list. To define a list group, Chained Selects introduces the following function calls: addListGroup("list-group-name", "first-list-name") The "first-list-name" is like the root of the folder tree, and the "list-group-name" will be referred to later when we are to bind form select lists to this list group. addList("first-list-name", "option text", "option value", "sub-list-name", default-selected) This is like adding a top-level folder to the folder tree. This option will populate the first select list binded to the list group. The "default-selected" parameter can be ignored. If supplied, it can be any value (1 would be handy). addOption("first-list-name", "option text", "option value", default-selected) This is like adding a top-level item to the folder tree. This option will populate the first select list binded to the list group. The "default-selected" parameter can be ignored. If supplied, it can be any value. The "addList()" and "addOption()" will be re-used to define options for the second select list and the rest of select lists: addList("sub-list-name", "option text", "option value", "nested-sub-list-name", default-selected) addOption("sub-list-name", "option text", "option value", default-selected) As you might notice, the first parameter in "addList()" and "addOption()" calls refer to some "list-name"s, the "addList()" calls also have a fourth parameter for the name of a nested sub-list. These names should be unique. We could specify many default options in a list (identified by a "list-name"). If such a list is mapping to a single-choice form select list, only the last default option will be taken. If the list is mapping to a multiple-choice form select list, all the default options will be selected. When you finish the definition of a list group, you can define another with the "addListGroup()" call again, followed by a bunch of "addList()" calls and "addOption()" calls. Once you have a list group, you can bind form select lists to it and populate the select lists with options defined in the list group. To do so, you can have: <body onload="initListGroup('list-group-name', select-list-1, select-list-2, ..., 'cookie_name')"> The 'cookie_name' parameter is optional, if provided, will be used as the name prefix of the cookies to store the last selections and resume them for re-visits within the same browser session. If you implement a list group into more than one page with the same 'cookie_name' parameter, those pages can share the last selections within the same browser session. If different 'cookie_name' parameters are used, each page will be able to have its own copy of last selections. If you have more than one list group in a single page, you should have different 'cookie_name' parameters for each list group. If you want to re-use a list group for different sets of select lists in a single page, you can do so like this: <body onload="initListGroup('MyList', select-list-1, select-list-2, 'cookie-A'); initListGroup('MyList', select-list-3, select-list-4, 'cookie-B')"> Following is an example of mapping a list group to some multiple-choice select lists, the same list group for the select lists at page top is re-used here:
Select some vehicles:
Sometimes you might want to do something when an option is picked from the list, to do so, you will need to define a JS callback function and pass the name of the function to the initListGroup() call, for example:
    <head>
    ...
    <script language="javascript">
    function checkList(list, order, instance) {
      alert("List Group Instance Order: " + instance + "\nSelect List Order: " + order + "\nOption Value: " + list.value);
    }
    </script>
    </head>

    <body onload="initListGroup('MyList', select-list-1, select-list-2, 'cookie_name', checkList)">
     ...
The function would be given three parameters: the select list object from which the option is just picked, the order of the select list in the initListGroup() call, and the instance number of the list group. Once such a function is set up, it will be called each time after an option is picked from a list and the sub-lists (if any) are refreshed. Here we re-use the vehicles list group again (the instance order will be 3 as this is the third instance of the same vehicles list group) and simply alert the option just picked:
Select a vehicle:
The callback function can be set up for many purposes. For example, in a frameset case we can put the select lists in the top frame and load a page in the bottom frame when an option is picked. To do so, we can code the callback function this way:
    function loadPage(list, order, instance) {
      if (list.value!="") {
        parent.bottom_frame.location=list.value;
      }
    }
    ...
    <body onload="initListGroup('MyList', select-list-1, select-list-2, 'cookie_name', loadPage)">
Usually the number of select lists should be equal to the number of maximum nested levels in a list group. For a selection that doesn't have sub-options for its "child" select list, its "child" select list and all the "grand-child" select lists will be emptied. When a select list is emptied, you can choose to just leave it there, to disable it or to hide it. To disable empty lists, you can embed the following line before the include line of the function script: var disable_empty_list=true; a disabled list will be enabled when there are some options to pupolate it. To hide empty lists, you can embed the following line before the include line of the function script: var hide_empty_list=true; a hidden list will become visible when there are some options to pupolate it. # Update History: fixed a bug that a disabled sub-list didn't get enabled again ... 2004-10-14. added support of multiple selection ... 2004-08-31. added the option to set up a callback function ... 2004-08-26. added the ability to re-use a list group ... 2004-08-23. fixed a bug in sub-list sharing ... 2004-08-13. added the "cookie_name" parameter ... 2004-07-17. added the "default-selected" parameter ... 2004-06-18. first release ... 2004-04-28.