Two AHAH issues... request expert assistance...
- I have a hobby Drupal website which maintains lists of authors and retrieves their publications from Amazon (www.authorcollector.com).
- There is a "Publications" page with two important blocks... a "Main" block which displays a table of publications... and a "Filter" block which allows users to filter what is displayed in the Main table.
- So one block, Filter, controls what is shown in another block, Main.
This all worked great before added AHAH to the Filter block... to remove the need for the user to hit an "Apply Filter" (submit) button (still does, for folks with JS disabled).
I added AHAH to all form objects... and with a lot of reading and some custom magic... it "mostly" works.
I have two issues:
1) "Filter form" text fields and "Enter"
If the user changes a text field and hits "Enter", this is taken to be as if the default button on the page was pressed... resulting in an "An HTTP error 0 occurred" alert (and the main table does not update properly). I've thoroughly read posts on forms and handling "Enter" and even incorporated code borrowed from the very nice AHAH_Helper module... all to no avail (note that I can't really use AHAH_Helper out-of-the-box as it was designed for forms which use AHAH to self-modify... I'm using a form's contents to modify the display of another block).
2) JS stops working in "Main" display
In the Main page, I use the Cluetip module to display rich popup messages to the user when they hover over a book title. Works great, until I update the page contents using AHAH... the I see the non-Cluetip enabled tooltip (which is ugly). I look at the page source... all necessary JS includes are present... just it seems JS (or perhaps jQuery) just stops working. I've tried pasting the "jq_add" and "drupal_add_js" commands within the Filter form to see if this helped... nope. Also, once the tooltips stop displaying, all I need do to fix it is hit the "Apply Filter" button (submit) and all is fixed.
Thanks in advance,
Mark
-------------------------------------------------------------------------
Undoubtedly someone will ask me to post code next... so I'll do it now...
In my main module...
// Publications section
$items['publications'] = array(
'title' => 'Publications',
'page callback' => 'publications_pager',
'access arguments' => array('any user'),
'description' => t('Paged publications table.'),
'type' => MENU_NORMAL_ITEM,
'file' => 'publications.pages.inc',
);
$items['publications/js'] = array(
'title' => 'Publications (JSON)',
'page callback' => 'publications_pager_js',
'access arguments' => array('any user'),
'description' => t('Paged publications table (JSON).'),
'type' => MENU_CALLBACK,
'file' => 'publications.pages.inc',
);
In publications.pages.inc... example of form declaration of text field...
$form['language'] = array(
'#type' => 'textfield',
'#title' => t('Language'),
'#description' => 'Leave blank for all languages.',
'#default_value' => get_user_preferences('language'),
'#ahah' => array(
'event' => 'change',
'method' => 'replace',
'path' => 'publications/js',
'wrapper' => 'publications-table',
'progress' => array('type' => 'throbber'),
),
);
In publications.pages.inc... code to handle the AHAH...
// Process Filter form AHAH request, rebuild Publications table, return JSON object
function publications_pager_js() {
// The following code was found in post "Doing AHAH Correctly in Drupal 6 and beyond"
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
$args = $form['#parameters'];
$form_id = array_shift($args);
$form_state['post'] = $form['#post'] = $_POST;
$form['#programmed'] = $form['#redirect'] = FALSE;
// The following was borrowed from AHAH_Helper to deal with the "Enter" issue
// So far this code doesn't help... "Enter" not handled, nor does AHAH even seem to work
if (true) {
$form_state['submitted'] = TRUE;
if (!isset($_POST['op'])) {
// For the default "{$form_id}_validate" and "{$form_id}_submit" handlers.
$form['#validate'] = NULL;
$form['#submit'] = NULL;
// For custom set #validate and #submit handlers
$form_state['submit_handlers'] = NULL;
$form_state['validate_handlers'] = NULL;
_ahah_helper_disable_validation($form);
}
}
// Process and rebuild form
drupal_process_form($form_id, $form, $form_state);
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
// Set user filter preferences based on the current state of this form
set_user_preferences(array('authorname' => trim(check_plain($form_state['values']['authorname'])),
'language' => trim(check_plain($form_state['values']['language'])),
'pubdate' => trim(check_plain($form_state['values']['pubdate'])),
'binding' => trim(check_plain($form_state['values']['binding'])),
'pricing' => trim(check_plain($form_state['values']['pricing'])))
);
// Cache GET and REQUEST so the 'table' and 'pager' themes called by publications_pager_inner() have proper context
$save_GET = $_GET; $save_REQUEST = $_REQUEST;
// Unset/change some values in GET/REQUEST so the 'table' and 'pager' themes called by publications_pager_inner() have proper context
$names = array('authorname', 'language', 'binding', 'pricing', 'pubdate', 'form_build_id', 'form_id', 'form_token');
foreach($names as $name) {
unset($_REQUEST[$name]);
}
$_GET['q'] = 'publications';
// Fetch the "inner" part of the publications page to display in the 'publications-table' DIV
$output = publications_pager_inner();
// Restore GET and REQUEST
$_GET = $save_GET; $_REQUEST = $save_REQUEST;
// Return the publications table to be inserted into the 'publications-table' DIV
return drupal_json(array('status' => TRUE, 'data' => $output));
}
// Borrowed from AHAH_Helper
function _ahah_helper_disable_validation(&$form) {
foreach (element_children($form) as $child) {
$form[$child]['#validated'] = TRUE;
_ahah_helper_disable_validation(&$form[$child]);
}
}
Comments
One issue "solved"... one to go...
So commenting on my own status... someday someone else might go down this road... and be interested in this story.
So we live and learn... I read something, somewhere that says "Blur" is the appropriate AHAH event type for a Textfield... not "Change". So I made that change, and now I can change the contents of a text field and hit return... no errors and it does what it is suppose do. Yay! Well, "mostly" what it is supposed to (so "solved" in quotes). The form contents reflect the new textfield, the table updates correctly... yet while this is happening there is no throbber showing activity. I do get a throbber when I change a textfield and click on something else. But I can live with no throbber as the results are what I want.
Still have the problem of Cluetip not working when the DIV containing my table is rebuilt via AHAH.
Mark
Monday morning bump
Suspect too few saw my post as it was over a weekend.
One last bump
Really disappointed that no one from the community has been able to help with this. Pretty please?
Issue: JS stops working (cluetip) after AHAH executes from a form. Next non-AHAH form call restores JS functionality.
re-attach your js behaviors
If your AHAH call is returning DHTML (e.g. cluetips, mouseover behaviors, etc.) you need to re-attach your javascript behaviors when the AHAH call returns.
Otherwise the javascript engine remains ignorant of your new DOM elements and doesn't trigger the events you want to attach.
if
Drupal.attachBehaviors();doesn't fix your tooltips, then dig into the tooltip js code and see what functions fire on document.load, and fire those functions on your AHAH return method(s).
Thanks
Aaron,
First, thanks for answering... appreciated.
But I just can't seem to get this to work. It seems to me that there is still just too much magic in this AHAH business for anyone but an expert. I've copied snippets of code like...
... to no avail, doesn't change anything.
When I put in debug statements to see what is in $javascript['setting'], I infer from what I see that this couldn't do what I wanted anyway. All I see are AHAH statements associated with the form which triggered the AHAH call, nothing to do with the table (in a different block entirely) that I regenerate as a result of the AHAH call.
I've tried adding calls to drupal_add_js('... my JS file ... ')... doesn't do anything.
I insert statement to embed the JS inline like... trying to "fire" the function in the return method.
I try to debug this stuff... I "view source" to see the results... but all I see is the original page contents. Even though the displayed page gets updated, the browser shows me contents before the AHAH call. Magic, but no help at all... as I can't even see what it is "doing."
I suppose the key gap in my knowledge is how to "reattach" behaviors. I understand conceptually that JS is ignorant of the XHTML returned by my AHAH handler, just not how to make it aware.
Mark
Even tried manually creating the inline jQuery code...
Prepending it the the XHTML ("$output" in the code snippet below) to be json-ified and returned by the AHAH handler. No luck.
Got it working! (after much studying)
Put a wrapper around the wrapper around the call to the Cluetip library... changing...
... into ...
By actually working *with* the Drupal behavior system, the cluetip behavior gets reattached to the HTML returned by the AHAH handler... automatically. I suppose the key mental block I had was that I didn't want to go digging through the cluetip code (some else's module) to figure out how to make this work... perhaps changing it... and then making upgrades difficult. Doing this with a wrapper removes such concerns.
Mark