diff --git a/includes/ajax.inc b/includes/ajax.inc index 1568e582f5c764d19ec80238028c08750061a082..49ff7e46b0f007e0efdfa040e10f6a0854054a20 100644 --- a/includes/ajax.inc +++ b/includes/ajax.inc @@ -20,11 +20,10 @@ * forms, it can be used with the #ajax property. * The #ajax property can be used to bind events to the AJAX framework. By * default, #ajax uses 'system/ajax' as its path for submission and thus calls - * @link ajax_form_callback ajax_form_callback @endlink and a defined - * #ajax['callback'] function. However, you may optionally specify a different - * path to request or a different callback function to invoke, which can return - * updated HTML or can also return a richer set of - * @link ajax_commands AJAX framework commands @endlink. + * ajax_form_callback() and a defined #ajax['callback'] function. + * However, you may optionally specify a different path to request or a + * different callback function to invoke, which can return updated HTML or can + * also return a richer set of @link ajax_commands AJAX framework commands @endlink. * * Standard form handling is as follows: * - A form element has a #ajax member. @@ -124,9 +123,10 @@ * selected automatically for the type of form widget being used, and * is only needed if you need to override the default behavior. * - #ajax['method']: The jQuery method to use to place the new HTML. - * Defaults to 'replace'. May be: 'replace', 'append', 'prepend', - * 'before', 'after', or 'html'. See the jQuery documentation for more - * information on these methods. + * Defaults to 'replaceWith'. May be: 'replaceWith', 'append', 'prepend', + * 'before', 'after', or 'html'. See the + * @link http://api.jquery.com/category/manipulation/ jQuery manipulators documentation @endlink + * for more information on these methods. * - #ajax['progress']: Choose either a throbber or progress bar that is * displayed while awaiting a response from the callback, and add an optional * message. Possible keys: 'type', 'message', 'url', 'interval'. @@ -336,13 +336,16 @@ function ajax_deliver($page_callback_result) { } } else { - // Like normal page callbacks, simple AJAX callbacks can return html - // content, as a string or renderable array, to replace what was previously - // there in the wrapper. In this case, in addition to the content, we want - // to add the status messages, but inside the new wrapper, so that they get - // replaced on subsequent AJAX calls for the same wrapper. + // Like normal page callbacks, simple AJAX callbacks can return HTML + // content, as a string or render array. This HTML is inserted in some + // relationship to #ajax['wrapper'], as determined by which jQuery DOM + // manipulation method is used. The method used is specified by + // #ajax['method']. The default method is 'replaceWith', which completely + // replaces the old wrapper element and its content with the new HTML. $html = is_string($page_callback_result) ? $page_callback_result : drupal_render($page_callback_result); - $commands[] = ajax_command_replace(NULL, $html); + $commands[] = ajax_command_insert(NULL, $html); + // Add the status messages inside the new content's wrapper element, so that + // on subsequent AJAX requests, it is treated as old content. $commands[] = ajax_command_prepend(NULL, theme('status_messages')); } @@ -460,10 +463,15 @@ function ajax_process_form($element, &$form_state) { 'selector' => '#' . $element['#id'], 'effect' => 'none', 'speed' => 'none', - 'method' => 'replace', + 'method' => 'replaceWith', 'progress' => array('type' => 'throbber'), ); + // @todo Legacy support. Remove in Drupal 8. + if ($settings['method'] == 'replace') { + $settings['method'] = 'replaceWith'; + } + // Change path to url. $settings['url'] = isset($settings['path']) ? url($settings['path']) : url('system/ajax'); unset($settings['path']); @@ -552,6 +560,37 @@ function ajax_command_alert($text) { ); } +/** + * Creates a Drupal AJAX 'insert' command using the method in #ajax['method']. + * + * This command instructs the client to insert the given HTML using whichever + * jQuery DOM manipulation method has been specified in the #ajax['method'] + * variable of the element that triggered the request. + * + * This command is implemented by Drupal.ajax.prototype.commands.insert() + * defined in misc/ajax.js. + * + * @param $selector + * A jQuery selector string. If the command is a response to a request from + * an #ajax form element then this value can be NULL. + * @param $html + * The data to use with the jQuery method. + * @param $settings + * An optional array of settings that will be used for this command only. + * + * @return + * An array suitable for use with the ajax_render() function. + */ +function ajax_command_insert($selector, $html, $settings = NULL) { + return array( + 'command' => 'insert', + 'method' => NULL, + 'selector' => $selector, + 'data' => $html, + 'settings' => $settings, + ); +} + /** * Creates a Drupal AJAX 'insert/replaceWith' command. * @@ -573,7 +612,7 @@ function ajax_command_alert($text) { * @return * An array suitable for use with the ajax_render() function. * - * @see http://docs.jquery.com/Manipulation/replaceWith#content + * See @link http://docs.jquery.com/Manipulation/replaceWith#content jQuery replaceWith command @endlink */ function ajax_command_replace($selector, $html, $settings = NULL) { return array( diff --git a/misc/ajax.js b/misc/ajax.js index 1d6c8295db8c4ab89b72b991e51d58fbb60cc4c4..339d167ebe56044b7bb474c60bd0cb3d60196640 100644 --- a/misc/ajax.js +++ b/misc/ajax.js @@ -93,7 +93,7 @@ Drupal.ajax = function (base, element, element_settings) { selector: '#' + base, effect: 'none', speed: 'slow', - method: 'replace', + method: 'replaceWith', progress: { type: 'bar', message: 'Please wait...' diff --git a/modules/field/field.form.inc b/modules/field/field.form.inc index 5fd367a070964b31386b6bccf346e71741d8eb6c..61a5833bc00714ab8906df2a943018ee0f348951 100644 --- a/modules/field/field.form.inc +++ b/modules/field/field.form.inc @@ -215,7 +215,6 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form, '#ajax' => array( 'callback' => 'field_add_more_js', 'wrapper' => $wrapper_id, - 'method' => 'replace', 'effect' => 'fade', ), // The field_add_more_submit() and field_add_more_js() handlers will diff --git a/modules/file/file.module b/modules/file/file.module index b925d7c2eb7d747bba5bb83b1a7d5688958070cc..44ef83c066a4740a870d4029a4cf16bfedcffdaa 100644 --- a/modules/file/file.module +++ b/modules/file/file.module @@ -351,7 +351,6 @@ function file_managed_file_process($element, &$form_state, $form) { $ajax_settings = array( 'path' => 'file/ajax/' . implode('/', $element['#parents']) . '/' . $form['form_build_id']['#value'], 'wrapper' => $element['#id'] . '-ajax-wrapper', - 'method' => 'replace', 'effect' => 'fade', 'progress' => array( 'type' => $element['#progress_indicator'], diff --git a/modules/poll/poll.module b/modules/poll/poll.module index 729a51dc945582131602893611a59f88fbf12ab6..f7eb9ebaad0f3ce023126b52782b23eecc1c89f3 100644 --- a/modules/poll/poll.module +++ b/modules/poll/poll.module @@ -297,7 +297,6 @@ function poll_form($node, &$form_state) { '#ajax' => array( 'callback' => 'poll_choice_js', 'wrapper' => 'poll-choices', - 'method' => 'replace', 'effect' => 'fade', ), ); diff --git a/modules/simpletest/tests/ajax.test b/modules/simpletest/tests/ajax.test index 80ea29f5819f993e2ad28d3ebd1b65be43b7a2b5..97cd2f5d2ff3751e5d66e4e51abea0cd831e45f9 100644 --- a/modules/simpletest/tests/ajax.test +++ b/modules/simpletest/tests/ajax.test @@ -146,6 +146,11 @@ class AJAXCommandsTestCase extends AJAXTestCase { $command = $commands[0]; $this->assertTrue($command['command'] == 'insert' && $command['method'] == 'html' && $command['data'] == 'replacement text', "'html' AJAX command issued with correct data"); + // Tests the 'insert' command. + $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX insert: Let client insert based on #ajax['method'].")))); + $command = $commands[0]; + $this->assertTrue($command['command'] == 'insert' && $command['method'] == NULL && $command['data'] == 'insert replacement text', "'insert' AJAX command issued with correct data"); + // Tests the 'prepend' command. $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'prepend': Click to prepend something")))); $command = $commands[0]; diff --git a/modules/simpletest/tests/ajax_forms_test.module b/modules/simpletest/tests/ajax_forms_test.module index 5de2b842c694aac4fd5bb708b1fe6011b8a565da..db8aa3b9253cd3e23b13c88ae623029247ffd28b 100644 --- a/modules/simpletest/tests/ajax_forms_test.module +++ b/modules/simpletest/tests/ajax_forms_test.module @@ -186,6 +186,17 @@ function ajax_forms_test_ajax_commands_form($form, &$form_state) { '#suffix' => '<div id="html_div">Original contents</div>', ); + // Shows the AJAX 'insert' command. + $form['insert_command_example'] = array( + '#value' => t("AJAX insert: Let client insert based on #ajax['method']."), + '#type' => 'submit', + '#ajax' => array( + 'callback' => 'ajax_forms_test_advanced_commands_insert_callback', + 'method' => 'prepend', + ), + '#suffix' => '<div id="insert_div">Original contents</div>', + ); + // Shows the AJAX 'prepend' command. $form['prepend_command_example'] = array( '#value' => t("AJAX 'prepend': Click to prepend something"), @@ -320,6 +331,15 @@ function ajax_forms_test_advanced_commands_html_callback($form, $form_state) { return array('#type' => 'ajax', '#commands' => $commands); } +/** + * AJAX callback for 'insert'. + */ +function ajax_forms_test_advanced_commands_insert_callback($form, $form_state) { + $commands = array(); + $commands[] = ajax_command_insert('#insert_div', 'insert replacement text'); + return array('#type' => 'ajax', '#commands' => $commands); +} + /** * AJAX callback for 'prepend'. */