\drupal_add_js
function
Adds a JavaScript file, setting, or inline code to the page.

Adds a JavaScript file, setting, or inline code to the page.

The behavior of this function depends on the parameters it is called with. Generally, it handles the addition of JavaScript to the page, either as reference to an existing file or as inline code. The following actions can be performed using this function:

  • Add a file ('file'): Adds a reference to a JavaScript file to the page.
  • Add inline JavaScript code ('inline'): Executes a piece of JavaScript code on the current page by placing the code directly in the page (for example, to tell the user that a new message arrived, by opening a pop up, alert box, etc.). This should only be used for JavaScript that cannot be executed from a file. When adding inline code, make sure that you are not relying on $() being the jQuery function. Wrap your code in
(function ($) {... })(jQuery); 

or use jQuery() instead of $().

  • Add external JavaScript ('external'): Allows the inclusion of external JavaScript files that are not hosted on the local server. Note that these external JavaScript references do not get aggregated when preprocessing is on.
  • Add settings ('setting'): Adds settings to Drupal's global storage of JavaScript settings. Per-page settings are required by some modules to function properly. All settings will be accessible at Drupal.settings.

Examples:

  drupal_add_js('misc/collapse.js');
  drupal_add_js('misc/collapse.js', 'file');
  drupal_add_js('jQuery(document).ready(function () { alert("Hello!"); });', 'inline');
  drupal_add_js('jQuery(document).ready(function () { alert("Hello!"); });',
    array('type' => 'inline', 'scope' => 'footer', 'weight' => 5)
  );
  drupal_add_js('http://example.com/example.js', 'external');
  drupal_add_js(array('myModule' => array('key' => 'value')), 'setting');

Calling drupal_static_reset('drupal_add_js') will clear all JavaScript added so far.

If JavaScript aggregation is enabled, all JavaScript files added with $options['preprocess'] set to TRUE will be merged into one aggregate file. Preprocessed inline JavaScript will not be aggregated into this single file. Externally hosted JavaScripts are never aggregated.

The reason for aggregating the files is outlined quite thoroughly here: http://www.die.net/musings/page_load_time/ "Load fewer external objects. Due to request overhead, one bigger file just loads faster than two smaller ones half its size."

$options['preprocess'] should be only set to TRUE when a file is required for all typical visitors and most pages of a site. It is critical that all preprocessed files are added unconditionally on every page, even if the files are not needed on a page. This is normally done by calling drupal_add_js() in a hook_init() implementation.

Non-preprocessed files should only be added to the page when they are actually needed.

Comments

ignasegovia’s picture

Having the ability to conditionally load js files depending on browser would help cross browser compatibility tremendously. add_js can be a little to stern to deal with and needs more flexibility.

mikeyjk’s picture

Just posting for reference, I doubt this will be of use to a post made 5 years ago.

If you are looking to achieve more flexibility (conditionally loading/adding JS based on a set of pre-conditions) then you could define a hook_menu entry pointing to a JS file which is actually generated from a template.

Then add this JS with drupal_add_js() when the pre-conditions are met, perhaps from hook_init().
But, I would agree that more in-built flexibility would be great - and the suggestion I've provided is probably far from perfect.

TwoD’s picture

The jQuery version bundled with D7 automatically runs a couple of tests to determine how capable the visiting browser is. The results are stored as properties of jQuery.support, which makes for easier branching in your scrpts based on available [or working] features.

I personally prefer a couple of branches (if put in the right places) rather than dealing with two or more files. It's easy to forget syncing multiple files and I think aggregation works better with just one.

Feature detection and browser based decision making on the client is also a lot more reliable than what Drupal's serverside code could do in drupal_add_js().

attiks’s picture

I needed to add an separate js file only for IE browsers to support canvas, I was hoping drupal_add_js would allow this.

Only solution I found is

$forie = array(
  '#type' => 'markup',
  '#markup' => '<!--[if IE]><script language="javascript" type="text/javascript" src="..."></script><![endif]-->',
);

drupal_add_html_head($forie, 'mymodule');
hdcwebteam’s picture

Quick example of use in your theme's template.php (I hunted around for a while trying to find such an example):

function MYTHEME_preprocess_page(&$variables) {
	drupal_add_js(drupal_get_path('theme', 'MYTHEME') .'/mytheme.js', 'file');
}
dlumberg’s picture

If it's included on every page then it's better to include it in your theme's mytheme.info file as it gets added to the theme registry.

scripts[] = js/script.js
scripts[] = js/otherscript.js
AlonGoldberg’s picture

Drupal 7 supports a weight attribute which is easy to use, like so:

$path = drupal_get_path('module', 'MODULE_NAME_HERE');
drupal_add_js($path . '/SCRIPT_NAME_HERE.js', array('weight' => 1));

Tip: DO NOT rely on firebug to check if the order of your scripts have changed, as firebug automatically groups and re-orders the scripts for display!

What you want to do is view the actual source-code instead...

I wasted a couple of hours on this.
Hope this helps someone else to avoid the same.

GamlaSonn’s picture

As a Drupal newbie I thought it was logical to call drupal_add_js (or drupal_add_library) to add jQuery in my module, just to point out that the other javascript files used in the module depend on this library. I figured surely it couldn't hurt and in worst case scenario the library is already in the queue. Turns out that doing so somehow reset or messed up the queue order and I got a lot of "jQuery not defined" errors in firebug as jQuery was no longer being included before jquery.once.js and drupal.js (and more).

I didn't realize the queue system worked like this, surely should it not ignore subsequent calls to libraries already in the queue? I suppose this scenario must be relevant for other libraries as well.

Just beware:)

earwax’s picture

What they call a "javascript file" is not really a javascript file. It's that weird jQuery format. So if your external file has <script type="javascript/text" >...</script>, then forget it because it will not work. You will need to wrap it in that jQuery syntax. I spent a good 2 hours banging my head on this.

Taghipour’s picture

type="text/javascript" is correct.

EvanDonovan’s picture

If the file has script tags wrapped around it, it's not a pure Javascript file. The script tags show up only to wrap JS that is being included inline in HTML. Any Javascript external file should not include them - not just ones that use the jQuery syntax.

Sivaji’s picture

See hook_js_alter() to alter js files added using drupal_add_js()

emmajane’s picture

JohnAlbin also gave the useful comment in IRC about ordering the files:

When you use drupal_add_js() it defaults to "i'm a module adding a js" and module JS come before theme JS. So you'll need to set the group for the new JS file as well.

pankaj.winaim’s picture

Solution : For this We can call the theme for call the javascipt like :

$form['pager'] = array('#theme' => 'copy_import_pagination');

osman’s picture

These are very cool improvements over v6. Thank you guys! :-)

My favorite feature is in external resources you can use protocol-relative URLs:

For example, if you need to include a javascript to load webfonts:

drupal_add_js('//fast.fonts.com/jsapi/00000000-0000-0000-0000-000000000000.js', array(
  'type' => 'external',
  'scope' => 'header',
  'group' => JS_THEME,
  'every_page' => TRUE,
  'weight' => -1,
));

I am guessing drupal_add_css also works the same way, and also in .info files too. I'll check that out later.

MD3’s picture

So you've successfully loaded your JS file and it won't work? Make sure your code is wrapped in anonymous function that casts jQuery as $:

jQuery(document).ready(function ($) {
});

Make sure to read Working with JavaScript and jQuery

zorroposada’s picture

Sample code on how to add conditional scripts in html head section.
Scripts will apply to IE browsers except IE9.
Place the following code inside template.php inside hook_preprocess_html().

<?php
// IE  Conditional scripts
  $ie_scripts = array(
    path_to_theme() . '/js/script1.js',
    path_to_theme() . '/js/script2.js',
    path_to_theme() . '/js/script3.js',
  );
  foreach ($ie_scripts as $key => $value) {
    $ie_script =  array(
      '#browsers' => array('IE' => 'lt IE 9', '!IE' => FALSE),
      '#tag' => 'script',
      '#attributes' => array(
        'type' => "text/javascript",
        'src' => $value,
      ),
      '#pre_render' => array('drupal_pre_render_conditional_comments'),
      '#weight' =>  999 + $key,
    );
    drupal_add_html_head($ie_script, "mytheme$key");
  }
?>
mail@victorquinn.com’s picture

The above example for loading external libraries is great if you don't have any options for them:

<?php drupal_add_js('http://example.com/example.js', 'external'); ?>

But if you do, you'll want to add it to the options array with a flag of 'type'.

For example, to change the weight of an external library:

<?php
drupal_add_js('http://example.com/example.js', array(
    'weight' => '-1000',
    'type' => 'external',
  )
);
?>

This can be figured out from the code but hopefully this will help make it a bit easier for some folks.

lmeurs’s picture

I wanted to attach a JS setting to a block and couldn't figure out how to do this. Finally I found out that I had to use the data key in the array. The explanation is as follows:

In some cases, the first parameter ($data) is an array. Arrays can't be passed as keys in PHP, so we have to get $data from the value array.

  $block['content'] = array(
    '#attached' => array(
      'js' => array(
        'path/to/a/script.js',
        array(
          'data' => array(
            'myModule' => array('mySettings' => 123),
          ),
        'type' => 'setting',
      )
    ),
  ),
  );

Source: http://deeson-online.co.uk/labs/how-use-formattached-javascript-setting-....

Fabianx’s picture

If you need a reg-exp to do the work for you, here it is:

s/drupal_add_js(\(.*\), array(\(.*\)));/$element['#attached']['js'][] = array('data' => \1, \2)/

Will automatically attach things to $element instead.

drclaw’s picture

This function has been removed in Drupa 8. Adding js to the page should now be done using the #attached property of a renderable array. @see Change Record https://drupal.org/node/2169605

cmcintosh’s picture

Oddly enough, https://www.drupal.org/node/2169605 states that drupal_add_js, and drupal_add_css are both dropped in favor of #attach. it is in fact the case that no js can be attached.

COBadger’s picture

The node to which you linked (https://www.drupal.org/node/2169605) refers to Drupal 8, not Drupal 7 - drupal_add_js is still very much a part of Drupal 7.

fen’s picture

You can build a site to DoD security standards, but if an external site hosting the JavaScript that you are are including gets hacked, then whatever access the intended JavaScript had to your data becomes available to the cracker. For example, the external JavaScript can send AJAX requests for data from your user and it can steal document.cookie. If you do include JavaScript, be certain that the links are secure (HTTPS) and your sources are trusted. As some people say, you are what you include.

ruvenshilpakar’s picture

drupal_add_js(drupal_get_path('module', 'mymodule') .'/myscript.js', 'file');

when i add this line in my custom module, it messes up site there are two issues seen:

1. When I add the line and flush the js and css cache in my site, the script codes work but I get an error
Notice: Undefined index: label in entity_views_field_definition() (line 191 of /srv/ceretreat/docroot/sites/all/modules/contrib/entity/views/entity.views.inc).
This messes up my rooms module data.

2. When i add the line and flush all cache I dont get the above error but the script doesnt work and jquery not defined issues or not a function issues are seen.

Does anyone have any idea on this? I am using Drupal 7

Thanks

Gaurav_drupal’s picture