11

I need to alter the "Webform AJAX" module's JavaScript code. Is this possible without hacking the module, and risking losing it all upon module updates?

19

You can use hook_js_alter() in a module. For example, this code replaces the jQuery library used by Drupal with the file present in the jquery_update directory.

function jquery_update_js_alter(&$javascript) {
  // Swap out jQuery to use an updated version of the library.
  $javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
} 

The same can be done for inline JavaScript code. The differences are:

  • Instead of 'misc/jquery.js', the first index is a number
  • $javascript[$index]['data'] will contain the JavaScript code

This means that first you have to find the entry for the JavaScript code to replace, and then alter it. The following code should work in this case.

function mymodule_js_alter(&$javascript) {
  $old_code = 'The code to alter';
  $new_code = 'The new code';

  foreach ($javascript as $index => $info) {
    if (is_numeric($index) && $info['data'] == $old_code) {
      $javascript[$index]['data'] = $new_code;
      break;
    }
  }
}

As alternative, if you need to alter the library implemented by a module, you can implement hook_library_alter(). For example, this is the code implemented by the latest version of the jQuery Update module.

function jquery_update_library_alter(&$javascript, $module) {

  // We are updating just the system module. For all other cases we return.
  if ($module != 'system') {
    return;
  }

  $path = drupal_get_path('module', 'jquery_update');

  // Make sure we inject either the minified or uncompressed version as desired.
  $min = variable_get('jquery_update_compression_type', 'min') == 'none' ? '' : '.min';
  $cdn = variable_get('jquery_update_jquery_cdn', 'none');

  // Replace jQuery with the latest version.
  $version = variable_get('jquery_update_jquery_version', '1.5');
  jquery_update_jquery_replace($javascript, $cdn, $path, $min, $version);

  // Replace jQuery UI with CDN or local files. If from a CDN include all of jQuery UI.
  jquery_update_jqueryui_replace($javascript, $cdn, $path, $min);

  // Replace the jQuery Cookie plugin.
  $javascript['cookie']['js']['misc/jquery.cookie.js']['data'] = $path . '/replace/ui/external/jquery.cookie.js';
  // Noting the version based on git commit as no version number is available.
  $javascript['cookie']['version'] = '67fb34f6a866c40d0570';

  // Replace jQuery Form plugin.
  $javascript['jquery.form']['js']['misc/jquery.form.js']['data'] = $path . '/replace/misc/jquery.form' . $min . '.js';
  $javascript['jquery.form']['version'] = '2.69';

  // Replace files for jQuery 1.7 and up
  if (version_compare($version, '1.7', '>=')) {
    $javascript['drupal.states']['js']['misc/states.js']['data'] = $path . '/replace/misc/1.7/states.js';
  }
}

This is valid also for JavaScript code used by Drupal core, since for those JavaScript files, the System module implements hook_library(). (See system_library().)

hook_js_alter() can be used for any JavaScript file/code, even for files used by Drupal core. Between hook_js_alter() and hook_library_alter(), it is preferable to implement the latter, when the JavaScript files are exposed as library.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.