=== modified file 'includes/common.inc' --- includes/common.inc 2009-03-28 03:54:37 +0000 +++ includes/common.inc 2009-03-29 11:26:37 +0000 @@ -3717,6 +3717,12 @@ 'form_element' => array( 'arguments' => array('element' => NULL), ), + 'vertical_tab' => array( + 'arguments' => array('element' => NULL), + ), + 'vertical_tabs' => array( + 'arguments' => array('element' => NULL), + ), ); } === modified file 'includes/form.inc' --- includes/form.inc 2009-03-28 18:09:10 +0000 +++ includes/form.inc 2009-03-29 13:42:41 +0000 @@ -939,7 +939,8 @@ /** * Walk through the structured form array, adding any required * properties to each element and mapping the incoming $_POST - * data to the proper elements. + * data to the proper elements. Also, execute any #process handlers + * attached to a specific element. * * @param $form_id * A unique string identifying the form for validation, submission, @@ -972,9 +973,22 @@ } } + if (!isset($form['#id'])) { + $form['#id'] = form_clean_id('edit-' . implode('-', $form['#parents'])); + } if (isset($form['#input']) && $form['#input']) { _form_builder_handle_input_element($form_id, $form, $form_state, $complete_form); } + // Allow for elements to expand to multiple elements, e.g., radios, + // checkboxes and files. + if (isset($form['#process']) && !$form['#processed']) { + foreach ($form['#process'] as $process) { + if (drupal_function_exists($process)) { + $form = $process($form, $form_state, $complete_form); + } + } + $form['#processed'] = TRUE; + } $form['#defaults_loaded'] = TRUE; // We start off assuming all form elements are in the correct order. @@ -1062,8 +1076,7 @@ /** * Populate the #value and #name properties of input elements so they - * can be processed and rendered. Also, execute any #process handlers - * attached to a specific element. + * can be processed and rendered. */ function _form_builder_handle_input_element($form_id, &$form, &$form_state, $complete_form) { if (!isset($form['#name'])) { @@ -1080,9 +1093,6 @@ } array_unshift($form['#parents'], $name); } - if (!isset($form['#id'])) { - $form['#id'] = form_clean_id('edit-' . implode('-', $form['#parents'])); - } if (!empty($form['#disabled'])) { $form['#attributes']['disabled'] = 'disabled'; @@ -1151,16 +1161,6 @@ } } } - // Allow for elements to expand to multiple elements, e.g., radios, - // checkboxes and files. - if (isset($form['#process']) && !$form['#processed']) { - foreach ($form['#process'] as $process) { - if (drupal_function_exists($process)) { - $form = $process($form, isset($edit) ? $edit : NULL, $form_state, $complete_form); - } - } - $form['#processed'] = TRUE; - } form_set_value($form, $form['#value'], $form_state); } @@ -1597,6 +1597,7 @@ $element['#attributes']['class'] .= ' collapsed'; } } + $element['#attributes']['id'] = $element['#id']; return '
\n"; } @@ -2222,6 +2223,81 @@ } /** + * Handles reset of the vertical tabs storage reset. + * + * @param $element + * An associative array containing the properties and children of the + * form element. + * + * @return + * The processed element. + */ +function form_process_form($element, &$form_state) { + $form_state['vertical tabs'] = array(); + return $element; +} + +/** + * Handles addition of fieldsets to a vertical tabs widget. + * + * @param $element + * An associative array containing the properties and children of the + * fieldset element. + * + * @return + * The processed element. + */ +function form_process_fieldset(&$element, &$form_state, $entire_form) { + if (isset($element['#vertical_tab'])) { + // Store a reference to this fieldset for the vertical tabs processing function. + $form_state['vertical tabs'][$element['#vertical_tab']][] = &$element; + + // Trick form_render() into believing this has already been output. + $element['#printed'] = TRUE; + + $element['#collapsible'] = FALSE; + + // Add CSS and JavaScript files. + foreach (array('css', 'js') as $kind) { + if (!empty($element['#vertical_tab_' . $kind]) && is_array($element['#vertical_tab_' . $kind])) { + foreach ($element['#vertical_tab_' . $kind] as $arguments) { + call_user_func_array('drupal_add_' . $kind, is_array($arguments) ? $arguments : array($arguments)); + } + } + } + } + return $element; +} + +function form_process_vertical_tabs($element, &$form_state, $entire_form) { + // Add the reference to the tabs to this element so that it's available + // in the theme function. + if (!isset($form_state['vertical tabs'][$element['#parents'][0]])) { + $form_state['vertical tabs'][$element['#parents'][0]] = array(); + } + $element['#tabs'] = &$form_state['vertical tabs'][$element['#parents'][0]]; + return $element; +} + +/** + * Makes the element's children fieldsets be vertical tabs. + */ +function theme_vertical_tabs(&$element) { + // Add required JavaScript and Stylesheet. + drupal_add_js('misc/vertical-tabs.js', array('weight' => JS_DEFAULT - 1)); + drupal_add_css('misc/vertical-tabs.css'); + + foreach ($element['#tabs'] as $tab) { + // Allow printing for this rendering. drupal_render_children() will + // set this back to TRUE. + $tab['#printed'] = FALSE; + $element[] = $tab; + } + + return '