Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/google_cse_adv/README.txt,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 README.txt
--- README.txt	6 Oct 2010 10:04:18 -0000	1.1.2.2
+++ README.txt	8 Oct 2010 07:46:18 -0000
@@ -1,25 +1,75 @@
-Google CSE Advanced module
---------------------------
-
-Created by Dynamite Heads http://www.dynamiteheads.com
-Module development sponsored by Brightcove, Inc. - http://www.brightcove.com
-
-Installation instructions
--------------------------
-
-1) Download module from http://drupal.org/project/google_cse_adv
-2) Extract to sites/all/modules or sites/[sitename]/modules
-3) Enable module at admin/build/modules
-4) Visit Admin -> Settings -> Google CSE Adv at admin/settings/google_cse_adv and set your CX key
-5) Optionally visit Admin -> Settings -> Search settings and set a "Number of
-   items to index per cron run" to 0 to disable core module indexing.
-
- 
-Notes
------
-
-Total number of search results fetched from Google CSE can be a bit
-different on each request - for example during a paging.
-See http://www.google.com/cse/docs/resultsxml.html and M result tag
-which says: "The <M> tag identifies the estimated total number of results
-for the search. Note: This estimate may not be accurate."
+Google CSE Advanced module
+--------------------------
+
+Created by Dynamite Heads http://www.dynamiteheads.com
+Module development sponsored by Brightcove, Inc. - http://www.brightcove.com
+
+Installation instructions
+-------------------------
+
+1) Download module from http://drupal.org/project/google_cse_adv
+2) Extract to sites/all/modules or sites/[sitename]/modules
+3) Enable module at admin/build/modules
+4) Visit Admin -> Settings -> Google CSE Adv at admin/settings/google_cse_adv and set your CX key
+5) Optionally visit Admin -> Settings -> Search settings and set a "Number of
+   items to index per cron run" to 0 to disable core module indexing.
+
+
+Notes
+-----
+
+* Results count
+---------------
+
+Total number of search results fetched from Google CSE can be a bit
+different on each request - for example during a paging.
+See http://www.google.com/cse/docs/resultsxml.html and M result tag
+which says: "The <M> tag identifies the estimated total number of results
+for the search. Note: This estimate may not be accurate."
+
+
+* Styling the autocompletion
+----------------------------
+
+Styles for the Google auto-completion table are provided by
+the default.css file from google. The selectors used are:
+
+  .gsc-completion-container
+  .gsc-completion-selected
+
+The default styles at this time are:
+
+.gsc-completion-selected {
+  background: #D5E2FF;
+}
+.gsc-completion-container {
+  font-family: Arial, sans-serif;
+  font-size: 13px;
+  position: absolute;
+  background: white;
+  border: 1px solid #666666;
+  margin-left: 0;
+  margin-right: 0;
+  /* The top, left, and width are set in JavaScript. */
+}
+
+These can be over-ridden by making the styles !important, or the
+selector more precise. The following selectors describe the markup
+that will be inserted:
+
+body > table.gsc-completion-container {
+  /* The table which contains the completions.
+  top, left, and width styles are all inserted inline into the
+  table element's style attribute. */
+}
+.gsc-completion-container > tbody > tr > td {
+  /* A suggested query. */
+}
+.gsc-completion-container > tbody > tr > td > strong {
+  /* Auto-completed text (i.e. the bits that the user did NOT type). */
+}
+.gsc-completion-container > tbody > tr > td.gsc-completion-selected,
+#csc-completion-selected {
+  /* A suggested query which the user has moused-over. */
+}
+
Index: google_cse_adv.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/google_cse_adv/google_cse_adv.module,v
retrieving revision 1.1.2.6
diff -u -p -r1.1.2.6 google_cse_adv.module
--- google_cse_adv.module	6 Oct 2010 10:06:37 -0000	1.1.2.6
+++ google_cse_adv.module	8 Oct 2010 07:46:19 -0000
@@ -58,6 +58,27 @@ function google_cse_adv_settings_form() 
     '#size' => 3,
     '#default_value' => variable_get('google_cse_adv_results_per_page', 10),
   );
+  $form['autocomplete'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Autocompletion'),
+    '#description' => t("Note that you must also enable this feature in your Google CSE control panel."),
+  );
+  $form['autocomplete']['google_cse_adv_autocomplete'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Apply to forms'),
+    '#options' => array(
+      'search_form' => t('Search form'),
+      'search_theme_form' => t('Search theme form'),
+      'search_block_form' => t('Search block form'),
+    ),
+    '#default_value' => variable_get('google_cse_adv_autocomplete', array()),
+  );
+  $form['autocomplete']['google_cse_adv_google_api_key'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Google AJAX API key (!optional)', array('!optional' => l(t('optional'), 'http://code.google.com/intl/en/apis/ajaxsearch/key.html'))),
+    '#description' => t("If you enter an AJAX API key here, it will be used when loading the AJAX library."),
+    '#default_value' => variable_get('google_cse_adv_google_api_key', ''),
+  );
   return system_settings_form($form);
 }
 
@@ -98,19 +119,33 @@ function google_cse_adv_menu_alter(&$men
 
 /**
  * Implementation of hook_form_[form_id]_alter().
- *
- * @see apachesolr_search_form_search_theme_form_alter()
+ */
+function google_cse_adv_form_search_form_alter(&$form, $form_state) {
+  google_cse_adv_form_alter_autocompletion($form, $form['basic']['inline']['keys']);
+}
+
+/**
+ * Implementation of hook_form_[form_id]_alter().
  */
 function google_cse_adv_form_search_theme_form_alter(&$form, $form_state) {
-  google_cse_adv_form_search_block_form_alter($form, $form_state);
+  _google_cse_adv_form_alter_search_box($form, $form_state);
+  google_cse_adv_form_alter_autocompletion($form, $form['search_theme_form']);
 }
 
 /**
  * Implementation of hook_form_[form_id]_alter().
+ */
+function google_cse_adv_form_search_block_form_alter(&$form, $form_state) {
+  _google_cse_adv_form_alter_search_box($form, $form_state);
+  google_cse_adv_form_alter_autocompletion($form, $form['search_block_form']);
+}
+
+/**
+ * Helper for altering forms derived from search_box().
  *
  * @see apachesolr_search_form_search_block_form_alter()
  */
-function google_cse_adv_form_search_block_form_alter(&$form, $form_state) {
+function _google_cse_adv_form_alter_search_box(&$form, $form_state) {
   if (!isset($form['#submit'])) {
     $form['#submit'] = array('google_cse_adv_search_box_form_submit');
   }
@@ -158,6 +193,78 @@ function google_cse_adv_search_box_form_
 }
 
 /**
+ * Helper for form_alter hooks.
+ * Enable autocompletion for the specified form field.
+ *
+ * Adding autocompletion involves generating inline javascript that
+ * knows the HTML id attribute of both the form and the relevant text
+ * input field.
+ *
+ * At form_alter time, we don't have a reliable id attribute for the
+ * textfield because form_clean_id() may subsequently modify it when
+ * form_builder() calls _form_builder_handle_input_element().
+ *
+ * The solution is to store a reference to the field id here at the
+ * form_alter stage, and do the processing with an #after_build
+ * callback (at which stage the id values will be final).
+ */
+function google_cse_adv_form_alter_autocompletion(&$form, &$field) {
+  // Only enable autocompletion for the forms specified on the
+  // settings page.
+  $autocomplete = variable_get('google_cse_adv_autocomplete', array());
+  if (!empty($autocomplete[$form['form_id']['#value']])) {
+    $form['#google_cse_adv_autocompletion_field_id'] =& $field['#id'];
+    $form['#after_build'][] = '_google_cse_adv_add_autocompletion_script';
+  }
+}
+
+/**
+ * Add the autocompletion javascript.
+ * Called by form_builder() as a result of the '#after_build' flag.
+ */
+function _google_cse_adv_add_autocompletion_script(&$form, $form_state) {
+  // Extract the final HTML 'id' attributes for the form and
+  // its autocompletion field.
+  $form_id = $form['#id'];
+  $field_id = $form['#google_cse_adv_autocompletion_field_id'];
+
+  // Generate the autocompletion javascript.
+  $autocompletion = theme(
+    'google_cse_adv_autocompletion_script', $form_id, $field_id
+  );
+  if ($autocompletion) {
+    _google_cse_adv_load_ajax_api();
+    drupal_add_js($autocompletion, 'inline');
+  }
+
+  return $form;
+}
+
+/**
+ * Load Google AJAX API.
+ *
+ * drupal_add_js() does not support external script sources
+ * so we must add an inline script which will write the
+ * real <script src="..."></script> element to load the
+ * required library.
+ */
+function _google_cse_adv_load_ajax_api() {
+  static $loaded = FALSE;
+
+  if (!$loaded) {
+    $google_ajax_api = 'http://www.google.com/jsapi';
+    if ($api_key = variable_get('google_cse_adv_google_api_key', FALSE)) {
+      $google_ajax_api .= '?key=' . urlencode($api_key);
+    }
+    $external_script = 'unescape("%3Cscript type=\"text/javascript\"'
+      . ' src=\"' . $google_ajax_api . '\"%3E%3C/script%3E")';
+
+    drupal_add_js("document.write({$external_script});", 'inline');
+    $loaded = TRUE;
+  }
+}
+
+/**
  * Re-implementation of search_view().
  *
  * @see apachesolr_search_view()
@@ -566,6 +673,9 @@ function google_cse_adv_theme($existing,
     'google_cse_adv_suggestion' => array(
       'arguments' => array('suggestions' => NULL)
     ),
+    'google_cse_adv_autocompletion_script' => array(
+      'arguments' => array('form_id' => NULL, 'input_id' => NULL),
+    ),
   );
 }
 
@@ -587,3 +697,24 @@ function theme_google_cse_adv_suggestion
   $output .= theme('item_list', $items);
   return $output;
 }
+
+/**
+ * Autocompletion javascript.
+ * This can be overridden in case the API changes.
+ */
+function theme_google_cse_adv_autocompletion_script($form_id = 'search-form', $input_id = 'edit-keys') {
+  if ($cx_key = check_plain(variable_get('google_cse_adv_cx', ''))) {
+    return <<<END
+      google.load('search', '1', {language : 'en'});
+      google.setOnLoadCallback(function() {
+        input = document.getElementById('{$input_id}');
+        // Disable browser's history-based completion
+        input.setAttribute('autocomplete', 'off');
+        // Attach Google CSE autocomplete behaviour
+        google.search.CustomSearchControl.attachAutoCompletion(
+          '{$cx_key}', input, '{$form_id}'
+        );
+      });
+END;
+  }
+}
