Commit 3cd58e7d authored by webchick's avatar webchick
Browse files

Issue #2256593 by jhodgdon, dawehner: Fixed Review and update the ajax @defgroup in ajax.inc.

parent c42156c8
......@@ -8,223 +8,155 @@
use Drupal\Core\Form\FormStateInterface;
/**
* @defgroup ajax Ajax framework
* @defgroup ajax Ajax API
* @{
* Functions for Drupal's Ajax framework.
* Overview for Drupal's Ajax API.
*
* Drupal's Ajax framework is used to dynamically update parts of a page's HTML
* based on data from the server. Upon a specified event, such as a button
* click, a callback function is triggered which performs server-side logic and
* may return updated markup, which is then replaced on-the-fly with no page
* refresh necessary.
* @section sec_overview Overview of Ajax
* Ajax is the process of dynamically updating parts of a page's HTML based on
* data from the server. When a specified event takes place, a PHP callback is
* triggered, which performs server-side logic and may return updated markup or
* JavaScript commands to run. After the return, the browser runs the JavaScript
* or updates the markup on the fly, with no full page refresh necessary.
*
* This framework creates a PHP macro language that allows the server to
* instruct JavaScript to perform actions on the client browser. When using
* 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
* \Drupal\system\FormAjaxController::content() 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.
* Many different events can trigger Ajax responses, including:
* - Clicking a button
* - Pressing a key
* - Moving the mouse
*
* Standard form handling is as follows:
* - A form element has a #ajax property that includes #ajax['callback'] and
* omits #ajax['path']. See below about using #ajax['path'] to implement
* advanced use-cases that require something other than standard form
* handling.
* - On the specified element, Ajax processing is triggered by a change to
* that element.
* - The browser submits an HTTP POST request to the 'system/ajax' Drupal
* path.
* - The controller for the route '/system/ajax',
* \Drupal\system\FormAjaxController::content(), calls drupal_process_form()
* to process the form submission and rebuild the form if necessary. The
* form is processed in much the same way as if it were submitted without
* Ajax, with the same #process functions and validation and submission
* handlers called in either case, making it easy to create Ajax-enabled
* forms that degrade gracefully when JavaScript is disabled.
* - After form processing is complete,
* \Drupal\system\FormAjaxController::content() calls the function named by
* #ajax['callback'], which returns the form element that has been updated
* and needs to be returned to the browser, or alternatively, an array of
* custom Ajax commands.
* - The array is serialized using
* \Drupal\Core\Ajax\AjaxResponse::ajaxRender() and sent to the browser.
* - The browser unserializes the returned JSON string into an array of
* command objects and executes each command, resulting in the old page
* content within and including the HTML element specified by
* #ajax['wrapper'] being replaced by the new content returned by
* #ajax['callback'], using a JavaScript animation effect specified by
* #ajax['effect'].
* @section sec_framework Ajax responses in forms
* Forms that use the Drupal Form API (see the
* @link form_api Form API topic @endlink for more information about forms) can
* trigger AJAX responses. Here is an outline of the steps:
* - Add property '#ajax' to a form element in your form array, to trigger an
* Ajax response.
* - Write an Ajax callback to process the input and respond.
* See sections below for details on these two steps.
*
* A simple example of basic Ajax use from the
* @link http://drupal.org/project/examples Examples module @endlink follows:
* @subsection sub_form Adding Ajax triggers to a form
* As an example of adding Ajax triggers to a form, consider editing a date
* format, where the user is provided with a sample of the generated date output
* as they type. To accomplish this, typing in the text field should trigger an
* Ajax response. This is done in the text field form array element
* in \Drupal\config_translation\FormElement\DateFormat::getFormElement():
* @code
* function main_page() {
* return \Drupal::formBuilder()->getForm('ajax_example_simplest');
* }
*
* function ajax_example_simplest($form, FormStateInterface $form_state) {
* $form = array();
* $form['changethis'] = array(
* '#type' => 'select',
* '#options' => array(
* 'one' => 'one',
* 'two' => 'two',
* 'three' => 'three',
* ),
* '#ajax' => array(
* 'callback' => 'ajax_example_simplest_callback',
* 'wrapper' => 'replace_textfield_div',
* ),
* );
*
* // This entire form element will be replaced with an updated value.
* $form['replace_textfield'] = array(
* '#type' => 'textfield',
* '#title' => t("The default value will be changed"),
* '#description' => t("Say something about why you chose") . "'" .
* (!empty($form_state['values']['changethis'])
* ? $form_state['values']['changethis'] : t("Not changed yet")) . "'",
* '#prefix' => '<div id="replace_textfield_div">',
* '#suffix' => '</div>',
* );
* return $form;
* }
*
* function ajax_example_simplest_callback($form, FormStateInterface $form_state) {
* // The form has already been submitted and updated. We can return the replaced
* // item as it is.
* return $form['replace_textfield'];
* }
* '#ajax' => array(
* 'callback' => 'Drupal\config_translation\FormElement\DateFormat::ajaxSample',
* 'event' => 'keyup',
* 'progress' => array(
* 'type' => 'throbber',
* 'message' => NULL,
* ),
* ),
* @endcode
*
* In the above example, the 'changethis' element is Ajax-enabled. The default
* #ajax['event'] is 'change', so when the 'changethis' element changes,
* an Ajax call is made. The form is submitted and reprocessed, and then the
* callback is called. In this case, the form has been automatically
* built changing $form['replace_textfield']['#description'], so the callback
* just returns that part of the form.
*
* To implement Ajax handling in a form, add '#ajax' to the form
* definition of a field. That field will trigger an Ajax event when it is
* clicked (or changed, depending on the kind of field). #ajax supports
* the following parameters (either 'path' or 'callback' is required at least):
* - #ajax['callback']: The callback to invoke to handle the server side of the
* Ajax event, which will receive a $form and $form_state as arguments, and
* returns a renderable array (most often a form or form fragment), an HTML
* string, or an array of Ajax commands. If returning a renderable array or
* a string, the value will replace the original element named in
* #ajax['wrapper'], and
* theme_status_messages()
* will be prepended to that
* element. (If the status messages are not wanted, return an array
* of Ajax commands instead.)
* #ajax['wrapper']. If an array of Ajax commands is returned, it will be
* executed by the calling code.
* - #ajax['path']: The menu path to use for the request. This is often omitted
* and the default is used. This path should map
* to a controller that returns data using
* \Drupal\Core\Ajax\AjaxResponse::ajaxRender(). Defaults to 'system/ajax',
* which invokes \Drupal\system\FormAjaxController::content(), eventually
* calling the function named in #ajax['callback']. If you use a custom path,
* you must set up the menu entry and handle the entire callback in your own
* code.
* - #ajax['wrapper']: The CSS ID of the area to be replaced by the content
* returned by the #ajax['callback'] function. The content returned from
* the callback will replace the entire element named by #ajax['wrapper'].
* The wrapper is usually created using #prefix and #suffix properties in the
* form. Note that this is the wrapper ID, not a CSS selector. So to replace
* the element referred to by the CSS selector #some-selector on the page,
* use #ajax['wrapper'] = 'some-selector', not '#some-selector'.
* - #ajax['effect']: The jQuery effect to use when placing the new HTML.
* Defaults to no effect. Valid options are 'none', 'slide', or 'fade'.
* - #ajax['speed']: The effect speed to use. Defaults to 'slow'. May be
* 'slow', 'fast' or a number in milliseconds which represents the length
* of time the effect should run.
* - #ajax['event']: The JavaScript event to respond to. This is normally
* selected automatically for the type of form widget being used, and
* is only needed if you need to override the default behavior.
* - #ajax['prevent']: A JavaScript event to prevent when 'event' is triggered.
* Defaults to 'click' for #ajax on #type 'submit', 'button', and
* 'image_button'. Multiple events may be specified separated by spaces.
* For example, when binding #ajax behaviors to form buttons, pressing the
* ENTER key within a textfield triggers the 'click' event of the form's first
* submit button. Triggering Ajax in this situation leads to problems, like
* breaking autocomplete textfields. Because of that, Ajax behaviors are bound
* to the 'mousedown' event on form buttons by default. However, binding to
* 'mousedown' rather than 'click' means that it is possible to trigger a
* click by pressing the mouse, holding the mouse button down until the Ajax
* request is complete and the button is re-enabled, and then releasing the
* mouse button. For this case, 'prevent' can be set to 'click', so an
* additional event handler is bound to prevent such a click from triggering a
* non-Ajax form submission. This also prevents a textfield's ENTER press
* triggering a button's non-Ajax form submission behavior.
* - #ajax['method']: The jQuery method to use to place the new HTML.
* 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'.
* More information is available in the
* @link forms_api_reference.html Form API Reference @endlink
*
* In addition to using Form API for doing in-form modification, Ajax may be
* enabled by adding classes to buttons and links. By adding the 'use-ajax'
* class to a link, the link will be loaded via an Ajax call. When using this
* method, the href of the link can contain '/nojs/' as part of the path. When
* the Ajax framework makes the request, it will convert this to '/ajax/'.
* The server is then able to easily tell if this request was made through an
* actual Ajax request or in a degraded state, and respond appropriately.
* As you can see from this example, the #ajax property for a form element is
* an array. Here are the details of its elements, all of which are optional:
* - callback: The callback to invoke to handle the server side of the
* Ajax event. More information on callbacks is below in @ref sub_callback.
* - path: The URL path to use for the request. If omitted, defaults to
* 'system/ajax', which invokes the default Drupal Ajax processing (this will
* call the callback supplied in the 'callback' element). If you supply a
* path, you must set up a routing entry to handle the request yourself and
* return output described in @ref sub_callback below. See the
* @link menu Routing topic @endlink for more information on routing.
* - wrapper: The HTML 'id' attribute of the area where the content returned by
* the callback should be placed. Note that callbacks have a choice of
* returning content or JavaScript commands; 'wrapper' is used for content
* returns.
* - method: The jQuery method for placing the new content (used with
* 'wrapper'). Valid options are 'replaceWith' (default), 'append', 'prepend',
* 'before', 'after', or 'html'. See
* http://api.jquery.com/category/manipulation/ for more information on these
* methods.
* - effect: The jQuery effect to use when placing the new HTML (used with
* 'wrapper'). Valid options are 'none' (default), 'slide', or 'fade'.
* - speed: The effect speed to use (used with 'effect' and 'wrapper'). Valid
* options are 'slow' (default), 'fast', or the number of milliseconds the
* effect should run.
* - event: The JavaScript event to respond to. This is selected automatically
* for the type of form element; provide a value to override the default.
* - prevent: A JavaScript event to prevent when the event is triggered. For
* example, if you use event 'mousedown' on a button, you might want to
* prevent 'click' events from also being triggered.
* - progress: An array indicating how to show Ajax processing progress. Can
* contain one or more of these elements:
* - type: Type of indicator: 'throbber' (default) or 'bar'.
* - message: Translated message to display.
* - url: For a bar progress indicator, URL path for determining progress.
* - interval: For a bar progress indicator, how often to update it.
*
* Similarly, submit buttons can be given the class 'use-ajax-submit'. The
* form will then be submitted via Ajax to the path specified in the #action.
* Like the ajax-submit class above, this path will have '/nojs/' replaced with
* '/ajax/' so that the submit handler can tell if the form was submitted
* in a degraded state or not.
*
* As a developer you basically create a \Drupal\Core\Ajax\AjaxResponse and add
* a couple of \Drupal\Core\Ajax\CommandInterface onto it, which will be
* converted to a commands array automatically. This commands array will be
* converted to a JSON object and returned to the client, which will then
* iterate over the array and process it like a macro language.
* @subsection sub_callback Setting up a callback to process Ajax
* Once you have set up your form to trigger an Ajax response (see @ref sub_form
* above), you need to write some PHP code to process the response. If you use
* 'path' in your Ajax set-up, your route controller will be triggered with only
* the information you provide in the URL. If you use 'callback', your callback
* method is a function, which will receive the $form and $form_state from the
* triggering form. You can use $form_state to get information about the
* data the user has entered into the form. For instance, in the above example
* for the date format preview,
* \Drupal\config_translation\FormElement\DateFormat\ajaxSample() does this to
* get the format string entered by the user:
* @code
* $format_value = \Drupal\Component\Utility\NestedArray::getValue(
* $form_state['values'],
* $form_state['triggering_element']['#array_parents']);
* @endcode
*
* Each command item is an associative array which will be converted to a
* command object on the JavaScript side. $command_item['command'] is the type
* of command, e.g. 'alert' or 'replace', and will correspond to a method in the
* Drupal.ajax[command] space. The command array may contain any other data that
* the command needs to process, e.g. 'method', 'selector', 'settings', etc.
* Once you have processed the input, you have your choice of returning HTML
* markup or a set of Ajax commands. If you choose to return HTML markup, you
* can return it as a string or a renderable array, and it will be placed in
* the defined 'wrapper' element (see documentation above in @ref sub_form).
* In addition, any messages returned by drupal_get_messages(), themed as in
* status-messages.html.twig, will be prepended.
*
* Commands are usually created with a couple of helper functions, so they
* look like this:
* To return commands, you need to set up an object of class
* \Drupal\Core\Ajax\AjaxResponse, and then use its addCommand() method to add
* individual commands to it. In the date format preview example, the format
* output is calculated, and then it is returned as replacement markup for a div
* like this:
* @code
* $commands = array();
* // Replace the content of '#object-1' on the page with 'some html here'.
* $commands[] = ajax_command_replace('#object-1', 'some html here');
* // Add a visual "changed" marker to the '#object-1' element.
* $commands[] = ajax_command_changed('#object-1');
* // #ajax['callback'] functions are supposed to return render arrays. If
* // returning an Ajax commands array, it must be encapsulated in a render
* // array structure.
* return array('#type' => 'ajax', '#commands' => $commands);
* $response = new AjaxResponse();
* $response->addCommand(new ReplaceCommand(
* '#edit-date-format-suffix',
* '<small id="edit-date-format-suffix">' . $format . '</small>'));
* return $response;
* @endcode
*
* When returning an Ajax command array, it is often useful to have
* status messages rendered along with other tasks in the command array.
* In that case the the Ajax commands array may be constructed like this:
* The individual commands that you can return implement interface
* \Drupal\Core\Ajax\CommandInterface. Available commands provide the ability
* to pop up alerts, manipulate text and markup in various ways, redirect
* to a new URL, and the generic \Drupal\Core\Ajax\InvokeCommand, which
* invokes an arbitrary jQuery commnd.
*
* As noted above, status messages are prepended automatically if you use the
* 'wrapper' method and return HTML markup. This is not the case if you return
* commands, but if you would like to show status messages, you can add
* @code
* $commands = array();
* $commands[] = ajax_command_replace(NULL, $output);
* $status_messages = array('#theme' => 'status_messages');
* $commands[] = ajax_command_prepend(NULL, drupal_render($status_messages));
* return array('#type' => 'ajax', '#commands' => $commands);
* array('#theme' => 'status_messages')
* @endcode
* to a render array, use drupal_render() to render it, and add a command to
* place the messages in an appropriate location.
*
* See @link ajax_commands Ajax framework commands @endlink
* @section sec_other Other methods for triggering Ajax
* Here are some additional methods you can use to trigger Ajax responses in
* Drupal:
* - Add class 'use-ajax' to a link. The link will be loaded using an Ajax
* call. When using this method, the href of the link can contain '/nojs/' as
* part of the path. When the Ajax JavaScript processes the page, it will
* convert this to '/ajax/'. The server is then able to easily tell if this
* request was made through an actual Ajax request or in a degraded state, and
* respond appropriately.
* - Add class 'use-ajax-submit' to a submit button in a form. The form will
* then be submitted via Ajax to the path specified in the #action. Like the
* ajax-submit class on links, this path will have '/nojs/' replaced with
* '/ajax/' so that the submit handler can tell if the form was submitted in a
* degraded state or not.
* - Add property '#autocomplete_route_name' to a text field in a form. The
* route controller for this route must return an array of options for
* autocomplete, as a \Symfony\Component\HttpFoundation\JsonResponse object.
* See the @link menu Routing topic @endlink for more information about
* routing.
*/
/**
......
......@@ -16,6 +16,8 @@
* defined in misc/ajax.js.
*
* @see misc/ajax.js
*
* @ingroup ajax
*/
class AddCssCommand implements CommandInterface {
......
......@@ -20,6 +20,8 @@
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/after#content
*
* @ingroup ajax
*/
class AfterCommand extends InsertCommand {
......
......@@ -13,6 +13,8 @@
/**
* JSON response object for AJAX requests.
*
* @ingroup ajax
*/
class AjaxResponse extends JsonResponse {
......
......@@ -11,6 +11,8 @@
/**
* AJAX command for a javascript alert box.
*
* @ingroup ajax
*/
class AlertCommand implements CommandInterface {
......
......@@ -20,6 +20,8 @@
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/append#content
*
* @ingroup ajax
*/
class AppendCommand extends InsertCommand {
......
......@@ -20,6 +20,8 @@
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/before#content
*
* @ingroup ajax
*/
class BeforeCommand extends InsertCommand {
......
......@@ -17,6 +17,8 @@
*
* This command is implemented by Drupal.AjaxCommands.prototype.changed()
* defined in misc/ajax.js.
*
* @ingroup ajax
*/
class ChangedCommand implements CommandInterface {
......
......@@ -9,6 +9,8 @@
/**
* Defines an AJAX command that closes the current active dialog.
*
* @ingroup ajax
*/
class CloseDialogCommand implements CommandInterface {
......
......@@ -11,6 +11,8 @@
/**
* Defines an AJAX command that closes the currently visible modal dialog.
*
* @ingroup ajax
*/
class CloseModalDialogCommand extends CloseDialogCommand {
......
......@@ -12,6 +12,8 @@
*
* All AJAX commands passed to AjaxResponse objects should implement these
* methods.
*
* @ingroup ajax
*/
interface CommandInterface {
......
......@@ -19,6 +19,8 @@
* in misc/ajax.js.
*
* @see http://docs.jquery.com/CSS/css#properties
*
* @ingroup ajax
*/
class CssCommand implements CommandInterface {
......
......@@ -17,6 +17,8 @@
*
* This command is implemented by Drupal.AjaxCommands.prototype.data() defined
* in misc/ajax.js.
*
* @ingroup ajax
*/
class DataCommand implements CommandInterface {
......
......@@ -20,6 +20,8 @@
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Attributes/html#val
*
* @ingroup ajax
*/
class HtmlCommand extends InsertCommand {
......
......@@ -18,6 +18,8 @@
*
* This command is implemented by Drupal.AjaxCommands.prototype.insert()
* defined in misc/ajax.js.
*
* @ingroup ajax
*/
class InsertCommand implements CommandInterface {
......
......@@ -19,6 +19,8 @@
*
* This command is implemented by Drupal.AjaxCommands.prototype.invoke()
* defined in misc/ajax.js.
*
* @ingroup ajax
*/
class InvokeCommand implements CommandInterface {
......
......@@ -11,6 +11,8 @@
/**
* Defines an AJAX command to open certain content in a dialog.
*
* @ingroup ajax
*/
class OpenDialogCommand implements CommandInterface {
......
......@@ -11,6 +11,8 @@
/**
* Defines an AJAX command to open certain content in a dialog in a modal dialog.
*
* @ingroup ajax
*/
class OpenModalDialogCommand extends OpenDialogCommand {
/**
......
......@@ -20,6 +20,8 @@
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/prepend#content
*
* @ingroup ajax
*/
class PrependCommand extends InsertCommand {
......
......@@ -11,6 +11,8 @@
/**
* Defines an AJAX command to set the window.location, loading that URL.
*
* @ingroup ajax
*/
class RedirectCommand implements CommandInterface {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment