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	17 Jul 2009 20:39:46 -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: includes/ajax.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/includes/ajax.inc,v
retrieving revision 1.9
diff -u -r1.9 ajax.inc
--- includes/ajax.inc	9 Jul 2009 00:07:04 -0000	1.9
+++ includes/ajax.inc	17 Jul 2009 20:39:46 -0000
@@ -363,3 +363,48 @@
   ctools_ajax_render($commands);
 }
 
+/**
+ * Associate a URL to a form element with a hidden form.
+ *
+ * This is a helper function to easily associate a URL with a form element
+ * which can be used for different ajax functionality. 
+ * 
+ * You would call this function on a form element in the form function like this:
+ *
+ * @code
+ *   $form['example'] = array(
+ *     '#title' => t('Example'),
+ *     '#type' => 'select',
+ *     '#options' => array(1 => 'One', 2 => 'Two', 3 => 'Three'),
+ *     '#default_value' => 1,
+ *   );
+ *   ctools_ajax_associate_url_to_element($form, $form['example'], 'example/ajax/urlpath');
+ * @endcode
+ * 
+ * The AJAX request will POST the value of the form element in the "ctools_changed" parameter.
+ *
+ * @param &$form
+ *   Reference to the form element. This is required to have the #id and #attribute
+ *   elements populated and to create the hidden form element for each select.
+ * @param &$form_element
+ *   The form element we are going to take action on.
+ * @param $dest
+ *   The URL to associate the form element to.
+ * @param $type
+ *   A type to use, in case a different behavior should be attached. Defaults
+ *   to ctools-use-ajax.
+ */
+function ctools_ajax_associate_url_to_element(&$form, &$form_element, $dest, $type = 'ctools-use-ajax') {
+  drupal_add_js('misc/jquery.form.js', 'core');
+  if (!isset($form_element['#id'])) {
+    //Create a unique ID to associate $form_element and hidden elements since we dont have an ID
+    $form_element['#id'] = uniqid('ctools-ajax-url-');
+  }
+  
+  //Add hidden form element to hold base URL
+  $form[$form_element['#id'] . '-url'] = array(
+    '#type' => 'hidden',
+    '#value' => $dest,
+    '#attributes' => array('class' =>  $form_element['#id'] . '-url'),
+  );
+}
Index: js/ajax-responder.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/js/ajax-responder.js,v
retrieving revision 1.10
diff -u -r1.10 ajax-responder.js
--- js/ajax-responder.js	11 Jul 2009 18:11:36 -0000	1.10
+++ js/ajax-responder.js	17 Jul 2009 20:39:46 -0000
@@ -124,6 +124,54 @@
 };
 
 /**
+ * Generic replacement for change handler to execute ajax method.
+ */
+Drupal.CTools.AJAX.changeAJAX = function () {
+  if ($(this).hasClass('ctools-ajaxing')) {
+    return false;
+  }
+  
+  var url = Drupal.CTools.AJAX.findURL(this);
+  $(this).addClass('ctools-ajaxing');
+  var object = $(this);
+  var form_id = $(object).parents('form').get(0).id;
+  try {
+    if (url) {
+      url = url.replace('/nojs/', '/ajax/');
+      $.ajax({
+        type: "POST",
+        url: url,
+        data: {'ctools_changed' : $(this).val()},
+        global: true,
+        success: Drupal.CTools.AJAX.respond,
+        error: function() { 
+          alert("An error occurred while attempting to process " + url); 
+        },
+        complete: function() {
+          object.removeClass('ctools-ajaxing');
+          if ($(object).hasClass('ctools-ajax-submit-onchange')) {
+            $('form#' + form_id).submit();
+          }
+        },
+        dataType: 'json'
+      });
+    }
+    else {
+      if ($(object).hasClass('ctools-ajax-submit-onchange')) {
+    	  $('form#' + form_id).submit();
+      }
+      return false;
+    }
+  }
+  catch (err) {
+    alert("An error occurred while attempting to process " + url); 
+    $(this).removeClass('ctools-ajaxing');
+    return false;
+  }
+  return false;
+};
+
+/**
  * Find a URL for an AJAX button.
  *
  * The URL for this gadget will be composed of the values of items by
@@ -238,7 +286,13 @@
     .click(Drupal.CTools.AJAX.clickAJAXLink);
 
   // Bind buttons
-  $('input.ctools-use-ajax:not(.ctools-use-ajax-processed)', context)
+  $('input.ctools-use-ajax:not(.ctools-use-ajax-processed):button', context)
     .addClass('ctools-use-ajax-processed')
     .click(Drupal.CTools.AJAX.clickAJAXButton);
+
+  // Bind select
+  $('select, input:text, input:radio, input:checkbox', context)
+     .filter('.ctools-use-ajax-onchange:not(.ctools-use-ajax-processed)')
+     .addClass('ctools-use-ajax-processed')
+     .change(Drupal.CTools.AJAX.changeAJAX);
 };
