hide_submit.module in Hide submit button 7
Same filename and directory in other branches
Hide the submit button after clicked to prevent/reduce duplicate postings.
Using a small jQuery snippet, this module will hide submit buttons afted clicked to prevent/reduce duplicate postings. A message and a nice loader animation will be displayed So the user will know its request is being processed
File
hide_submit.moduleView source
<?php
/**
* @file
* Hide the submit button after clicked to prevent/reduce duplicate postings.
*
* Using a small jQuery snippet, this module will hide submit buttons
* afted clicked to prevent/reduce duplicate postings.
* A message and a nice loader animation will be displayed
* So the user will know its request is being processed
*/
// --- Constants ---
define('HIDE_SUBMIT_IN_CONTENT_ADD_EDIT', 0);
define('HIDE_SUBMIT_EXCLUDE_LISTED_PAGES', 1);
define('HIDE_SUBMIT_IN_LISTED_PAGES', 2);
define('HIDE_SUBMIT_MODE_HIDE', 0);
define('HIDE_SUBMIT_MODE_DISABLE', 1);
define('HIDE_SUBMIT_BUTTON_ONLY', 0);
define('HIDE_SUBMIT_BUTTON_AND_KEY', 1);
define('HIDE_SUBMIT_DEFAULT_JS_LOAD', HIDE_SUBMIT_IN_CONTENT_ADD_EDIT);
define('HIDE_SUBMIT_DEFAULT_MESSAGE', t("Please wait..."));
define('HIDE_SUBMIT_ADMIN_SETTINGS_JS', drupal_get_path('module', 'hide_submit') . '/hide_submit_admin_settings.js');
define('HIDE_SUBMIT_MODULE_DIRECTORY', drupal_get_path('module', 'hide_submit'));
define('HIDE_SUBMIT_IMG_DIRECTORY', 'public://hide_submit');
//define('HIDE_SUBMIT_IMG_DIRECTORY', file_directory_path() . '/hide_submit');
define('HIDE_SUBMIT_DEFAULT_IMAGE_BASENAME', 'loader.gif');
define('HIDE_SUBMIT_DEFAULT_IMAGE', HIDE_SUBMIT_MODULE_DIRECTORY . '/images/' . HIDE_SUBMIT_DEFAULT_IMAGE_BASENAME);
define('HIDE_SUBMIT_EXCLUDE_CLASS', 'hide-submit-exclude');
define('HIDE_SUBMIT_EXCLUDE_LISTED_FORMS', 0);
define('HIDE_SUBMIT_EXCLUDE_UNLISTED_FORMS', 1);
/**
* Implements hook_help().
*/
function hide_submit_help($path, $arg) {
$output = '';
switch ($path) {
case 'admin/help#hide_submit':
case 'admin/config/hide-submit':
$output = '<p>' . t('The hide_submit module provides a way to hide the submit button in a form after it has been clicked. This will indicate to the user that his or her request is being processed and helps to prevent duplicate postings from impatient "double clickers".') . '</p>' . '<p>' . t('For more information please visit the !project page or the !documentation page', array(
'!documentation' => l('documentation', 'http://drupal.org/node/338935'),
'!project' => l('hide submit project', 'http://drupal.org/project/hide_submit'),
)) . '</p>';
if (module_exists('advanced_help')) {
// TODO Please change this theme call to use an associative array for the $variables parameter.
$output .= '<p>' . theme('advanced_help_topic', 'hide_submit', 'using-hide-submit') . ' ' . t('Click the icon to read the extended help.');
}
break;
}
return $output;
}
/**
* Implements hook_menu().
*/
function hide_submit_menu() {
$items = array();
$items['admin/config/content/hide-submit'] = array(
'title' => 'Hide Submit',
'description' => 'Configure hide submit',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'hide_submit_admin_settings',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'hide_submit_admin.inc',
);
$items['admin/config/content/hide-submit/settings'] = array(
'title' => 'Hide Submit',
'file' => 'hide_submit_admin.inc',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 10,
);
$items['admin/config/content/hide-submit/delete/%'] = array(
'title' => 'Confirm delete',
'description' => 'Delete an image file',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'hide_submit_admin_delete_image',
5,
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'hide_submit_admin.inc',
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implements hook_init().
*/
function hide_submit_init() {
if (!hide_submit_js_loaded() && _hide_submit_load_js_check_condition()) {
drupal_add_js(_hide_submit_get_javascript_settings(), array(
'type' => 'setting',
'scope' => JS_DEFAULT,
));
drupal_add_js(drupal_get_path('module', 'hide_submit') . '/hide_submit.js');
hide_submit_js_loaded(TRUE);
}
}
/**
* Memory function for checking or setting script status
*
* @param mixed $status - new status or NULL to leave status unchanged
* @returns TRUE or FALSE indicating script was loaded
*/
function hide_submit_js_loaded($status = NULL) {
static $hide_submit_js_loaded = FALSE;
if ($status !== NULL) {
$hide_submit_js_loaded = $status;
}
return $hide_submit_js_loaded;
}
/**
* Implements hook_form_alter().
*
* Used to add "hide-submit-exclude" class to some forms
* Avoid conflicts and refine hiding
*/
function hide_submit_form_alter(&$form, $form_state, $form_id) {
// Act only if script was loaded
if (!hide_submit_js_loaded()) {
return;
}
$exclude_forms = explode("\r\n", variable_get('hide_submit_form_exclusion', ''));
$found = FALSE;
$mode = variable_get('hide_submit_form_exclusion_mode', HIDE_SUBMIT_EXCLUDE_LISTED_FORMS);
// Prevent known conflicts by adding form ids of known ajax forms
if (variable_get('hide_submit_fix_known_conflicts', TRUE) && $mode == HIDE_SUBMIT_EXCLUDE_LISTED_FORMS) {
// shoutbox module
if (module_exists('shoutbox')) {
$exclude_forms[] = 'shoutbox_add_form';
if (_hide_submit_debug_on()) {
drupal_set_message("hide submit: Possible conflict detected and handled - shoutbox module");
}
}
}
foreach ($exclude_forms as $exclude_form_id) {
if ($form_id == $exclude_form_id) {
$found = TRUE;
if ($mode == HIDE_SUBMIT_EXCLUDE_LISTED_FORMS) {
_hide_submit_add_exclude_class($form);
if (_hide_submit_debug_on()) {
drupal_set_message("hide_submit: Excluding form " . $exclude_form_id);
}
}
}
}
if (!$found && $mode == HIDE_SUBMIT_EXCLUDE_UNLISTED_FORMS) {
_hide_submit_add_exclude_class($form);
if (_hide_submit_debug_on()) {
drupal_set_message("hide_submit: Excluding form " . $form_id);
}
}
// Comment workaround
// When disable button mode is selected
// Comments won't submit because disabled button value is not included in the $_POST[] data
// This workaround should fix this
if (($form_id == 'comment_form' || preg_match('/node_form$/', $form_id)) && variable_get('hide_submit_script_mode', HIDE_SUBMIT_MODE_HIDE) == HIDE_SUBMIT_MODE_DISABLE) {
$form['hide_submit_fake_op'] = array(
'#type' => 'hidden',
'#value' => "",
);
}
}
/**
* Implements hook_theme().
*/
function hide_submit_theme() {
$theme = array(
'hide_submit_images_fieldset' => array(
'render element' => 'form',
),
);
return $theme;
}
//------------------------------------------------------------------------
// Private functions
//------------------------------------------------------------------------
/**
* A recursive function to add class to all excluded submit buttons
*/
function _hide_submit_add_exclude_class(&$elements) {
// Recurse through all children.
foreach (element_children($elements) as $key) {
if (isset($elements[$key]) && $elements[$key]) {
_hide_submit_add_exclude_class($elements[$key]);
}
}
// Add class to submit buttons
if (isset($elements['#type']) && $elements['#type'] == 'submit') {
$elements['#attributes']['class'][] = HIDE_SUBMIT_EXCLUDE_CLASS;
}
}
/**
* Check if JS should be loaded for current page
*/
function _hide_submit_load_js_check_condition() {
$js_load_option = variable_get('hide_submit_js_load_option', HIDE_SUBMIT_DEFAULT_JS_LOAD);
switch ($js_load_option) {
case HIDE_SUBMIT_IN_LISTED_PAGES:
case HIDE_SUBMIT_EXCLUDE_LISTED_PAGES:
$pages = variable_get('hide_submit_js_load_pages', '');
break;
case HIDE_SUBMIT_IN_CONTENT_ADD_EDIT:
default:
$pages = "node/add/*\r\nnode/*/edit";
break;
}
if ($js_load_option != HIDE_SUBMIT_EXCLUDE_LISTED_PAGES) {
$pages .= "\r\nadmin/settings/hide-submit";
}
$path = drupal_get_path_alias($_GET['q']);
$regexp = '/^(' . preg_replace(array(
'/(\\r\\n?|\\n)/',
'/\\\\\\*/',
'/(^|\\|)\\\\<front\\\\>($|\\|)/',
), array(
'|',
'.*',
'\\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\\2',
), preg_quote($pages, '/')) . ')$/';
// Compare with the internal and path alias (if any).
$page_match = preg_match($regexp, $path);
if ($path != $_GET['q']) {
$page_match = $page_match || preg_match($regexp, $_GET['q']);
}
// Do we have a match on our page list?
if ($js_load_option == HIDE_SUBMIT_EXCLUDE_LISTED_PAGES) {
return !($page_match == 1);
}
return $page_match == 1;
}
/**
* scrub the format strings for things that make bad javascript.
*
* @param $format_string
* @return
* cleaned $format_string
*/
function _hide_submit_clean_for_javascript($format_string = '') {
$patterns = array(
'/\\n/',
'/\\r/',
'/\'/',
);
$replacements = array(
'<br/>',
'',
'`',
);
return preg_replace($patterns, $replacements, $format_string);
}
/**
* get the image according to user selection, default, random etc...
*/
function _hide_submit_get_image() {
// Use static to assure the same image is returned for the current page
static $image = FALSE;
if ($image !== FALSE) {
return $image;
}
if (variable_get('hide_submit_text_only', FALSE)) {
$image = FALSE;
}
else {
$image = variable_get('hide_submit_image', HIDE_SUBMIT_DEFAULT_IMAGE);
if (is_array($image)) {
list($usec, $sec) = explode(' ', microtime());
srand((double) $sec + (double) $usec * 100000);
$image = $image[rand() % count($image)];
}
}
// Allow modules to modify the image.
drupal_alter('hide_submit_image', $image);
// Theme should be able to play with those settings too.
// Theme may not be initialized at this time, so we have to force its
// initialization if $GLOBALS['theme'] is NULL.
// Because of this initialisation, the module weight is heavy, to let
// others modules (like theme_keys or section) do their job before.
if (empty($GLOBALS['theme'])) {
init_theme();
}
$function = $GLOBALS['theme'] . '_hide_submit_image_alter';
if (function_exists($function)) {
$function($image);
}
return $image;
}
/**
* Get javascript code for injection
*/
function _hide_submit_get_message() {
global $language;
$message = variable_get('hide_submit_message_' . $language->language, "");
if ($message == "") {
$message = variable_get('hide_submit_message', HIDE_SUBMIT_DEFAULT_MESSAGE);
}
$image = _hide_submit_get_image();
if ($image !== FALSE) {
$image = '<img src="' . file_create_url($image) . '" alt="" title="" /> ';
}
return '<p class="hide_submit">' . $image . ' ' . $message . ' </p>';
}
/**
* Get javascript code for injection
*/
function _hide_submit_get_javascript_settings() {
// Set base path for local image, none for external
$image = _hide_submit_get_image();
if ($image !== FALSE) {
$image = url($image) == $image ? $image : base_path() . $image;
$image = check_url($image);
}
// Assemble jQuery selector
$selector = 'input:submit:not(.' . HIDE_SUBMIT_EXCLUDE_CLASS . ')';
$selector .= implode("", explode("\r\n", filter_xss_admin(variable_get('hide_submit_attribute_filter', ''))));
// Prevent known conflicts by using jquery attributes
if (variable_get('hide_submit_fix_known_conflicts', TRUE)) {
// Draft module
if (module_exists('draft')) {
$selector .= check_plain('[value!=' . t('Save As Draft') . ']');
if (_hide_submit_debug_on()) {
drupal_set_message("hide submit: Possible conflict detected and handled - draft module");
}
}
}
$mode = variable_get('hide_submit_script_mode', HIDE_SUBMIT_MODE_HIDE) == HIDE_SUBMIT_MODE_HIDE ? "hide" : "disable";
$settings = array(
'hide_submit' => array(
'selector' => $selector,
'mode' => $mode,
'keypress' => variable_get('hide_submit_keypress', HIDE_SUBMIT_BUTTON_AND_KEY),
'dbg' => _hide_submit_debug_on(),
),
);
// Add Message and image only when needed
if ($mode == 'hide') {
$settings['hide_submit']['message'] = filter_xss_admin(_hide_submit_clean_for_javascript(_hide_submit_get_message()));
$settings['hide_submit']['image'] = $image;
}
return $settings;
}
/**
* Debug mode check
*/
function _hide_submit_debug_on() {
return variable_get('hide_submit_debug', FALSE) && user_access('administer site configuration');
}
Functions
Name![]() |
Description |
---|---|
hide_submit_form_alter | Implements hook_form_alter(). |
hide_submit_help | Implements hook_help(). |
hide_submit_init | Implements hook_init(). |
hide_submit_js_loaded | Memory function for checking or setting script status |
hide_submit_menu | Implements hook_menu(). |
hide_submit_theme | Implements hook_theme(). |
_hide_submit_add_exclude_class | A recursive function to add class to all excluded submit buttons |
_hide_submit_clean_for_javascript | scrub the format strings for things that make bad javascript. |
_hide_submit_debug_on | Debug mode check |
_hide_submit_get_image | get the image according to user selection, default, random etc... |
_hide_submit_get_javascript_settings | Get javascript code for injection |
_hide_submit_get_message | Get javascript code for injection |
_hide_submit_load_js_check_condition | Check if JS should be loaded for current page |