SELECT Grouping Proposal

Last Revised 10-19-97

BACKGROUND:

Some HTML documents include forms with very long selection menus. The large number of options on these menus makes them hard to browse when using speech-based browsers or browsers that show a few words at a time in a very large print. And grouped lists have long been a standard navigational system for most UAs.

A possible solution is to find a way to break up such menus into smaller labeled pieces. This would be done by allowing authors to group options and to add labels to these groups. This can be done in such a way as avoid problems for people using existing browsers. Authors would need to consider both old and new browsers when writing HTML pages.

Regular windows based browsers would be able to render option groups in a variety of ways, e.g. horizontal rules between groups, slide-right menus as used by Windows 95, or tabbed dialogs. Everyone wins, including people with disabilities.


PROPOSALS:

The changes to HTML required for this basically involve adding one new element to be called OPTGROUP which represents a group of options. The WAI-HC list has been discussing two proposals.


PROPOSAL ONE - CONTAINER:

One approach is to use OPTGROUP as a container for the OPTION elements that define the options in each group. To allow for hierarchically nested option groups, the OPTGROUP elements can be nested. Each option group can be labeled using an attribute called, naturally enough, "label".

Authors provide labels for options that make sense when viewed with older browsers. In the absence of the context provided by the option groups, these labels need to spell-out the full meaning of each option. For newer browsers that do show the option groups, this would make the options look rather long winded. To deal with this, the label attribute is also added to the OPTION element. Newer browsers use this attribute, when present, in preference to the element's content when fetching the label for each option.

This proposal makes the option group structure immediately apparent in the markup, particularly so if the elements are indented to reflect the level of nesting.

Example:

 <SELECT name="ComOS">
   <OPTGROUP label="Comm Servers">
     <OPTGROUP label="PortMaster 3">
       <OPTION label="3.7.1" value="pm3_3.7.1">PortMaster 3 with ComOS 3.7.1
       <OPTION label="3.7" value="pm3_3.7">PortMaster 3 with ComOS 3.7
       <OPTION value="pm3_3.5">PortMaster 3 with ComOS 3.5
     </OPTGROUP>
     <OPTGROUP label="PortMaster 2">
       <OPTION label="3.7" value="pm2_3.7">PortMaster 2 with ComOS 3.7
       <OPTION label="3.5" value="pm2_3.5">PortMaster 2 with ComOS 3.5
     </OPTGROUP>
   </OPTGROUP>
   <OPTGROUP label="Comm Servers">
     <OPTGROUP label="IRX">
       <OPTION label="3.7R" value="IRX_3.7R">IRX with ComOS 3.7R
       <OPTION label="3.5R" value="IRX_3.5R">IRX with ComOS 3.5R
     </OPTGROUP>
   </OPTGROUP>
 </SELECT>

On your UA this renders as:

Users of old browsers might see:
+-----------------------------+
|PortMaster 3 with ComOS 3.7.1|
|PortMaster 3 with ComOS 3.7  |
|PortMaster 3 with ComOS 3.5  |
|PortMaster 2 with ComOS 3.5  |
|PortMaster 2 with ComOS 3.7  |
|IRX with ComOS 3.7R          |
|IRX with ComOS 3.5R          |
+-----------------------------+

While users with new browsers might see:
+-------------+
|Comm Servers>|
|Routers>     |
+--------------+

If a user were to them go to 'Comm Servers' it might be:
+-------------+
|Comm Servers>+-------------+
|Routers>     |PortMaster 3>|
+-------------|PortMaster 2>|
              +-------------+

'PortMaster 3' would then expand to:
+-------------+
|Comm Servers>+-------------+
|Routers>     |PortMaster 3>+-----+
+-------------|PortMaster 2>|3.7.1|
              +-------------|3.7  |
                            |3.5  |
                            +-----+

PROPOSAL TWO - AXIS/AXES:

Another proposal is to make OPTGROUP an empty element like BR, and to use attributes to markup which OPTGROUP each OPTION belongs. To allow for nested option groups, you can also state which OPTGROUP's a given OPTGROUP belongs. Each OPTGROUP is given a unique name with the ID attribute. The axes attribute for OPTION and OPTGROUP lists a set of ID values that name the groups the element belongs to. The option group label is stated using the label attribute on each OPTGROUP.

Example:

 <SELECT name="ComOS">
   <OPTGROUP id="master1" axis="Product Type" label="Comm Servers">
   <OPTGROUP id="master2" axis="Product Type" label="Routers">
   <OPTGROUP id="group1" axes="master1" axis="Model" label="PortMaster3">
   <OPTGROUP id="group2" axes="master1" axis="Model" label="PortMaster2">
   <OPTGROUP id="group3" axes="master2" axis="Model" label="IRX">
     <OPTION axes="group1" axis="ComOS" label="3.7.1">3.7.1
     <OPTION axes="group1 group2" axis="ComOS" label="3.7">3.7
     <OPTION axes="group1 group2" axis="ComOS" label="3.5">3.5
     <OPTION axes="group3" axis="ComOS" label="3.7R">3.7R
     <OPTION axes="group3" axis="ComOS" label="3.5R">3.5R
 </SELECT>

On your UA this renders as:

In any older UA it might simply be:
+-----+
|3.7.1|
|3.7  |
|3.5  |
|3.7R |
|3.5R |
+-----+

A newer UA might present something like:
+-------------+
|Comm Servers>|
|Routers>     |
+--------------+

If a user were to them go to 'Comm Servers' it might be:
+-------------+
|Comm Servers>+-------------+
|Routers>     |PortMaster 3>|
+-------------|PortMaster 2>|
              +-------------+

'PortMaster 3' would then expand to:
+-------------+
|Comm Servers>+-------------+
|Routers>     |PortMaster 3>+-----+
+-------------|PortMaster 2>|3.7.1|
              +-------------|3.7  |
                            |3.5  |
                            +-----+

COMMONALITY:

In both cases, non-graphic UAs could build a hierarchy, as they can with tables under HTML 4.0:

Comm Servers
	PortMaster 3
		3.7.1
		3.7
		3.5
	PortMaster 2
		3.7
		3.5
Routers
	IRX
		3.7R
		3.5R

Both proposals allow for OPTION grouping and directed navigation.


DIFFERENCES:

The primary difference between the two proposals are case where differentiation is not important, or not desirable. Where an author would want the same option to be presented in two places. The container proposal forces differentiation be the nature of not allowing duplicate OPTION entries. The axis/axes proposal allows a single OPTION to be a member of multiple groups. If the same value is listed twice but in separate groups, older UAs will repeat it in the collapsed list, which may not be what the author wants.

The axis/axes proposal also appears to allow for a more precise hierarchy to be constructed. Allowing users to explicitly label each AXIS. For example a UA may take this example and form:

Product Type: Comm Servers
	Model: PortMaster 3
		ComOS: 3.7.1
		       3.7
		       3.5

The first issue - differentiation/repetition - is probably not exceedingly common. And it is probably tolerable for the cases where it would occur. But it would be good to get more input on this issue.

The second issue - additional hierarchical information - is vague at this point. Would this benefit accessibility?

The price for these two features is greater complexity to the markup. Containers explicitly group, while axis/axes takes more effort and understanding on the part of the author. The container proposal appears to meet the basic requirements of grouping and provides a basic hierarchy. The question then is - is the additional flexibility provided by axis/axes worth the additional cost in complexity?


REAL WORLD EXAMPLES:

The examples included here are based off of the OS pick list for the support form at Livingston Enterprises, the employer of the original proposal author.

A common kludged usage for groups in the real world involves placing bogus <OPTIONS> in a select to act as group delimiters. The problems with this are:

  1. The delimiters become selectable and are usually invalid options.
  2. It does not build any hierarchy for UAs to use.

An example of this can be found at: <URL:http://www.baynetworks.com/Products/nav/DA510-2742EC-B-nav.html#docs> if you choose the 'Related Documents' list. An edited version of the HTML source is included here:

<FORM TARGET="_top" ACTION="/cgi-bin/baypage.cgi" >
<SELECT NAME=url1
onchange="window.open(this.options[this.selectedIndex].value,'_top')"
>
<OPTION VALUE="">--> Related Documents
<OPTION VALUE="">
<OPTION VALUE="">___Brochures
<OPTION VALUE="/Products/nav/BR190-2590EC-A.html">5000 MSX
<OPTION VALUE="/Products/nav/BR190-2602EC-A.html">BayStream
<OPTION VALUE="/Products/nav/BR510-2260WC-C.html">System 5000
<OPTION VALUE="">
<OPTION VALUE="">___Data Sheets
<OPTION VALUE="/Products/nav/DA510-2781WC-A.html">ATMSpeed Switching
Modules
[many OPTIONSs snipped]
<OPTION VALUE="/Products/nav/DA510-2777WC-A.html">TokenSpeed Switching
Modules
<OPTION VALUE="">
<OPTION VALUE="">___White Papers
<OPTION VALUE="/Products/nav/WP508-2745EC-B.html">56K
[some OPTIONS snipped]
<OPTION VALUE="/Products/nav/WP510-2676EC-A.html">Windows NT
<OPTION VALUE="">________________________________________
</SELECT> <INPUT TYPE=SUBMIT VALUE=GO  ><BR>
</FORM>

You can see how this is displayed on your UA:

As you can see, the group headers are included inline, along with blank OPTIONs to provide spacing. This type of use can be found at many sites, indicating authors have a desire for grouped SELECT lists even without accessibility concerns.


DTD FRAGMENTS:

Below are the proposed changes to the HTML 4.0 DTD to provide for the new functionality.


PROPOSAL ONE - CONTAINER:

<!ELEMENT SELECT - - (OPTGROUP | OPTION)+ -- option selector -->
<!ATTLIST SELECT
  %attrs;                          -- %coreattrs, %i18n, %events --
  name        CDATA      #IMPLIED  -- field name --
  size        NUMBER     #IMPLIED  -- rows visible --
  multiple  (multiple)   #IMPLIED  -- default is single selection --
  disabled  (disabled)   #IMPLIED  -- control is unavailable in this context --
  tabindex    NUMBER     #IMPLIED  -- position in tabbing order --
  onfocus     %Script;   #IMPLIED  -- the element got the focus --
  onblur      %Script;   #IMPLIED  -- the element lost the focus --
  onchange    %Script;   #IMPLIED  -- the element value was changed --
  %reserved;                       -- reserved for possible future use --
  >
 
<!ELEMENT OPTION - O (#PCDATA) -- selectable choice -->
<!ATTLIST OPTION
  %attrs;                          -- %coreattrs, %i18n, %events --
  selected  (selected)   #IMPLIED
  disabled  (disabled)   #IMPLIED  -- control is unavailable in this context --
  value       CDATA      #IMPLIED  -- defaults to element content --
  label       CDATA      #IMPLIED  -- text to display, defaults to content --
  >
 
<!ELEMENT OPTGROUP - - (OPTGROUP | OPTION)+ -- grouping for OPTION -->
<!ATTLIST OPTGROUP
  %attrs;                          -- %coreattrs, %i18n, %events --
  selected  (selected)   #IMPLIED
  disabled  (disabled)   #IMPLIED  -- control is unavailable in this context --
  label       CDATA      #REQUIRED -- text to display --
  >

PROPOSAL TWO - AXIS/AXES:

<!ELEMENT SELECT - - (OPTGROUP*,OPTION+) -- option selector -->
<!ATTLIST SELECT
  %attrs;                          -- %coreattrs, %i18n, %events --
  name        CDATA      #IMPLIED  -- field name --
  size        NUMBER     #IMPLIED  -- rows visible --
  multiple  (multiple)   #IMPLIED  -- default is single selection --
  disabled  (disabled)   #IMPLIED  -- control is unavailable in this context --
  tabindex    NUMBER     #IMPLIED  -- position in tabbing order --
  onfocus     %Script;   #IMPLIED  -- the element got the focus --
  onblur      %Script;   #IMPLIED  -- the element lost the focus --
  onchange    %Script;   #IMPLIED  -- the element value was changed --
  %reserved;                       -- reserved for possible future use --
  >
 
<!ELEMENT OPTION - O (#PCDATA) -- selectable choice -->
<!ATTLIST OPTION
  %attrs;                          -- %coreattrs, %i18n, %events --
  selected  (selected)   #IMPLIED
  disabled  (disabled)   #IMPLIED  -- control is unavailable in this context --
  value       CDATA      #IMPLIED  -- defaults to element content --
  label       CDATA      #IMPLIED  -- text to display, defaults to content --
  axes        IDREFS     #IMPLIED  -- list of id's for OPTGROUPs --
  axis        CDATA      #IMPLIED  -- names groups of related options --
  >
 
<!ELEMENT OPTGROUP - 0 EMPTY -- grouping for OPTION -->
<!ATTLIST OPTGROUP
  %attrs;                          -- %coreattrs, %i18n, %events --
  selected  (selected)   #IMPLIED
  disabled  (disabled)   #IMPLIED  -- control is unavailable in this context --
  label       CDATA      #REQUIRED -- text to display --
  axes        IDREFS     #IMPLIED  -- list of id's for OPTGROUPs --
  axis        CDATA      #IMPLIED  -- names groups of related optgroups --
  >

FOLLOW UP:

Please discuss this issue by sending email to w3c-wai-ig@w3.org . Include the symbol OPTION in the subject heading of your message, to help other subscribers organize the volume of mail we hope this will generate.