Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.829 diff -u -r1.829 common.inc --- includes/common.inc 22 Nov 2008 13:55:27 -0000 1.829 +++ includes/common.inc 23 Nov 2008 08:24:33 -0000 @@ -2143,7 +2143,9 @@ * performed using this function: * * - Add a file ('file'): - * Adds a reference to a JavaScript file to the page. + * Adds a reference to a JavaScript file to the page. This may either be a file + * relative to base_path(), or the absolute path to a JavaScript file hosted + * externally. * * - Add inline JavaScript code ('inline'): * Executes a piece of JavaScript code on the current page by placing the code @@ -2164,11 +2166,13 @@ * drupal_add_js('$(document).ready(function(){alert("Hello!");});', * array('type' => 'inline', 'scope' => 'footer', 'weight' => 5) * ); + * drupal_add_js('http://yui.yahooapis.com/2.6.0/build/utilities/utilities.js'); * @endcode * * @param $data * (optional) If given, the value depends on the $options parameter: - * - 'file': Path to the file relative to base_path(). + * - 'file': Path to the file relative to base_path(), or the absolute path + * to a JavaScript file hosted externally. * - 'inline': The JavaScript code that should be placed in the given scope. * - 'setting': An array with configuration options as associative array. The * array is directly placed in Drupal.settings. All modules should wrap @@ -2379,7 +2383,10 @@ case 'file': if (!$item['preprocess'] || !$is_writable || !$preprocess_js) { - $no_preprocess .= '\n"; + // Local JavaScript files require a base_path() prefix, while scripts + // that are hosted externally require not having any prefix at all. + $prefix = filter_var($item['data'], FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED) ? '' : base_path(); + $no_preprocess .= '\n"; } else { $files[$item['data']] = $item; @@ -2552,8 +2559,16 @@ // Build aggregate JS file. foreach ($files as $path => $info) { if ($info['preprocess']) { - // Append a ';' after each JS file to prevent them from running together. - $contents .= file_get_contents($path) . ';'; + // Local files are aggregated inline, while external scripts are loaded + // through JavaScript. + if (!filter_var($path, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)) { + // Append a ';' after each JS file to prevent them from running together. + $contents .= file_get_contents($path) . ';'; + } + else { + // Use jQuery's getScript function to load the external script. + $contents .= '$.getScript("' . $path . '");'; + } } } Index: modules/simpletest/tests/common.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v retrieving revision 1.14 diff -u -r1.14 common.test --- modules/simpletest/tests/common.test 16 Nov 2008 15:19:34 -0000 1.14 +++ modules/simpletest/tests/common.test 23 Nov 2008 08:24:33 -0000 @@ -455,6 +455,17 @@ } /** + * Test rendering an external JavaScript file. + */ + function testRenderExternal() { + $external = 'http://yui.yahooapis.com/2.6.0/build/utilities/utilities.js'; + drupal_add_js($external); + $javascript = drupal_get_js(); + // Local files have a base_path() prefix, external files should not. + $this->assertTrue(strpos($javascript, 'src="' . $external) > 0, t('Rendering an external JavaScript file.')); + } + + /** * Test drupal_get_js() with a footer scope. */ function testFooterHTML() {