Drupal has a Taxonomy module for categorizing content. The module can generate a select box based on the defined taxonomy. However, it does not support option groups. I figured I’d share my modification for those who’d like to do the same. It was based on code from a Drupal forum post which I think was based on Drupal 5, not 6.
The code that needs to be modified is from _taxonomy_term_select() in modules/taxonomy/taxonomy.module, after line 1032.
function _taxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $exclude = array()) { $tree = taxonomy_get_tree($vocabulary_id); $options = array(); if ($blank) { $options[''] = $blank; } if ($tree) { $curr_group = ''; foreach ($tree as $term) { if (!in_array($term->tid, $exclude)) { if($term->parents[0] == 0) { $curr_group=$term->name; $options[$curr_group] = array(); } else { $choice = new stdClass(); $choice->option = array($term->tid => str_repeat('-', $term->depth) . $term->name); $options[$curr_group][] = $choice; } } } } return array('#type' => 'select', '#title' => $title, '#default_value' => $value, '#options' => $options, '#description' => $description, '#multiple' => $multiple, '#size' => $multiple ? min(9, count($options)) : 0, '#weight' => -15, '#theme' => 'taxonomy_term_select', ); }
Essentially, the code simply iterates through the tree like the original code, except when it encounters a root node it creates a new key with an array value to contain the individual options, thereby creating an option group using the term’s name as its label. The code isn’t very flexible since it won’t account for root nodes with no children. Also it doesn’t account for options with a depth greater than 1, in which case you’d probably want to set a class and disabled attribute to make it look and act like an option group (since option groups can’t be nested). Such a change would also involve modifying form_select_options() in includes/form.inc since attributes for option tags is not supported.