Drupal - Add JavaScript files to the administrative pages

Using a module, you can follow two methods:

  • Implementing hook_init()
  • Implementing hook_form_alter()

The first method would allow you to add the extra JavaScript (or CSS) files to any administration pages, while the second method would allow you to add those files only to pages containing forms.

function mymodule_init() {
  if (arg(0) == 'admin') {
    $path = drupal_get_path('module', 'mymodule');
    drupal_add_js($path . '/mymodule.js');
    drupal_add_css($path . '/mymodule.css');
  }
}
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if (arg(0) == 'admin') {
    $path = drupal_get_path('module', 'mymodule');  
    $form['#attached']['css'][] = $path . '/mymodule.css';
    $form['#attached']['js'][] = $path . '/mymodule.js';
  }
}

Replace "mymodule" with the short name of your module; replace "mymodule.js" and "mymodule.css" with the actual names of the JavaScript and CSS files.

system_init() contains the following code, to add specific files to administrative pages.

  $path = drupal_get_path('module', 'system');
  // Add the CSS for this module. These aren't in system.info, because they
  // need to be in the CSS_SYSTEM group rather than the CSS_DEFAULT group.
  drupal_add_css($path . '/system.base.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));

  // Add the system.admin.css file to the administrative pages.
  if (path_is_admin(current_path())) {
    drupal_add_css($path . '/system.admin.css', array('group' => CSS_SYSTEM));
  }

  drupal_add_css($path . '/system.menus.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
  drupal_add_css($path . '/system.messages.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
  drupal_add_css($path . '/system.theme.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));

path_is_admin() is the function that in its documentation is described as:

Determine whether a path is in the administrative section of the site.

Consider that some node-related paths, such as node/<nid>/edit, could be included in the administrative section, depending on the setting found on admin/appearance.

screenshot

The list of the node paths that could be included in the administrative pages is returned from node_admin_paths().

  if (variable_get('node_admin_theme')) {
    $paths = array(
      'node/*/edit' => TRUE, 
      'node/*/delete' => TRUE, 
      'node/*/revisions' => TRUE, 
      'node/*/revisions/*/revert' => TRUE, 
      'node/*/revisions/*/delete' => TRUE, 
      'node/add' => TRUE, 
      'node/add/*' => TRUE,
    );
    return $paths;

If, for any reason, you need to avoid any page with a path like node/*, you need to add specific code to avoid those, if you are using path_is_admin(). Consider that any module could change the pages that are considered part of the administrative pages.

In both the cases, the alternative would be using a library, if the module implements hooks_library() with code similar to the following one.

function mymodule_library() {
  $path = drupal_get_path('module', 'mymodule');

  $libraries['mymodule.library'] = array(
    'title' => 'MyModule Library', 
    'version' => '1.0', 
    'js' => array(
      $path . '/mymodule.js' => array(),
    ), 
    'css' => array(
      $path . '/mymodule.css' => array(
        'type' => 'file', 
        'media' => 'screen',
      ),
    ),
  );

  return $libraries;
}

In this case, the previous implementation of hook_form_alter() would become the following.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if (arg(0) == 'admin') {
    $form['#attached']['library'][] = array('mymodule', 'mymodule.library');
  }
}

Instead of calling drupal_add_js(), and drupal_add_css(), the code should call drupal_add_library('mymodule', 'mymodule.library').

The pro of using hook_library() is:

  • Dependencies between libraries are automatically handled. That is what happens in the case of system_library(), which defines two libraries using the following definitions.

      // Drupal's form library.
      $libraries['drupal.form'] = array(
        'title' => 'Drupal form library', 
        'version' => VERSION, 
        'js' => array(
          'misc/form.js' => array(
            'group' => JS_LIBRARY,
            'weight' => 1,
          ),
        ),
      );
    
      // Drupal's collapsible fieldset.
      $libraries['drupal.collapse'] = array(
        'title' => 'Drupal collapsible fieldset', 
        'version' => VERSION, 
        'js' => array(
          'misc/collapse.js' => array('group' => JS_DEFAULT),
        ), 
        'dependencies' => array(
          // collapse.js relies on drupalGetSummary in form.js
          array('system', 'drupal.form'),
        ),
      );
    

    Calling drupal_add_library('system', 'drupal.collapse'), misc/collapse.js and misc/form.js would both be included.

  • The CSS files associated with the library would be automatically loaded together the JavaScript files.

  • Whenever the library would use more JavaScript, or CSS files, the code to include the library would not change; it would still be using $form['#attached']['library'][] = array('mymodule', 'mymodule.library');, or drupal_add_library('mymodule', 'mymodule.library').

 

There is no need to use current_path() when you can use arg(). If the path for the current page is admin/structure/block, then

  • arg(0) will return "admin"
  • arg(1) will return "structure"
  • arg(2) will return "block"

Update

hook_init() is not used anymore from Drupal 8. The alternative for Drupal 8 is using hook_form_alter(), hook_page_attachments(), or hook_page_attachements_alter(). hook_page_build() and hook_page_alter() are not anymore used in Drupal 8.
What I said about using a JavaScript library is still true, even if it is suggested to use #attached to attach a library (or a Javascript file, or a CSS file) to a page. Drupal 8 doesn't allow anymore to attach just JavaScript or CSS files to a page; you need to always attach a library, which a set of JavaScript and CSS files, eventually made of just JavaScript or CSS files.


Here are two approaches to adding JS/CSS to pages.

You can add JavaScript and CSS directly to the template file page.tpl.php, since the template files are PHP files, you can check the URL using arg() and present accordingly.

Alternatively, and better since it's theme independent, create a module that implements hook_init(), and call drupal_add_js() or drupal_add_css() based on current_path().

Something like the following code would work.

// Runs on every page load.
function mymodule_init() {
  // Check if current path is under "admin"
  if (substr(current_path(), 0, 5) == 'admin') {
    drupal_add_css('path/to/my/css');
    drupal_add_js('path/to/my/js');
  }
}