diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 37a2bf2..9a93fe6 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -809,6 +809,26 @@ function system_modules($form, $form_state = array()) { return system_modules_confirm_form($visible_files, $form_state['storage']); } + // JS-only table filters. + $form['filters'] = array( + '#type' => 'container', + '#attributes' => array( + 'class' => array('table-filter', 'js-show'), + ), + ); + $form['filters']['text'] = array( + '#type' => 'search', + '#title' => t('Search module list'), + '#title_display' => 'invisible', + '#size' => 20, + '#placeholder' => t('Search module...'), + '#attributes' => array( + 'class' => array('table-filter-text'), + 'data-table' => '#system-modules', + 'autocomplete' => 'off', + ), + ); + $modules = array(); $form['modules'] = array('#tree' => TRUE); @@ -2336,11 +2356,11 @@ function theme_system_modules_details($variables) { $row[] = array('class' => array('checkbox'), 'data' => drupal_render($module['enable'])); // Add the module label and expand/collapse functionalty. - $col2 = ''; + $col2 = ''; $row[] = array('class' => array('module'), 'data' => $col2); // Add the description, along with any modules it requires. - $description = '' . drupal_render($module['description']) . ''; + $description = '' . drupal_render($module['description']) . ''; if ($version || $requires || $required_by) { $description .= '
'; if ($version) { diff --git a/core/modules/system/system.base.css b/core/modules/system/system.base.css index 233c6d7..c386b3e 100644 --- a/core/modules/system/system.base.css +++ b/core/modules/system/system.base.css @@ -204,6 +204,16 @@ tr .ajax-progress-throbber .throbber { } /** + * For anything you want to show on page load only when JS is enabled. + */ +.js-show { + display: none; +} +.js .js-show { + display: block; +} + +/** * Hide elements from all users. * * Used for elements which should not be immediately displayed to any user. An diff --git a/core/modules/system/system.module b/core/modules/system/system.module index c621915..6d25a04 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2133,7 +2133,7 @@ function system_library_info() { ), ); $libraries['drupal.system.modules'] = array( - 'title' => 'System cron', + 'title' => 'System modules', 'version' => VERSION, 'js' => array( drupal_get_path('module', 'system') . '/system.modules.js' => array(), diff --git a/core/modules/system/system.modules.js b/core/modules/system/system.modules.js index 0df6629..2b20d8d 100644 --- a/core/modules/system/system.modules.js +++ b/core/modules/system/system.modules.js @@ -64,4 +64,59 @@ Drupal.behaviors.hideModuleInformation = { } }; +/** + * Filters the module list table by a text input search string. + * + * Additionally accounts for multiple tables being wrapped in "package" details + * elements. + * + * Text search input: input.table-filter-text + * Target table: input.table-filter-text[data-table] + * Source text: .table-filter-text-source + */ +Drupal.behaviors.tableFilterByText = { + attach: function (context, settings) { + var $input = $('input.table-filter-text').once('table-filter-text'); + var $table = $($input.attr('data-table')); + var $rowsAndDetails, $labels, $details; + + function hidePackageDetails(index, element) { + var $details = $(element); + var $visibleRows = $details.find('table:not(.sticky-header)').find('tbody tr:visible'); + $details.toggle($visibleRows.length > 0); + } + + function filterModuleList (e) { + var query = $(e.target).val().toLowerCase(); + + function showModuleRow (index, element) { + var $element = $(element); + var textMatch = $element.text().toLowerCase().indexOf(query) !== -1; + $element.closest('tr').toggle(textMatch); + } + + // Filter if the length of the query is at least 2 characters. + if (query.length >= 2) { + $labels.each(showModuleRow); + + // Hide the package
if they don't have any visible rows. + // Note that we first show() all
to be able to use ':visible'. + $details.show().each(hidePackageDetails); + } + else { + $rowsAndDetails.show(); + } + } + + if ($table.length) { + $rowsAndDetails = $table.find('tr, details'); + $labels = $table.find('.table-filter-text-source'); + $details = $table.find('details'); + + // @todo Use autofocus attribute when possible. + $input.focus().on('keyup', filterModuleList); + } + } +}; + }(jQuery, Drupal));