Drupal 6: Improving AJAX usability by fading the screen and preventing the user from clicking on anything with jQuery
In this article I’ll share some code that I use to gray out the screen during AJAX calls to prevent users from clicking on anything, and displays a visual cue to the user that their click request is still being processed.
In the following code, I created a hook_menu() implementation and 2 page callbacks; one to show a clickable link and the other to process the AJAX request.
<?php
/**
* Implements hook_menu()
*/
function helper_menu() {
$items = array();
// define the page callback to show the clickable link
$items['shadow-test'] = array(
'title' => t('Shadow Test'),
'page callback' => '_helper_page_callback_shadow_test',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
// define the page callback to process the AJAX request
$items['shadow-test-ajax'] = array(
'title' => t('Shadow Test Ajax'),
'page callback' => '_helper_page_callback_shadow_test_ajax',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implements the page callback to show the clickable link
*/
function _helper_page_callback_shadow_test() {
// include module css
drupal_add_css(drupal_get_path('module', 'helper') .'/helper.css');
// include module javascript
drupal_add_js(drupal_get_path('module', 'helper') .'/helper.js');
// generate shadow html
$shadow_html = "<div id='shadow' style='background: url(" . '"' . base_path() . drupal_get_path('module', 'helper') .'/shadow.png' . '"' . ")'></div>";
// define javascript variables to be passed to the DOM
$js_vars = array(
'helper' => array(
'ajax_path' => base_path() . 'shadow-test-ajax',
'shadow_html' => $shadow_html,
),
);
// pass variables to javascript
drupal_add_js($js_vars, 'setting');
// create a variable for page output
$output = "";
// create a clickable link
// NOT: this link will be overwritten via jQuery
$output .= l(
t('Click Me'),
$_REQUEST['q'],
array(
'attributes' => array(
'class' => 'ajax_clickable',
),
)
);
// return page output
return $output;
}
/**
* Implements page callback to process the AJAX request
*/
function _helper_page_callback_shadow_test_ajax() {
// wait 2 seconds
// NOTE: this line is just used to demo the "shadow" effect
sleep(3);
// return a JSON value
$ret = new StdClass();
$ret->status = true;
print drupal_json($ret);
die;
}
?>
After flushing my menu cache, and browsing to the first page callback, I see the following:
I added some CSS to my module’s CSS include file (helper.css), to help position the “shadow” full screen:
#shadow {
z-index: 1000;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
}
I created a 50% black transparent PNG image in PhotoShop:
I added some jQuery to my module’s javascript include file (helper.js), to add the click event to the link, and two functions to hide and show the shadow.
Drupal.behaviors.helper = function(context) {
// find the link with the matching class, and add a click event
$('.ajax_clickable').click(function(){
// show shadow
$(this).show_shadow();
// make ajax call
$.getJSON(
Drupal.settings.helper.ajax_path,
function(data) {
// when the ajax call is done, hide the shadow
$(this).hide_shadow();
}
);
// prevent the a tag from actually going anywhere
return false;
});
}
;(function($) {
// defines the function to show the shadow
$.fn.show_shadow = function() {
// ensure the shadow does not already exist
if ($('body #shadow').length == 0) {
// add shadow html, and fade it in
$('body').append(Drupal.settings.helper.shadow_html).find('#shadow').fadeIn();
}
}
// defines the function to hide the shadow
$.fn.hide_shadow = function() {
// fade it out, and then remove it from the dom
$('#shadow').fadeOut('slow', function() {
$(this).remove();
});
}
})(jQuery);
Now when I click on the link the page fades to black and the user cannot click on anything. After the 3 second delay (defined in the AJAX callback), the black shadow fades away.