Index: misc/instasearch.css =================================================================== RCS file: misc/instasearch.css diff -N misc/instasearch.css --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ misc/instasearch.css 21 Nov 2009 03:43:34 -0000 @@ -0,0 +1,10 @@ +/* $Id$ */ + +.instasearch-irrelevant, +.instasearch-no-contents { + display:none; +} + +.instasearch-no-results { + padding:0 0 16px 0; +} Index: misc/instasearch.js =================================================================== RCS file: misc/instasearch.js diff -N misc/instasearch.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ misc/instasearch.js 21 Nov 2009 03:43:34 -0000 @@ -0,0 +1,114 @@ +// $Id$ + +(function ($) { + +Drupal.instasearch = function (container) { + var data = { items: undefined, index: undefined }; + + var textfield = container.find('.instasearch-textfield'); + + var text = function (elem) { + var ret = ''; + if (!$(elem).is('.instasearch-ignore')) + for (var i = 0; i < elem.childNodes.length; i++) + if (elem.childNodes[i].nodeType != 8) + ret += elem.childNodes[i].nodeType != 1 ? + elem.childNodes[i].nodeValue : + text(elem.childNodes[i]); + return ret; + }; + + var rebuildIndex = function () { + data.items = container.find('.instasearch-item'); + data.index = $.map(data.items, function (elem) { + return text(elem).toLowerCase(); + }); + container.find('.instasearch-group').data('instasearch:group', undefined); + data.groups = $.map(data.items, function (elem) { + var group = $(elem).closest('.instasearch-group'); + if (group.length) { + var x = group.data('instasearch:group'); + if (x === undefined) { + group.data('instasearch:group', x = { group: group, total: 0 }); + } + x.total++; + return x; + } + }); + }; + + var addPlaceholder = function() { + if (!container.find('.instasearch-no-results').length) + textfield.closest('.form-item').after($('

').text(Drupal.t('There were no results.'))); + }; + + var removePlaceholder = function () { + container.find('.instasearch-no-results').remove(); + }; + + var filter = function () { + if (data.index === undefined) { + rebuildIndex(); + } + + var value = $.trim(textfield.val().toLowerCase()); + if (value !== '') { + var results = 0; + $.each($.unique(data.groups), function () { + this.current = 0; + }); + $.each(data.index, function (i, text) { + var match = text.indexOf(value) >= 0; + results += match; + data.groups[i].current += match; + data.items.eq(i) + [match ? 'addClass' : 'removeClass']('instasearch-match') + [match ? 'removeClass' : 'addClass']('instasearch-irrelevant'); + }); + $.each($.unique(data.groups), function () { + this.group + [this.current ? 'addClass' : 'removeClass']('instasearch-has-contents') + [this.current ? 'removeClass' : 'addClass']('instasearch-no-contents'); + }); + if (results) { + removePlaceholder(); + } + else { + addPlaceholder(); + } + } + else { + data.items.removeClass('instasearch-match').removeClass('instasearch-irrelevant'); + removePlaceholder(); + } + + container.trigger('instasearch'); + }; + + textfield.bind('click keyup', filter); + + if (textfield[0]) { + textfield[0].type = 'search'; + textfield.attr('results', 5); + } + + return data; +}; + +Drupal.behaviors.instasearch = { + attach: function (context) { + $('.instasearch-container', context).once('instasearch', function () { + var container = $(this); + container.data('instasearch', Drupal.instasearch(container)); + }); + + $(context).closest('.instasearch-container').each(function () { + var data = $(this).data('instasearch'); + if (data) { + data.index = undefined; + } + }); + } +}; + +})(jQuery); Index: modules/system/system.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v retrieving revision 1.223 diff -u -p -r1.223 system.admin.inc --- modules/system/system.admin.inc 17 Nov 2009 21:24:18 -0000 1.223 +++ modules/system/system.admin.inc 21 Nov 2009 03:49:27 -0000 @@ -776,6 +776,7 @@ function system_modules($form, $form_sta '#title' => t($package), '#collapsible' => TRUE, '#theme' => 'system_modules_fieldset', + '#attributes' => array('class' => array('instasearch-group')), '#header' => array( array('data' => t('Enabled'), 'class' => array('checkbox')), t('Name'), @@ -791,6 +792,24 @@ function system_modules($form, $form_sta '#value' => t('Save configuration'), ); $form['#action'] = url('admin/config/modules/list/confirm'); + $form['#attributes']['class'] = 'instasearch-container'; + $form['#attached_js']['misc/instasearch.js'] = array(); + $form['instasearch'] = array( + '#type' => 'textfield', + '#weight' => -5, + '#input' => FALSE, + '#title' => t('Filter modules'), + '#name' => 'instasearch', + '#size' => 30, + '#value' => '', + '#description' => t('Enter the name of a module to filter the list.'), + '#attributes' => array('class' => array('instasearch-textfield')), + '#attached' => array( + 'js' => array('misc/instasearch.js'), + 'css' => array('misc/instasearch.css'), + ), + ); + return $form; } @@ -2347,7 +2366,7 @@ function theme_system_modules_fieldset($ foreach (array('help', 'permissions', 'configure') as $key) { $row[] = array('data' => drupal_render($module['links'][$key]), 'class' => array($key)); } - $rows[] = $row; + $rows[] = array('data' => $row, 'class' => array('instasearch-item')); } return theme('table', array('header' => $form['#header'], 'rows' => $rows));