Index: misc/collapse.js =================================================================== RCS file: /cvs/drupal/drupal/misc/collapse.js,v retrieving revision 1.20 diff -u -r1.20 collapse.js --- misc/collapse.js 13 Mar 2009 23:15:08 -0000 1.20 +++ misc/collapse.js 9 Apr 2009 23:09:16 -0000 @@ -60,6 +60,14 @@ fieldset.removeClass('collapsed'); } + var summary = $(''); + fieldset. + bind('summaryUpdated', function() { + var text = $.trim(fieldset.getSummary()); + summary.html(text ? ' (' + text + ')' : ''); + }) + .trigger('summaryUpdated'); + // Turn the legend into a clickable link and wrap the contents of the fieldset // in a div for easier animation var text = this.innerHTML; @@ -72,6 +80,7 @@ } return false; })) + .append(summary) .after($('
') .append(fieldset.children(':not(legend):not(.action)'))) .addClass('collapse-processed'); Index: misc/form.js =================================================================== RCS file: /cvs/drupal/drupal/misc/form.js,v retrieving revision 1.6 diff -u -r1.6 form.js --- misc/form.js 30 Mar 2009 03:15:40 -0000 1.6 +++ misc/form.js 9 Apr 2009 23:09:16 -0000 @@ -1,6 +1,51 @@ // $Id: form.js,v 1.6 2009/03/30 03:15:40 webchick Exp $ (function($) { +/** + * Retrieves the summary for the first element. + */ +$.fn.getSummary = function() { + var callback = this.data('summaryCallback'); + return (this[0] && callback) ? $.trim(callback(this[0])) : ''; +}; + +/** + * Sets the summary for all matched elements. + * + * @param callback + * Either a function that will be called each time the summary is + * retrieved or a string (which is returned each time). + */ +$.fn.setSummary = function(callback) { + var that = this; + if (typeof callback != 'function') { + var val = callback; + callback = function() { return val; }; + } + + return this + .data('summaryCallback', callback) + .unbind('formUpdated.summary') + .bind('formUpdated.summary', function() { + that.trigger('summaryUpdated'); + }) + .trigger('summaryUpdated'); +}; + +/** + * Sends a 'formUpdated' event each time a form element is modified. + */ +Drupal.behaviors.formUpdated = { + attach: function(context) { + var events = 'change.formUpdated click.formUpdated blur.formUpdated keyup.formUpdated'; + $(context) + .find(':select').andSelf().filter(':select') + .unbind(events).bind(events, function() { + $(this).trigger('formUpdated'); + }); + } +}; + Drupal.behaviors.multiselectSelector = { attach: function(context, settings) { // Automatically selects the right radio button in a multiselect control. Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.326 diff -u -r1.326 form.inc --- includes/form.inc 30 Mar 2009 03:15:40 -0000 1.326 +++ includes/form.inc 9 Apr 2009 23:09:16 -0000 @@ -227,6 +227,7 @@ 'method' => 'post', 'rerender' => TRUE, 'programmed' => FALSE, + 'groups' => array(), ); } @@ -286,6 +287,10 @@ // then process the form for rendering. $form_state['input'] = array(); + // Also clear out all group associations as these might be different + // when rerendering the form. + $form_state['groups'] = array(); + // Do not call drupal_process_form(), since it would prevent the rebuilt form // to submit. $form = form_builder($form_id, $form, $form_state); @@ -939,7 +944,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 +978,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 +1081,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 +1098,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 +1166,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 +1602,7 @@ $element['#attributes']['class'] .= ' collapsed'; } } + $element['#attributes']['id'] = $element['#id']; return '' . ($element['#title'] ? '' . $element['#title'] . '' : '') . (isset($element['#description']) && $element['#description'] ? '
' . $element['#description'] . '
' : '') . (!empty($element['#children']) ? $element['#children'] : '') . (isset($element['#value']) ? $element['#value'] : '') . "\n"; } @@ -2143,7 +2149,6 @@ * An associative array containing the properties and children of the * tableselect element. * Properties used: header, options, empty, js_select. - * * @return * A themed HTML string representing the table. * @@ -2186,7 +2191,6 @@ * @param $element * An associative array containing the properties and children of the * tableselect element. - * * @return * The processed element. */ @@ -2248,6 +2252,128 @@ } /** + * Adds fieldsets to the specified group or adds group members to this + * fieldset. + * + * @param $element + * An associative array containing the properties and children of the + * fieldset. + * @param $form_state + * The $form_state array for the form this fieldset belongs to. + * @return + * The processed element. + */ +function form_process_fieldset(&$element, &$form_state) { + $parents = implode('][', $element['#parents']); + + // Add this fieldset to a group if one is set and if it's not being + // added to itself. + if (isset($element['#group']) && $element['#group'] != $parents) { + if (isset($form_state['groups'][$element['#group']]) && !empty($form_state['groups'][$element['#group']]['#group_exists'])) { + // Trick drupal_render() into believing this has already been output. + // The group widget will rerender this later. It's only set to + // #printed if the group already exists. That way, we can be sure + // that the fieldset /will/ be rendered later. + $element['#printed'] = TRUE; + } + + // Store a reference to this fieldset for the vertical tabs processing function. + $form_state['groups'][$element['#group']][] = &$element; + } + + // Each fieldset can be a group itself and gets a reference to all + // elements in its group. + $form_state['groups'][$parents]['#group_exists'] = TRUE; + foreach (element_children($form_state['groups'][$parents]) as $key) { + $form_state['groups'][$parents][$key]['#printed'] = TRUE; + } + $element['#group_members'] = &$form_state['groups'][$parents]; + + // Contains form element summary functionalities. + drupal_add_js('misc/form.js', array('weight' => JS_LIBRARY + 1)); + + return $element; +} + +/** + * Adds members of this group as actual elements for rendering. + * + * @param $element + * An associative array containing the properties and children of the + * fieldset. + * @return + * The modified element with all group members. + */ +function form_pre_render_fieldset($element) { + if (!empty($element['#group_members'])) { + // Add the group members to this fieldset for rendering purposes only. + foreach (element_children($element['#group_members']) as $key) { + // This was set in form_process_fieldset so that fieldsets which are + // added to groups are not rendered at their original location. + // drupal_render_children() will set this back to TRUE. + unset($element['#group_members'][$key]['#printed']); + $element[] = &$element['#group_members'][$key]; + } + + // Resort the element's children after the group members have been added. + $element['#sorted'] = FALSE; + } + + return $element; +} + +/** + * Creates a group formatted as vertical tabs. + * + * @param $element + * An associative array containing the properties and children of the + * fieldset. + * @param $form_state + * The $form_state array for the form this vertical tab widget belongs to. + * @return + * The processed element. + */ +function form_process_vertical_tabs($element, &$form_state) { + $element['group'] = array( + '#type' => 'fieldset', + '#theme_wrapper' => '', + '#parents' => $element['#parents'], + ); + + + // The JavaScript stores the currently selected tab in this hidden + // field so that the active tab can be restored the next time the + // form is rendered, e.g. on preview pages or when form validation + // fails. + $name = implode('__', $element['#parents']); + if (isset($form_state['values'][$name . '__active_tab'])) { + $element['#default_tab'] = $form_state['values'][$name . '__active_tab']; + } + $element[$name . '__active_tab'] = array( + '#type' => 'hidden', + '#default_value' => $element['#default_tab'], + '#attributes' => array('class' => 'vertical-tabs-active-tab'), + ); + + return $element; +} + +/** + * Makes the element's children fieldsets be vertical tabs. + * + * @param $element + * An associative array containing the properties and children of the + * fieldset. + */ +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'); + + return '
' . $element['#children'] . '
'; +} + +/** * Theme a form submit button. * * @ingroup themeable Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.874 diff -u -r1.874 common.inc --- includes/common.inc 30 Mar 2009 05:13:45 -0000 1.874 +++ includes/common.inc 9 Apr 2009 23:09:16 -0000 @@ -3368,6 +3368,15 @@ } } + // Add additional CSS and JavaScript files associated with this element. + foreach (array('css', 'js') as $kind) { + if (!empty($elements['#attached_' . $kind]) && is_array($elements['#attached_' . $kind])) { + foreach ($elements['#attached_' . $kind] as $arguments) { + call_user_func_array('drupal_add_' . $kind, is_array($arguments) ? $arguments : array($arguments)); + } + } + } + // Get the children of the element, sorted by weight. $children = element_children($elements, TRUE); @@ -3750,6 +3759,9 @@ 'text_format_wrapper' => array( 'arguments' => array('element' => NULL), ), + 'vertical_tabs' => array( + 'arguments' => array('element' => NULL), + ), ); } Index: themes/garland/fix-ie.css =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/fix-ie.css,v retrieving revision 1.10 diff -u -r1.10 fix-ie.css --- themes/garland/fix-ie.css 13 Mar 2008 20:02:18 -0000 1.10 +++ themes/garland/fix-ie.css 9 Apr 2009 23:09:16 -0000 @@ -25,6 +25,10 @@ background: none; } +div.vertical-tabs ul.vertical-tabs-list li.first { + background-image: none; +} + ul.primary { /* Fix missing top margin */ position: relative; /* LTR */ Index: themes/garland/style-rtl.css =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/style-rtl.css,v retrieving revision 1.11 diff -u -r1.11 style-rtl.css --- themes/garland/style-rtl.css 19 Dec 2008 15:42:26 -0000 1.11 +++ themes/garland/style-rtl.css 9 Apr 2009 23:09:16 -0000 @@ -199,6 +199,14 @@ } /** + * Vertical tabs. + */ +div.vertical-tabs { + margin-left: 5%; + margin-right: 15em; +} + +/** * Syndication Block */ #block-node-syndicate h2 { Index: themes/garland/style.css =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/style.css,v retrieving revision 1.49 diff -u -r1.49 style.css --- themes/garland/style.css 30 Mar 2009 03:15:41 -0000 1.49 +++ themes/garland/style.css 9 Apr 2009 23:09:16 -0000 @@ -230,7 +230,7 @@ color: #ffae00; } -span.submitted, .description { +span.submitted, .description, .vertical-tab-button .summary { font-size: 0.92em; color: #898989; } @@ -827,6 +827,12 @@ background-position: 0 0; } +/* Keep the background position at 0 for filters and vertical tabs. */ +*:first-child+html fieldset.filter-wrapper, +*:first-child+html fieldset.vertical-tabs-pane { + background-position: 0 0; +} + *:first-child+html fieldset > .description, *:first-child+html fieldset .fieldset-wrapper .description { padding-top: 1em; } @@ -851,11 +857,48 @@ background: url(images/menu-expanded.gif) no-repeat 0% 50%; /* LTR */ } +html.js fieldset.collapsible legend span.summary { + color: #898989; +} + html.js fieldset.collapsed legend a { background: url(images/menu-collapsed.gif) no-repeat 0% 50%; /* LTR */ } /** + * Vertical tabs. + */ +div.vertical-tabs { + margin-right: 5%; + border-color: #d9eaf5; +} + +div.vertical-tabs .vertical-tabs-panes fieldset.vertical-tabs-pane { + padding: 0.5em 1em; +} + +div.vertical-tabs ul.vertical-tabs-list { + border-color: #d9eaf5; +} + +div.vertical-tabs ul.vertical-tabs-list li { + background-color: #edf5fa; + border-color: #d9eaf5; +} + +div.vertical-tabs ul.vertical-tabs-list li.selected { + background: #fff repeat-x 0 0; +} + +div.vertical-tabs ul.vertical-tabs-list li.selected.first { + background-image: url(images/gradient-inner.png); +} + +div.vertical-tabs ul.vertical-tabs-list li.selected a strong { + color: #494949; +} + +/** * Syndication icons and block */ #block-node-syndicate h2 { Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.676 diff -u -r1.676 system.module --- modules/system/system.module 25 Mar 2009 18:40:50 -0000 1.676 +++ modules/system/system.module 9 Apr 2009 23:09:16 -0000 @@ -381,6 +381,7 @@ '#theme' => 'file', '#theme_wrapper' => 'form_element', ); + $type['tableselect'] = array( '#input' => TRUE, '#js_select' => TRUE, @@ -419,10 +420,17 @@ '#collapsible' => FALSE, '#collapsed' => FALSE, '#value' => NULL, - '#process' => array('form_process_ahah'), + '#process' => array('form_process_fieldset', 'form_process_ahah'), + '#pre_render' => array('form_pre_render_fieldset'), '#theme_wrapper' => 'fieldset', ); + $type['vertical_tabs'] = array( + '#theme_wrapper' => 'vertical_tabs', + '#default_tab' => '', + '#process' => array('form_process_vertical_tabs'), + ); + $type['token'] = array( '#input' => TRUE, '#theme' => array('hidden'), Index: modules/system/system.css =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.css,v retrieving revision 1.53 diff -u -r1.53 system.css --- modules/system/system.css 5 Dec 2008 12:50:28 -0000 1.53 +++ modules/system/system.css 9 Apr 2009 23:09:16 -0000 @@ -320,11 +320,19 @@ } html.js fieldset.collapsed legend { display: block; + overflow: hidden; } html.js fieldset.collapsible legend a { + display: inline; padding-left: 15px; /* LTR */ background: url(../../misc/menu-expanded.png) 5px 75% no-repeat; /* LTR */ } +html.js fieldset.collapsible legend span.summary { + display: inline; + font-size: 0.9em; + color: #999; + margin-left: 0.5em; +} html.js fieldset.collapsed legend a { background-image: url(../../misc/menu-collapsed.png); /* LTR */ background-position: 5px 50%; /* LTR */ @@ -339,9 +347,6 @@ html.js fieldset.collapsible { position: relative; } -html.js fieldset.collapsible legend a { - display: block; -} /* Avoid jumping around due to margins collapsing into collapsible fieldset border */ html.js fieldset.collapsible .fieldset-wrapper { overflow: auto; Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.701 diff -u -r1.701 comment.module --- modules/comment/comment.module 4 Apr 2009 12:35:16 -0000 1.701 +++ modules/comment/comment.module 9 Apr 2009 23:09:16 -0000 @@ -580,6 +580,8 @@ '#title' => t('Comment settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'comment') . '/comment-node-form.js'), '#weight' => 30, ); $comment_count = isset($node->nid) ? db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() : 0; Index: modules/upload/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v retrieving revision 1.231 diff -u -r1.231 upload.module --- modules/upload/upload.module 25 Mar 2009 16:43:02 -0000 1.231 +++ modules/upload/upload.module 9 Apr 2009 23:09:16 -0000 @@ -231,9 +231,9 @@ '#title' => t('File attachments'), '#collapsible' => TRUE, '#collapsed' => empty($node->files), + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'upload') .'/upload.js'), '#description' => t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.'), - '#prefix' => '
', - '#suffix' => '
', '#weight' => 30, ); Index: modules/book/book.css =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.css,v retrieving revision 1.8 diff -u -r1.8 book.css --- modules/book/book.css 19 Dec 2008 15:42:26 -0000 1.8 +++ modules/book/book.css 9 Apr 2009 23:09:16 -0000 @@ -35,6 +35,9 @@ margin-top: 0; margin-bottom: 0; } +html.js #edit-book-pick-book { + display: none; +} #edit-book-bid-wrapper .description { clear: both; } Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.488 diff -u -r1.488 book.module --- modules/book/book.module 30 Mar 2009 05:40:44 -0000 1.488 +++ modules/book/book.module 9 Apr 2009 23:09:16 -0000 @@ -415,7 +415,6 @@ function _book_add_form_elements(&$form, $node) { // Need this for AJAX. $form['#cache'] = TRUE; - drupal_add_js("if (Drupal.jsEnabled) { jQuery(function() { jQuery('#edit-book-pick-book').css('display', 'none'); }); }", 'inline'); $form['book'] = array( '#type' => 'fieldset', @@ -423,6 +422,8 @@ '#weight' => 10, '#collapsible' => TRUE, '#collapsed' => TRUE, + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'book') .'/book.js'), '#tree' => TRUE, '#attributes' => array('class' => 'book-outline-form'), ); Index: modules/node/node.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v retrieving revision 1.58 diff -u -r1.58 node.pages.inc --- modules/node/node.pages.inc 26 Mar 2009 13:31:25 -0000 1.58 +++ modules/node/node.pages.inc 9 Apr 2009 23:09:16 -0000 @@ -152,6 +152,10 @@ $form['#node'] = $node; + $form['additional_settings'] = array( + '#type' => 'vertical_tabs', + ); + // Add a log field if the "Create new revision" option is checked, or if the // current user has the ability to check that option. if (!empty($node->revision) || user_access('administer nodes')) { @@ -161,6 +165,8 @@ '#collapsible' => TRUE, // Collapsed by default when "Create new revision" is unchecked '#collapsed' => !$node->revision, + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'node') . '/node.js'), '#weight' => 20, ); $form['revision_information']['revision'] = array( @@ -172,7 +178,7 @@ $form['revision_information']['log'] = array( '#type' => 'textarea', '#title' => t('Revision log message'), - '#rows' => 2, + '#rows' => 4, '#description' => t('Provide an explanation of the changes you are making. This will help other authors understand your motivations.'), ); } @@ -184,6 +190,8 @@ '#title' => t('Authoring information'), '#collapsible' => TRUE, '#collapsed' => TRUE, + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'node') . '/node.js'), '#weight' => 90, ); $form['author']['name'] = array( @@ -213,6 +221,8 @@ '#title' => t('Publishing options'), '#collapsible' => TRUE, '#collapsed' => TRUE, + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'node') . '/node.js'), '#weight' => 95, ); $form['options']['status'] = array( @@ -283,7 +293,7 @@ $form = array( '#after_build' => array('node_teaser_js', 'node_teaser_include_verify')); - $form['#prefix'] = '
'; + $form['#prefix'] = '
'; $form['#suffix'] = '
'; $form['teaser_js'] = array( Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.183 diff -u -r1.183 menu.module --- modules/menu/menu.module 2 Apr 2009 03:40:05 -0000 1.183 +++ modules/menu/menu.module 9 Apr 2009 23:09:16 -0000 @@ -395,6 +395,8 @@ '#access' => user_access('administer menu'), '#collapsible' => TRUE, '#collapsed' => FALSE, + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'menu') . '/menu.js'), '#tree' => TRUE, '#weight' => -2, '#attributes' => array('class' => 'menu-item-form'), Index: modules/path/path.module =================================================================== RCS file: /cvs/drupal/drupal/modules/path/path.module,v retrieving revision 1.154 diff -u -r1.154 path.module --- modules/path/path.module 30 Mar 2009 05:30:39 -0000 1.154 +++ modules/path/path.module 9 Apr 2009 23:09:16 -0000 @@ -194,6 +194,8 @@ '#title' => t('URL path settings'), '#collapsible' => TRUE, '#collapsed' => empty($path), + '#group' => 'additional_settings', + '#attached_js' => array(drupal_get_path('module', 'path') .'/path.js'), '#access' => user_access('create url aliases'), '#weight' => 30, ); Index: misc/vertical-tabs-rtl.css =================================================================== RCS file: misc/vertical-tabs-rtl.css diff -N misc/vertical-tabs-rtl.css --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ misc/vertical-tabs-rtl.css 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,15 @@ +/* $Id */ + +.vertical-tabs { + margin-left: 0; + margin-right: 15em; +} +.vertical-tabs-list { + margin-right: -15em; + right: 0; + float: right; +} +.vertical-tabs-list li.selected { + border-left-width: 0; + border-right-width: 1px; +} Index: modules/menu/menu.js =================================================================== RCS file: modules/menu/menu.js diff -N modules/menu/menu.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/menu/menu.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,13 @@ +// $Id$ + +(function($) { + +Drupal.behaviors.menuFieldsetSummaries = { + attach: function(context) { + $('fieldset#edit-menu', context).setSummary(function (context) { + return Drupal.checkPlain($('#edit-menu-link-title', context).val()) || Drupal.t('Not in menu'); + }); + } +}; + +})(jQuery); Index: modules/upload/upload.js =================================================================== RCS file: modules/upload/upload.js diff -N modules/upload/upload.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,14 @@ +// $Id$ + +(function($) { + +Drupal.behaviors.bookFieldsetSummaries = { + attach: function(context) { + $('fieldset#edit-attachments', context).setSummary(function (context) { + var size = $('#upload-attachments tbody tr').size(); + return Drupal.formatPlural(size, '1 attachment', '@count attachments'); + }); + } +}; + +})(jQuery); Index: modules/path/path.js =================================================================== RCS file: modules/path/path.js diff -N modules/path/path.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/path/path.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,17 @@ +// $Id$ + +(function($) { + +Drupal.behaviors.pathFieldsetSummaries = { + attach: function(context) { + $('fieldset#edit-path', context).setSummary(function (context) { + var path = $('#edit-path-1').val(); + + return path ? + Drupal.t('Alias: @alias', { '@alias': path }) : + Drupal.t('No alias'); + }); + } +}; + +})(jQuery); Index: modules/comment/comment-node-form.js =================================================================== RCS file: modules/comment/comment-node-form.js diff -N modules/comment/comment-node-form.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment-node-form.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,13 @@ +// $Id$ + +(function($) { + +Drupal.behaviors.commentFieldsetSummaries = { + attach: function(context) { + $('fieldset#edit-comment-settings', context).setSummary(function (context) { + return Drupal.checkPlain($('input:checked', context).parent().text()); + }); + } +}; + +})(jQuery); Index: modules/node/node.js =================================================================== RCS file: modules/node/node.js diff -N modules/node/node.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,35 @@ +// $Id$ + +(function($) { + +Drupal.behaviors.nodeFieldsetSummaries = { + attach: function(context) { + $('fieldset#edit-revision-information', context).setSummary(function (context) { + return $('#edit-revision', context).is(':checked') ? + Drupal.t('New revision') : + Drupal.t("No revision"); + }); + + $('fieldset#edit-author', context).setSummary(function (context) { + var name = $('#edit-name').val(), date = $('#edit-date').val(); + return date ? + Drupal.t('By @name on @date', { '@name': name, '@date': date }) : + Drupal.t('By @name', { '@name': name }); + }); + + $('fieldset#edit-options', context).setSummary(function (context) { + var vals = []; + + $('input:checked', context).parent().each(function() { + vals.push(Drupal.checkPlain($.trim($(this).text()))); + }); + + if (!$('#edit-status', context).is(':checked')) { + vals.unshift(Drupal.t('Not published')); + } + return vals.join(', '); + }); + } +}; + +})(jQuery); Index: modules/book/book.js =================================================================== RCS file: modules/book/book.js diff -N modules/book/book.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/book/book.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,20 @@ +// $Id$ + +(function($) { + +Drupal.behaviors.bookFieldsetSummaries = { + attach: function(context) { + $('fieldset#edit-book', context).setSummary(function (context) { + var val = $('#edit-book-bid').val(); + + if (val === '0') + return Drupal.t('Not in book'); + else if (val === 'new') + return Drupal.t('New book'); + else + return Drupal.checkPlain($('#edit-book-bid :selected').text()); + }); + } +}; + +})(jQuery); Index: misc/vertical-tabs.css =================================================================== RCS file: misc/vertical-tabs.css diff -N misc/vertical-tabs.css --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ misc/vertical-tabs.css 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,71 @@ +/* $Id */ + +.vertical-tabs { + margin: 1em 0 1em 15em; + border: 1px solid #ccc; +} +.vertical-tabs-list { + width: 15em; + list-style: none; + list-style-image: none; /* IE6 */ + border-top: 1px solid #ccc; + padding: 0; + position: relative; /* IE6 */ + margin: -1px -100% -1px 0; + left: -15em; + float: left; +} +.vertical-tabs .vertical-tabs-panes fieldset.vertical-tabs-pane { + margin: 0 !important; + padding: 0 1em; + border: 0; +} +.vertical-tabs .vertical-tabs-panes fieldset.vertical-tabs-pane legend { + display: none; +} + +/* Layout of each tab */ +.vertical-tabs-list li { + background: #eee; + border: 1px solid #ccc; + border-top: 0; + padding: 0; + margin: 0; + height: 1%; +} +.vertical-tabs-list li a { + display: block; + text-decoration: none; + padding: 0.5em 0.6em; + line-height: 1.3em; + height: 1%; +} +.vertical-tabs-list li a:focus { + position:relative; + z-index: 5; +} +.vertical-tabs-list li a:hover { + text-decoration: none; +} +.vertical-tabs-list li strong { + font-weight:normal; +} +.vertical-tabs-list li.selected { + background: #fff; + border-right-width: 0; + position: relative; +} +.vertical-tabs-list li.selected a:focus { + outline: 0; +} +.vertical-tabs-list li.selected strong { + font-weight: bold; + color: #000; +} +.vertical-tabs-list .summary { + display: block; +} +.vertical-tabs ul.vertical-tabs-list .summary { + line-height: normal; + margin-bottom: 0; +} Index: misc/vertical-tabs.js =================================================================== RCS file: misc/vertical-tabs.js diff -N misc/vertical-tabs.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ misc/vertical-tabs.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,118 @@ +// $Id$ + +(function($) { + +/** + * Vertical Tabs. + * + * This script transforms a set of fieldsets into a stack of vertical + * tabs. Another tab pane can be selected by clicking on the respective + * tab. + * + * Each tab may have a summary which can be updated by another + * script. For that to work, each fieldset has an associated + * 'verticalTabCallback' (with jQuery.data() attached to the fieldset), + * which is called every time the user performs an update to a form + * element inside the tab pane. + */ +Drupal.behaviors.verticalTabs = { + attach: function(context) { + $('.vertical-tabs-panes:not(.vertical-tabs-processed)', context).each(function() { + var focusID = $(':hidden.vertical-tabs-active-tab', this).val(); + var focus; + // Create the tab column. + var list = $(''); + $(this).wrap('
').before(list); + + // Transform each fieldset into a tab. + $('> fieldset', this).each(function(i) { + var tab = new Drupal.verticalTab({ title: $('> legend', this).text(), fieldset: $(this) }); + list.append(tab.item); + $(this) + .removeClass('collapsible collapsed') + .addClass('vertical-tabs-pane') + .data('verticalTab', tab); + if (this.id == focusID) focus = $(this); + }); + + $('> li:first', list).addClass('first'); + $('> li:last', list).addClass('last'); + + if (!focus) focus = $('> .vertical-tabs-pane:first', this); + focus.data('verticalTab').focus(); + }).addClass('vertical-tabs-processed'); + } +}; + +/** + * Vertical Tab + * + * @param settings + * An object with the following keys: + * - title: The name of the tab. + * - fieldset: The jQuery object of the fieldset that is the tab pane. + */ +Drupal.verticalTab = function(settings) { + var that = this; + $.extend(this, settings, Drupal.theme('verticalTab', settings)); + + this.link.click(function() { + that.focus(); + return false; + }); + + this.fieldset + .bind('summaryUpdated', function() { + that.updateSummary(); + }) + .trigger('summaryUpdated'); +}; + +Drupal.verticalTab.prototype = { + // Displays the tab's content pane. + focus: function() { + this.fieldset + .siblings('fieldset.vertical-tabs-pane') + .each(function() { + var tab = $(this).data('verticalTab'); + tab.fieldset.hide(); + tab.item.removeClass('selected'); + }) + .end() + .show() + .siblings(':hidden.vertical-tabs-active-tab') + .val(this.fieldset.attr('id')); + this.item.addClass('selected'); + }, + + // Updates the tab's summary. + updateSummary: function() { + this.summary.html(this.fieldset.getSummary()); + } +}; + +/** + * Theme function for a vertical tab. + * + * @param settings + * An object with the following keys: + * - title: The name of the tab. + * @return + * This function has to return an object with at least these keys: + * - item: The root tab jQuery element + * - link: The anchor tag that acts as the clickable area of the tab + * (jQuery version) + * - summary: The jQuery element that contains the tab summary + */ +Drupal.theme.prototype.verticalTab = function(settings) { + var tab = {}; + tab.item = $('
  • ') + .append(tab.link = $('') + .append(tab.title = $('').text(settings.title)) + .append(tab.summary = $('') + ) + ); + return tab; +}; + +})(jQuery);