Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.659 diff -u -r1.659 system.module --- modules/system/system.module 14 Jan 2009 21:13:41 -0000 1.659 +++ modules/system/system.module 17 Jan 2009 05:23:09 -0000 @@ -388,6 +388,12 @@ 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); + $items['system/ahah'] = array( + 'title' => 'AHAH callback', + 'page callback' => 'form_ahah_callback', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); $items['system/timezone'] = array( 'title' => 'Time zone', 'page callback' => 'system_timezone', Index: modules/poll/poll.module =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v retrieving revision 1.284 diff -u -r1.284 poll.module --- modules/poll/poll.module 8 Jan 2009 08:42:12 -0000 1.284 +++ modules/poll/poll.module 17 Jan 2009 05:23:08 -0000 @@ -118,13 +118,6 @@ 'type' => MENU_LOCAL_TASK, ); - $items['poll/js'] = array( - 'title' => 'Javascript Choice Form', - 'page callback' => 'poll_choice_js', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - return $items; } @@ -266,7 +259,7 @@ '#weight' => 1, '#submit' => array('poll_more_choices_submit'), // If no javascript action. '#ahah' => array( - 'path' => 'poll/js', + 'callback' => 'poll_choice_js', 'wrapper' => 'poll-choices', 'method' => 'replace', 'effect' => 'fade', @@ -315,7 +308,7 @@ // Make the changes we want to the form state. if ($form_state['values']['poll_more']) { - $n = $_GET['q'] == 'poll/js' ? 1 : 5; + $n = $_GET['q'] == 'system/ahah' ? 1 : 5; $form_state['choice_count'] = count($form_state['values']['choice']) + $n; } } @@ -361,36 +354,27 @@ } /** - * Menu callback for AHAH additions. + * Menu callback for AHAH additions. Render the new poll choices. */ -function poll_choice_js() { - $form_state = array('storage' => NULL, 'submitted' => FALSE); - $form_build_id = $_POST['form_build_id']; - - // Get the form from the cache. - $form = form_get_cache($form_build_id, $form_state); - $args = $form['#parameters']; - $form_id = array_shift($args); - - // We will run some of the submit handlers so we need to disable redirecting. - $form['#redirect'] = FALSE; - - // We need to process the form, prepare for that by setting a few internals - // variables. - $form['#post'] = $_POST; - $form['#programmed'] = FALSE; - $form_state['post'] = $_POST; - - // Build, validate and if possible, submit the form. - drupal_process_form($form_id, $form, $form_state); - - // This call recreates the form relying solely on the form_state that the - // drupal_process_form set up. - $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id); - - // Render the new output. +function poll_choice_js($form, $form_state) { $choice_form = $form['choice_wrapper']['choice']; - unset($choice_form['#prefix'], $choice_form['#suffix']); // Prevent duplicate wrappers. + $last_choice = ''; + foreach (element_children($choice_form) as $key) { + if (strpos($key, 'new:') !== FALSE) { + $last_choice = $key; + } + } + + // Add a class to the last row to have it fade in separately. + if (isset($choice_form[$last_choice]['#attributes']['class'])) { + $choice_form[$last_choice]['#attributes']['class'] .= ' ahah-new-content'; + } + else { + $choice_form[$last_choice]['#attributes']['class'] = 'ahah-new-content'; + } + + // Prevent duplicate wrappers. + unset($choice_form['#prefix'], $choice_form['#suffix']); $output = theme('status_messages') . drupal_render($choice_form); drupal_json(array('status' => TRUE, 'data' => $output)); Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.312 diff -u -r1.312 form.inc --- includes/form.inc 12 Jan 2009 06:23:57 -0000 1.312 +++ includes/form.inc 17 Jan 2009 05:23:08 -0000 @@ -1755,6 +1755,39 @@ } /** + * Menu callback for AHAH callbacks through the #ahah['callback'] FAPI property. + */ +function form_ahah_callback() { + $form_state = array('storage' => NULL, 'submitted' => FALSE); + $form_build_id = $_POST['form_build_id']; + + // Get the form from the cache. + $form = form_get_cache($form_build_id, $form_state); + $args = $form['#parameters']; + $form_id = array_shift($args); + + // We will run some of the submit handlers so we need to disable redirecting. + $form['#redirect'] = FALSE; + + // We need to process the form, prepare for that by setting a few internals + // variables. + $form['#post'] = $_POST; + $form['#programmed'] = FALSE; + $form_state['post'] = $_POST; + + // Build, validate and if possible, submit the form. + drupal_process_form($form_id, $form, $form_state); + + // This call recreates the form relying solely on the form_state that the + // drupal_process_form set up. + $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id); + + // Get the callback function from the clicked button. + $callback = $form_state['clicked_button']['#ahah']['callback']; + $callback($form, $form_state); +} + +/** * Roll out a single radios element to a list of radios, * using the options array as index. */ @@ -1871,7 +1904,7 @@ function form_process_ahah($element) { static $js_added = array(); // Add a reasonable default event handler if none specified. - if (isset($element['#ahah']['path']) && !isset($element['#ahah']['event'])) { + if (isset($element['#ahah']) && !isset($element['#ahah']['event'])) { switch ($element['#type']) { case 'submit': case 'button': @@ -1901,12 +1934,12 @@ // Adding the same javascript settings twice will cause a recursion error, // we avoid the problem by checking if the javascript has already been added. - if (isset($element['#ahah']['path']) && isset($element['#ahah']['event']) && !isset($js_added[$element['#id']])) { + if ((isset($element['#ahah']['callback']) || isset($element['#ahah']['path'])) && isset($element['#ahah']['event']) && !isset($js_added[$element['#id']])) { drupal_add_js('misc/jquery.form.js', array('weight' => JS_LIBRARY)); drupal_add_js('misc/ahah.js'); $ahah_binding = array( - 'url' => url($element['#ahah']['path']), + 'url' => isset($element['#ahah']['callback']) ? url('system/ahah') : url($element['#ahah']['path']), 'event' => $element['#ahah']['event'], 'keypress' => empty($element['#ahah']['keypress']) ? NULL : $element['#ahah']['keypress'], 'wrapper' => empty($element['#ahah']['wrapper']) ? NULL : $element['#ahah']['wrapper'],