| 1 |
<?php
|
| 2 |
// $Id: quicksearch.module,v 1.3 2007/05/09 10:09:38 stevemckenzie Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Live searching with jQuery and autocomplete.js.
|
| 7 |
*/
|
| 8 |
|
| 9 |
define('QUICKSEARCH_PERMALINK', variable_get('quicksearch_permalink', t('Permalink')));
|
| 10 |
define('QUICKSEARCH_CLOSE_BUTTON_LABEL', variable_get('quicksearch_close_button_label', t('x')));
|
| 11 |
define('QUICKSEARCH_CLOSE_BUTTON_TITLE', variable_get('quicksearch_close_button_title', t('Close')));
|
| 12 |
define('QUICKSEARCH_FIELD_LABEL', variable_get('quicksearch_field_label', t('Search')));
|
| 13 |
define('QUICKSEARCH_FIELD_SIZE', variable_get('quicksearch_field_size', 24));
|
| 14 |
define('QUICKSEARCH_HIDER', variable_get('quicksearch_hider', 0.6));
|
| 15 |
define('QUICKSEARCH_SELECTOR', variable_get('quicksearch_selector', ''));
|
| 16 |
define('QUICKSEARCH_TITLE', variable_get('quicksearch_title', t('Search Results')));
|
| 17 |
define('QUICKSEARCH_UI_DELAY', variable_get('quicksearch_ui_delay', 800));
|
| 18 |
define('QUICKSEARCH_UI_WIDTH', variable_get('quicksearch_ui_width', 700));
|
| 19 |
|
| 20 |
/**
|
| 21 |
* Implementation of hook_perm().
|
| 22 |
*/
|
| 23 |
function quicksearch_perm() {
|
| 24 |
return array('administer quicksearch', 'access quicksearch');
|
| 25 |
}
|
| 26 |
|
| 27 |
/**
|
| 28 |
* Implementation of hook_menu().
|
| 29 |
*/
|
| 30 |
function quicksearch_menu() {
|
| 31 |
$items[] = array(
|
| 32 |
'path' => 'quicksearch',
|
| 33 |
'callback' => 'quicksearch_callback',
|
| 34 |
'access' => user_access('access quicksearch'),
|
| 35 |
'type' => MENU_CALLBACK
|
| 36 |
);
|
| 37 |
|
| 38 |
$items[] = array(
|
| 39 |
'path' => 'admin/settings/quicksearch',
|
| 40 |
'title' => t('Quick search'),
|
| 41 |
'description' => t('Control how the quicksearch module works.'),
|
| 42 |
'callback' => 'drupal_get_form',
|
| 43 |
'callback arguments' => array('quicksearch_settings'),
|
| 44 |
'access' => user_access('administer quicksearch'),
|
| 45 |
'type' => MENU_NORMAL_ITEM
|
| 46 |
);
|
| 47 |
|
| 48 |
return $items;
|
| 49 |
}
|
| 50 |
|
| 51 |
/**
|
| 52 |
* Implementation of hook_form_alter().
|
| 53 |
*/
|
| 54 |
function quicksearch_form_alter($form_id, &$form) {
|
| 55 |
$fields = variable_get('quicksearch_fields', _quicksearch_fields());
|
| 56 |
// Check if form is configured to use quicksearch.
|
| 57 |
if (!in_array($form_id, array_keys($fields))) {
|
| 58 |
return false;
|
| 59 |
}
|
| 60 |
|
| 61 |
// Check user permissions.
|
| 62 |
if (!user_access('access quicksearch')) {
|
| 63 |
return false;
|
| 64 |
|
| 65 |
}
|
| 66 |
|
| 67 |
// Include craqbox jQuery plugin.
|
| 68 |
if (!QUICKSEARCH_SELECTOR) {
|
| 69 |
if (!module_exists('craqbox')) {
|
| 70 |
if (user_access('administer quicksearch')) {
|
| 71 |
// TODO: maybe a better message.. maybe.
|
| 72 |
drupal_set_message(t('This module requires the craqbox module because of the configurations selected.'), 'error');
|
| 73 |
}
|
| 74 |
return false;
|
| 75 |
}
|
| 76 |
craqbox_include();
|
| 77 |
}
|
| 78 |
|
| 79 |
// Include our JS as 'theme' level because for some reason autocomplete.js will come after it when its in 'module' level?
|
| 80 |
drupal_add_js(drupal_get_path('module', 'quicksearch') .'/quicksearch.js', 'theme');
|
| 81 |
|
| 82 |
// Basic configurable options for JavaScript.
|
| 83 |
$settings = array(
|
| 84 |
'searchPath' => url('quicksearch'),
|
| 85 |
'closeButtonLabel' => QUICKSEARCH_CLOSE_BUTTON_LABEL,
|
| 86 |
'closeButtonTitle' => QUICKSEARCH_CLOSE_BUTTON_TITLE,
|
| 87 |
'fieldLabel' => QUICKSEARCH_FIELD_LABEL,
|
| 88 |
'fields' => array_keys($fields),
|
| 89 |
'hider' => QUICKSEARCH_HIDER,
|
| 90 |
'minCharacters' => variable_get('minimum_word_size', 3),
|
| 91 |
'selector' => QUICKSEARCH_SELECTOR,
|
| 92 |
'title' => QUICKSEARCH_TITLE,
|
| 93 |
'uiDelay' => QUICKSEARCH_UI_DELAY,
|
| 94 |
'uiWidth' => QUICKSEARCH_UI_WIDTH
|
| 95 |
);
|
| 96 |
drupal_add_js(array('quicksearch' => $settings), 'setting');
|
| 97 |
|
| 98 |
$form[$form_id .'_keys']['#autocomplete_path'] = 'quicksearch/node';
|
| 99 |
|
| 100 |
// This option exists to help theming.
|
| 101 |
$form[$form_id .'_keys']['#size'] = QUICKSEARCH_FIELD_SIZE;
|
| 102 |
unset($form['submit']);
|
| 103 |
}
|
| 104 |
|
| 105 |
/**
|
| 106 |
* Settings page.
|
| 107 |
*/
|
| 108 |
function quicksearch_settings() {
|
| 109 |
$form['quicksearch_fields'] = array(
|
| 110 |
'#type' => 'select',
|
| 111 |
'#multiple' => true,
|
| 112 |
'#required' => true,
|
| 113 |
'#title' => t('Search Fields'),
|
| 114 |
'#options' => _quicksearch_fields(),
|
| 115 |
'#default_value' => array_keys(variable_get('quicksearch_fields', _quicksearch_fields())),
|
| 116 |
'#description' => t('Choose which fields to apply quicksearch to. Use Ctrl (command) + click to select multiples.')
|
| 117 |
);
|
| 118 |
$form['quicksearch_close_button_label'] = array(
|
| 119 |
'#type' => 'textfield',
|
| 120 |
'#title' => t('Close Button Label'),
|
| 121 |
'#description' => t('Language / character to use as the close button label.'),
|
| 122 |
'#default_value' => QUICKSEARCH_CLOSE_BUTTON_LABEL
|
| 123 |
);
|
| 124 |
$form['quicksearch_close_button_title'] = array(
|
| 125 |
'#type' => 'textfield',
|
| 126 |
'#title' => t('Close Button Title'),
|
| 127 |
'#description' => t('Language / character to use as the close button title.'),
|
| 128 |
'#default_value' => QUICKSEARCH_CLOSE_BUTTON_TITLE
|
| 129 |
);
|
| 130 |
$form['quicksearch_permalink'] = array(
|
| 131 |
'#type' => 'textfield',
|
| 132 |
'#title' => t('Permalink Label'),
|
| 133 |
'#description' => t('Language / characters to use as the permalink text for the search results.'),
|
| 134 |
'#default_value' => QUICKSEARCH_PERMALINK
|
| 135 |
);
|
| 136 |
|
| 137 |
$form['themer'] = array('#type' => 'fieldset', '#title' => t('Themers'), '#collapsible' => true, '#collapsed' => true);
|
| 138 |
$form['themer']['quicksearch_field_label'] = array(
|
| 139 |
'#type' => 'textfield',
|
| 140 |
'#required' => true,
|
| 141 |
'#size' => QUICKSEARCH_FIELD_SIZE,
|
| 142 |
'#title' => t('Field label'),
|
| 143 |
'#description' => t('The label displayed in the textfield when no keys are provided.'),
|
| 144 |
'#default_value' => QUICKSEARCH_FIELD_LABEL
|
| 145 |
);
|
| 146 |
$form['themer']['quicksearch_field_size'] = array(
|
| 147 |
'#type' => 'textfield',
|
| 148 |
'#required' => true,
|
| 149 |
'#size' => 2,
|
| 150 |
'#title' => t('Field Width'),
|
| 151 |
'#description' => t('Sometimes when theming drupal forms, textfields can be a pain with the #size value. Here you can customize it for the search fields that get live search and the field above to set the field label uses the exact size you provide here.'),
|
| 152 |
'#default_value' => QUICKSEARCH_FIELD_SIZE
|
| 153 |
);
|
| 154 |
|
| 155 |
$selector_description = '<strong>ONLY USE THIS IF YOU KNOW WHAT YOU ARE DOING.</strong>
|
| 156 |
<p>Provide a CSS selector for jQuery to display the search results in.
|
| 157 |
If you provide a possible "bad" value you can break the visuals of your site when quicksearch is used.</p>
|
| 158 |
<p>Garland Theme: <em>#squeeze div.left-corner</em></p>';
|
| 159 |
|
| 160 |
$form['themer']['quicksearch_selector'] = array(
|
| 161 |
'#type' => 'textfield',
|
| 162 |
'#title' => t('CSS Selector'),
|
| 163 |
'#description' => t($selector_description),
|
| 164 |
'#default_value' => QUICKSEARCH_SELECTOR
|
| 165 |
);
|
| 166 |
|
| 167 |
$form['themer']['ui'] = array(
|
| 168 |
'#type' => 'fieldset',
|
| 169 |
'#title' => t('UI Mode'),
|
| 170 |
'#description' => t('If a CSS selector is not provided, UI mode is how search results are displayed.'),
|
| 171 |
'#collapsible' => true,
|
| 172 |
'#collapsed' => true
|
| 173 |
);
|
| 174 |
$form['themer']['ui']['quicksearch_title'] = array(
|
| 175 |
'#type' => 'textfield',
|
| 176 |
'#required' => true,
|
| 177 |
'#title' => t('Window Title'),
|
| 178 |
'#description' => t('The title to be displayed for this search window.'),
|
| 179 |
'#default_value' => QUICKSEARCH_TITLE
|
| 180 |
);
|
| 181 |
$form['themer']['ui']['quicksearch_hider'] = array(
|
| 182 |
'#type' => 'textfield',
|
| 183 |
'#required' => true,
|
| 184 |
'#size' => 2,
|
| 185 |
'#title' => t('Hider Opacity'),
|
| 186 |
'#description' => t('This value goes between 0.0 - 1.0 and is used to set the opacity level of the quicksearch hider. If 0, the hider will not be used.'),
|
| 187 |
'#default_value' => QUICKSEARCH_HIDER
|
| 188 |
);
|
| 189 |
$form['themer']['ui']['quicksearch_ui_delay'] = array(
|
| 190 |
'#type' => 'textfield',
|
| 191 |
'#required' => true,
|
| 192 |
'#size' => 5,
|
| 193 |
'#title' => t('UI Window Popup Delay'),
|
| 194 |
'#description' => t('Change how long it takes for the UI window to popup once you have stopped typing.'),
|
| 195 |
'#default_value' => QUICKSEARCH_UI_DELAY
|
| 196 |
);
|
| 197 |
$form['themer']['ui']['quicksearch_ui_width'] = array(
|
| 198 |
'#type' => 'textfield',
|
| 199 |
'#required' => true,
|
| 200 |
'#size' => 4,
|
| 201 |
'#field_suffix' => t('px'),
|
| 202 |
'#title' => t('UI Window Width'),
|
| 203 |
'#description' => t('Instead of specifying this with CSS, it is configurable here because JavaScript uses this value to center the results to the screen.'),
|
| 204 |
'#default_value' => QUICKSEARCH_UI_WIDTH
|
| 205 |
);
|
| 206 |
|
| 207 |
return system_settings_form($form);
|
| 208 |
}
|
| 209 |
|
| 210 |
/**
|
| 211 |
* Search callback. (Basically search_view() with a few tweaks)
|
| 212 |
*/
|
| 213 |
function quicksearch_callback($type = 'node', $keys) {
|
| 214 |
// Grab the keys.
|
| 215 |
list($page, $search_type, $keys) = explode('/', $_GET['q'], 3);
|
| 216 |
|
| 217 |
// Only perform search if there is non-whitespace search term.
|
| 218 |
if (trim($keys)) {
|
| 219 |
// Log the search keys.
|
| 220 |
watchdog('search', t('%keys (@type).', array('%keys' => $keys, '@type' => module_invoke($type, 'search', 'name'))), WATCHDOG_NOTICE, l(t('results'), 'search/'. $type .'/'. $keys));
|
| 221 |
|
| 222 |
// Collect the search results.
|
| 223 |
$results = search_data($keys, $type);
|
| 224 |
print theme('quicksearch_results', $keys, $type, $results);
|
| 225 |
}
|
| 226 |
exit;
|
| 227 |
}
|
| 228 |
|
| 229 |
/**
|
| 230 |
* Themable search results.
|
| 231 |
*/
|
| 232 |
function theme_quicksearch_results($keys, $type, $results) {
|
| 233 |
// Content or user searching. These id's are needed.
|
| 234 |
$output .= '<ul class="tabs primary quicksearch-tabs">' ."\n";
|
| 235 |
$output .= ' <li id="quicksearch-node-link" class="'. ($type == 'node' ? 'active' : '') .'">'. l(t('Content'), 'quicksearch/node/'. $keys, array('title' => t('Content'))) .'</li>' ."\n";
|
| 236 |
$output .= ' <li id="quicksearch-user-link" class="'. ($type == 'user' ? 'active' : '') .'">'. l(t('Users'), 'quicksearch/user/'. $keys, array('title' => t('Users'))) .'</li>' ."\n";
|
| 237 |
$output .= '</ul>';
|
| 238 |
|
| 239 |
if ($results) {
|
| 240 |
// Do not display the title if using craqbox because of the craqbox titlebar.
|
| 241 |
$output .= theme('box', QUICKSEARCH_SELECTOR ? t('Search results') : '', $results);
|
| 242 |
}
|
| 243 |
else {
|
| 244 |
$output .= theme('box', t('Your search yielded no results'), search_help('search#noresults'));
|
| 245 |
}
|
| 246 |
$output .= l(QUICKSEARCH_PERMALINK, 'search/'. $type .'/'. $keys, array('class' => 'permalink'));
|
| 247 |
|
| 248 |
return $output;
|
| 249 |
}
|
| 250 |
|
| 251 |
/**
|
| 252 |
* Helper functions.
|
| 253 |
*/
|
| 254 |
|
| 255 |
/**
|
| 256 |
* Search forms available to autoattach to.
|
| 257 |
* TODO: should probably handle this function a little nicer for maintaining?
|
| 258 |
*/
|
| 259 |
function _quicksearch_fields() {
|
| 260 |
return array('search_theme_form' => t('Theme Layer Search Form'), 'search_block_form' => t('Block Search Form'));
|
| 261 |
}
|