- Patch #769226 by Owen Barton, sun, effulgentsia, alanburke, bleen18, mfer: optimize JS/CSS aggregation for front-end performance and DX.

merge-requests/26/head
Dries Buytaert 2010-10-05 19:59:10 +00:00
parent 0614a78538
commit facc581013
12 changed files with 236 additions and 90 deletions

View File

@ -565,7 +565,7 @@ function ajax_process_form($element, &$form_state) {
// Attach JavaScript settings to the element.
if (isset($element['#ajax']['event'])) {
$element['#attached']['library'][] = array('system', 'form');
$element['#attached']['js']['misc/ajax.js'] = array('weight' => JS_LIBRARY + 2);
$element['#attached']['js']['misc/ajax.js'] = array('group' => JS_LIBRARY, 'weight' => 2);
$settings = $element['#ajax'];

View File

@ -56,33 +56,33 @@ define('SAVED_UPDATED', 2);
define('SAVED_DELETED', 3);
/**
* The default weight of system CSS files added to the page.
* The default group for system CSS files added to the page.
*/
define('CSS_SYSTEM', -100);
/**
* The default weight of CSS files added to the page.
* The default group for module CSS files added to the page.
*/
define('CSS_DEFAULT', 0);
/**
* The default weight of theme CSS files added to the page.
* The default group for theme CSS files added to the page.
*/
define('CSS_THEME', 100);
/**
* The weight of JavaScript libraries, settings or jQuery plugins being
* added to the page.
* The default group for JavaScript libraries, settings or jQuery plugins added
* to the page.
*/
define('JS_LIBRARY', -100);
/**
* The default weight of JavaScript being added to the page.
* The default group for module JavaScript code added to the page.
*/
define('JS_DEFAULT', 0);
/**
* The weight of theme JavaScript code being added to the page.
* The default group for theme JavaScript code added to the page.
*/
define('JS_THEME', 100);
@ -2734,19 +2734,50 @@ function drupal_add_html_head_link($attributes, $header = FALSE) {
* 'modules/node/node.css' is 'node.css'. If the external library "node.js"
* ships with a 'node.css', then a different, unique basename would be
* 'node.js.css'.
* - 'weight': The weight of the stylesheet specifies the order in which the
* CSS will appear when presented on the page. Available constants are:
* - 'group': A number identifying the group in which to add the stylesheet.
* Available constants are:
* - CSS_SYSTEM: Any system-layer CSS.
* - CSS_DEFAULT: Any module-layer CSS.
* - CSS_THEME: Any theme-layer CSS.
* If you need to embed a CSS file before any other module's stylesheets,
* for example, you would use CSS_DEFAULT - 1. Note that inline CSS is
* simply appended to the end of the specified scope (region), so they
* always come last.
* The group number serves as a weight: the markup for loading a stylesheet
* within a lower weight group is output to the page before the markup for
* loading a stylesheet within a higher weight group, so CSS within higher
* weight groups take precendence over CSS within lower weight groups.
* - 'every_page': For optimal front-end performance when aggregation is
* enabled, this should be set to TRUE if the stylesheet is present on every
* page of the website for users for whom it is present at all. This
* defaults to FALSE. It is set to TRUE for stylesheets added via module and
* theme .info files. Modules that add stylesheets within hook_init()
* implementations, or from other code that ensures that the stylesheet is
* added to all website pages, should also set this flag to TRUE. All
* stylesheets within the same group that have the 'every_page' flag set to
* TRUE and do not have 'preprocess' set to FALSE are aggregated together
* into a single aggregate file, and that aggregate file can be reused
* across a user's entire site visit, leading to faster navigation between
* pages. However, stylesheets that are only needed on pages less frequently
* visited, can be added by code that only runs for those particular pages,
* and that code should not set the 'every_page' flag. This minimizes the
* size of the aggregate file that the user needs to download when first
* visiting the website. Stylesheets without the 'every_page' flag are
* aggregated into a separate aggregate file. This other aggregate file is
* likely to change from page to page, and each new aggregate file needs to
* be downloaded when first encountered, so it should be kept relatively
* small by ensuring that most commonly needed stylesheets are added to
* every page.
* - 'weight': The weight of the stylesheet specifies the order in which the
* CSS will appear relative to other stylesheets with the same group and
* 'every_page' flag. The exact ordering of stylesheets is as follows:
* - First by group.
* - Then by the 'every_page' flag, with TRUE coming before FALSE.
* - Then by weight.
* - Then by the order in which the CSS was added. For example, all else
* being the same, a stylesheet added by a call to drupal_add_css() that
* happened later in the page request gets added to the page after one for
* which drupal_add_css() happened earlier in the page request.
* - 'media': The media type for the stylesheet, e.g., all, print, screen.
* Defaults to 'all'.
* - 'preprocess': If TRUE and CSS aggregation/compression is enabled, the
* styles will be aggregated and compressed. Defaults to FALSE.
* styles will be aggregated and compressed. Defaults to TRUE.
* - 'browsers': An array containing information specifying which browsers
* should load the CSS item. See drupal_pre_render_conditional_comments()
* for details.
@ -2772,9 +2803,11 @@ function drupal_add_css($data = NULL, $options = NULL) {
if (isset($data)) {
$options += array(
'type' => 'file',
'weight' => CSS_DEFAULT,
'group' => CSS_DEFAULT,
'weight' => 0,
'every_page' => FALSE,
'media' => 'all',
'preprocess' => FALSE,
'preprocess' => TRUE,
'data' => $data,
'browsers' => array(),
);
@ -2783,6 +2816,11 @@ function drupal_add_css($data = NULL, $options = NULL) {
'!IE' => TRUE,
);
// Files with a query string cannot be preprocessed.
if ($options['type'] === 'file' && $options['preprocess'] && strpos($options['data'], '?') !== FALSE) {
$options['preprocess'] = FALSE;
}
// Always add a tiny value to the weight, to conserve the insertion order.
$options['weight'] += count($css) / 1000;
@ -2839,8 +2877,8 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE) {
drupal_alter('css', $css);
}
// Sort CSS items according to their weights.
uasort($css, 'drupal_sort_weight');
// Sort CSS items, so that they appear in the correct order.
uasort($css, 'drupal_sort_css_js');
// Remove the overridden CSS files. Later CSS files override former ones.
$previous_item = array();
@ -2870,6 +2908,46 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE) {
return drupal_render($styles);
}
/**
* Function used by uasort to sort the array structures returned by drupal_add_css() and drupal_add_js().
*
* This sort order helps optimize front-end performance while providing modules
* and themes with the necessary control for ordering the CSS and JavaScript
* appearing on a page.
*/
function drupal_sort_css_js($a, $b) {
// First order by group, so that, for example, all items in the CSS_SYSTEM
// group appear before items in the CSS_DEFAULT_GROUP, which appear before
// all items in the CSS_THEME group. Modules may create additional groups by
// defining their own constants.
if ($a['group'] < $b['group']) {
return -1;
}
elseif ($a['group'] > $b['group']) {
return 1;
}
// Within a group, order all infrequently needed, page-specific files after
// common files needed throughout the website. Separating this way allows for
// the aggregate file generated for all of the common files to be reused
// across a site visit without being cut by a page using a less common file.
elseif ($a['every_page'] && !$b['every_page']) {
return -1;
}
elseif (!$a['every_page'] && $b['every_page']) {
return 1;
}
// Finally, order by weight.
elseif ($a['weight'] < $b['weight']) {
return -1;
}
elseif ($a['weight'] > $b['weight']) {
return 1;
}
else {
return 0;
}
}
/**
* Default callback to group CSS items.
*
@ -2933,7 +3011,10 @@ function drupal_group_css($css) {
switch ($item['type']) {
case 'file':
// Group file items if their 'preprocess' flag is TRUE.
$group_keys = $item['preprocess'] ? array($item['type'], $item['media'], $item['browsers']) : FALSE;
// Help ensure maximum reuse of aggregate files by only grouping
// together items that share the same 'group' value and 'every_page'
// flag. See drupal_add_css() for details about that.
$group_keys = $item['preprocess'] ? array($item['type'], $item['group'], $item['every_page'], $item['media'], $item['browsers']) : FALSE;
break;
case 'inline':
// Always group inline items.
@ -3683,27 +3764,63 @@ function drupal_region_class($region) {
* - scope: The location in which you want to place the script. Possible
* values are 'header' or 'footer'. If your theme implements different
* regions, you can also use these. Defaults to 'header'.
* - weight: A number defining the order in which the JavaScript is added to
* the page. In some cases, the order in which the JavaScript is presented
* on the page is very important. jQuery, for example, must be added to
* the page before any jQuery code is run, so jquery.js uses a weight of
* JS_LIBRARY - 20, jquery.once.js (a library drupal.js depends on) uses
* a weight of JS_LIBRARY - 19, drupal.js uses a weight of JS_LIBRARY - 1,
* and all following scripts depending on jQuery and Drupal behaviors are
* simply added using the default weight of JS_DEFAULT. Available constants
* are:
* - 'group': A number identifying the group in which to add the JavaScript.
* Available constants are:
* - JS_LIBRARY: Any libraries, settings, or jQuery plugins.
* - JS_DEFAULT: Any module-layer JavaScript.
* - JS_THEME: Any theme-layer JavaScript.
* If you need to invoke a JavaScript file before any other module's
* JavaScript, for example, you would use JS_DEFAULT - 1.
* The group number serves as a weight: JavaScript within a lower weight
* group is presented on the page before JavaScript within a higher weight
* group.
* - 'every_page': For optimal front-end performance when aggregation is
* enabled, this should be set to TRUE if the JavaScript is present on every
* page of the website for users for whom it is present at all. This
* defaults to FALSE. It is set to TRUE for JavaScript files that are added
* via module and theme .info files. Modules that add JavaScript within
* hook_init() implementations, or from other code that ensures that the
* JavaScript is added to all website pages, should also set this flag to
* TRUE. All JavaScript files within the same group and that have the
* 'every_page' flag set to TRUE and do not have 'preprocess' set to FALSE
* are aggregated together into a single aggregate file, and that aggregate
* file can be reused across a user's entire site visit, leading to faster
* navigation between pages. However, JavaScript that is only needed on
* pages less frequently visited, can be added by code that only runs for
* those particular pages, and that code should not set the 'every_page'
* flag. This minimizes the size of the aggregate file that the user needs
* to download when first visiting the website. JavaScript without the
* 'every_page' flag is aggregated into a separate aggregate file. This
* other aggregate file is likely to change from page to page, and each new
* aggregate file needs to be downloaded when first encountered, so it
* should be kept relatively small by ensuring that most commonly needed
* JavaScript is added to every page.
* - weight: A number defining the order in which the JavaScript is added to
* the page relative to other JavaScript with the same 'scope', 'group',
* and 'every_page' value. In some cases, the order in which the JavaScript
* is presented on the page is very important. jQuery, for example, must be
* added to the page before any jQuery code is run, so jquery.js uses the
* JS_LIBRARY group and a weight of -20, jquery.once.js (a library drupal.js
* depends on) uses the JS_LIBRARY group and a weight of -19, drupal.js uses
* the JS_LIBRARY group and a weight of -1, other libraries use the
* JS_LIBRARY group and a weight of 0 or higher, and all other scripts use
* one of the other group constants. The exact ordering of JavaScript is as
* follows:
* - First by scope, with 'header' first, 'footer' last, and any other
* scopes provided by a custom theme coming in between, as determined by
* the theme.
* - Then by group.
* - Then by the 'every_page' flag, with TRUE coming before FALSE.
* - Then by weight.
* - Then by the order in which the JavaScript was added. For example, all
* else being the same, JavaScript added by a call to drupal_add_js() that
* happened later in the page request gets added to the page after one for
* which drupal_add_js() happened earlier in the page request.
* - defer: If set to TRUE, the defer attribute is set on the &lt;script&gt;
* tag. Defaults to FALSE.
* - cache: If set to FALSE, the JavaScript file is loaded anew on every page
* call; in other words, it is not cached. Used only when 'type' references
* a JavaScript file. Defaults to TRUE.
* - preprocess: If TRUE and JavaScript aggregation is enabled, the script
* file will be aggregated. Defaults to FALSE.
* file will be aggregated. Defaults to TRUE.
*
* @return
* The current array of JavaScript files, settings, and in-line code,
@ -3744,21 +3861,25 @@ function drupal_add_js($data = NULL, $options = NULL) {
),
'type' => 'setting',
'scope' => 'header',
'weight' => JS_LIBRARY,
'group' => JS_LIBRARY,
'every_page' => TRUE,
'weight' => 0,
),
'misc/drupal.js' => array(
'data' => 'misc/drupal.js',
'type' => 'file',
'scope' => 'header',
'weight' => JS_LIBRARY - 1,
'group' => JS_LIBRARY,
'every_page' => TRUE,
'weight' => -1,
'preprocess' => TRUE,
'cache' => TRUE,
'defer' => FALSE,
'preprocess' => TRUE,
),
);
// Register all required libraries.
drupal_add_library('system', 'jquery');
drupal_add_library('system', 'once');
drupal_add_library('system', 'jquery', TRUE);
drupal_add_library('system', 'once', TRUE);
}
switch ($options['type']) {
@ -3792,11 +3913,13 @@ function drupal_add_js($data = NULL, $options = NULL) {
function drupal_js_defaults($data = NULL) {
return array(
'type' => 'file',
'weight' => JS_DEFAULT,
'group' => JS_DEFAULT,
'every_page' => FALSE,
'weight' => 0,
'scope' => 'header',
'cache' => TRUE,
'defer' => FALSE,
'preprocess' => FALSE,
'preprocess' => TRUE,
'version' => NULL,
'data' => $data,
);
@ -3880,8 +4003,8 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
// third-party code might require the use of a different query string.
$js_version_string = variable_get('drupal_js_version_query_string', 'v=');
// Sort the JavaScript by weight so that it appears in the correct order.
uasort($items, 'drupal_sort_weight');
// Sort the JavaScript so that it appears in the correct order.
uasort($items, 'drupal_sort_css_js');
// Provide the page with information about the individual JavaScript files
// used, information not otherwise available when aggregation is enabled.
@ -3942,8 +4065,13 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
}
else {
// By increasing the index for each aggregated file, we maintain
// the relative ordering of JS by weight.
$key = 'aggregate' . $index;
// the relative ordering of JS by weight. We also set the key such
// that groups are split by items sharing the same 'group' value and
// 'every_page' flag. While this potentially results in more aggregate
// files, it helps make each one more reusable across a site visit,
// leading to better front-end performance of a website as a whole.
// See drupal_add_js() for details.
$key = 'aggregate_' . $item['group'] . '_' . $item['every_page'] . '_' . $index;
$processed[$key] = '';
$files[$key][$item['data']] = $item;
}
@ -4007,9 +4135,9 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
*
* @param $elements
* The structured array describing the data being rendered.
* @param $weight
* The default weight of JavaScript and CSS being added. This is only applied
* to the stylesheets and JavaScript items that don't have an explicit weight
* @param $group
* The default group of JavaScript and CSS being added. This is only applied
* to the stylesheets and JavaScript items that don't have an explicit group
* assigned to them.
* @param $dependency_check
* When TRUE, will exit if a given library's dependencies are missing. When
@ -4025,7 +4153,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
* @see drupal_add_css()
* @see drupal_render()
*/
function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_check = FALSE) {
function drupal_process_attached($elements, $group = JS_DEFAULT, $dependency_check = FALSE, $every_page = NULL) {
// Add defaults to the special attached structures that should be processed differently.
$elements['#attached'] += array(
'library' => array(),
@ -4036,7 +4164,7 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch
// Add the libraries first.
$success = TRUE;
foreach ($elements['#attached']['library'] as $library) {
if (drupal_add_library($library[0], $library[1]) === FALSE) {
if (drupal_add_library($library[0], $library[1], $every_page) === FALSE) {
$success = FALSE;
// Exit if the dependency is missing.
if ($dependency_check) {
@ -4063,9 +4191,13 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch
$data = $options['data'];
unset($options['data']);
}
// Apply the default weight if the weight isn't explicitly given.
if (!isset($options['weight'])) {
$options['weight'] = $weight;
// Apply the default group if it isn't explicitly given.
if (!isset($options['group'])) {
$options['group'] = $group;
}
// Set the every_page flag if one was passed.
if (isset($every_page)) {
$options['every_page'] = $every_page;
}
call_user_func('drupal_add_' . $type, $data, $options);
}
@ -4212,7 +4344,7 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch
* @see form_example_states_form()
*/
function drupal_process_states(&$elements) {
$elements['#attached']['js']['misc/states.js'] = array('weight' => JS_LIBRARY + 1);
$elements['#attached']['js']['misc/states.js'] = array('group' => JS_LIBRARY, 'weight' => 1);
$elements['#attached']['js'][] = array(
'type' => 'setting',
'data' => array('states' => array('#' . $elements['#id'] => $elements['#states'])),
@ -4241,7 +4373,7 @@ function drupal_process_states(&$elements) {
* @see hook_library()
* @see hook_library_alter()
*/
function drupal_add_library($module, $name) {
function drupal_add_library($module, $name, $every_page = NULL) {
$added = &drupal_static(__FUNCTION__, array());
// Only process the library if it exists and it was not added already.
@ -4253,7 +4385,7 @@ function drupal_add_library($module, $name) {
'js' => $library['js'],
'css' => $library['css'],
);
$added[$module][$name] = drupal_process_attached($elements, JS_LIBRARY, TRUE);
$added[$module][$name] = drupal_process_attached($elements, JS_LIBRARY, TRUE, $every_page);
}
else {
// Requested library does not exist.
@ -4434,8 +4566,8 @@ function drupal_add_tabledrag($table_id, $action, $relationship, $group, $subgro
// Add the table drag JavaScript to the page before the module JavaScript
// to ensure that table drag behaviors are registered before any module
// uses it.
drupal_add_js('misc/jquery.cookie.js', array('weight' => JS_DEFAULT - 2));
drupal_add_js('misc/tabledrag.js', array('weight' => JS_DEFAULT - 1));
drupal_add_js('misc/jquery.cookie.js', array('weight' => -2));
drupal_add_js('misc/tabledrag.js', array('weight' => -1));
$js_added = TRUE;
}

View File

@ -3061,7 +3061,7 @@ function form_process_fieldset(&$element, &$form_state) {
}
// Contains form element summary functionalities.
$element['#attached']['js']['misc/form.js'] = array('weight' => JS_LIBRARY + 1);
$element['#attached']['js']['misc/form.js'] = array('group' => JS_LIBRARY, 'weight' => 1);
// The .form-wrapper class is required for #states to treat fieldsets like
// containers.

View File

@ -173,7 +173,7 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
// And now add the stylesheets properly
foreach ($final_stylesheets as $media => $stylesheets) {
foreach ($stylesheets as $stylesheet) {
drupal_add_css($stylesheet, array('weight' => CSS_THEME, 'media' => $media, 'preprocess' => TRUE));
drupal_add_css($stylesheet, array('group' => CSS_THEME, 'every_page' => TRUE, 'media' => $media));
}
}
@ -198,7 +198,7 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
// Add scripts used by this theme.
foreach ($final_scripts as $script) {
drupal_add_js($script, array('weight' => JS_THEME, 'preprocess' => TRUE));
drupal_add_js($script, array('group' => JS_THEME, 'every_page' => TRUE));
}
$theme_engine = NULL;

View File

@ -247,7 +247,7 @@ function theme_color_scheme_form($variables) {
$preview_js_path = isset($info['preview_js']) ? $path . $info['preview_js'] : drupal_get_path('module', 'color') . '/' . 'preview.js';
// Add the JS at a weight below color.js.
drupal_add_js($preview_js_path, array('weight' => JS_DEFAULT - 1));
drupal_add_js($preview_js_path, array('weight' => -1));
$output = '';
$output .= '<div class="color-form clearfix">';

View File

@ -880,7 +880,7 @@ function locale_library_alter(&$libraries, $module) {
global $language;
if ($module == 'system' && isset($libraries['system']['ui.datepicker'])) {
$datepicker = drupal_get_path('module', 'locale') . '/locale.datepicker.js';
$libraries['system']['ui.datepicker']['js'][$datepicker] = array('weight' => JS_THEME);
$libraries['system']['ui.datepicker']['js'][$datepicker] = array('group' => JS_THEME);
$libraries['system']['ui.datepicker']['js'][] = array(
'data' => array(
'jqueryuidatepicker' => array(

View File

@ -655,7 +655,7 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
function testRenderInlinePreprocess() {
$css = 'body { padding: 0px; }';
$css_preprocessed = '<style type="text/css" media="all">' . drupal_load_stylesheet_content($css, TRUE) . '</style>';
drupal_add_css($css, array('type' => 'inline', 'preprocess' => TRUE));
drupal_add_css($css, array('type' => 'inline'));
$styles = drupal_get_css();
$this->assertEqual(trim($styles), $css_preprocessed, t('Rendering preprocessed inline CSS adds it to the page.'));
}
@ -665,7 +665,7 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
*/
function testRenderInlineNoPreprocess() {
$css = 'body { padding: 0px; }';
drupal_add_css($css, array('type' => 'inline'));
drupal_add_css($css, array('type' => 'inline', 'preprocess' => FALSE));
$styles = drupal_get_css();
$this->assertTrue(strpos($styles, $css) > 0, t('Rendering non-preprocessed inline CSS adds it to the page.'));
}
@ -675,7 +675,9 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
*/
function testRenderInlineFullPage() {
$css = 'body { font-size: 254px; }';
$expected = $css;
// Inline CSS is minified unless 'preprocess' => FALSE is passed as a
// drupal_add_css() option.
$expected = 'body{font-size:254px;}';
// Create a node, using the PHP filter that tests drupal_add_css().
$php_format_id = db_query_range('SELECT format FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'PHP code'))->fetchField();
@ -706,9 +708,9 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css');
// A few system CSS files, ordered in a strange way.
$system_path = drupal_get_path('module', 'system');
drupal_add_css($system_path . '/system.menus.css', array('weight' => CSS_SYSTEM));
drupal_add_css($system_path . '/system.base.css', array('weight' => CSS_SYSTEM - 10));
drupal_add_css($system_path . '/system.theme.css', array('weight' => CSS_SYSTEM));
drupal_add_css($system_path . '/system.menus.css', array('group' => CSS_SYSTEM));
drupal_add_css($system_path . '/system.base.css', array('group' => CSS_SYSTEM, 'weight' => -10));
drupal_add_css($system_path . '/system.theme.css', array('group' => CSS_SYSTEM));
$expected = array(
$system_path . '/system.base.css',
@ -1241,12 +1243,20 @@ class JavaScriptTestCase extends DrupalWebTestCase {
$this->assertFalse($javascript['misc/collapse.js']['preprocess'], t('Setting cache to FALSE sets proprocess to FALSE when adding JavaScript.'));
}
/**
* Test adding a JavaScript file with a different group.
*/
function testDifferentGroup() {
$javascript = drupal_add_js('misc/collapse.js', array('group' => JS_THEME));
$this->assertEqual($javascript['misc/collapse.js']['group'], JS_THEME, t('Adding a JavaScript file with a different group caches the given group.'));
}
/**
* Test adding a JavaScript file with a different weight.
*/
function testDifferentWeight() {
$javascript = drupal_add_js('misc/collapse.js', array('weight' => JS_THEME));
$this->assertEqual($javascript['misc/collapse.js']['weight'], JS_THEME, t('Adding a JavaScript file with a different weight caches the given weight.'));
$javascript = drupal_add_js('misc/collapse.js', array('weight' => 2));
$this->assertEqual($javascript['misc/collapse.js']['weight'], 2, t('Adding a JavaScript file with a different weight caches the given weight.'));
}
/**
@ -1295,7 +1305,10 @@ class JavaScriptTestCase extends DrupalWebTestCase {
* Test rendering the JavaScript with a file's weight above jQuery's.
*/
function testRenderDifferentWeight() {
drupal_add_js('misc/collapse.js', array('weight' => JS_LIBRARY - 21));
// JavaScript files are sorted first by group, then by the 'every_page'
// flag, then by weight (see drupal_sort_css_js()), so to test the effect of
// weight, we need the other two options to be the same.
drupal_add_js('misc/collapse.js', array('group' => JS_LIBRARY, 'every_page' => TRUE, 'weight' => -21));
$javascript = drupal_get_js();
$this->assertTrue(strpos($javascript, 'misc/collapse.js') < strpos($javascript, 'misc/jquery.js'), t('Rendering a JavaScript file above jQuery.'));
}
@ -1308,7 +1321,7 @@ class JavaScriptTestCase extends DrupalWebTestCase {
function testAlter() {
// Add both tableselect.js and simpletest.js, with a larger weight on SimpleTest.
drupal_add_js('misc/tableselect.js');
drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js', array('weight' => JS_THEME));
drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js', array('weight' => 9999));
// Render the JavaScript, testing if simpletest.js was altered to be before
// tableselect.js. See simpletest_js_alter() to see where this alteration

View File

@ -1066,7 +1066,7 @@ function system_library() {
'website' => 'http://jquery.com',
'version' => '1.4.2',
'js' => array(
'misc/jquery.js' => array('weight' => JS_LIBRARY - 20, 'preprocess' => TRUE),
'misc/jquery.js' => array('group' => JS_LIBRARY, 'weight' => -20),
),
);
@ -1076,7 +1076,7 @@ function system_library() {
'website' => 'http://plugins.jquery.com/project/once',
'version' => '1.2',
'js' => array(
'misc/jquery.once.js' => array('weight' => JS_LIBRARY - 19, 'preprocess' => TRUE),
'misc/jquery.once.js' => array('group' => JS_LIBRARY, 'weight' => -19),
),
);
@ -1142,7 +1142,7 @@ function system_library() {
'website' => 'http://jqueryui.com',
'version' => '1.8',
'js' => array(
'misc/ui/jquery.ui.core.min.js' => array('weight' => JS_LIBRARY - 11),
'misc/ui/jquery.ui.core.min.js' => array('group' => JS_LIBRARY, 'weight' => -11),
),
'css' => array(
'misc/ui/jquery.ui.core.css' => array(),
@ -1359,7 +1359,7 @@ function system_library() {
'website' => 'http://docs.jquery.com/UI/Widget',
'version' => '1.8',
'js' => array(
'misc/ui/jquery.ui.widget.min.js' => array('weight' => JS_LIBRARY - 10),
'misc/ui/jquery.ui.widget.min.js' => array('group' => JS_LIBRARY, 'weight' => -10),
),
'dependencies' => array(
array('system', 'ui'),
@ -1370,7 +1370,7 @@ function system_library() {
'website' => 'http://jqueryui.com/demos/effect/',
'version' => '1.8',
'js' => array(
'misc/ui/jquery.effects.core.min.js' => array('weight' => JS_LIBRARY - 9),
'misc/ui/jquery.effects.core.min.js' => array('group' => JS_LIBRARY, 'weight' => -9),
),
);
$libraries['effects.blind'] = array(
@ -1819,14 +1819,15 @@ function _system_filetransfer_backend_form_common() {
*/
function system_init() {
$path = drupal_get_path('module', 'system');
// Add the CSS for this module.
drupal_add_css($path . '/system.base.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
// 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));
if (arg(0) == 'admin' || (variable_get('node_admin_theme', '0') && arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit' || arg(2) == 'delete'))) {
drupal_add_css($path . '/system.admin.css', array('weight' => CSS_SYSTEM));
drupal_add_css($path . '/system.admin.css', array('group' => CSS_SYSTEM));
}
drupal_add_css($path . '/system.menus.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
drupal_add_css($path . '/system.messages.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
drupal_add_css($path . '/system.theme.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
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));
// Ignore slave database servers for this request.
//
@ -1862,13 +1863,13 @@ function system_add_module_assets() {
if (!empty($info['stylesheets'])) {
foreach ($info['stylesheets'] as $media => $stylesheets) {
foreach ($stylesheets as $stylesheet) {
drupal_add_css($stylesheet, array('media' => $media, 'preprocess' => TRUE));
drupal_add_css($stylesheet, array('every_page' => TRUE, 'media' => $media));
}
}
}
if (!empty($info['scripts'])) {
foreach ($info['scripts'] as $script) {
drupal_add_js($script, array('preprocess' => TRUE));
drupal_add_js($script, array('every_page' => TRUE));
}
}
}

View File

@ -188,7 +188,7 @@ function toolbar_view() {
'#attached'=> array(
'js' => array(
$module_path . '/toolbar.js',
array('data' => 'misc/jquery.cookie.js', 'weight' => JS_LIBRARY + 2),
array('data' => 'misc/jquery.cookie.js', 'group' => JS_LIBRARY, 'weight' => 2),
array(
'data' => array('tableHeaderOffset' => 'Drupal.toolbar.height'),
'type' => 'setting'

View File

@ -23,8 +23,8 @@ function bartik_preprocess_html(&$variables) {
}
// Add conditional stylesheets for IE
drupal_add_css(path_to_theme() . '/css/ie.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 7', '!IE' => FALSE)));
drupal_add_css(path_to_theme() . '/css/ie6.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'IE 6', '!IE' => FALSE)));
drupal_add_css(path_to_theme() . '/css/ie.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 7', '!IE' => FALSE), 'preprocess' => FALSE));
drupal_add_css(path_to_theme() . '/css/ie6.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'IE 6', '!IE' => FALSE), 'preprocess' => FALSE));
}
/**

View File

@ -42,7 +42,7 @@ function garland_preprocess_html(&$vars) {
$vars['classes_array'][] = 'fluid-width';
}
// Add conditional CSS for IE6.
drupal_add_css(path_to_theme() . '/fix-ie.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE)));
drupal_add_css(path_to_theme() . '/fix-ie.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE), 'preprocess' => FALSE));
}
/**

View File

@ -18,9 +18,9 @@ function seven_preprocess_maintenance_page(&$vars) {
*/
function seven_preprocess_html(&$vars) {
// Add conditional CSS for IE8 and below.
drupal_add_css(path_to_theme() . '/ie.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE)));
drupal_add_css(path_to_theme() . '/ie.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE), 'preprocess' => FALSE));
// Add conditional CSS for IE6.
drupal_add_css(path_to_theme() . '/ie6.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE)));
drupal_add_css(path_to_theme() . '/ie6.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE), 'preprocess' => FALSE));
}
/**