diff --git misc/instasearch.css misc/instasearch.css new file mode 100644 index 0000000..eb05476 --- /dev/null +++ misc/instasearch.css @@ -0,0 +1,5 @@ +/* $Id$ */ + +.instasearch-irrelevant { + display:none; +} \ No newline at end of file diff --git misc/instasearch.js misc/instasearch.js new file mode 100644 index 0000000..ee5fb77 --- /dev/null +++ misc/instasearch.js @@ -0,0 +1,66 @@ +// $Id$ + +(function ($) { + +Drupal.instasearch = function (container) { + var data = { items: undefined, index: undefined }; + + 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-textfield').keyup(function (e) { + if (data.index === undefined) { + rebuildIndex(); + } + + var value = $.trim($(this).val().toLowerCase()); + if (value !== '') { + $.each(data.index, function (i, text) { + var match = text.indexOf(value) >= 0; + data.items.eq(i) + [match ? 'addClass' : 'removeClass']('instasearch-match') + [match ? 'removeClass' : 'addClass']('instasearch-irrelevant'); + }); + } + else { + data.items.removeClass('instasearch-match').removeClass('instasearch-irrelevant'); + } + + container.trigger('instasearch'); + }); + + 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); \ No newline at end of file diff --git modules/system/system.admin.inc modules/system/system.admin.inc index 32edba8..245d595 100644 --- modules/system/system.admin.inc +++ modules/system/system.admin.inc @@ -719,6 +719,7 @@ function system_modules($form, $form_state = array()) { '#title' => t($package), '#collapsible' => TRUE, '#theme' => 'system_modules_fieldset', + '#attributes' => array('class' => array('instasearch-item')), '#header' => array( array('data' => t('Enabled'), 'class' => array('checkbox')), t('Name'), @@ -734,6 +735,18 @@ function system_modules($form, $form_state = array()) { ); $form['#action'] = url('admin/config/modules/list/confirm'); + $form['#attributes']['class'] = 'instasearch-container'; + $form['#attached_js']['misc/instasearch.js'] = array(); + $form['instasearch'] = array( + '#type' => 'markup', + '#weight' => -5, + '#markup' => '', + '#attached' => array( + 'js' => array('misc/instasearch.js'), + 'css' => array('misc/instasearch.css'), + ), + ); + return $form; } @@ -2166,7 +2179,7 @@ function theme_system_modules_fieldset($form) { // If we have help, it becomes the first part // of the description - with CSS, it is float: right'd. if (isset($module['help'])) { - $description = '
' . drupal_render($module['help']) . '
'; + $description = '
' . drupal_render($module['help']) . '
'; } // Add the description, along with any modules it requires. $description .= drupal_render($module['description']); @@ -2177,7 +2190,7 @@ function theme_system_modules_fieldset($form) { $description .= '
' . t('Required by: !module-list', array('!module-list' => implode(', ', $module['#required_by']))) . '
'; } $row[] = array('data' => $description, 'class' => array('description')); - $rows[] = $row; + $rows[] = array('data' => $row, 'class' => array('instasearch-item')); } return theme('table', $form['#header'], $rows);