Chained Selects

Chained Selects allows you to "chain" any number of form selection lists together in an interdependent manner, creating a multi-level form menu! Very unique, very powerful.




Over 2000+ free Javascript
at JavaScriptBank.com Website
Sampled by JavaScriptBank.com [ Download ]
Select a vehicle: 

To implement Chained Selects, you will need to:

  1. define the structure of your select options, which would be referred to as a list group
  2. include the Chained Selects function script (chainedselects.js) in the page
  3. embed the definitions of list groups in the page, or include it if put in a JS file
  4. set up the form select lists as usual (or just set up some empty select lists)
  5. 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, value) {
  alert("List Group Instance Order: " + instance + "\nSelect List Order: " + order + "\nOption Value: " + value);
}
</script>
</head>

<body onload="initListGroup('MyList', select-list-1, select-list-2, 'cookie_name', checkList)">
 ...

The function would be given four parameters: the select list object from which the option is just picked, the order of the select list in the initListGroup() call, the instance number of the list group, and the value (separated by comma if many) of the selected option. 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, value) {
  if (value!="") {
    parent.bottom_frame.location=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.



Many server side scripts support form element arrays and usually those elements are named as, for example, cars[]:

  • <select name="cars[]">
    ...
    <select name="cars[]">
so that the server script can refer to them as cars[0], cars[1], etc.

If you have multiple sets of select lists that share the same list content, like the following:

  • <select name="makes[]">
    <select name="types[]">
    <select name="models[]">
    ...
    <select name="makes[]">
    <select name="types[]">
    <select name="models[]">
and your server script would refer to them as makes[0]/types[0]/models[0], ..., makes[n]/types[n]/models[n], then you can use the initListGroups() call once instead of using the initListGroup() call many times, like this:
  • <body onload="initListGroups('vehicles', document.forms[0]['makes[]'], document.forms[0]['types[]'], document.forms[0]['models[]'])">

The initListGroups() also supports cookie and callback function. All the sets of select lists will share the same callback function if defined, but initListGroups() will add an index suffix to the cookie name given so that each set will have its own cookie.

Select 4 vehicles: 
1.
2.
3.
4.


Label is now supported by the following calls:

addList("list_name", "text", "value", "sub_list_name", selected_flag, "label");
addOption("list_name", "text", "value", selected_flag, "label");
addOptGroup("list_name", "label");

If you want to implement the option groups, for example we have:

and the HTML codes would look like this:

<select>
<option>Select a vehicle</option>
<optgroup label="Toyota">
  <option>Cars</option>
  <option>SUVs/Van</option>
  <option>Trucks</option>
</optgroup>
<optgroup label="Honda">
  <option>Cars</option>
  <option>SUVs/Van</option>
</optgroup>
</select>

To do so with CS, we map the <optgroup> to addOptGroup(sub-list, label) and </optgroup> to endOptGroup(sub-list):

addOption("vehicles", "Select a vehicle", "");

addOptGroup("vehicles", "Toyota");
  addOption("vehicles", "Cars", "");
  addOption("vehicles", "SUVs/Van", "");
  addOption("vehicles", "Trucks", "");
endOptGroup("vehicles");

addOptGroup("vehicles", "Honda");
  addOption("vehicles", "Cars", "");
  addOption("vehicles", "SUVs/Van", "");
endOptGroup("vehicles");

and here is an example:

Note: Option group support in CS is disabled for Opera and browsers that don't support DOM.

 

# Update History:

  • fixed some minor bugs ... 2004-12-25.
  • added support of OPTGROUP with addOptGroup() and endOptGroup() ... 2004-12-19.
  • added support of labels ... 2004-12-16.
  • added comma-separated values of selected options as the forth parameter to a callback function ... 2004-12-16.
  • added support of select list arrays with initListGroups() ... 2004-12-07.
  • fixed a bug in creating new options when page is being loaded ... 2004-11-27.
  • 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.