Commit 25b9f686 authored by webchick's avatar webchick

#544418 by merlinofchaos, sun, drewish, quicksketch, et al: Integrate CTools...

#544418 by merlinofchaos, sun, drewish, quicksketch, et al: Integrate CTools AJAX framework with Drupal to extend (and replace) existing ahah framework. Everything about AJAX/AHAH is more betterer now.
parent 55d94637
......@@ -3549,6 +3549,7 @@ function _drupal_bootstrap_full() {
require_once DRUPAL_ROOT . '/includes/form.inc';
require_once DRUPAL_ROOT . '/includes/mail.inc';
require_once DRUPAL_ROOT . '/includes/actions.inc';
require_once DRUPAL_ROOT . '/includes/ajax.inc';
// Set the Drupal custom error handler.
set_error_handler('_drupal_error_handler');
set_exception_handler('_drupal_exception_handler');
......
......@@ -1800,48 +1800,6 @@ function weight_value(&$form) {
}
}
/**
* Menu callback for AHAH callbacks through the #ahah['callback'] FAPI property.
*/
function form_ahah_callback() {
$form_state = form_state_defaults();
$form_build_id = $_POST['form_build_id'];
// Get the form from the cache.
$form = form_get_cache($form_build_id, $form_state);
if (!$form) {
// If $form cannot be loaded from the cache, the form_build_id in $_POST must
// be invalid, which means that someone performed a POST request onto
// system/ahah without actually viewing the concerned form in the browser.
// This is likely a hacking attempt as it never happens under normal
// circumstances, so we just do nothing.
exit;
}
// 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_state['input'] = $_POST;
$form_state['args'] = $form['#args'];
$form_id = $form['#form_id'];
// 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, $form_build_id);
// Get the callback function from the clicked button.
$callback = $form_state['clicked_button']['#ahah']['callback'];
if (drupal_function_exists($callback)) {
$callback($form, $form_state);
}
}
/**
* Roll out a single radios element to a list of radios,
* using the options array as index.
......@@ -1861,7 +1819,7 @@ function form_process_radios($element) {
'#attributes' => $element['#attributes'],
'#parents' => $element['#parents'],
'#id' => form_clean_id('edit-' . implode('-', $parents_for_id)),
'#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL,
'#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
);
}
}
......@@ -1970,91 +1928,6 @@ function theme_text_format_wrapper($element) {
return $output;
}
/**
* Add AHAH information about a form element to the page to communicate with
* javascript. If #ahah[path] is set on an element, this additional javascript is
* added to the page header to attach the AHAH behaviors. See ahah.js for more
* information.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: ahah_event, ahah_path, ahah_wrapper, ahah_parameters,
* ahah_effect.
* @return
* None. Additional code is added to the header of the page using
* drupal_add_js.
*/
function form_process_ahah($element) {
$js_added = &drupal_static(__FUNCTION__, array());
// Add a reasonable default event handler if none specified.
if (isset($element['#ahah']) && !isset($element['#ahah']['event'])) {
switch ($element['#type']) {
case 'submit':
case 'button':
case 'image_button':
// Use the mousedown instead of the click event because form
// submission via pressing the enter key triggers a click event on
// submit inputs, inappropriately triggering AHAH behaviors.
$element['#ahah']['event'] = 'mousedown';
// Attach an additional event handler so that AHAH behaviors
// can be triggered still via keyboard input.
$element['#ahah']['keypress'] = TRUE;
break;
case 'password':
case 'textfield':
case 'textarea':
$element['#ahah']['event'] = 'blur';
break;
case 'radio':
case 'checkbox':
case 'select':
$element['#ahah']['event'] = 'change';
break;
default:
return $element;
}
}
// 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']['callback']) || isset($element['#ahah']['path'])) && isset($element['#ahah']['event']) && !isset($js_added[$element['#id']])) {
drupal_add_library('system', 'form');
drupal_add_js('misc/ahah.js');
$ahah_binding = array(
'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'],
'selector' => empty($element['#ahah']['selector']) ? '#' . $element['#id'] : $element['#ahah']['selector'],
'effect' => empty($element['#ahah']['effect']) ? 'none' : $element['#ahah']['effect'],
'method' => empty($element['#ahah']['method']) ? 'replace' : $element['#ahah']['method'],
'progress' => empty($element['#ahah']['progress']) ? array('type' => 'throbber') : $element['#ahah']['progress'],
'button' => isset($element['#executes_submit_callback']) ? array($element['#name'] => $element['#value']) : FALSE,
);
// Convert a simple #ahah[progress] type string into an array.
if (is_string($ahah_binding['progress'])) {
$ahah_binding['progress'] = array('type' => $ahah_binding['progress']);
}
// Change progress path to a full url.
if (isset($ahah_binding['progress']['path'])) {
$ahah_binding['progress']['url'] = url($ahah_binding['progress']['path']);
}
// Add progress.js if we're doing a bar display.
if ($ahah_binding['progress']['type'] == 'bar') {
drupal_add_js('misc/progress.js', array('cache' => FALSE));
}
drupal_add_js(array('ahah' => array($element['#id'] => $ahah_binding)), 'setting');
$js_added[$element['#id']] = TRUE;
$element['#cache'] = TRUE;
}
return $element;
}
/**
* Format a checkbox.
*
......@@ -2132,7 +2005,7 @@ function form_process_checkboxes($element) {
'#return_value' => $key,
'#default_value' => isset($value[$key]),
'#attributes' => $element['#attributes'],
'#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL,
'#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
);
}
}
......@@ -2245,7 +2118,7 @@ function form_process_tableselect($element) {
'#return_value' => $key,
'#default_value' => isset($value[$key]),
'#attributes' => $element['#attributes'],
'#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL,
'#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
);
}
else {
......@@ -2260,7 +2133,7 @@ function form_process_tableselect($element) {
'#attributes' => $element['#attributes'],
'#parents' => $element['#parents'],
'#id' => form_clean_id('edit-' . implode('-', $parents_for_id)),
'#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL,
'#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
);
}
}
......
// $Id$
(function ($) {
/**
* Provides AJAX-like page updating via AHAH (Asynchronous HTML and HTTP).
*
* AHAH is a method of making a request via Javascript while viewing an HTML
* page. The request returns a small chunk of HTML, which is then directly
* injected into the page.
*
* Drupal uses this file to enhance form elements with #ahah[path] and
* #ahah[wrapper] properties. If set, this file will automatically be included
* to provide AHAH capabilities.
*/
Drupal.ahah = Drupal.ahah || {};
/**
* Attaches the ahah behavior to each ahah form element.
*/
Drupal.behaviors.ahah = {
attach: function (context, settings) {
for (var base in settings.ahah) {
if (!$('#' + base + '.ahah-processed').size()) {
var element_settings = settings.ahah[base];
$(element_settings.selector).each(function () {
element_settings.element = this;
Drupal.ahah[base] = new Drupal.ahah(base, element_settings);
});
$('#' + base).addClass('ahah-processed');
}
}
}
};
/**
* AHAH object.
*
* All AHAH objects on a page are accessible through the global Drupal.ahah object
* and are keyed by the submit button's ID. You can access them from your module's
* JavaScript file to override properties or functions.
* For example, if your AHAH enabled button has the ID 'edit-submit', you can
* redefine the function that is called to insert the new content like this
* (inside a Drupal.behaviors attach block):
* @code
* Drupal.behaviors.myCustomAhahStuff = {
* attach: function(context, settings) {
* Drupal.ahah['edit-submit'].insertNewContent = function(response, status) {
* new_content = $(response.data);
* $('#my-wrapper').append(new_content);
* alert('New content was appended to #my-wrapper');
* }
* }
* };
* @endcode
*/
Drupal.ahah = function (base, element_settings) {
// Set the properties for this object.
this.element = element_settings.element;
this.selector = element_settings.selector;
this.event = element_settings.event;
this.keypress = element_settings.keypress;
this.url = element_settings.url;
this.wrapper = '#' + element_settings.wrapper;
this.effect = element_settings.effect;
this.method = element_settings.method;
this.progress = element_settings.progress;
this.button = element_settings.button || { };
if (this.effect == 'none') {
this.showEffect = 'show';
this.hideEffect = 'hide';
this.showSpeed = '';
}
else if (this.effect == 'fade') {
this.showEffect = 'fadeIn';
this.hideEffect = 'fadeOut';
this.showSpeed = 'slow';
}
else {
this.showEffect = this.effect + 'Toggle';
this.hideEffect = this.effect + 'Toggle';
this.showSpeed = 'slow';
}
// Record the form action and target, needed for iFrame file uploads.
var form = $(this.element).parents('form');
this.form_action = form.attr('action');
this.form_target = form.attr('target');
this.form_encattr = form.attr('encattr');
// Set the options for the ajaxSubmit function.
// The 'this' variable will not persist inside of the options object.
var ahah = this;
var options = {
url: ahah.url,
data: ahah.button,
beforeSubmit: function (form_values, element_settings, options) {
return ahah.beforeSubmit(form_values, element_settings, options);
},
success: function (response, status) {
// Sanity check for browser support (object expected).
// When using iFrame uploads, responses must be returned as a string.
if (typeof response == 'string') {
response = Drupal.parseJson(response);
}
return ahah.success(response, status);
},
complete: function (response, status) {
if (status == 'error' || status == 'parsererror') {
return ahah.error(response, ahah.url);
}
},
dataType: 'json',
type: 'POST'
};
// Bind the ajaxSubmit function to the element event.
$(element_settings.element).bind(element_settings.event, function () {
$(element_settings.element).parents('form').ajaxSubmit(options);
return false;
});
// If necessary, enable keyboard submission so that AHAH behaviors
// can be triggered through keyboard input as well as e.g. a mousedown
// action.
if (element_settings.keypress) {
$(element_settings.element).keypress(function (event) {
// Detect enter key.
if (event.keyCode == 13) {
$(element_settings.element).trigger(element_settings.event);
return false;
}
});
}
};
/**
* Handler for the form redirection submission.
*/
Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) {
// Disable the element that received the change.
$(this.element).addClass('progress-disabled').attr('disabled', true);
// Insert progressbar or throbber.
if (this.progress.type == 'bar') {
var progressBar = new Drupal.progressBar('ahah-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
if (this.progress.message) {
progressBar.setProgress(-1, this.progress.message);
}
if (this.progress.url) {
progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
}
this.progress.element = $(progressBar.element).addClass('ahah-progress ahah-progress-bar');
this.progress.object = progressBar;
$(this.element).after(this.progress.element);
}
else if (this.progress.type == 'throbber') {
this.progress.element = $('<div class="ahah-progress ahah-progress-throbber"><div class="throbber">&nbsp;</div></div>');
if (this.progress.message) {
$('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
}
$(this.element).after(this.progress.element);
}
};
/**
* Handler for the form redirection completion.
*/
Drupal.ahah.prototype.success = function (response, status) {
var form = $(this.element).parents('form');
// Restore the previous action and target to the form.
form.attr('action', this.form_action);
this.form_target ? form.attr('target', this.form_target) : form.removeAttr('target');
this.form_encattr ? form.attr('target', this.form_encattr) : form.removeAttr('encattr');
// Remove the progress element.
if (this.progress.element) {
$(this.progress.element).remove();
}
if (this.progress.object) {
this.progress.object.stopMonitoring();
}
$(this.element).removeClass('progress-disabled').attr('disabled', false);
Drupal.freezeHeight();
// Call the insertNewContent handler to insert the new content into the page.
this.insertNewContent(response, status);
Drupal.unfreezeHeight();
};
/**
* Handler to insert the new content into the page.
*/
Drupal.ahah.prototype.insertNewContent = function (response, status) {
var wrapper = $(this.wrapper);
// Manually insert HTML into the jQuery object, using $() directly crashes
// Safari with long string lengths. http://dev.jquery.com/ticket/1152
var new_content = $('<div></div>').html(response.data);
// Add the new content to the page.
if (this.method == 'replace') {
wrapper.empty().append(new_content);
}
else {
wrapper[this.method](new_content);
}
// Immediately hide the new content if we're using any effects.
if (this.showEffect != 'show') {
new_content.hide();
}
// Determine what effect use and what content will receive the effect, then
// show the new content.
if ($('.ahah-new-content', new_content).size() > 0) {
$('.ahah-new-content', new_content).hide();
new_content.show();
$('.ahah-new-content', new_content)[this.showEffect](this.showSpeed);
}
else if (this.showEffect != 'show') {
new_content[this.showEffect](this.showSpeed);
}
// Attach all javascript behaviors to the new content, if it was successfully
// added to the page, this if statement allows #ahah[wrapper] to be optional.
if (new_content.parents('html').length > 0) {
// Apply any settings from the returned JSON if available.
var settings = response.settings || Drupal.settings;
Drupal.attachBehaviors(new_content, settings);
}
};
/**
* Handler for the form redirection error.
*/
Drupal.ahah.prototype.error = function (response, uri) {
alert(Drupal.ahahError(response, uri));
// Resore the previous action and target to the form.
$(this.element).parent('form').attr({ action: this.form_action, target: this.form_target });
// Remove the progress element.
if (this.progress.element) {
$(this.progress.element).remove();
}
if (this.progress.object) {
this.progress.object.stopMonitoring();
}
// Undo hide.
$(this.wrapper).show();
// Re-enable the element.
$(this.element).removeClass('progress-disabled').attr('disabled', false);
};
})(jQuery);
This diff is collapsed.
......@@ -289,7 +289,7 @@ Drupal.ACDB.prototype.search = function (searchString) {
}
},
error: function (xmlhttp) {
alert(Drupal.ahahError(xmlhttp, db.uri));
alert(Drupal.ajaxError(xmlhttp, db.uri));
}
});
}, this.delay);
......
......@@ -294,9 +294,9 @@ Drupal.getSelection = function (element) {
};
/**
* Build an error message from ahah response.
* Build an error message from an AJAX response.
*/
Drupal.ahahError = function (xmlhttp, uri) {
Drupal.ajaxError = function (xmlhttp, uri) {
if (xmlhttp.status == 200 || (xmlhttp.status == 500 && xmlhttp.statusText == 'Service unavailable (with message)')) {
if ($.trim(xmlhttp.responseText)) {
var message = Drupal.t("An error occurred. \nPath: @uri\nMessage: !text", { '@uri': uri, '!text': xmlhttp.responseText });
......
......@@ -84,7 +84,7 @@ Drupal.progressBar.prototype.sendPing = function () {
pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay);
},
error: function (xmlhttp) {
pb.displayError(Drupal.ahahError(xmlhttp, pb.uri));
pb.displayError(Drupal.ajaxError(xmlhttp, pb.uri));
}
});
}
......
......@@ -47,7 +47,7 @@ html.js #edit-book-pick-book {
#book-admin-edit select.progress-disabled {
margin-right: 0;
}
#book-admin-edit tr.ahah-new-content {
#book-admin-edit tr.ajax-new-content {
background-color: #ffd;
}
#book-admin-edit .form-item {
......
......@@ -490,10 +490,11 @@ function _book_add_form_elements(&$form, $node) {
'#description' => t('Your page will be a part of the selected book.'),
'#weight' => -5,
'#attributes' => array('class' => 'book-title-select'),
'#ahah' => array(
'#ajax' => array(
'path' => 'book/js/form',
'wrapper' => 'edit-book-plid-wrapper',
'effect' => 'slide',
'effect' => 'fade',
'speed' => 'fast',
),
);
}
......
......@@ -234,28 +234,26 @@ function book_remove_form_submit($form, &$form_state) {
* Prints the replacement HTML in JSON format.
*/
function book_form_update() {
$cached_form_state = array();
// Load the form based upon the $_POST data sent via the ajax call.
list($form, $form_state) = ajax_get_form();
$commands = array();
$bid = $_POST['book']['bid'];
if ($form = form_get_cache($_POST['form_build_id'], $cached_form_state)) {
// Validate the bid.
if (isset($form['book']['bid']['#options'][$bid])) {
$book_link = $form['#node']->book;
$book_link['bid'] = $bid;
// Get the new options and update the cache.
$form['book']['plid'] = _book_parent_select($book_link);
form_set_cache($_POST['form_build_id'], $form, $cached_form_state);
// Build and render the new select element, then return it in JSON format.
$form_state = array();
$form = form_builder($form['form_id']['#value'] , $form, $form_state);
$output = drupal_render($form['book']['plid']);
drupal_json(array('status' => TRUE, 'data' => $output));
}
else {
drupal_json(array('status' => FALSE, 'data' => ''));
}
}
else {
drupal_json(array('status' => FALSE, 'data' => ''));
// Validate the bid.
if (isset($form['book']['bid']['#options'][$bid])) {
$book_link = $form['#node']->book;
$book_link['bid'] = $bid;
// Get the new options and update the cache.
$form['book']['plid'] = _book_parent_select($book_link);
form_set_cache($form['values']['form_build_id'], $form, $form_state);
// Build and render the new select element, then return it in JSON format.
$form_state = array();
$form = form_builder($form['form_id']['#value'], $form, $form_state);
$commands[] = ajax_command_replace(NULL, drupal_render($form['book']['plid']));
}
exit();
ajax_render($commands);
}
......@@ -190,7 +190,7 @@ function field_multiple_value_form($field, $instance, $items, &$form, &$form_sta
'#value' => t('Add another item'),
// Submit callback for disabled JavaScript.
'#submit' => array('field_add_more_submit'),
'#ahah' => array(
'#ajax' => array(
'path' => 'field/js_add_more/' . $bundle_name_url_css . '/' . $field_name_url_css,
'wrapper' => $field_name_url_css . '-wrapper',
'method' => 'replace',
......@@ -362,13 +362,13 @@ function field_add_more_js($bundle_name, $field_name) {
}
if ($invalid) {
drupal_json(array('data' => ''));
exit;
ajax_render(array());
}
// We don't simply return a new empty widget row to append to existing ones,
// because:
// - ahah.js won't simply let us add a new row to a table
// @todo ajax.js lets you. :)
// - attaching the 'draggable' behavior won't be easy
// So we resort to rebuilding the whole table of widgets including the
// existing ones, which makes us jump through a few hoops.
......@@ -428,21 +428,15 @@ function field_add_more_js($bundle_name, $field_name) {
foreach ($form_path as $key) {
$field_form = $field_form[$key];
}
// Add a div around the new field to receive the ahah effect.
$field_form[$delta]['#prefix'] = '<div class="ahah-new-content">' . (isset($field_form[$delta]['#prefix']) ? $field_form[$delta]['#prefix'] : '');
// Add a DIV around the new field to receive the AJAX effect.
$field_form[$delta]['#prefix'] = '<div class="ajax-new-content">' . (isset($field_form[$delta]['#prefix']) ? $field_form[$delta]['#prefix'] : '');
$field_form[$delta]['#suffix'] = (isset($field_form[$delta]['#suffix']) ? $field_form[$delta]['#suffix'] : '') . '</div>';
// Prevent duplicate wrapper.
unset($field_form['#prefix'], $field_form['#suffix']);
// If a newly inserted widget contains AHAH behaviors, they normally won't
// work because AHAH doesn't know about those - it just attaches to the exact
// form elements that were initially specified in the Drupal.settings object.
// The new ones didn't exist then, so we need to update Drupal.settings
// by ourselves in order to let AHAH know about those new form elements.
$javascript = drupal_add_js(NULL, NULL);
$output_js = isset($javascript['setting']) ? '<script type="text/javascript">jQuery.extend(Drupal.settings, ' . drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) . ');</script>' : '';
$output = theme('status_messages') . drupal_render($field_form) . $output_js;
drupal_json(array('status' => TRUE, 'data' => $output));
exit;
$output = theme('status_messages') . drupal_render($field_form);
$commands = array();
$commands[] = ajax_command_replace(NULL, $output);
ajax_render($commands);
}
......@@ -1336,12 +1336,19 @@ class FieldFormTestCase extends DrupalWebTestCase {
unset($this->additionalCurlOptions[CURLOPT_URL]);
// The response is drupal_json, so we need to undo some escaping.
$response = json_decode(str_replace(array('\x3c', '\x3e', '\x26'), array("<", ">", "&"), $this->drupalGetContent()));
$this->assertTrue(is_object($response), t('The response is an object'));
$this->assertIdentical($response->status, TRUE, t('Response status is true'));
$commands = json_decode(str_replace(array('\x3c', '\x3e', '\x26'), array("<", ">", "&"), $this->drupalGetContent()));
// The JSON response will be two AJAX commands. The first is a settings
// command and the second is the replace command.
$settings = reset($commands);
$replace = next($commands);
$this->assertTrue(is_object($settings), t('The response settings command is an object'));
$this->assertTrue(is_object($replace), t('The response replace command is an object'));
// This response data is valid HTML so we will can reuse everything we have
// for HTML pages.
$this->content = $response->data;
$this->content = $replace->data;
// Needs to be emptied out so the new content will be parsed.
$this->elements = '';
......
......@@ -263,14 +263,14 @@ function poll_form($node, $form_state) {
}
// We name our button 'poll_more' to avoid conflicts with other modules using
// AHAH-enabled buttons with the id 'more'.
// AJAX-enabled buttons with the id 'more'.
$form['choice_wrapper']['poll_more'] = array(
'#type' => 'submit',
'#value' => t('More choices'),
'#description' => t("If the amount of boxes above isn't enough, click here to add more choices."),
'#weight' => 1,
'#submit' => array('poll_more_choices_submit'), // If no javascript action.
'#ahah' => array(
'#ajax' => array(
'callback' => 'poll_choice_js',
'wrapper' => 'poll-choices',
'method' => 'replace',
......@@ -320,7 +320,7 @@ function poll_more_choices_submit($form, &$form_state) {
// Make the changes we want to the form state.
if ($form_state['values']['poll_more']) {
$n = $_GET['q'] == 'system/ahah' ? 1 : 5;
$n = $_GET['q'] == 'system/ajax' ? 1 : 5;
$form_state['choice_count'] = count($form_state['values']['choice']) + $n;
}
}
......@@ -373,9 +373,7 @@ function poll_choice_js($form, $form_state) {
// 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));
return theme('status_messages') . drupal_render($choice_form);
}
/**
......
......@@ -340,17 +340,24 @@ class PollJSAddChoice extends DrupalWebTestCase {
// @TODO: the framework should make it possible to submit a form to a
// different URL than its action or the current. For now, we can just force
// it.
$this->additionalCurlOptions[CURLOPT_URL] = url('system/ahah', array('absolute' => TRUE));
$this->additionalCurlOptions[CURLOPT_URL] = url('system/ajax', array('absolute' => TRUE));
$this->drupalPost(NULL, $edit, t('More choices'));
unset($this->additionalCurlOptions[CURLOPT_URL]);
// The response is drupal_json, so we need to undo some escaping.
$response = json_decode(str_replace(array('\x3c', '\x3e', '\x26'), array("<", ">", "&"), $this->drupalGetContent()));
$this->assertTrue(is_object($response), t('The response is an object'));
$this->assertIdentical($response->status, TRUE, t('Response status is true'));
// This response data is valid HTML so we will can reuse everything we have
$commands = json_decode(str_replace(array('\x3c', '\x3e', '\x26'), array("<", ">", "&"), $this->drupalGetContent()));
// The JSON response will be two AJAX commands. The first is a settings
// command and the second is the replace command.
$settings = reset($commands);
$replace = next($commands);
$this->assertTrue(is_object($settings), t('The response settings command is an object'));
$this->assertTrue(is_object($replace), t('The response replace command is an object'));
// This replace data is valid HTML so we will can reuse everything we have
// for HTML pages.
$this->content = $response->data;
$this->content = $replace->data;
// Needs to be emptied out so the new content will be parsed.
$this->elements = '';
......
......@@ -294,7 +294,7 @@ function form_test_mock_form_submit($form, &$form_state) {
* It uses two steps for editing a virtual "thing". Any changes to it are saved
* in the form storage and have to be present during any step. By setting the
* request parameter "cache" the form can be tested with caching enabled, as
* it would be the case, if the form would contain some #ahah callbacks.
* it would be the case, if the form would contain some #ajax callbacks.
*
* @see form_storage_test_form_submit().
*/
......
......@@ -81,10 +81,10 @@ div.teaser-button-wrapper {
.progress-disabled {
float: right;
}
.ahah-progress {
.ajax-progress {
float: right;
}
.ahah-progress .throbber {
.ajax-progress .throbber {
float: right;