AHAH, is a method for updating webpages dynamically using Javascript, similar to Ajax, but with the difference that the response from the request is used directly without parsing on the clientside. This means that server responses need to be text or already include valid XHTML/HTML structure.
Basically when a user performs an action (like clicking a link or form button) AHAH can respond to this action by calling a URL and returning the URLs respond(HTML or text) without needing to refresh the whole page.
How it works
The AHAH framework is fully integrated into Drupal 6 so all you need to do is hook into it using Drupals form API. Here's an example of how to make the form API to use AHAH.<?php
$form['my_form_submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
'#weight' => 1,
'#submit' => array('my_form_submit'),//none JS version
'#ahah' => array(
'event' => 'click',
'path' => 'mymodule/js',
'wrapper' => 'myform-wrapper',
'method' => 'replace',
'effect' => 'fade',
'progress' => array(
'type' => 'bar',
'message' => t('Loading...')
)
),?>#ahah['event']
This is the type of event that must be perform on the $form item (in this example the Submit button) in order for the AHAH behaviour to be triggered.
Possible values: 'click', 'blur', 'change' (Optional will default to click)
Examples: user clicking a button (click) or user selecting a value in a drop down menu (change)
Possible values: 'click', 'blur', 'change' (Optional will default to click)
Examples: user clicking a button (click) or user selecting a value in a drop down menu (change)
#ahah['path']
This is the menu item or URL that is called when the "event" has been triggered. Without this AHAH will not be triggered.
In the above example you would need to have a coresponding menu item defined in your hook_menu like so:
It's important the you use the drupal_json function so that Javascript can understand the returned values/HTML.
Alternatively you could use the AHAH helper module which can handle all the menu definitions for you.
In the above example you would need to have a coresponding menu item defined in your hook_menu like so:
<?phpfunction mymodule_menu() {
$items['mymodule/js'] = array(
'page callback' => 'mymodule_js',
'access arguments' => array('access mymodule js'),
'type' => MENU_CALLBACK,
);
...
return $items;
}/**
* callback function for mymodule/js
* The return HTML will be outputted by AHAH
*/function mymodule_js() {
return drupal_json(array('status' => TRUE, 'data' => "Hello Drupal World"));;
}?>Alternatively you could use the AHAH helper module which can handle all the menu definitions for you.
#ahah['wrapper']
This is the ID of the HTML element on the current page that should be updated with the returned HTML from our #ahah['path'] defined menu path.
In our example
In our example
'wrapper' => 'mymodule-wrapper' corresponds to <div id="mymodule-wrapper">.....</div> and this div would display the "Hello Drupal World" text returned by our mymodule_js() menu function when AHAH has been triggered. #ahah['method']
This is how you want the HTML returned from our #ahah['path'] menu function to be attached to our #ahah['wrapper'] defined wrapper.
By default it with replace the HTML currently in the wrapper with the new HTML, but you can also have the follow:
'after' = Insert returned HTML after the wrapper element
'append' = Append returned HTML to the inside of our wrapper element.
'before' = Insert returned HTML before our wrapper element.
'prepend' = Prepend returned HTML to the inside of our wrapper element.
By default it with replace the HTML currently in the wrapper with the new HTML, but you can also have the follow:
'after' = Insert returned HTML after the wrapper element
'append' = Append returned HTML to the inside of our wrapper element.
'before' = Insert returned HTML before our wrapper element.
'prepend' = Prepend returned HTML to the inside of our wrapper element.
#ahah['effect']
This is the jQuery effect you want to apply to the wrapper element when it receives the new HTML from our menu function.
Possible values: 'none' (default), 'fade', 'slide'.
Possible values: 'none' (default), 'fade', 'slide'.
#ahah['progress']
This is the type of animation you want to display while the user is waiting for the AHAH menu function to response. It can either be a progress bar or a throbber icon and you can also add an optional message too.


The #ahah['progress'] value should be an array of settings (see example above). Here are the full parameters:
#ahah['progress']['type'] = Type of animation to display, bar or throbber
#ahah['progress']['message'] = An optional message that should be displayed with the progress bar or throbber. You should wrap the text in the t().
#ahah['progress']['url'] = An optional URL to a menu item that determines how full the progress bar is.
The poll module uses AHAH on the poll creation page to allow users to add more choices to a poll question.
In the poll_form function the following code declares that AHAH should interact with the "poll_more" form item:
This states that the poll/js menu should be called when AHAH is triggered so the module must define a menu item for this like so:
As you can see the menu item calls a function called poll_choice_js, so now let's see what that does:
This is quite a complex callback function which is beyond the scope of this tutorial but this function basically creates a new form item for an extra choice, renders the form item and then returns it to AHAH via the drupal_json function.

To see this in action simply enable the poll module and go to yoursite.com/node/add/poll.

The #ahah['progress'] value should be an array of settings (see example above). Here are the full parameters:
#ahah['progress']['type'] = Type of animation to display, bar or throbber
#ahah['progress']['message'] = An optional message that should be displayed with the progress bar or throbber. You should wrap the text in the t().
#ahah['progress']['url'] = An optional URL to a menu item that determines how full the progress bar is.
An example
Right, lets quickly go over a real life example of where AHAH is already used in Drupal. For this we're going to look at the poll module that is shipped as part of Drupal 6 core.The poll module uses AHAH on the poll creation page to allow users to add more choices to a poll question.
In the poll_form function the following code declares that AHAH should interact with the "poll_more" form item:
<?php
//AHAH declaration in poll_form function$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(
'path' => 'poll/js',
'wrapper' => 'poll-choices',
'method' => 'replace',
'effect' => 'fade',
),
);?><?phpfunction poll_menu() {
.....
$items['poll/js'] = array(
'title' => 'Javascript Choice Form',
'page callback' => 'poll_choice_js',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
......
}?><?phpfunction poll_choice_js() {
$delta = count($_POST['choice']);
// Build our new form element.
$form_element = _poll_choice_form($delta);
drupal_alter('form', $form_element, array(), 'poll_choice_js');
// Build the new form.
$form_state = array('submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
// Add the new element to the stored form. Without adding the element to the
// form, Drupal is not aware of this new elements existence and will not
// process it. We retreive the cached form, add the element, and resave.
if (!$form = form_get_cache($form_build_id, $form_state)) {
exit();
}
$form['choice_wrapper']['choice'][$delta] = $form_element;
form_set_cache($form_build_id, $form, $form_state);
$form += array(
'#post' => $_POST,
'#programmed' => FALSE,
);
// Rebuild the form.
$form = form_builder('poll_node_form', $form, $form_state);
// Render the new output.
$choice_form = $form['choice_wrapper']['choice'];
unset($choice_form['#prefix'], $choice_form['#suffix']); // Prevent duplicate wrappers.
$choice_form[$delta]['#attributes']['class'] = empty($choice_form[$delta]['#attributes']['class']) ? 'ahah-new-content' : $choice_form[$delta]['#attributes']['class'] .' ahah-new-content';
$choice_form[$delta]['chvotes']['#value'] = 0;
$output = theme('status_messages') . drupal_render($choice_form);
drupal_json(array('status' => TRUE, 'data' => $output));
}?>
To see this in action simply enable the poll module and go to yoursite.com/node/add/poll.
No comments:
Post a Comment