Index: css/ctools.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/css/ctools.css,v
retrieving revision 1.3
diff -u -r1.3 ctools.css
--- css/ctools.css	22 Apr 2009 22:31:28 -0000	1.3
+++ css/ctools.css	16 May 2009 03:46:18 -0000
@@ -12,7 +12,8 @@
 }
 
 a.ctools-ajaxing,
-input.ctools-ajaxing {
+input.ctools-ajaxing,
+select.ctools-ajaxing {
   padding-right: 18px !important;
   background: url(../images/status-active.gif) right center no-repeat;
 }
Index: js/ajax-responder.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/js/ajax-responder.js,v
retrieving revision 1.7
diff -u -r1.7 ajax-responder.js
--- js/ajax-responder.js	22 Apr 2009 22:31:28 -0000	1.7
+++ js/ajax-responder.js	16 May 2009 03:47:07 -0000
@@ -210,6 +210,16 @@
     $.extend(Drupal.settings, data.argument);
   },
 
+  data: function(data) {
+    $(data.selector).data(data.name, data.value);
+  },
+  
+  messages: function(data) {
+    $('div.messages').remove();
+    $('form:not([id*="search"]):first').before(data.data);
+    Drupal.attachBehaviors($('div.messages'));
+  },
+
   restripe: function(data) {
     // :even and :odd are reversed because jquery counts from 0 and
     // we count from 1, so we're out of sync.
@@ -223,7 +233,42 @@
         .addClass('even');
   }
 };
-
+/**
+ * Generic replacement for drop down select change handler to execute ajax method.
+ */
+Drupal.CTools.AJAX.changeAJAXSelect = function () {
+  if ($(this).hasClass('ctools-ajaxing')) {
+    return false;
+  }
+  
+  if (!$(this).data('url')) {
+    $(this).data('url', Drupal.settings.CToolsAjaxSelect.url);
+  }
+  var object = $(this).addClass('ctools-ajaxing');
+  var url = $(this).data('url') + $(this).find('option:selected').attr('value');
+  try {
+    $.ajax({
+      type: "POST",
+      url: url,
+      data: '',
+      global: true,
+      success: Drupal.CTools.AJAX.respond,
+      error: function() {
+        alert("An error occurred while attempting to process " + url);
+      },
+      complete: function() {
+        object.removeClass('ctools-ajaxing');
+      },
+      dataType: 'json'
+    });
+  }
+  catch (err) {
+    alert("An error occurred while attempting to process " + url);
+    object.removeClass('ctools-ajaxing');
+    return false;
+  }
+  return false;
+};
 /**
  * Bind links that will open modals to the appropriate function.
  */
@@ -237,4 +282,9 @@
   $('input.ctools-use-ajax:not(.ctools-use-ajax-processed)', context)
     .addClass('ctools-use-ajax-processed')
     .click(Drupal.CTools.AJAX.clickAJAXButton);
+
+  // Bind select
+  $('select.ctools-use-ajax:not(.ctools-use-ajax-processed)', context)
+     .addClass('ctools-use-ajax-processed')
+     .change(Drupal.CTools.AJAX.changeAJAXSelect);
 };
Index: includes/ajax.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/includes/ajax.inc,v
retrieving revision 1.7
diff -u -r1.7 ajax.inc
--- includes/ajax.inc	11 May 2009 22:09:53 -0000	1.7
+++ includes/ajax.inc	16 May 2009 03:46:58 -0000
@@ -58,6 +58,14 @@
  * - settings
  *   - argument: An array of settings to add to Drupal.settings via $.extend
  *
+ * - data
+ *   - selector: The CSS selector. This can be any selector jquery uses in $().
+ *   - name: The name or key of the data attached to this selector.
+ *   - value: The value of the data. Not just limited to strings can be any format.
+ *
+ * - messages
+ *   - no arguments since content is retrieved from drupal_get_messages().
+ *
  * Commands are usually created with a couple of helper functions, so they
  * look like this:
  *
@@ -295,6 +303,41 @@
 }
 
 /**
+ * Create a data command for the AJAX responder.
+ *
+ * This will attach the name=value pair of data to the selector via
+ * jquery's data cache.
+ *
+ * @param $selector
+ *   The CSS selector. This can be any selector jquery uses in $().
+ * @param $name
+ *   The name or key: of the data attached to this selector.
+ * @param $value
+ *  The value of the data. Not just limited to strings can be any format.
+ */
+function ctools_ajax_command_data($selector, $name, $value) {
+  return array(
+    'command' => 'data',
+    'selector' => $selector,
+    'name' => $name,
+    'value' => $value,
+  );
+}
+
+/**
+ * Create a messages command for the AJAX responder.
+ *
+ * This will first remove previous status messages before attempting to add
+ * the status messages with content from drupal_get_messages().
+ */
+function ctools_ajax_command_messages() {
+  return array(
+    'command' => 'messages',
+    'data' => theme('status_messages'),
+  );
+}
+
+/**
  * Force a table to be restriped.
  *
  * This is usually used after a table has been modifed by a replace or append
@@ -336,3 +379,155 @@
   ctools_ajax_render($commands);
 }
 
+/**
+ * Retrieve a select element compatible with ctools_ajax_select_change().
+ *
+ * This is a helper function to easily populate a select form element
+ * which can be used for on select change ajax functionality. By assigning
+ * a destination url to a select form element the selected value will be
+ * sent to the url via ajax when the element's onchange event fires.
+ *
+ * A simple example to append a select item to the end of the first div
+ * which will call the url some/ajax/url/0..2 when the select field
+ * changes.
+ *
+ * @code
+ *   $element = ctools_ajax_select_change_element('select-1', array('a', 'b', 'c'));
+ *   $output = ctools_ajax_select_change('append', 'div:first', 'some/ajax/url', $element);
+ *   ctools_ajax_render($output);
+ * @endcode
+ *
+ * @param $name
+ *   The name for this element. This is required to have the #name attribute populated and
+ *   to attach the destination url to this unique key.
+ * @param $options
+ *   The items displayed in the select list. This is an array collection of key: value pairs
+ *   populated as values in the select list.
+ * @param $title
+ *   The label of the field. Optional label or titel for this field.
+ * @param $description
+ *   The description of the field. Optional description or help information rendered below the field.
+ * @param $required
+ *   Whether this value is required. Defaults set to FALSE, not required.
+ * @param $class
+ *   Any class to apply to the link. Space-delimited string or options array.
+ * @param $type
+ *   A type to use, in case a different behavior should be attached. Defaults
+ *   to ctools-use-ajax.
+ * @return Standard select form element which can be used in any drupal form.
+ */
+function ctools_ajax_select_change_element($name, $options, $title = '', $description = '', $required = FALSE, $class = '', $type = 'ctools-use-ajax') {
+  $classes = is_array($class) ? implode(' ', $class) : $class;
+  return array(
+    '#name' => $name,
+    '#type' => 'select',
+    '#title' => $title,
+    '#options' => $options,
+    '#description' => $description,
+    '#required' => $required,
+    '#attributes' => array('class' => "$classes $type"),
+  );
+}
+
+/**
+ * Inject a new select element into the document and attach an ajax url to it.
+ *
+ * This method is used when answering an ajax call and replying with output commands
+ * via ctools_ajax_render().
+ *
+ * A choice of 5 methods are provided to insert the select element into the document.
+ * The available options are:
+ *    after - insert the element after the selector element.
+ *    append - insert the element inside the selector element at the end of all its children.
+ *    prepend - insert the element inside the selector element at the start of all its children.
+ *    before - insert the element before the selector element.
+ *    replace - replace the selector element with the select list.
+ *
+ * This will attach a destination url to the element which will generate an ajax call when the
+ * on change event fires.
+ *
+ * Requirements:
+ * The $element['#name'] must be populated and unique. This is used to attach the
+ * destination url to the element.
+ * The element should have the class ctools-use-ajax assigned as attribute to allow
+ * the underlying javasctipt to function.
+ *
+ * @param $command
+ *   The injection method/command to use. Either; after, append, prepend, before or replace.
+ * @param $selector
+ *   The CSS selector. This can be any selector jquery uses in $().
+ * @param $dest
+ *   The destination of the ajax call. Add a trailing / allowing the selected value to be
+ *   added at the end of the url.
+ * @param $element
+ *   The select element to attach the url to. With #name property and class ctools-use-ajax assigned.
+ * @return 2 commands to forward to ctools_ajax_render().
+ */
+function ctools_ajax_select_change($command, $selector, $dest, $element) {
+  $output = array();
+  switch ($command) {
+    case 'after' :
+      $output[] = ctools_ajax_command_after($selector, theme('select', $element));
+      break;
+    case 'append' :
+      $output[] = ctools_ajax_command_append($selector, theme('select', $element));
+      break;
+    case 'prepend' :
+      $output[] = ctools_ajax_command_prepend($selector, theme('select', $element));
+      break;
+    case 'before' :
+      $output[] = ctools_ajax_command_before($selector, theme('select', $element));
+      break;
+    case 'replace' :
+      $output[] = ctools_ajax_command_replace($selector, theme('select', $element));
+      break;
+  }
+  $output[] = ctools_ajax_command_data("select[name='{$element['#name']}']", 'url', $dest);
+  return $output;
+}
+
+/**
+ * Attach a url to a select field to make an ajax call on change event.
+ *
+ * This method is used in a normal drupal_get_form callback function when not answering
+ * an ajax call and normal html will be returned. Adds the required JavaScript files and
+ * allows for one url to be attached to a select form field element which has the class
+ * ctools-use-ajax assigned.
+ *
+ * Example:
+ * @code
+ *   function mymodule_drilldown_form() {
+ *     ctools_ajax_select_change_add_js('mymodule/ajax/drill-down/');
+ *     $form = array();
+ *     $form['drill'] = ctools_ajax_select_change_element(
+ *       'drill',
+ *       $options,
+ *       t('Drill down'),
+ *       t('Select an option and more options will be retrieved.'),
+ *     );
+ *     return $form;
+ *   }
+ * @endcode
+ *
+ * @param $dest
+ *   The destination of the ajax call. Add a trailing / allowing the selected value to be
+ *   added at the end of the url.
+ */
+function ctools_ajax_select_change_add_js($dest) {
+  // Provide a gate so we only do this once.
+  static $done = FALSE;
+  if ($done) {
+    return;
+  }
+
+  $settings = array(
+    'CToolsAjaxSelect' => array(
+      'url' => $dest,
+    ),
+  );
+
+  drupal_add_js($settings, 'setting');
+  ctools_add_js('ajax-responder');
+  ctools_add_css('ctools');
+  $done = TRUE;
+}
