| 1 |
<?php
|
| 2 |
// $Id: ajax.inc,v 1.16 2009/10/18 05:14:39 webchick Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Functions for use with Drupal's AJAX framework.
|
| 7 |
*/
|
| 8 |
|
| 9 |
/**
|
| 10 |
* @defgroup ajax AJAX framework
|
| 11 |
* @{
|
| 12 |
* Drupal's AJAX framework is used to dynamically update parts of a page's HTML
|
| 13 |
* based on data from the server. Upon a specified event, such as a button
|
| 14 |
* click, a callback function is triggered which performs server-side logic and
|
| 15 |
* may return updated markup, which is then replaced on-the-fly with no page
|
| 16 |
* refresh necessary.
|
| 17 |
*
|
| 18 |
* This framework creates a PHP macro language that allows the server to
|
| 19 |
* instruct JavaScript to perform actions on the client browser. When using
|
| 20 |
* forms, it can be used with the #ajax property.
|
| 21 |
* The #ajax property can be used to bind events to the AJAX framework. By
|
| 22 |
* default, #ajax uses 'system/ajax' as path, along with its defined page
|
| 23 |
* callback. However, you may optionally specify a different path to request or
|
| 24 |
* a different callback function to invoke, which can return updated HTML or can
|
| 25 |
* also return a richer set of AJAX framework commands.
|
| 26 |
*
|
| 27 |
* See @link ajax_commands AJAX framework commands @endlink
|
| 28 |
*
|
| 29 |
* To implement AJAX handling in a normal form, add '#ajax' to the form
|
| 30 |
* definition of a field. That field will trigger an AJAX event when it is
|
| 31 |
* clicked (or changed, depending on the kind of field). #ajax supports
|
| 32 |
* the following parameters (either 'path' or 'callback' is required at least):
|
| 33 |
* - #ajax['path']: The menu path to use for the request. This path should map
|
| 34 |
* to a menu page callback that returns data using ajax_render(). Defaults to
|
| 35 |
* 'system/ajax', which invokes ajax_form_callback(). If you use a custom
|
| 36 |
* path, you must set up the menu entry and handle the entire callback in your
|
| 37 |
* own code.
|
| 38 |
* - #ajax['callback']: The callback to invoke to handle the server side of the
|
| 39 |
* AJAX event, which will receive a $form and $form_state as arguments, and
|
| 40 |
* should return a HTML string to replace the original element named in
|
| 41 |
* #ajax['wrapper'] or a list of AJAX commands.
|
| 42 |
* - #ajax['wrapper']: The CSS ID of the area to be replaced by the HTML
|
| 43 |
* returned by the #ajax['callback'] function. The HTML string returned from
|
| 44 |
* the callback will replace the entire element named by #ajax['wrapper'].
|
| 45 |
* The wrapper is usually created using #prefix and #suffix properties in the
|
| 46 |
* form. Note that this is the wrapper ID, not a CSS selector. So to replace
|
| 47 |
* the element referred to by the CSS selector #some-selector on the page,
|
| 48 |
* use #ajax['wrapper'] = 'some-selector', not '#some-selector'.
|
| 49 |
* - #ajax['effect']: The jQuery effect to use when placing the new HTML.
|
| 50 |
* Defaults to no effect. Valid options are 'none', 'slide', or 'fade'.
|
| 51 |
* - #ajax['speed']: The effect speed to use. Defaults to 'slow'. May be
|
| 52 |
* 'slow', 'fast' or a number in milliseconds which represents the length
|
| 53 |
* of time the effect should run.
|
| 54 |
* - #ajax['event']: The JavaScript event to respond to. This is normally
|
| 55 |
* selected automatically for the type of form widget being used, and
|
| 56 |
* is only needed if you need to override the default behavior.
|
| 57 |
* - #ajax['method']: The jQuery method to use to place the new HTML.
|
| 58 |
* Defaults to 'replace'. May be: 'replace', 'append', 'prepend',
|
| 59 |
* 'before', 'after', or 'html'. See the jQuery documentation for more
|
| 60 |
* information on these methods.
|
| 61 |
* - #ajax['progress']: Choose either a throbber or progress bar that is
|
| 62 |
* displayed while awaiting a response from the callback, and add an optional
|
| 63 |
* message. Possible keys: 'type', 'message', 'url', 'interval'.
|
| 64 |
* More information is available in the
|
| 65 |
* @link http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7 Form API Reference @endlink
|
| 66 |
*
|
| 67 |
* In addition to using Form API for doing in-form modification, AJAX may be
|
| 68 |
* enabled by adding classes to buttons and links. By adding the 'use-ajax'
|
| 69 |
* class to a link, the link will be loaded via an AJAX call. When using this
|
| 70 |
* method, the href of the link can contain '/nojs/' as part of the path. When
|
| 71 |
* the AJAX framework makes the request, it will convert this to '/ajax/'.
|
| 72 |
* The server is then able to easily tell if this request was made through an
|
| 73 |
* actual AJAX request or in a degraded state, and respond appropriately.
|
| 74 |
*
|
| 75 |
* Similarly, submit buttons can be given the class 'use-ajax-submit'. The
|
| 76 |
* form will then be submitted via AJAX to the path specified in the #action.
|
| 77 |
* Like the ajax-submit class above, this path will have '/nojs/' replaced with
|
| 78 |
* '/ajax/' so that the submit handler can tell if the form was submitted
|
| 79 |
* in a degraded state or not.
|
| 80 |
*
|
| 81 |
* When responding to AJAX requests, the server should do what it needs to do
|
| 82 |
* for that request, then create a commands array. This commands array will
|
| 83 |
* be converted to a JSON object and returned to the client, which will then
|
| 84 |
* iterate over the array and process it like a macro language.
|
| 85 |
*
|
| 86 |
* Each command is an object. $object->command is the type of command and will
|
| 87 |
* be used to find the method (it will correlate directly to a method in
|
| 88 |
* the Drupal.ajax[command] space). The object may contain any other data that
|
| 89 |
* the command needs to process.
|
| 90 |
*
|
| 91 |
* Commands are usually created with a couple of helper functions, so they
|
| 92 |
* look like this:
|
| 93 |
* @code
|
| 94 |
* $commands = array();
|
| 95 |
* // Replace the content of '#object-1' on the page with 'some html here'.
|
| 96 |
* $commands[] = ajax_command_replace('#object-1', 'some html here');
|
| 97 |
* // Add a visual "changed" marker to the '#object-1' element.
|
| 98 |
* $commands[] = ajax_command_changed('#object-1');
|
| 99 |
* // Output new markup to the browser and end the request.
|
| 100 |
* // Note: Only custom AJAX paths/page callbacks need to do this manually.
|
| 101 |
* ajax_render($commands);
|
| 102 |
* @endcode
|
| 103 |
*
|
| 104 |
* When the system's default #ajax['path'] is used, the invoked callback
|
| 105 |
* function can either return a HTML string or an AJAX command structure.
|
| 106 |
*
|
| 107 |
* In case an AJAX callback returns a HTML string instead of an AJAX command
|
| 108 |
* structure, ajax_form_callback() automatically replaces the original container
|
| 109 |
* by using the ajax_command_replace() command and additionally prepends the
|
| 110 |
* returned output with any status messages.
|
| 111 |
*
|
| 112 |
* When returning an AJAX command structure, it is likely that any status
|
| 113 |
* messages shall be output with the given HTML. To achieve the same result
|
| 114 |
* using an AJAX command structure, the AJAX callback may use the following:
|
| 115 |
* @code
|
| 116 |
* $commands = array();
|
| 117 |
* $commands[] = ajax_command_replace(NULL, $output);
|
| 118 |
* $commands[] = ajax_command_prepend(NULL, theme('status_messages'));
|
| 119 |
* return $commands;
|
| 120 |
* @endcode
|
| 121 |
*
|
| 122 |
* See @link ajax_commands AJAX framework commands @endlink
|
| 123 |
*/
|
| 124 |
|
| 125 |
/**
|
| 126 |
* Render a commands array into JSON and exit.
|
| 127 |
*
|
| 128 |
* Commands are immediately handed back to the AJAX requester. This function
|
| 129 |
* will render and immediately exit.
|
| 130 |
*
|
| 131 |
* @param $commands
|
| 132 |
* A list of macro commands generated by the use of ajax_command_*()
|
| 133 |
* functions.
|
| 134 |
* @param $header
|
| 135 |
* If set to FALSE the 'text/javascript' header used by drupal_json_output()
|
| 136 |
* will not be used, which is necessary when using an IFRAME. If set to
|
| 137 |
* 'multipart' the output will be wrapped in a textarea, which can also be
|
| 138 |
* used as an alternative method when uploading files.
|
| 139 |
*/
|
| 140 |
function ajax_render($commands = array(), $header = TRUE) {
|
| 141 |
// Automatically extract any 'settings' added via drupal_add_js() and make
|
| 142 |
// them the first command.
|
| 143 |
$scripts = drupal_add_js(NULL, NULL);
|
| 144 |
if (!empty($scripts['settings'])) {
|
| 145 |
array_unshift($commands, ajax_command_settings(call_user_func_array('array_merge_recursive', $scripts['settings']['data'])));
|
| 146 |
}
|
| 147 |
|
| 148 |
// Allow modules to alter any AJAX response.
|
| 149 |
drupal_alter('ajax_render', $commands);
|
| 150 |
|
| 151 |
// Use === here so that bool TRUE doesn't match 'multipart'.
|
| 152 |
if ($header === 'multipart') {
|
| 153 |
// We do not use drupal_json_output() here because the header is not true.
|
| 154 |
// We are not really returning JSON, strictly-speaking, but rather JSON
|
| 155 |
// content wrapped in a textarea as per the "file uploads" example here:
|
| 156 |
// http://malsup.com/jquery/form/#code-samples
|
| 157 |
print '<textarea>' . drupal_json_encode($commands) . '</textarea>';
|
| 158 |
}
|
| 159 |
elseif ($header) {
|
| 160 |
drupal_json_output($commands);
|
| 161 |
}
|
| 162 |
else {
|
| 163 |
print drupal_json_encode($commands);
|
| 164 |
}
|
| 165 |
drupal_exit();
|
| 166 |
}
|
| 167 |
|
| 168 |
/**
|
| 169 |
* Send an error response back via AJAX and immediately exit.
|
| 170 |
*
|
| 171 |
* This function can be used to quickly create a command array with an error
|
| 172 |
* string and send it, short-circuiting the error handling process.
|
| 173 |
*
|
| 174 |
* @param $error
|
| 175 |
* A string to display in an alert.
|
| 176 |
*/
|
| 177 |
function ajax_render_error($error = '') {
|
| 178 |
$commands = array();
|
| 179 |
$commands[] = ajax_command_alert(empty($error) ? t('An error occurred while handling the request: The server received invalid input.') : $error);
|
| 180 |
ajax_render($commands);
|
| 181 |
}
|
| 182 |
|
| 183 |
/**
|
| 184 |
* Get a form submitted via #ajax during an AJAX callback.
|
| 185 |
*
|
| 186 |
* This will load a form from the form cache used during AJAX operations. It
|
| 187 |
* pulls the form info from $_POST.
|
| 188 |
*
|
| 189 |
* @return
|
| 190 |
* An array containing the $form and $form_state. Use the list() function
|
| 191 |
* to break these apart:
|
| 192 |
* @code
|
| 193 |
* list($form, $form_state, $form_id, $form_build_id) = ajax_get_form();
|
| 194 |
* @endcode
|
| 195 |
*/
|
| 196 |
function ajax_get_form() {
|
| 197 |
$form_state = form_state_defaults();
|
| 198 |
|
| 199 |
$form_build_id = $_POST['form_build_id'];
|
| 200 |
|
| 201 |
// Get the form from the cache.
|
| 202 |
$form = form_get_cache($form_build_id, $form_state);
|
| 203 |
if (!$form) {
|
| 204 |
// If $form cannot be loaded from the cache, the form_build_id in $_POST
|
| 205 |
// must be invalid, which means that someone performed a POST request onto
|
| 206 |
// system/ajax without actually viewing the concerned form in the browser.
|
| 207 |
// This is likely a hacking attempt as it never happens under normal
|
| 208 |
// circumstances, so we just do nothing.
|
| 209 |
watchdog('ajax', 'Invalid form POST data.', array(), WATCHDOG_WARNING);
|
| 210 |
drupal_exit();
|
| 211 |
}
|
| 212 |
|
| 213 |
// Since some of the submit handlers are run, redirects need to be disabled.
|
| 214 |
$form_state['no_redirect'] = TRUE;
|
| 215 |
|
| 216 |
// The form needs to be processed; prepare for that by setting a few internal
|
| 217 |
// variables.
|
| 218 |
$form_state['input'] = $_POST;
|
| 219 |
$form_id = $form['#form_id'];
|
| 220 |
|
| 221 |
return array($form, $form_state, $form_id, $form_build_id);
|
| 222 |
}
|
| 223 |
|
| 224 |
/**
|
| 225 |
* Menu callback; handles AJAX requests for the #ajax Form API property.
|
| 226 |
*
|
| 227 |
* This rebuilds the form from cache and invokes the defined #ajax['callback']
|
| 228 |
* to return an AJAX command structure for JavaScript. In case no 'callback' has
|
| 229 |
* been defined, nothing will happen.
|
| 230 |
*
|
| 231 |
* The Form API #ajax property can be set both for buttons and other input
|
| 232 |
* elements.
|
| 233 |
*
|
| 234 |
* ajax_process_form() defines an additional 'formPath' JavaScript setting
|
| 235 |
* that is used by Drupal.ajax.prototype.beforeSubmit() to automatically inject
|
| 236 |
* an additional field 'ajax_triggering_element' to the submitted form values,
|
| 237 |
* which contains the array #parents of the element in the form structure.
|
| 238 |
* This additional field allows ajax_form_callback() to determine which
|
| 239 |
* element triggered the action, as non-submit form elements do not
|
| 240 |
* provide this information in $form_state['clicked_button'], which can
|
| 241 |
* also be used to determine triggering element, but only submit-type
|
| 242 |
* form elements.
|
| 243 |
*
|
| 244 |
* This function is also the canonical example of how to implement
|
| 245 |
* #ajax['path']. If processing is required that cannot be accomplished with
|
| 246 |
* a callback, re-implement this function and set #ajax['path'] to the
|
| 247 |
* enhanced function.
|
| 248 |
*/
|
| 249 |
function ajax_form_callback() {
|
| 250 |
// Find the triggering element, which was set up for us on the client side.
|
| 251 |
if (!empty($_REQUEST['ajax_triggering_element'])) {
|
| 252 |
$triggering_element_path = $_REQUEST['ajax_triggering_element'];
|
| 253 |
// Remove the value for form validation.
|
| 254 |
unset($_REQUEST['ajax_triggering_element']);
|
| 255 |
}
|
| 256 |
list($form, $form_state, $form_id, $form_build_id) = ajax_get_form();
|
| 257 |
|
| 258 |
// Build, validate and if possible, submit the form.
|
| 259 |
drupal_process_form($form_id, $form, $form_state);
|
| 260 |
|
| 261 |
// This call recreates the form relying solely on the $form_state that
|
| 262 |
// drupal_process_form() set up.
|
| 263 |
$form = drupal_rebuild_form($form_id, $form_state, $form_build_id);
|
| 264 |
|
| 265 |
// $triggering_element_path in a simple form might just be 'myselect', which
|
| 266 |
// would mean we should use the element $form['myselect']. For nested form
|
| 267 |
// elements we need to recurse into the form structure to find the triggering
|
| 268 |
// element, so we can retrieve the #ajax['callback'] from it.
|
| 269 |
if (!empty($triggering_element_path)) {
|
| 270 |
if (!isset($form['#access']) || $form['#access']) {
|
| 271 |
$triggering_element = $form;
|
| 272 |
foreach (explode('/', $triggering_element_path) as $key) {
|
| 273 |
if (!empty($triggering_element[$key]) && (!isset($triggering_element[$key]['#access']) || $triggering_element[$key]['#access'])) {
|
| 274 |
$triggering_element = $triggering_element[$key];
|
| 275 |
}
|
| 276 |
else {
|
| 277 |
// We did not find the $triggering_element or do not have #access,
|
| 278 |
// so break out and do not provide it.
|
| 279 |
$triggering_element = NULL;
|
| 280 |
break;
|
| 281 |
}
|
| 282 |
}
|
| 283 |
}
|
| 284 |
}
|
| 285 |
if (empty($triggering_element)) {
|
| 286 |
$triggering_element = $form_state['clicked_button'];
|
| 287 |
}
|
| 288 |
// Now that we have the element, get a callback if there is one.
|
| 289 |
if (!empty($triggering_element)) {
|
| 290 |
$callback = $triggering_element['#ajax']['callback'];
|
| 291 |
}
|
| 292 |
if (!empty($callback) && function_exists($callback)) {
|
| 293 |
return $callback($form, $form_state);
|
| 294 |
}
|
| 295 |
}
|
| 296 |
|
| 297 |
/**
|
| 298 |
* Package and send the result of a page callback to the browser as an AJAX response.
|
| 299 |
*
|
| 300 |
* @param $page_callback_result
|
| 301 |
* The result of a page callback. Can be one of:
|
| 302 |
* - NULL: to indicate no content.
|
| 303 |
* - An integer menu status constant: to indicate an error condition.
|
| 304 |
* - A string of HTML content.
|
| 305 |
* - A renderable array of content.
|
| 306 |
*/
|
| 307 |
function ajax_deliver($page_callback_result) {
|
| 308 |
$commands = array();
|
| 309 |
if (!isset($page_callback_result)) {
|
| 310 |
// Simply delivering an empty commands array is sufficient. This results
|
| 311 |
// in the AJAX request being completed, but nothing being done to the page.
|
| 312 |
}
|
| 313 |
elseif (is_int($page_callback_result)) {
|
| 314 |
switch ($page_callback_result) {
|
| 315 |
case MENU_NOT_FOUND:
|
| 316 |
$commands[] = ajax_command_alert(t('The requested page could not be found.'));
|
| 317 |
break;
|
| 318 |
|
| 319 |
case MENU_ACCESS_DENIED:
|
| 320 |
$commands[] = ajax_command_alert(t('You are not authorized to access this page.'));
|
| 321 |
break;
|
| 322 |
|
| 323 |
case MENU_SITE_OFFLINE:
|
| 324 |
$commands[] = ajax_command_alert(filter_xss_admin(variable_get('maintenance_mode_message',
|
| 325 |
t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal'))))));
|
| 326 |
break;
|
| 327 |
}
|
| 328 |
}
|
| 329 |
elseif (is_array($page_callback_result) && isset($page_callback_result['#type']) && ($page_callback_result['#type'] == 'ajax_commands')) {
|
| 330 |
// Complex AJAX callbacks can return a result that contains a specific
|
| 331 |
// set of commands to send to the browser.
|
| 332 |
if (isset($page_callback_result['#ajax_commands'])) {
|
| 333 |
$commands = $page_callback_result['#ajax_commands'];
|
| 334 |
}
|
| 335 |
}
|
| 336 |
else {
|
| 337 |
// Like normal page callbacks, simple AJAX callbacks can return html
|
| 338 |
// content, as a string or renderable array, to replace what was previously
|
| 339 |
// there in the wrapper. In this case, in addition to the content, we want
|
| 340 |
// to add the status messages, but inside the new wrapper, so that they get
|
| 341 |
// replaced on subsequent AJAX calls for the same wrapper.
|
| 342 |
$html = is_string($page_callback_result) ? $page_callback_result : drupal_render($page_callback_result);
|
| 343 |
$commands[] = ajax_command_replace(NULL, $html);
|
| 344 |
$commands[] = ajax_command_prepend(NULL, theme('status_messages'));
|
| 345 |
}
|
| 346 |
ajax_render($commands);
|
| 347 |
}
|
| 348 |
|
| 349 |
/**
|
| 350 |
* Add AJAX information about a form element to the page to communicate with JavaScript.
|
| 351 |
*
|
| 352 |
* If #ajax['path'] is set on an element, this additional JavaScript is added
|
| 353 |
* to the page header to attach the AJAX behaviors. See ajax.js for more
|
| 354 |
* information.
|
| 355 |
*
|
| 356 |
* @param $element
|
| 357 |
* An associative array containing the properties of the element.
|
| 358 |
* Properties used:
|
| 359 |
* - #ajax['event']
|
| 360 |
* - #ajax['path']
|
| 361 |
* - #ajax['wrapper']
|
| 362 |
* - #ajax['parameters']
|
| 363 |
* - #ajax['effect']
|
| 364 |
*
|
| 365 |
* @return
|
| 366 |
* None. Additional code is added to the header of the page using
|
| 367 |
* drupal_add_js().
|
| 368 |
*/
|
| 369 |
function ajax_process_form($element) {
|
| 370 |
$js_added = &drupal_static(__FUNCTION__, array());
|
| 371 |
|
| 372 |
// Add a reasonable default event handler if none was specified.
|
| 373 |
if (isset($element['#ajax']) && !isset($element['#ajax']['event'])) {
|
| 374 |
switch ($element['#type']) {
|
| 375 |
case 'submit':
|
| 376 |
case 'button':
|
| 377 |
case 'image_button':
|
| 378 |
// Use the mousedown instead of the click event because form
|
| 379 |
// submission via pressing the enter key triggers a click event on
|
| 380 |
// submit inputs, inappropriately triggering AJAX behaviors.
|
| 381 |
$element['#ajax']['event'] = 'mousedown';
|
| 382 |
// Attach an additional event handler so that AJAX behaviors
|
| 383 |
// can be triggered still via keyboard input.
|
| 384 |
$element['#ajax']['keypress'] = TRUE;
|
| 385 |
break;
|
| 386 |
|
| 387 |
case 'password':
|
| 388 |
case 'textfield':
|
| 389 |
case 'textarea':
|
| 390 |
$element['#ajax']['event'] = 'blur';
|
| 391 |
break;
|
| 392 |
|
| 393 |
case 'radio':
|
| 394 |
case 'checkbox':
|
| 395 |
case 'select':
|
| 396 |
$element['#ajax']['event'] = 'change';
|
| 397 |
break;
|
| 398 |
|
| 399 |
default:
|
| 400 |
return $element;
|
| 401 |
}
|
| 402 |
}
|
| 403 |
|
| 404 |
// Adding the same JavaScript settings twice will cause a recursion error,
|
| 405 |
// we avoid the problem by checking if the JavaScript has already been added.
|
| 406 |
if (!isset($js_added[$element['#id']]) && (isset($element['#ajax']['callback']) || isset($element['#ajax']['path'])) && isset($element['#ajax']['event'])) {
|
| 407 |
drupal_add_library('system', 'form');
|
| 408 |
$element['#attached']['js'][] = 'misc/ajax.js';
|
| 409 |
|
| 410 |
$ajax_binding = array(
|
| 411 |
'url' => isset($element['#ajax']['callback']) ? url('system/ajax') : url($element['#ajax']['path']),
|
| 412 |
'event' => $element['#ajax']['event'],
|
| 413 |
'keypress' => empty($element['#ajax']['keypress']) ? NULL : $element['#ajax']['keypress'],
|
| 414 |
'wrapper' => empty($element['#ajax']['wrapper']) ? NULL : $element['#ajax']['wrapper'],
|
| 415 |
'selector' => empty($element['#ajax']['selector']) ? '#' . $element['#id'] : $element['#ajax']['selector'],
|
| 416 |
'effect' => empty($element['#ajax']['effect']) ? 'none' : $element['#ajax']['effect'],
|
| 417 |
'speed' => empty($element['#ajax']['effect']) ? 'none' : $element['#ajax']['effect'],
|
| 418 |
'method' => empty($element['#ajax']['method']) ? 'replace' : $element['#ajax']['method'],
|
| 419 |
'progress' => empty($element['#ajax']['progress']) ? array('type' => 'throbber') : $element['#ajax']['progress'],
|
| 420 |
'button' => isset($element['#executes_submit_callback']) ? array($element['#name'] => $element['#value']) : FALSE,
|
| 421 |
'formPath' => implode('/', $element['#array_parents']),
|
| 422 |
);
|
| 423 |
|
| 424 |
// Convert a simple #ajax['progress'] type string into an array.
|
| 425 |
if (is_string($ajax_binding['progress'])) {
|
| 426 |
$ajax_binding['progress'] = array('type' => $ajax_binding['progress']);
|
| 427 |
}
|
| 428 |
// Change progress path to a full URL.
|
| 429 |
if (isset($ajax_binding['progress']['path'])) {
|
| 430 |
$ajax_binding['progress']['url'] = url($ajax_binding['progress']['path']);
|
| 431 |
}
|
| 432 |
// Add progress.js if we're doing a bar display.
|
| 433 |
if ($ajax_binding['progress']['type'] == 'bar') {
|
| 434 |
drupal_add_js('misc/progress.js', array('cache' => FALSE));
|
| 435 |
}
|
| 436 |
|
| 437 |
drupal_add_js(array('ajax' => array($element['#id'] => $ajax_binding)), 'setting');
|
| 438 |
|
| 439 |
$js_added[$element['#id']] = TRUE;
|
| 440 |
$element['#cache'] = TRUE;
|
| 441 |
}
|
| 442 |
return $element;
|
| 443 |
}
|
| 444 |
|
| 445 |
/**
|
| 446 |
* @} End of "defgroup ajax".
|
| 447 |
*/
|
| 448 |
|
| 449 |
/**
|
| 450 |
* @defgroup ajax_commands AJAX framework commands
|
| 451 |
* @{
|
| 452 |
*/
|
| 453 |
|
| 454 |
/**
|
| 455 |
* Creates a Drupal AJAX 'alert' command.
|
| 456 |
*
|
| 457 |
* The 'alert' command instructs the client to display a JavaScript alert
|
| 458 |
* dialog box.
|
| 459 |
*
|
| 460 |
* This command is implemented by Drupal.ajax.prototype.commands.alert()
|
| 461 |
* defined in misc/ajax.js.
|
| 462 |
*
|
| 463 |
* @param $text
|
| 464 |
* The message string to dipslay to the user.
|
| 465 |
*
|
| 466 |
* @return
|
| 467 |
* An array suitable for use with the ajax_render() function.
|
| 468 |
*/
|
| 469 |
function ajax_command_alert($text) {
|
| 470 |
return array(
|
| 471 |
'command' => 'alert',
|
| 472 |
'text' => $text,
|
| 473 |
);
|
| 474 |
}
|
| 475 |
|
| 476 |
/**
|
| 477 |
* Creates a Drupal AJAX 'insert/replaceWith' command.
|
| 478 |
*
|
| 479 |
* The 'insert/replaceWith' command instructs the client to use jQuery's
|
| 480 |
* replaceWith() method to replace each element matched matched by the given
|
| 481 |
* selector with the given HTML.
|
| 482 |
*
|
| 483 |
* This command is implemented by Drupal.ajax.prototype.commands.insert()
|
| 484 |
* defined in misc/ajax.js.
|
| 485 |
*
|
| 486 |
* @param $selector
|
| 487 |
* A jQuery selector string. If the command is a response to a request from
|
| 488 |
* an #ajax form element then this value can be NULL.
|
| 489 |
* @param $html
|
| 490 |
* The data to use with the jQuery replaceWith() method.
|
| 491 |
* @param $settings
|
| 492 |
* An optional array of settings that will be used for this command only.
|
| 493 |
*
|
| 494 |
* @return
|
| 495 |
* An array suitable for use with the ajax_render() function.
|
| 496 |
*
|
| 497 |
* @see http://docs.jquery.com/Manipulation/replaceWith#content
|
| 498 |
*/
|
| 499 |
function ajax_command_replace($selector, $html, $settings = NULL) {
|
| 500 |
return array(
|
| 501 |
'command' => 'insert',
|
| 502 |
'method' => 'replaceWith',
|
| 503 |
'selector' => $selector,
|
| 504 |
'data' => $html,
|
| 505 |
'settings' => $settings,
|
| 506 |
);
|
| 507 |
}
|
| 508 |
|
| 509 |
/**
|
| 510 |
* Creates a Drupal AJAX 'insert/html' command.
|
| 511 |
*
|
| 512 |
* The 'insert/html' command instructs the client to use jQuery's html()
|
| 513 |
* method to set the HTML content of each element matched by the given
|
| 514 |
* selector while leaving the outer tags intact.
|
| 515 |
*
|
| 516 |
* This command is implemented by Drupal.ajax.prototype.commands.insert()
|
| 517 |
* defined in misc/ajax.js.
|
| 518 |
*
|
| 519 |
* @param $selector
|
| 520 |
* A jQuery selector string. If the command is a response to a request from
|
| 521 |
* an #ajax form element then this value can be NULL.
|
| 522 |
* @param $html
|
| 523 |
* The data to use with the jQuery html() method.
|
| 524 |
* @param $settings
|
| 525 |
* An optional array of settings that will be used for this command only.
|
| 526 |
*
|
| 527 |
* @return
|
| 528 |
* An array suitable for use with the ajax_render() function.
|
| 529 |
*
|
| 530 |
* @see http://docs.jquery.com/Attributes/html#val
|
| 531 |
*/
|
| 532 |
function ajax_command_html($selector, $html, $settings = NULL) {
|
| 533 |
return array(
|
| 534 |
'command' => 'insert',
|
| 535 |
'method' => 'html',
|
| 536 |
'selector' => $selector,
|
| 537 |
'data' => $html,
|
| 538 |
'settings' => $settings,
|
| 539 |
);
|
| 540 |
}
|
| 541 |
|
| 542 |
/**
|
| 543 |
* Creates a Drupal AJAX 'insert/prepend' command.
|
| 544 |
*
|
| 545 |
* The 'insert/prepend' command instructs the client to use jQuery's prepend()
|
| 546 |
* method to prepend the given HTML content to the inside each element matched
|
| 547 |
* by the given selector.
|
| 548 |
*
|
| 549 |
* This command is implemented by Drupal.ajax.prototype.commands.insert()
|
| 550 |
* defined in misc/ajax.js.
|
| 551 |
*
|
| 552 |
* @param $selector
|
| 553 |
* A jQuery selector string. If the command is a response to a request from
|
| 554 |
* an #ajax form element then this value can be NULL.
|
| 555 |
* @param $html
|
| 556 |
* The data to use with the jQuery prepend() method.
|
| 557 |
* @param $settings
|
| 558 |
* An optional array of settings that will be used for this command only.
|
| 559 |
*
|
| 560 |
* @return
|
| 561 |
* An array suitable for use with the ajax_render() function.
|
| 562 |
*
|
| 563 |
* @see http://docs.jquery.com/Manipulation/prepend#content
|
| 564 |
*/
|
| 565 |
function ajax_command_prepend($selector, $html, $settings = NULL) {
|
| 566 |
return array(
|
| 567 |
'command' => 'insert',
|
| 568 |
'method' => 'prepend',
|
| 569 |
'selector' => $selector,
|
| 570 |
'data' => $html,
|
| 571 |
'settings' => $settings,
|
| 572 |
);
|
| 573 |
}
|
| 574 |
|
| 575 |
/**
|
| 576 |
* Creates a Drupal AJAX 'insert/append' command.
|
| 577 |
*
|
| 578 |
* The 'insert/append' command instructs the client to use jQuery's append()
|
| 579 |
* method to append the given HTML content to the inside each element matched
|
| 580 |
* by the given selector.
|
| 581 |
*
|
| 582 |
* This command is implemented by Drupal.ajax.prototype.commands.insert()
|
| 583 |
* defined in misc/ajax.js.
|
| 584 |
*
|
| 585 |
* @param $selector
|
| 586 |
* A jQuery selector string. If the command is a response to a request from
|
| 587 |
* an #ajax form element then this value can be NULL.
|
| 588 |
* @param $html
|
| 589 |
* The data to use with the jQuery append() method.
|
| 590 |
* @param $settings
|
| 591 |
* An optional array of settings that will be used for this command only.
|
| 592 |
*
|
| 593 |
* @return
|
| 594 |
* An array suitable for use with the ajax_render() function.
|
| 595 |
*
|
| 596 |
* @see http://docs.jquery.com/Manipulation/append#content
|
| 597 |
*/
|
| 598 |
function ajax_command_append($selector, $html, $settings = NULL) {
|
| 599 |
return array(
|
| 600 |
'command' => 'insert',
|
| 601 |
'method' => 'append',
|
| 602 |
'selector' => $selector,
|
| 603 |
'data' => $html,
|
| 604 |
'settings' => $settings,
|
| 605 |
);
|
| 606 |
}
|
| 607 |
|
| 608 |
/**
|
| 609 |
* Creates a Drupal AJAX 'insert/after' command.
|
| 610 |
*
|
| 611 |
* The 'insert/after' command instructs the client to use jQuery's after()
|
| 612 |
* method to insert the given HTML content after each element matched by
|
| 613 |
* the given selector.
|
| 614 |
*
|
| 615 |
* This command is implemented by Drupal.ajax.prototype.commands.insert()
|
| 616 |
* defined in misc/ajax.js.
|
| 617 |
*
|
| 618 |
* @param $selector
|
| 619 |
* A jQuery selector string. If the command is a response to a request from
|
| 620 |
* an #ajax form element then this value can be NULL.
|
| 621 |
* @param $html
|
| 622 |
* The data to use with the jQuery after() method.
|
| 623 |
* @param $settings
|
| 624 |
* An optional array of settings that will be used for this command only.
|
| 625 |
*
|
| 626 |
* @return
|
| 627 |
* An array suitable for use with the ajax_render() function.
|
| 628 |
*
|
| 629 |
* @see http://docs.jquery.com/Manipulation/after#content
|
| 630 |
*/
|
| 631 |
function ajax_command_after($selector, $html, $settings = NULL) {
|
| 632 |
return array(
|
| 633 |
'command' => 'insert',
|
| 634 |
'method' => 'after',
|
| 635 |
'selector' => $selector,
|
| 636 |
'data' => $html,
|
| 637 |
'settings' => $settings,
|
| 638 |
);
|
| 639 |
}
|
| 640 |
|
| 641 |
/**
|
| 642 |
* Creates a Drupal AJAX 'insert/before' command.
|
| 643 |
*
|
| 644 |
* The 'insert/before' command instructs the client to use jQuery's before()
|
| 645 |
* method to insert the given HTML content before each of elements matched by
|
| 646 |
* the given selector.
|
| 647 |
*
|
| 648 |
* This command is implemented by Drupal.ajax.prototype.commands.insert()
|
| 649 |
* defined in misc/ajax.js.
|
| 650 |
*
|
| 651 |
* @param $selector
|
| 652 |
* A jQuery selector string. If the command is a response to a request from
|
| 653 |
* an #ajax form element then this value can be NULL.
|
| 654 |
* @param $html
|
| 655 |
* The data to use with the jQuery before() method.
|
| 656 |
* @param $settings
|
| 657 |
* An optional array of settings that will be used for this command only.
|
| 658 |
*
|
| 659 |
* @return
|
| 660 |
* An array suitable for use with the ajax_render() function.
|
| 661 |
*
|
| 662 |
* @see http://docs.jquery.com/Manipulation/before#content
|
| 663 |
*/
|
| 664 |
function ajax_command_before($selector, $html, $settings = NULL) {
|
| 665 |
return array(
|
| 666 |
'command' => 'insert',
|
| 667 |
'method' => 'before',
|
| 668 |
'selector' => $selector,
|
| 669 |
'data' => $html,
|
| 670 |
'settings' => $settings,
|
| 671 |
);
|
| 672 |
}
|
| 673 |
|
| 674 |
/**
|
| 675 |
* Creates a Drupal AJAX 'remove' command.
|
| 676 |
*
|
| 677 |
* The 'remove' command instructs the client to use jQuery's remove() method
|
| 678 |
* to remove each of elements matched by the given selector, and everything
|
| 679 |
* within them.
|
| 680 |
*
|
| 681 |
* This command is implemented by Drupal.ajax.prototype.commands.remove()
|
| 682 |
* defined in misc/ajax.js.
|
| 683 |
*
|
| 684 |
* @param $selector
|
| 685 |
* A jQuery selector string. If the command is a response to a request from
|
| 686 |
* an #ajax form element then this value can be NULL.
|
| 687 |
*
|
| 688 |
* @return
|
| 689 |
* An array suitable for use with the ajax_render() function.
|
| 690 |
*
|
| 691 |
* @see http://docs.jquery.com/Manipulation/remove#expr
|
| 692 |
*/
|
| 693 |
function ajax_command_remove($selector) {
|
| 694 |
return array(
|
| 695 |
'command' => 'remove',
|
| 696 |
'selector' => $selector,
|
| 697 |
);
|
| 698 |
}
|
| 699 |
|
| 700 |
/**
|
| 701 |
* Creates a Drupal AJAX 'changed' command.
|
| 702 |
*
|
| 703 |
* This command instructs the client to mark each of the elements matched by the
|
| 704 |
* given selector as 'ajax-changed'.
|
| 705 |
*
|
| 706 |
* This command is implemented by Drupal.ajax.prototype.commands.changed()
|
| 707 |
* defined in misc/ajax.js.
|
| 708 |
*
|
| 709 |
* @param $selector
|
| 710 |
* A jQuery selector string. If the command is a response to a request from
|
| 711 |
* an #ajax form element then this value can be NULL.
|
| 712 |
* @param $asterisk
|
| 713 |
* An optional CSS selector which must be inside $selector. If specified,
|
| 714 |
* an asterisk will be appended to the HTML inside the $asterisk selector.
|
| 715 |
*
|
| 716 |
* @return
|
| 717 |
* An array suitable for use with the ajax_render() function.
|
| 718 |
*/
|
| 719 |
function ajax_command_changed($selector, $asterisk = '') {
|
| 720 |
return array(
|
| 721 |
'command' => 'changed',
|
| 722 |
'selector' => $selector,
|
| 723 |
'star' => $asterisk,
|
| 724 |
);
|
| 725 |
}
|
| 726 |
|
| 727 |
/**
|
| 728 |
* Creates a Drupal AJAX 'css' command.
|
| 729 |
*
|
| 730 |
* The 'css' command will instruct the client to use the jQuery css() method
|
| 731 |
* to apply the CSS arguments to elements matched by the given selector.
|
| 732 |
*
|
| 733 |
* This command is implemented by Drupal.ajax.prototype.commands.insert()
|
| 734 |
* defined in misc/ajax.js.
|
| 735 |
*
|
| 736 |
* @param $selector
|
| 737 |
* A jQuery selector string. If the command is a response to a request from
|
| 738 |
* an #ajax form element then this value can be NULL.
|
| 739 |
* @param $argument
|
| 740 |
* An array of key/value pairs to set in the CSS for the selector.
|
| 741 |
*
|
| 742 |
* @return
|
| 743 |
* An array suitable for use with the ajax_render() function.
|
| 744 |
*
|
| 745 |
* @see http://docs.jquery.com/CSS/css#properties
|
| 746 |
*/
|
| 747 |
function ajax_command_css($selector, $argument) {
|
| 748 |
return array(
|
| 749 |
'command' => 'css',
|
| 750 |
'selector' => $selector,
|
| 751 |
'argument' => $argument,
|
| 752 |
);
|
| 753 |
}
|
| 754 |
|
| 755 |
/**
|
| 756 |
* Creates a Drupal AJAX 'settings' command.
|
| 757 |
*
|
| 758 |
* The 'settings' command instructs the client to extend Drupal.settings with
|
| 759 |
* the given array.
|
| 760 |
*
|
| 761 |
* This command is implemented by Drupal.ajax.prototype.commands.settings()
|
| 762 |
* defined in misc/ajax.js.
|
| 763 |
*
|
| 764 |
* @param $argument
|
| 765 |
* An array of key/value pairs to add to the settings. This will be utilized
|
| 766 |
* for all commands after this if they do not include their own settings
|
| 767 |
* array.
|
| 768 |
*
|
| 769 |
* @return
|
| 770 |
* An array suitable for use with the ajax_render() function.
|
| 771 |
*/
|
| 772 |
function ajax_command_settings($argument) {
|
| 773 |
return array(
|
| 774 |
'command' => 'settings',
|
| 775 |
'settings' => $argument,
|
| 776 |
);
|
| 777 |
}
|
| 778 |
|
| 779 |
/**
|
| 780 |
* Creates a Drupal AJAX 'data' command.
|
| 781 |
*
|
| 782 |
* The 'data' command instructs the client to attach the name=value pair of
|
| 783 |
* data to the selector via jQuery's data cache.
|
| 784 |
*
|
| 785 |
* This command is implemented by Drupal.ajax.prototype.commands.data()
|
| 786 |
* defined in misc/ajax.js.
|
| 787 |
*
|
| 788 |
* @param $selector
|
| 789 |
* A jQuery selector string. If the command is a response to a request from
|
| 790 |
* an #ajax form element then this value can be NULL.
|
| 791 |
* @param $name
|
| 792 |
* The name or key (in the key value pair) of the data attached to this
|
| 793 |
* selector.
|
| 794 |
* @param $value
|
| 795 |
* The value of the data. Not just limited to strings can be any format.
|
| 796 |
*
|
| 797 |
* @return
|
| 798 |
* An array suitable for use with the ajax_render() function.
|
| 799 |
*
|
| 800 |
* @see http://docs.jquery.com/Core/data#namevalue
|
| 801 |
*/
|
| 802 |
function ajax_command_data($selector, $name, $value) {
|
| 803 |
return array(
|
| 804 |
'command' => 'data',
|
| 805 |
'selector' => $selector,
|
| 806 |
'name' => $name,
|
| 807 |
'value' => $value,
|
| 808 |
);
|
| 809 |
}
|
| 810 |
|
| 811 |
/**
|
| 812 |
* Creates a Drupal AJAX 'restripe' command.
|
| 813 |
*
|
| 814 |
* The 'restripe' command instructs the client to restripe a table. This is
|
| 815 |
* usually used after a table has been modifed by a replace or append command.
|
| 816 |
*
|
| 817 |
* This command is implemented by Drupal.ajax.prototype.commands.restripe()
|
| 818 |
* defined in misc/ajax.js.
|
| 819 |
*
|
| 820 |
* @param $selector
|
| 821 |
* A jQuery selector string.
|
| 822 |
*
|
| 823 |
* @return
|
| 824 |
* An array suitable for use with the ajax_render() function.
|
| 825 |
*/
|
| 826 |
function ajax_command_restripe($selector) {
|
| 827 |
return array(
|
| 828 |
'command' => 'restripe',
|
| 829 |
'selector' => $selector,
|
| 830 |
);
|
| 831 |
}
|
| 832 |
|