diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 37a2bf2..f4d9959 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -788,6 +788,16 @@ function _system_is_incompatible(&$incompatible, $files, $file) { * @see system_modules_submit() */ function system_modules($form, $form_state = array()) { + $form['filter_by'] = array( + '#type' => 'textfield', + '#title' => t('Filter by'), + '#title_display' => 'invisible', + '#placeholder' => t('Search module nameā€¦'), + '#wrapper_attributes' => array( + 'class' => array('js-show'), + ), + ); + // Get current list of modules. $files = system_rebuild_module_data(); diff --git a/core/modules/system/system.base.css b/core/modules/system/system.base.css index 233c6d7..d145b5f 100644 --- a/core/modules/system/system.base.css +++ b/core/modules/system/system.base.css @@ -204,6 +204,17 @@ 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 17015c6..525f66c 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..8cdad1b 100644 --- a/core/modules/system/system.modules.js +++ b/core/modules/system/system.modules.js @@ -64,4 +64,53 @@ Drupal.behaviors.hideModuleInformation = { } }; +/** + * Filter the module list based on the value of the "filter_by" field. + */ +Drupal.behaviors.filterModuleList = { + attach: function (context, settings) { + var $table = $('#system-modules').once('filter-module-list'); + var $rowsAndDetails, $labels, $details; + + function hidePackageDetails(index, element) { + // We must select the last table because the sticky headers + // functionality prepends another table. + var $details = $(element); + var $visibleRows = $details.find('table.sticky-enabled').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 if (query === '') { + $rowsAndDetails.show(); + } + } + + if ($table.length) { + $rowsAndDetails = $table.find('tr, details'); + $labels = $table.find('label'); + $details = $table.find('details'); + + // @todo use autofocus attribute when browser support is good enough. + $('#edit-filter-by').focus().on('keyup', filterModuleList); + } + } +}; + }(jQuery, Drupal));