Skip to content
Snippets Groups Projects
Commit a8de1e92 authored by Dries Buytaert's avatar Dries Buytaert
Browse files

- Patch #76637 by timnc: streamline JavaScript addition and add settings storage.

parent 4936f4df
Branches
Tags
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
...@@ -1276,44 +1276,129 @@ function drupal_get_css($css = NULL) { ...@@ -1276,44 +1276,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, * The behavior of this function depends on the parameters it is called with.
* it adds "misc/drupal.js" to the output. Other scripts * Generally, it handles the addition of JavaScript to the page, either as
* depends on the 'killswitch' inside it. * 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 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. 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 <script> tag.
* Defaults to FALSE. This parameter is not used with $type == 'setting'.
* @param $cache
* (optional) If set to FALSE, the JavaScript file is loaded anew on every page
* call, that means, it is not cached. Defaults to TRUE. Used only when $type
* references a JavaScript file.
* @return
* If the first parameter is NULL, the JavaScript array that has been built so
* far for $scope is returned.
*/ */
function drupal_add_js($file, $nocache = FALSE) { function drupal_add_js($data = NULL, $type = 'module', $scope = 'header', $defer = FALSE, $cache = TRUE) {
static $sent = array(); static $javascript = array();
if (!isset($javascript[$scope])) {
$javascript[$scope] = array('core' => array(), 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array());
$postfix = $nocache ? '?'. time() : ''; if (empty($javascript['header']['core']['misc/drupal.js'])) {
if (!isset($sent['misc/drupal.js'])) { drupal_add_js('misc/drupal.js', 'core');
drupal_set_html_head('<script type="text/javascript" src="'. base_path() .'misc/drupal.js'. $postfix .'"></script>'); }
$sent['misc/drupal.js'] = TRUE; }
if (!isset($javascript[$scope][$type])) {
$javascript[$scope][$type] = array();
} }
if (!isset($sent[$file])) {
drupal_set_html_head('<script type="text/javascript" src="'. check_url(base_path() . $file) . $postfix .'"></script>'); if (!is_null($data)) {
$sent[$file] = TRUE; 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. * Returns a themed presentation of all JavaScript code for the current page.
* PHP arrays are turned into JS objects to preserve keys. This means the array * References to JavaScript files are placed in a certain order: first, all
* keys must conform to JS's member naming rules. * '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 * @parameter $scope
* The name of the function to call. * (optional) The scope for which the JavaScript rules should be returned.
* @param $arguments * Defaults to 'header'.
* An array of arguments. * @parameter $javascript
*/ * (optional) An array with all JavaScript code. Defaults to the default
function drupal_call_js($function) { * JavaScript array for the given scope.
$arguments = func_get_args(); * @return
array_shift($arguments); * All JavaScript code segments and includes for the scope as HTML tags.
$args = array(); */
foreach ($arguments as $arg) { function drupal_get_js($scope = 'header', $javascript = NULL) {
$args[] = drupal_to_js($arg); $output = '';
} if (is_null($javascript)) {
$output = '<script type="text/javascript">'. $function .'('. implode(', ', $args) .');</script>'; $javascript = drupal_add_js(NULL, NULL, $scope);
}
foreach ($javascript as $type => $data) {
if (!$data) continue;
switch ($type) {
case 'setting':
$output .= '<script type="text/javascript">Drupal.extend({ settings: '. drupal_to_js(call_user_func_array('array_merge_recursive', $data)) ." });</script>\n";
break;
case 'inline':
foreach ($data as $info) {
$output .= '<script type="text/javascript"'. ($info['defer'] ? ' defer="defer"' : '') .'>'. $info['code'] ."</script>\n";
}
break;
default:
foreach ($data as $path => $flags) {
$output .= '<script type="text/javascript"'. ($info['defer'] ? ' defer="defer"' : '') .' src="'. check_url(base_path() . $path) . ($flags['cache'] ? '' : '?'. time()) ."\"></script>\n";
}
}
}
return $output; return $output;
} }
......
...@@ -365,6 +365,7 @@ function theme_page($content) { ...@@ -365,6 +365,7 @@ function theme_page($content) {
$output .= ' <title>'. (drupal_get_title() ? strip_tags(drupal_get_title()) : variable_get('site_name', 'drupal')) .'</title>'; $output .= ' <title>'. (drupal_get_title() ? strip_tags(drupal_get_title()) : variable_get('site_name', 'drupal')) .'</title>';
$output .= drupal_get_html_head(); $output .= drupal_get_html_head();
$output .= drupal_get_css(); $output .= drupal_get_css();
$output .= drupal_get_js();
$output .= ' </head>'; $output .= ' </head>';
$output .= ' <body style="background-color: #fff; color: #000;">'; $output .= ' <body style="background-color: #fff; color: #000;">';
...@@ -406,6 +407,7 @@ function theme_maintenance_page($content, $messages = TRUE, $partial = FALSE) { ...@@ -406,6 +407,7 @@ function theme_maintenance_page($content, $messages = TRUE, $partial = FALSE) {
$output .= ' <title>'. strip_tags(drupal_get_title()) .'</title>'; $output .= ' <title>'. strip_tags(drupal_get_title()) .'</title>';
$output .= drupal_get_html_head(); $output .= drupal_get_html_head();
$output .= drupal_get_css(); $output .= drupal_get_css();
$output .= drupal_get_js();
$output .= '</head>'; $output .= '</head>';
$output .= '<body>'; $output .= '<body>';
$output .= '<h1>' . drupal_get_title() . '</h1>'; $output .= '<h1>' . drupal_get_title() . '</h1>';
...@@ -435,6 +437,7 @@ function theme_install_page($content) { ...@@ -435,6 +437,7 @@ function theme_install_page($content) {
$output .= ' <title>'. strip_tags(drupal_get_title()) .'</title>'; $output .= ' <title>'. strip_tags(drupal_get_title()) .'</title>';
$output .= drupal_get_html_head(); $output .= drupal_get_html_head();
$output .= drupal_get_css(); $output .= drupal_get_css();
$output .= drupal_get_js();
$output .= '</head>'; $output .= '</head>';
$output .= '<body>'; $output .= '<body>';
$output .= '<h1>' . drupal_get_title() . '</h1>'; $output .= '<h1>' . drupal_get_title() . '</h1>';
...@@ -920,7 +923,7 @@ function theme_feed_icon($url) { ...@@ -920,7 +923,7 @@ function theme_feed_icon($url) {
*/ */
function theme_closure($main = 0) { function theme_closure($main = 0) {
$footer = module_invoke_all('footer', $main); $footer = module_invoke_all('footer', $main);
return implode("\n", $footer); return implode("\n", $footer) . drupal_get_js('footer');
} }
/** /**
......
...@@ -21,6 +21,19 @@ if (isJsEnabled()) { ...@@ -21,6 +21,19 @@ if (isJsEnabled()) {
document.documentElement.className = 'js'; 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() * Make IE's XMLHTTP object accessible through XMLHttpRequest()
*/ */
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<title><?php print $head_title ?></title> <title><?php print $head_title ?></title>
<?php print $head ?> <?php print $head ?>
<?php print $styles ?> <?php print $styles ?>
<?php print $scripts ?>
<script type="text/javascript"><?php /* Needed to avoid Flash of Unstyle Content in IE */ ?> </script> <script type="text/javascript"><?php /* Needed to avoid Flash of Unstyle Content in IE */ ?> </script>
</head> </head>
......
...@@ -38,6 +38,7 @@ function chameleon_page($content) { ...@@ -38,6 +38,7 @@ function chameleon_page($content) {
$output .= " <title>". ($title ? strip_tags($title) ." | ". variable_get("site_name", "drupal") : variable_get("site_name", "drupal") ." | ". variable_get("site_slogan", "")) ."</title>\n"; $output .= " <title>". ($title ? strip_tags($title) ." | ". variable_get("site_name", "drupal") : variable_get("site_name", "drupal") ." | ". variable_get("site_slogan", "")) ."</title>\n";
$output .= drupal_get_html_head(); $output .= drupal_get_html_head();
$output .= drupal_get_css(); $output .= drupal_get_css();
$output .= drupal_get_js();
$output .= "</head>"; $output .= "</head>";
$output .= "<body>\n"; $output .= "<body>\n";
$output .= " <div id=\"header\">"; $output .= " <div id=\"header\">";
......
...@@ -214,6 +214,7 @@ function phptemplate_page($content) { ...@@ -214,6 +214,7 @@ function phptemplate_page($content) {
'site_slogan' => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''), 'site_slogan' => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''),
'css' => drupal_add_css(), 'css' => drupal_add_css(),
'styles' => drupal_get_css(), 'styles' => drupal_get_css(),
'scripts' => drupal_get_js(),
'tabs' => theme('menu_local_tasks'), 'tabs' => theme('menu_local_tasks'),
'title' => drupal_get_title() 'title' => drupal_get_title()
); );
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<meta http-equiv="Content-Style-Type" content="text/css" /> <meta http-equiv="Content-Style-Type" content="text/css" />
<?php print $head ?> <?php print $head ?>
<?php print $styles ?> <?php print $styles ?>
<?php print $scripts ?>
</head> </head>
<body bgcolor="#ffffff"> <body bgcolor="#ffffff">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment