Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.555 diff -u -d -F^\s*function -r1.555 common.inc --- includes/common.inc 14 Aug 2006 07:14:48 -0000 1.555 +++ includes/common.inc 16 Aug 2006 19:16:53 -0000 @@ -1250,44 +1250,129 @@ function drupal_get_css($css = NULL) { } /** - * Add a JavaScript file to the output. + * Add a JavaScript file, setting or inline code to the page. * - * The first time this function is invoked per page request, - * it adds "misc/drupal.js" to the output. Other scripts - * depends on the 'killswitch' inside it. + * 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 ('core', 'module' and 'theme'): + * Adds a reference to a JavaScript file to the page. JavaScript files + * are placed in a certain order, from 'core' first, to 'module' and finally + * 'theme' so that files, that are added later, can override previously added + * files with ease. + * + * - Add inline JavaScript code ('inline'): + * Executes a piece of JavaScript code on the current page by placing the code + * directly in the page. This can, for example, be useful to tell the user that + * a new message arrived, by opening a pop up, alert box etc. + * + * - Add settings ('setting'): + * Adds a setting to Drupal's global storage of JavaScript settings. Per-page + * settings are required by some modules to function properly. The settings + * will be accessible at Drupal.settings. + * + * @param $data + * (optional) If given, the value depends on the $type parameter: + * - 'core', 'module' or 'theme': Path to the file relative to base_path(). + * - 'inline': The JS code that should be placed directly in the page head. + * - 'setting': An array with configuration options as associative array. The + * array is directly placed in Drupal.settings. You might want to wrap your + * actual configuration settings in another variable to prevent the pollution + * of the Drupal.settings namespace. + * @param $type + * (optional) The type of JavaScript that should be added to the page. Allowed + * values are 'core', 'module', 'theme', 'inline' and 'setting'. You + * can, however, specify any value. It is treated as a reference to a JavaScript + * file. Defaults to 'module'. + * @param $scope + * (optional) The location in which you want to place the script. Possible + * values are 'header' and 'footer' by default. If your theme implements + * different locations, however, you can also use these. + * @param $defer + * (optional) If set to TRUE, the defer attribute is set on the '); - $sent['misc/drupal.js'] = TRUE; +function drupal_add_js($data = NULL, $type = 'module', $scope = 'header', $defer = FALSE, $cache = TRUE) { + static $javascript = array(); + + if (!isset($javascript[$scope])) { + $javascript[$scope] = array('core' => array(), 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array()); + + if (empty($javascript['header']['core']['misc/drupal.js'])) { + drupal_add_js('misc/drupal.js', 'core'); + } } - if (!isset($sent[$file])) { - drupal_set_html_head(''); - $sent[$file] = TRUE; + + if (!isset($javascript[$scope][$type])) { + $javascript[$scope][$type] = array(); + } + + if (!is_null($data)) { + switch ($type) { + case 'setting': + $javascript[$scope][$type][] = $data; + break; + case 'inline': + $javascript[$scope][$type][] = array('code' => $data, 'defer' => $defer); + break; + default: + $javascript[$scope][$type][$data] = array('cache' => $cache, 'defer' => $defer); + } } + + return $javascript[$scope]; } /** - * Generates a Javascript call, while importing the arguments as is. - * PHP arrays are turned into JS objects to preserve keys. This means the array - * keys must conform to JS's member naming rules. + * Returns a themed presentation of all JavaScript code for the current page. + * References to JavaScript files are placed in a certain order: first, all + * 'core' files, then all 'module' and finally all 'theme' JavaScript files + * are added to the page. Then, all settings are output, followed by 'inline' + * JavaScript code. * - * @param $function - * The name of the function to call. - * @param $arguments - * An array of arguments. + * @parameter $scope + * (optional) The scope for which the JavaScript rules should be returned. + * Defaults to 'header'. + * @parameter $javascript + * (optional) An array with all JavaScript code. Defaults to the default + * JavaScript array for the given scope. + * @return + * All JavaScript code segments and includes for the scope as HTML tags. */ -function drupal_call_js($function) { - $arguments = func_get_args(); - array_shift($arguments); - $args = array(); - foreach ($arguments as $arg) { - $args[] = drupal_to_js($arg); +function drupal_get_js($scope = 'header', $javascript = NULL) { + $output = ''; + if (is_null($javascript)) { + $javascript = drupal_add_js(NULL, NULL, $scope); } - $output = ''; + + foreach ($javascript as $type => $data) { + if (!$data) continue; + + switch ($type) { + case 'setting': + $data = array(array('code' => 'Drupal.extend({ settings: '. drupal_to_js(call_user_func_array('array_merge_recursive', $data)) .' });', 'defer' => FALSE)); + case 'inline': + print_r($data); + foreach ($data as $info) { + $output .= '\n"; + } + break; + default: + foreach ($data as $path => $flags) { + $output .= '\n"; + } + } + } + return $output; } Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.306 diff -u -d -F^\s*function -r1.306 theme.inc --- includes/theme.inc 5 Aug 2006 22:17:31 -0000 1.306 +++ includes/theme.inc 16 Aug 2006 19:16:55 -0000 @@ -366,6 +366,7 @@ function theme_page($content) { $output .= ' '. (drupal_get_title() ? strip_tags(drupal_get_title()) : variable_get('site_name', 'drupal')) .''; $output .= drupal_get_html_head(); $output .= drupal_get_css(); + $output .= drupal_get_js(); $output .= ' '; $output .= ' '; @@ -407,6 +408,7 @@ function theme_maintenance_page($content $output .= ' '. strip_tags(drupal_get_title()) .''; $output .= drupal_get_html_head(); $output .= drupal_get_css(); + $output .= drupal_get_js(); $output .= ''; $output .= ''; $output .= '

' . drupal_get_title() . '

'; @@ -436,6 +438,7 @@ function theme_install_page($content) { $output .= ' '. strip_tags(drupal_get_title()) .''; $output .= drupal_get_html_head(); $output .= drupal_get_css(); + $output .= drupal_get_js(); $output .= ''; $output .= ''; $output .= '

' . drupal_get_title() . '

'; @@ -913,7 +916,7 @@ function theme_feed_icon($url) { */ function theme_closure($main = 0) { $footer = module_invoke_all('footer', $main); - return implode("\n", $footer); + return implode("\n", $footer) . drupal_get_js('footer'); } /** Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.24 diff -u -d -F^\s*function -r1.24 drupal.js --- misc/drupal.js 7 Jun 2006 09:34:11 -0000 1.24 +++ misc/drupal.js 16 Aug 2006 19:16:56 -0000 @@ -21,6 +21,19 @@ function isJsEnabled() { document.documentElement.className = 'js'; } +Drupal = { }; + +Drupal.extend = function(obj) { + for (var i in obj) { + if (this[i]) { + Drupal.extend.apply(this[i], [obj[i]]); + } + else { + this[i] = obj[i]; + } + } +} + /** * Make IE's XMLHTTP object accessible through XMLHttpRequest() */ Index: themes/bluemarine/page.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/bluemarine/page.tpl.php,v retrieving revision 1.17 diff -u -d -F^\s*function -r1.17 page.tpl.php --- themes/bluemarine/page.tpl.php 1 Feb 2006 16:04:02 -0000 1.17 +++ themes/bluemarine/page.tpl.php 16 Aug 2006 19:16:56 -0000 @@ -5,6 +5,7 @@ <?php print $head_title ?> + Index: themes/chameleon/chameleon.theme =================================================================== RCS file: /cvs/drupal/drupal/themes/chameleon/chameleon.theme,v retrieving revision 1.46 diff -u -d -F^\s*function -r1.46 chameleon.theme --- themes/chameleon/chameleon.theme 3 Aug 2006 07:06:36 -0000 1.46 +++ themes/chameleon/chameleon.theme 16 Aug 2006 19:16:57 -0000 @@ -38,6 +38,7 @@ function chameleon_page($content) { $output .= " ". ($title ? strip_tags($title) ." | ". variable_get("site_name", "drupal") : variable_get("site_name", "drupal") ." | ". variable_get("site_slogan", "")) ."\n"; $output .= drupal_get_html_head(); $output .= drupal_get_css(); + $output .= drupal_get_js(); $output .= ""; $output .= "\n"; $output .= "
"; Index: themes/engines/phptemplate/phptemplate.engine =================================================================== RCS file: /cvs/drupal/drupal/themes/engines/phptemplate/phptemplate.engine,v retrieving revision 1.40 diff -u -d -F^\s*function -r1.40 phptemplate.engine --- themes/engines/phptemplate/phptemplate.engine 15 Aug 2006 05:32:46 -0000 1.40 +++ themes/engines/phptemplate/phptemplate.engine 16 Aug 2006 19:16:58 -0000 @@ -214,6 +214,7 @@ function phptemplate_page($content) { 'site_slogan' => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''), 'css' => drupal_add_css(), 'styles' => drupal_get_css(), + 'scripts' => drupal_get_js(), 'tabs' => theme('menu_local_tasks'), 'title' => drupal_get_title() ); Index: themes/pushbutton/page.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/pushbutton/page.tpl.php,v retrieving revision 1.13 diff -u -d -F^\s*function -r1.13 page.tpl.php --- themes/pushbutton/page.tpl.php 1 Feb 2006 16:04:03 -0000 1.13 +++ themes/pushbutton/page.tpl.php 16 Aug 2006 19:16:58 -0000 @@ -5,6 +5,7 @@ +