18

How do I add JavaScript/CSS files in every administration pages, using a module?

25

Using a module, you can follow two methods:

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.

  • What if I want to add on every page if i want drupal access "user_access('access administration pages')" ? – confiq Feb 13 '12 at 16:15
  • 1
    Replace arg(0) == 'admin' with user_access('access administration pages'). – kiamlaluno Feb 13 '12 at 16:32
  • 4
    The proper way to check if the current page is an admin page would be the path_is_admin function. Some administration pages' paths don't start with 'admin'. For instance, depending on the configuration, the node/add/<content-type> pages may be configuration ones. – Pierre Buyle Jun 4 '12 at 14:36
  • Awesome post, super thorough, thanks for really covering this one, very helpful and appreciated. – DrCord Nov 15 '13 at 19:11
  • Pierre Buyle comment is very very useful! – Moshe Shaham Feb 27 '14 at 13:59
3

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');
  }
}
1

I created a module using the steps described here: http://purewebmedia.biz/article/2014/04/23/adding-your-own-css-admin-theme

Copied the module text as desribed on that page:

    function mymodule_preprocess_html(&$variables) {
// Add conditional stylesheets for admin pages on admin theme.
  if (arg(0)=="admin") {
    // reference your current admin theme  
    $theme_path = drupal_get_path('theme', 'commerce_kickstart_admin');
    // reference your own stylesheet    
    drupal_add_css(drupal_get_path('module', 'mymodule') . '/css/mymodule.css', array('weight' => CSS_THEME));
  }
}

However the admin check was faulty when I (as one of the things) wanted to style the submit buttons in all pages as well as the node edit form. Since that path goes to node/edit and not admin the check made me scratch my head for hours.

So I came up with this version to make my simple module called admin_css.

admin_css.info

name = admin_css
description = Custom css alterations for editor interface
core = 7.x
version = 7.x-1.01

admin_css.module

function admin_css_preprocess_html(&$variables) {
    if (path_is_admin) {
        $theme_path = drupal_get_path('theme', 'seven');
        drupal_add_css(drupal_get_path('module', 'admin_css') . '/css/admin_css.css', array('weight' => 0));
    }
}

What is different to the answer here is to check if the path is in the administrative part of the site with path_is_admin instead of using arg. Using arg caused my css-file not to load on the node-edit and other pages.

1

It's considered bad practice to add JS and CSS from hook_init(). Instead you'ld use hook_page_build():

/**
 * Implements hook_page_build().
 */
function MYMODULE_page_build(&$page) {

  if (path_is_admin(current_path())) {

    drupal_add_js(drupal_get_path('module', 'MYMODULE') . '/scripts/magic.js');
  }
}
1

I just used another method that may appeal to front-end devs. Subtheme your preferred admin theme and then add a simple:

scripts[] = myscripts.js

to your theme.info file that contains the javascript you need for your admin pages. If you wish, you can add more overrides, since this will inherit your favorite admin theme's resources.

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.