? misc/collapse.js Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.454 diff -u -r1.454 common.inc --- includes/common.inc 5 Jun 2005 19:10:53 -0000 1.454 +++ includes/common.inc 8 Jun 2005 09:14:03 -0000 @@ -1110,6 +1110,33 @@ } /** + * Format a group of form items. + * + * @param $legend + * The label for the form item group. + * @param $group + * The form items within the group, as an HTML string. + * @param $collapsed + * A boolean value decided whether the group starts collapsed. + * @param $description + * Explanatory text to display after the form item group. + * @param $attributes + * An associative array of HTML attributes to add to the fieldset tag. + * @return + * A themed HTML string representing the form item group. + */ +function form_group_collapsible($legend, $group, $collapsed = FALSE, $description = NULL, $attributes = NULL) { + drupal_add_js('misc/collapse.js'); + + $attributes['class'] .= ' collapsible'; + if ($collapsed) { + $attributes['class'] .= ' collapsed'; + } + + return '' . ($legend ? ''. $legend .'' : '') . $group . ($description ? '
'. $description .'
' : '') . "\n"; +} + +/** * Format a radio button. * * @param $title Index: misc/drupal.css =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.css,v retrieving revision 1.107 diff -u -r1.107 drupal.css --- misc/drupal.css 31 May 2005 23:23:48 -0000 1.107 +++ misc/drupal.css 8 Jun 2005 09:23:12 -0000 @@ -586,3 +586,31 @@ input.throbbing { background-position: 100% -18px; } + +/* +** Collapsing fieldsets +*/ +html.js fieldset.collapsed { + border-bottom-width: 0; + border-left-width: 0; + border-right-width: 0; + margin-bottom: 0; +} + +html.js fieldset.collapsed * { + display: none; +} + +html.js fieldset.collapsed legend, +html.js fieldset.collapsed legend * { + display: inline; +} + +html.js fieldset.collapsible legend a { + padding-left: 15px; + background: url('menu-expanded.png') 5px 50% no-repeat; +} + +html.js fieldset.collapsed legend a { + background-image: url('menu-collapsed.png'); +} Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.2 diff -u -r1.2 drupal.js --- misc/drupal.js 1 Jun 2005 17:43:33 -0000 1.2 +++ misc/drupal.js 9 Jun 2005 08:29:25 -0000 @@ -8,6 +8,7 @@ !document.getElementsByTagName || !document.createElement || !document.createTextNode || + !document.documentElement || !document.getElementById); } return document.jsEnabled; @@ -15,7 +16,7 @@ // Global Killswitch if (isJsEnabled()) { - + document.documentElement.className = 'js'; } /** Index: modules/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment.module,v retrieving revision 1.353 diff -u -r1.353 comment.module --- modules/comment.module 22 May 2005 21:14:59 -0000 1.353 +++ modules/comment.module 8 Jun 2005 10:47:04 -0000 @@ -254,7 +254,7 @@ if (user_access('administer comments')) { $selected = isset($node->comment) ? $node->comment : variable_get("comment_$node->type", 2); $output = form_radios('', 'comment', $selected, array(t('Disabled'), t('Read only'), t('Read/write'))); - return form_group(t('User comments'), $output); + return form_group_collapsible(t('User comments'), $output, TRUE); } break; Index: modules/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter.module,v retrieving revision 1.64 diff -u -r1.64 filter.module --- modules/filter.module 1 Jun 2005 03:21:44 -0000 1.64 +++ modules/filter.module 8 Jun 2005 09:54:27 -0000 @@ -725,7 +725,8 @@ $output .= theme('filter_tips', $tips); $output .= ''; } - return theme('form_element', t('Input format'), $output, $extra, NULL, _form_get_error($name)); + $group = theme('form_element', NULL, $output, $extra, NULL, _form_get_error($name)); + return form_group_collapsible(t('Input format'), $group, TRUE); } else { // Only one format available: use a hidden form item and only show tips. Index: modules/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node.module,v retrieving revision 1.496 diff -u -r1.496 node.module --- modules/node.module 6 Jun 2005 14:07:04 -0000 1.496 +++ modules/node.module 8 Jun 2005 11:17:49 -0000 @@ -1292,7 +1292,7 @@ $author .= form_textfield(t('Authored on'), 'date', $edit->date, 20, 25, NULL, NULL, TRUE); $output .= '
'; - $output .= form_group(t('Authoring information'), $author); + $output .= form_group_collapsible(t('Authoring information'), $author, TRUE); $output .= "
\n"; $node_options = variable_get('node_options_'. $edit->type, array('status', 'promote')); @@ -1303,7 +1303,7 @@ $options .= form_checkbox(t('Create new revision'), 'revision', 1, isset($edit->revision) ? $edit->revision : in_array('revision', $node_options)); $output .= '
'; - $output .= form_group(t('Options'), $options); + $output .= form_group_collapsible(t('Publishing Options'), $options, TRUE); $output .= "
\n"; $extras .= implode('
', node_invoke_nodeapi($edit, 'form admin')); Index: modules/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system.module,v retrieving revision 1.214 diff -u -r1.214 system.module --- modules/system.module 7 Jun 2005 18:39:35 -0000 1.214 +++ modules/system.module 8 Jun 2005 09:28:25 -0000 @@ -201,7 +201,7 @@ // We will use a random URL so there is no way a proxy or a browser could cache the "no such image" answer. $group .= ''; - $output = form_group(t('General settings'), $group); + $output = form_group_collapsible(t('General settings'), $group, TRUE); // Error handling: $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); @@ -211,12 +211,12 @@ $group .= form_select(t('Error reporting'), 'error_level', variable_get('error_level', 1), array(t('Write errors to the log'), t('Write errors to the log and to the screen')), t('Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that errors are only written to the error log. On a test server it can be helpful to write logs to the screen.')); $group .= form_select(t('Discard log entries older than'), 'watchdog_clear', variable_get('watchdog_clear', 604800), $period, t('The time log entries should be kept. Older entries will be automatically discarded. Requires crontab.')); - $output .= form_group(t('Error handling'), $group); + $output .= form_group_collapsible(t('Error handling'), $group, TRUE); // Caching: $group = form_radios(t('Page cache'), 'cache', variable_get('cache', CACHE_DISABLED), array(CACHE_DISABLED => t('Disabled (low-traffic sites)'), CACHE_ENABLED_STRICT => t('Strict (medium-traffic sites)'), CACHE_ENABLED_LOOSE => t('Loose (high-traffic sites)')), t("Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached. In order to reduce server load and save bandwidth, Drupal stores and sends cached pages compressed. Drupal supports strict caching and loose caching. Strict caching immediately deletes cached data as soon as it becomes invalid for any user. Loose caching delays the deletion of cached data to provide better performance for high traffic sites.")); - $output .= form_group(t('Cache settings'), $group); + $output .= form_group_collapsible(t('Cache settings'), $group, TRUE); // File system: $directory_path = variable_get('file_directory_path', 'files'); @@ -228,7 +228,7 @@ $group = form_textfield(t('File system path'), 'file_directory_path', $directory_path, 70, 255, t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.')); $group .= form_textfield(t('Temporary directory'), 'file_directory_temp', $directory_temp, 70, 255, t('Location where uploaded files will be kept during previews. Relative paths will be resolved relative to the file system path.')); $group .= form_radios(t('Download method'), 'file_downloads', variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC), array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using http directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')), t('If you want any sort of access control on the downloading of files, this needs to be set to private. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.')); - $output .= form_group(t('File system settings'), $group); + $output .= form_group_collapsible(t('File system settings'), $group, TRUE); // Image handling: $group = ''; @@ -238,7 +238,7 @@ } $group .= image_toolkit_invoke('settings'); if ($group) { - $output .= form_group(t('Image handling'), $group); + $output .= form_group_collapsible(t('Image handling'), '

'.$group.'

', TRUE); } // Date settings: @@ -274,7 +274,7 @@ $group .= form_select(t('Long date format'), 'date_format_long', variable_get('date_format_long', $datelong[0]), $datelongchoices, t('Longer date format used for detailed display.')); $group .= form_select(t('First day of week'), 'date_first_day', variable_get('date_first_day', 0), array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')), t('The first day of the week for calendar views.')); - $output .= form_group(t('Date settings'), $group); + $output .= form_group_collapsible(t('Date settings'), $group, TRUE); return $output; } Index: modules/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload.module,v retrieving revision 1.40 diff -u -r1.40 upload.module --- modules/upload.module 31 May 2005 04:10:21 -0000 1.40 +++ modules/upload.module 9 Jun 2005 08:28:16 -0000 @@ -383,7 +383,7 @@ $output .= form_button(t('Attach'), 'fileop'); } - return '
'. form_group(t('Attachments'), $output, t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'
'; + return '
'. form_group_collapsible(t('File Attachments'), $output, TRUE, t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'
'; } function upload_load($node) { --- misc/collapse.js +++ misc/collapse.js @@ -0,0 +1,48 @@ +if (isJsEnabled()) { + addLoadEvent(collapseAutoAttach); +} + +function collapseAutoAttach() { + var fieldsets = document.getElementsByTagName('fieldset'); + var legend, fieldset; + for (var i = 0; fieldset = fieldsets[i]; i++) { + if (!hasClass(fieldset, 'collapsible')) { + continue; + } + legend = fieldset.getElementsByTagName('legend'); + if (legend.length == 0) { + continue; + } + legend = legend[0]; + var a = document.createElement('a'); + a.href = '#'; + a.onclick = function() { + toggleClass(this.parentNode.parentNode, 'collapsed'); + this.blur(); + return false; + }; + a.innerHTML = legend.innerHTML; + while (legend.hasChildNodes()) { + removeNode(legend.childNodes[0]); + } + legend.appendChild(a); + collapseEnsureErrorsVisible(fieldset); + } +} + +function collapseEnsureErrorsVisible(fieldset) { + if (!hasClass(fieldset, 'collapsed')) { + return; + } + var inputs = []; + inputs = inputs.concat(fieldset.getElementsByTagName('input')); + inputs = inputs.concat(fieldset.getElementsByTagName('textarea')); + inputs = inputs.concat(fieldset.getElementsByTagName('select')); + for (var j = 0; j<3; j++) { + for (var i = 0; i < inputs[j].length; i++) { + if (hasClass(inputs[j][i], 'error')) { + return removeClass(fieldset, 'collapsed'); + } + } + } +}