Index: update.php =================================================================== RCS file: /cvs/drupal/drupal/update.php,v retrieving revision 1.211.2.2 diff -u -F^f -r1.211.2.2 update.php --- update.php 8 Apr 2007 00:54:04 -0000 1.211.2.2 +++ update.php 26 Jan 2008 22:32:42 -0000 @@ -405,8 +405,8 @@ function update_update_page() { function update_progress_page() { // Prevent browser from using cached drupal.js or update.js - drupal_add_js('misc/progress.js', 'core', 'header', FALSE, TRUE); - drupal_add_js('misc/update.js', 'core', 'header', FALSE, TRUE); + drupal_add_js('misc/progress.js', 'core', 'header', FALSE, FALSE); + drupal_add_js('misc/update.js', 'core', 'header', FALSE, FALSE); drupal_set_title('Updating'); $output = '
'; @@ -448,6 +448,7 @@ function update_do_updates() { cache_clear_all('*', 'cache_menu', TRUE); cache_clear_all('*', 'cache_filter', TRUE); drupal_clear_css_cache(); + drupal_clear_js_cache(); } return array($percentage, isset($update['module']) ? 'Updating '. $update['module'] .' module' : 'Updating complete'); Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.611.2.15 diff -u -F^f -r1.611.2.15 common.inc --- includes/common.inc 22 Jan 2008 09:36:49 -0000 1.611.2.15 +++ includes/common.inc 26 Jan 2008 22:32:43 -0000 @@ -1378,6 +1378,57 @@ function base_path() { return $GLOBALS['base_path']; } + +/** + * Returns a rewritten file URL. Allows you to serve files from different + * servers than the server on which Drupal is hosted. + * + * @param $file_path + * Path to a file, relative to the root directory. E.g.: "misc/jquery.js". + * @param $absolute_url + * Whether to generate an absolute URL or not. + * @return + * A valid file URL. + */ +function file_url($file_path, $absolute_url = FALSE) { + static $modules; + $file_url = FALSE; + + if (!isset($modules)) { + $modules = array(); + foreach (module_implements('file_server') as $module) { + $modules[] = array( + 'module' => $module, + 'weight' => variable_get("file_server_{$module}_weight", 0), + ); + } + + // Sort file server types by weight. + uasort($modules, create_function('$a, $b', 'return $a["weight"] > $b["weight"];')); + } + + // Try the first preferred file server to check if it can serve the file. + // Then try the second, and so on. + foreach ($modules as $module) { + $file_url = module_invoke($module['module'], 'file_server', 'url', $file_path, $absolute_url); + + // If the URL rewriting function sucesfully generated a URL, we can stop + // trying to find a server that can serve the file. + if ($file_url) { + break; + } + } + + // Always fall back to Drupal's default file server, to guarantee a working + // file URL. + if (!$file_url) { + $prefix = ($absolute_url) ? $GLOBALS['base_url'] .'/' : base_path(); + $file_url = $prefix . $file_path; + } + + return $file_url; +} + /** * Provide a substitute clone() function for PHP4. */ @@ -1474,15 +1525,15 @@ function drupal_get_css($css = NULL) { // If a CSS file is not to be preprocessed and it's a module CSS file, it needs to *always* appear at the *top*, // regardless of whether preprocessing is on or off. if (!$preprocess && $type == 'module') { - $no_module_preprocess .= '' ."\n"; + $no_module_preprocess .= '' ."\n"; } // If a CSS file is not to be preprocessed and it's a theme CSS file, it needs to *always* appear at the *bottom*, // regardless of whether preprocessing is on or off. else if (!$preprocess && $type == 'theme') { - $no_theme_preprocess .= '' ."\n"; + $no_theme_preprocess .= '' ."\n"; } else { - $output .= '' ."\n"; + $output .= '' ."\n"; } } } @@ -1491,7 +1542,7 @@ function drupal_get_css($css = NULL) { if ($is_writable && $preprocess_css) { $filename = md5(serialize($types)) .'.css'; $preprocess_file = drupal_build_css_cache($types, $filename); - $output .= ''. "\n"; + $output .= ''. "\n"; } } @@ -1607,24 +1658,26 @@ function drupal_clear_css_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. + * @param $preprocess + * (optional) Should this JS file be aggregated if this + * feature has been turned on under the performance section? * @return * If the first parameter is NULL, the JavaScript array that has been built so * far for $scope is returned. */ -function drupal_add_js($data = NULL, $type = 'module', $scope = 'header', $defer = FALSE, $cache = TRUE) { - if (!is_null($data)) { - _drupal_add_js('misc/jquery.js', 'core', 'header', FALSE, $cache); - _drupal_add_js('misc/drupal.js', 'core', 'header', FALSE, $cache); - } - return _drupal_add_js($data, $type, $scope, $defer, $cache); -} - -/** - * Helper function for drupal_add_js(). - */ -function _drupal_add_js($data, $type, $scope, $defer, $cache) { +function drupal_add_js($data = NULL, $type = 'module', $scope = 'footer', $defer = FALSE, $cache = TRUE, $preprocess = TRUE) { static $javascript = array(); + // Add jquery.js and drupal.js the first time a Javascript file is added. + if ($data && empty($javascript)) { + $javascript['footer'] = array( + 'core' => array( + 'misc/jquery.js' => array('cache' => TRUE, 'defer' => FALSE, 'preprocess' => TRUE), + 'misc/drupal.js' => array('cache' => TRUE, 'defer' => FALSE, 'preprocess' => TRUE), + ), + 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array(), + ); + } if (!isset($javascript[$scope])) { $javascript[$scope] = array('core' => array(), 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array()); } @@ -1633,7 +1686,7 @@ function _drupal_add_js($data, $type, $s $javascript[$scope][$type] = array(); } - if (!is_null($data)) { + if (isset($data)) { switch ($type) { case 'setting': $javascript[$scope][$type][] = $data; @@ -1642,7 +1695,8 @@ function _drupal_add_js($data, $type, $s $javascript[$scope][$type][] = array('code' => $data, 'defer' => $defer); break; default: - $javascript[$scope][$type][$data] = array('cache' => $cache, 'defer' => $defer); + // If cache is FALSE, don't preprocess the JS file. + $javascript[$scope][$type][$data] = array('cache' => $cache, 'defer' => $defer, 'preprocess' => (!$cache ? FALSE : $preprocess)); } } @@ -1665,13 +1719,25 @@ function _drupal_add_js($data, $type, $s * @return * All JavaScript code segments and includes for the scope as HTML tags. */ -function drupal_get_js($scope = 'header', $javascript = NULL) { - $output = ''; - if (is_null($javascript)) { +function drupal_get_js($scope = 'header', $javascript = NULL) { + if (!isset($javascript)) { $javascript = drupal_add_js(NULL, NULL, $scope); } + if (count($javascript) < 1) { + return ''; + } + + $output = ''; + $preprocessed = ''; + $no_preprocess = array('core' => '', 'module' => '', 'theme' => ''); + $files = array(); + $preprocess_js = variable_get('preprocess_js', FALSE); + $directory = file_directory_path(); + $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC); + foreach ($javascript as $type => $data) { + if (!$data) continue; switch ($type) { @@ -1684,16 +1750,74 @@ function drupal_get_js($scope = 'header' } break; default: + // If JS preprocessing is off, we still need to output the scripts. + // Additionally, go through any remaining scripts if JS preprocessing is on and output the non-cached ones. foreach ($data as $path => $info) { - $output .= '\n"; + if (!$info['preprocess'] || !$is_writable || !$preprocess_js) { + $no_preprocess[$type] .= '\n"; + } + else { + $files[$path] = $info; + } } } } - + + // Aggregate any remaining JS files that haven't already been output. + if ($is_writable && $preprocess_js && count($files) > 0) { + $filename = md5(serialize($files)) .'.js'; + $preprocess_file = drupal_build_js_cache($files, $filename); + $preprocessed .= ''. "\n"; + } + + // Keep the order of JS files consistent as some are preprocessed and others are not. + // Make sure any inline or JS setting variables appear last after libraries have loaded. + $output = $preprocessed . implode('', $no_preprocess) . $output; + return $output; } /** + * Aggregate JS files, putting them in the files directory. + * + * @param $files + * An array of JS files to aggregate into one file. + * @param $filename + * The name of the aggregate JS file. + * @return + * The name of the JS file. + */ +function drupal_build_js_cache($files, $filename) { + $contents = ''; + + // Create the js/ within the files folder. + $jspath = file_create_path('js'); + file_check_directory($jspath, FILE_CREATE_DIRECTORY); + + if (!file_exists($jspath .'/'. $filename)) { + // 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). ';'; + } + } + + // Create the JS file. + file_save_data($contents, $jspath .'/'. $filename, FILE_EXISTS_REPLACE); + } + + return $jspath .'/'. $filename; +} + +/** + * Delete all cached JS files. + */ +function drupal_clear_js_cache() { + file_scan_directory(file_create_path('js'), '.*', array('.', '..', 'CVS'), 'file_delete', TRUE); +} + +/** * Converts a PHP variable into its Javascript equivalent. * * We use HTML-safe strings, i.e. with <, > and & escaped. Index: includes/file.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/file.inc,v retrieving revision 1.90.2.3 diff -u -F^f -r1.90.2.3 file.inc --- includes/file.inc 7 Jan 2008 01:00:22 -0000 1.90.2.3 +++ includes/file.inc 26 Jan 2008 22:32:44 -0000 @@ -33,7 +33,7 @@ function file_create_url($path) { } switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) { case FILE_DOWNLOADS_PUBLIC: - return $GLOBALS['base_url'] .'/'. file_directory_path() .'/'. str_replace('\\', '/', $path); + return file_url(file_directory_path() .'/'. str_replace('\\', '/', $path), TRUE); case FILE_DOWNLOADS_PRIVATE: return url('system/files/'. $path, NULL, NULL, TRUE); } Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.337.2.2 diff -u -F^f -r1.337.2.2 theme.inc --- includes/theme.inc 31 May 2007 05:52:42 -0000 1.337.2.2 +++ includes/theme.inc 26 Jan 2008 22:32:44 -0000 @@ -322,24 +322,24 @@ function theme_get_setting($setting_name if ($settings['toggle_logo']) { if ($settings['default_logo']) { - $settings['logo'] = base_path() . dirname($theme_object->filename) .'/logo.png'; + $settings['logo'] = file_url(dirname($theme_object->filename) .'/logo.png'); } elseif ($settings['logo_path']) { - $settings['logo'] = base_path() . $settings['logo_path']; + $settings['logo'] = file_url($settings['logo_path']); } } if ($settings['toggle_favicon']) { if ($settings['default_favicon']) { if (file_exists($favicon = dirname($theme_object->filename) .'/favicon.ico')) { - $settings['favicon'] = base_path() . $favicon; + $settings['favicon'] = file_url($favicon); } else { - $settings['favicon'] = base_path() . 'misc/favicon.ico'; + $settings['favicon'] = file_url('misc/favicon.ico'); } } elseif ($settings['favicon_path']) { - $settings['favicon'] = base_path() . $settings['favicon_path']; + $settings['favicon'] = file_url($settings['favicon_path']); } else { $settings['toggle_favicon'] = FALSE; @@ -613,8 +613,7 @@ function theme_links($links, $attributes function theme_image($path, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) { if (!$getsize || (is_file($path) && (list($width, $height, $type, $image_attributes) = @getimagesize($path)))) { $attributes = drupal_attributes($attributes); - $url = (url($path) == $path) ? $path : (base_path() . $path); - return ''. check_plain($alt) .''; + return ''. check_plain($alt) .''; } } Index: misc/autocomplete.js =================================================================== RCS file: /cvs/drupal/drupal/misc/autocomplete.js,v retrieving revision 1.17 diff -u -F^f -r1.17 autocomplete.js --- misc/autocomplete.js 9 Jan 2007 07:31:04 -0000 1.17 +++ misc/autocomplete.js 26 Jan 2008 22:32:45 -0000 @@ -15,7 +15,7 @@ $(input.form).submit(Drupal.autocompleteSubmit); new Drupal.jsAC(input, acdb[uri]); }); -} +}; /** * Prevents the form from submitting if the suggestions popup is open @@ -25,7 +25,7 @@ return $('#autocomplete').each(function () { this.owner.hidePopup(); }).size() == 0; -} +}; /** * An AutoComplete object @@ -59,7 +59,7 @@ default: // all other keys return true; } -} +}; /** * Handler for the "keyup" event @@ -96,14 +96,14 @@ this.hidePopup(e.keyCode); return true; } -} +}; /** * Puts the currently highlighted suggestion into the autocomplete field */ Drupal.jsAC.prototype.select = function (node) { this.input.value = node.autocompleteValue; -} +}; /** * Highlights the next suggestion @@ -118,7 +118,7 @@ this.highlight(lis.get(0)); } } -} +}; /** * Highlights the previous suggestion @@ -127,7 +127,7 @@ if (this.selected && this.selected.previousSibling) { this.highlight(this.selected.previousSibling); } -} +}; /** * Highlights a suggestion @@ -138,7 +138,7 @@ } $(node).addClass('selected'); this.selected = node; -} +}; /** * Unhighlights a suggestion @@ -146,7 +146,7 @@ Drupal.jsAC.prototype.unhighlight = function (node) { $(node).removeClass('selected'); this.selected = false; -} +}; /** * Hides the autocomplete suggestions @@ -163,7 +163,7 @@ $(popup).fadeOut('fast', function() { $(popup).remove(); }); } this.selected = false; -} +}; /** * Positions the suggestions popup and starts a search @@ -187,7 +187,7 @@ // Do search this.db.owner = this; this.db.search(this.input.value); -} +}; /** * Fills the suggestion popup with any matches received @@ -222,7 +222,7 @@ this.hidePopup(); } } -} +}; Drupal.jsAC.prototype.setStatus = function (status) { switch (status) { @@ -235,7 +235,7 @@ $(this.input).removeClass('throbbing'); break; } -} +}; /** * An AutoComplete DataBase object @@ -244,7 +244,7 @@ this.uri = uri; this.delay = 300; this.cache = {}; -} +}; /** * Performs a cached and delayed search @@ -286,7 +286,7 @@ } }); }, this.delay); -} +}; /** * Cancels the current autocomplete request @@ -295,7 +295,7 @@ if (this.owner) this.owner.setStatus('cancel'); if (this.timer) clearTimeout(this.timer); this.searchString = ''; -} +}; // Global Killswitch if (Drupal.jsEnabled) { Index: misc/collapse.js =================================================================== RCS file: /cvs/drupal/drupal/misc/collapse.js,v retrieving revision 1.10 diff -u -F^f -r1.10 collapse.js --- misc/collapse.js 11 Jan 2007 03:38:31 -0000 1.10 +++ misc/collapse.js 26 Jan 2008 22:32:45 -0000 @@ -19,7 +19,7 @@ Drupal.collapseScrollIntoView(this.parentNode); } }); - if (typeof Drupal.textareaAttach != 'undefined') { + if (typeof(Drupal.textareaAttach) != 'undefined') { // Initialize resizable textareas that are now revealed Drupal.textareaAttach(null, fieldset); } @@ -30,7 +30,7 @@ this.parentNode.animating = false; }); } -} +}; /** * Scroll a given fieldset into view as much as possible. @@ -47,7 +47,7 @@ window.scrollTo(0, pos.y + node.offsetHeight - h + fudge); } } -} +}; // Global Killswitch if (Drupal.jsEnabled) { Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.29.2.1 diff -u -F^f -r1.29.2.1 drupal.js --- misc/drupal.js 15 Jul 2007 23:07:06 -0000 1.29.2.1 +++ misc/drupal.js 26 Jan 2008 22:32:45 -0000 @@ -50,7 +50,7 @@ // Restore form submission button.form.action = action; button.form.target = target; - + // Get response from iframe body try { response = (iframe.contentWindow || iframe.contentDocument || iframe).document.body.innerHTML; @@ -64,7 +64,7 @@ catch (e) { response = null; } - + response = Drupal.parseJson(response); // Check response code if (response.status == 0) { @@ -74,14 +74,14 @@ handler.oncomplete(response.data); return true; - } + }; return true; - } - } + }; + }; button.onmouseout = button.onblur = function() { button.onclick = null; - } + }; }; /** Index: misc/progress.js =================================================================== RCS file: /cvs/drupal/drupal/misc/progress.js,v retrieving revision 1.14 diff -u -F^f -r1.14 progress.js --- misc/progress.js 14 Dec 2006 14:21:36 -0000 1.14 +++ misc/progress.js 26 Jan 2008 22:32:45 -0000 @@ -23,7 +23,7 @@ $(this.element).html('
'+ '
 
'+ '
'); -} +}; /** * Set the percentage and status message for the progressbar. @@ -37,7 +37,7 @@ if (this.updateCallback) { this.updateCallback(percentage, message, this); } -} +}; /** * Start monitoring progress via Ajax. @@ -46,7 +46,7 @@ this.delay = delay; this.uri = uri; this.sendPing(); -} +}; /** * Stop monitoring progress via Ajax. @@ -55,7 +55,7 @@ clearTimeout(this.timer); // This allows monitoring to be stopped from within the callback this.uri = null; -} +}; /** * Request progress data from server. @@ -90,7 +90,7 @@ } }); } -} +}; /** * Display errors on the page. @@ -105,4 +105,4 @@ if (this.errorCallback) { this.errorCallback(this); } -} +}; Index: misc/tableselect.js =================================================================== RCS file: /cvs/drupal/drupal/misc/tableselect.js,v retrieving revision 1.1 diff -u -F^f -r1.1 tableselect.js --- misc/tableselect.js 21 Nov 2006 08:16:39 -0000 1.1 +++ misc/tableselect.js 26 Jan 2008 22:32:45 -0000 @@ -40,7 +40,7 @@ // Keep track of the last checked checkbox. lastChecked = e.target; }); -} +}; Drupal.tableSelectRange = function(from, to, state) { // We determine the looping mode based on the the order of from and to. @@ -65,7 +65,7 @@ else if (jQuery.filter(to, [i]).r.length) break; } -} +}; // Global Killswitch if (Drupal.jsEnabled) { Index: misc/textarea.js =================================================================== RCS file: /cvs/drupal/drupal/misc/textarea.js,v retrieving revision 1.11.2.1 diff -u -F^f -r1.11.2.1 textarea.js --- misc/textarea.js 18 Apr 2007 02:41:19 -0000 1.11.2.1 +++ misc/textarea.js 26 Jan 2008 22:32:45 -0000 @@ -29,7 +29,7 @@ textarea.css('opacity', 1); } }); -} +}; if (Drupal.jsEnabled) { $(document).ready(Drupal.textareaAttach); Index: misc/update.js =================================================================== RCS file: /cvs/drupal/drupal/misc/Attic/update.js,v retrieving revision 1.10 diff -u -F^f -r1.10 update.js --- misc/update.js 27 Dec 2006 14:11:45 -0000 1.10 +++ misc/update.js 26 Jan 2008 22:32:45 -0000 @@ -12,7 +12,7 @@ pb.stopMonitoring(); window.location = window.location.href.split('op=')[0] +'op=finished'; } - } + }; // Failure: point out error message and provide link to the summary. var errorCallback = function (pb) { @@ -21,7 +21,7 @@ $(div).html('An unrecoverable error has occured. You can find the error message below. It is advised to copy it to the clipboard for reference. Please continue to the update summary'); $(holder).prepend(div); $('#wait').hide(); - } + }; var progress = new Drupal.progressBar('updateprogress', updateCallback, "POST", errorCallback); progress.setProgress(-1, 'Starting updates'); Index: misc/upload.js =================================================================== RCS file: /cvs/drupal/drupal/misc/Attic/upload.js,v retrieving revision 1.11 diff -u -F^f -r1.11 upload.js --- misc/upload.js 31 Aug 2006 23:31:25 -0000 1.11 +++ misc/upload.js 26 Jan 2008 22:32:45 -0000 @@ -13,7 +13,7 @@ var hide = base + '-hide'; var upload = new Drupal.jsUpload(uri, button, wrapper, hide); }); -} +}; /** * JS upload object. @@ -25,7 +25,7 @@ this.wrapper = '#'+ wrapper; this.hide = '#'+ hide; Drupal.redirectFormButton(uri, $(this.button).get(0), this); -} +}; /** * Handler for the form redirection submission. @@ -49,7 +49,7 @@ $(hide).after(el); $(el).fadeIn('slow'); $(hide).fadeOut('slow'); -} +}; /** * Handler for the form redirection completion. @@ -92,7 +92,7 @@ Drupal.uploadAutoAttach(); } Drupal.unfreezeHeight(); -} +}; /** * Handler for the form redirection error. @@ -107,7 +107,7 @@ position: 'static', left: '0px' }); -} +}; // Global killswitch Index: misc/farbtastic/farbtastic.js =================================================================== RCS file: /cvs/drupal/drupal/misc/farbtastic/farbtastic.js,v retrieving revision 1.3 diff -u -F^f -r1.3 farbtastic.js --- misc/farbtastic/farbtastic.js 10 Jan 2007 07:03:48 -0000 1.3 +++ misc/farbtastic/farbtastic.js 26 Jan 2008 22:32:45 -0000 @@ -9,7 +9,7 @@ jQuery.farbtastic = function (container, callback) { var container = $(container).get(0); return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback)); -} +}; jQuery._farbtastic = function (container, callback) { // Store farbtastic object @@ -62,12 +62,12 @@ } } return this; - } + }; fb.updateValue = function (event) { if (this.value && this.value != fb.color) { fb.setColor(this.value); } - } + }; /** * Change color with HTML syntax #123456 @@ -81,7 +81,7 @@ fb.updateDisplay(); } return this; - } + }; /** * Change color with HSL triplet [0..1, 0..1, 0..1] @@ -92,7 +92,7 @@ fb.color = fb.pack(fb.rgb); fb.updateDisplay(); return this; - } + }; ///////////////////////////////////////////////////// @@ -121,7 +121,7 @@ // Look for the coordinates starting from the wheel widget. var e = reference; - var offset = { x: 0, y: 0 } + var offset = { x: 0, y: 0 }; while (e) { if (typeof e.mouseX != 'undefined') { x = e.mouseX - offset.x; @@ -149,7 +149,7 @@ } // Subtract distance to middle return { x: x - fb.width / 2, y: y - fb.width / 2 }; - } + }; /** * Mousedown handler @@ -168,7 +168,7 @@ // Process fb.mousemove(event); return false; - } + }; /** * Mousemove handler @@ -189,7 +189,7 @@ fb.setHSL([fb.hsl[0], sat, lum]); } return false; - } + }; /** * Mouseup handler @@ -199,7 +199,7 @@ $(document).unbind('mousemove', fb.mousemove); $(document).unbind('mouseup', fb.mouseup); document.dragging = false; - } + }; /** * Update the markers and styles @@ -238,7 +238,7 @@ else if (typeof fb.callback == 'function') { fb.callback.call(fb, fb.color); } - } + }; /** * Get absolute position of element @@ -262,7 +262,7 @@ return '#' + (r < 16 ? '0' : '') + r.toString(16) + (g < 16 ? '0' : '') + g.toString(16) + (b < 16 ? '0' : '') + b.toString(16); - } + }; fb.unpack = function (color) { if (color.length == 7) { @@ -275,7 +275,7 @@ parseInt('0x' + color.substring(2, 3)) / 15, parseInt('0x' + color.substring(3, 4)) / 15]; } - } + }; fb.HSLToRGB = function (hsl) { var m1, m2, r, g, b; @@ -285,7 +285,7 @@ return [this.hueToRGB(m1, m2, h+0.33333), this.hueToRGB(m1, m2, h), this.hueToRGB(m1, m2, h-0.33333)]; - } + }; fb.hueToRGB = function (m1, m2, h) { h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h); @@ -293,7 +293,7 @@ if (h * 2 < 1) return m2; if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6; return m1; - } + }; fb.RGBToHSL = function (rgb) { var min, max, delta, h, s, l; @@ -314,7 +314,7 @@ h /= 6; } return [h, s, l]; - } + }; // Install mousedown handler (the others are set on the document on-demand) $('*', e).mousedown(fb.mousedown); @@ -326,4 +326,4 @@ if (callback) { fb.linkTo(callback); } -} \ No newline at end of file +}; \ No newline at end of file Index: modules/color/color.js =================================================================== RCS file: /cvs/drupal/drupal/modules/color/color.js,v retrieving revision 1.1.2.1 diff -u -F^f -r1.1.2.1 color.js --- modules/color/color.js 18 Apr 2007 03:38:58 -0000 1.1.2.1 +++ modules/color/color.js 26 Jan 2008 22:32:45 -0000 @@ -223,7 +223,7 @@ ); $(this).after(lock); locks.push(lock); - } + }; // Add hook var hook = $('
'); @@ -236,7 +236,7 @@ }) .focus(focus); - $('#palette label', form) + $('#palette label', form); // Focus first color focus.call(inputs[0]); Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.440.2.28 diff -u -F^f -r1.440.2.28 system.module --- modules/system/system.module 11 Jan 2008 00:47:17 -0000 1.440.2.28 +++ modules/system/system.module 26 Jan 2008 22:32:47 -0000 @@ -229,7 +229,7 @@ function system_menu($may_cache) { $items[] = array( 'path' => 'admin/settings/performance', 'title' => t('Performance'), - 'description' => t('Enable or disable page caching for anonymous users, and enable or disable CSS preprocessor.'), + 'description' => t('Enable or disable page caching for anonymous users and set CSS and JS bandwidth optimization options.'), 'callback' => 'drupal_get_form', 'callback arguments' => array('system_performance_settings')); $items[] = array( @@ -690,22 +690,32 @@ function system_performance_settings() { $form['bandwidth_optimizations'] = array( '#type' => 'fieldset', '#title' => t('Bandwidth optimizations'), - '#description' => t('These options can help reduce both the size and number of requests made to your website. This can reduce the server load, the bandwidth used, and the average page loading time for your visitors.') + '#description' => t('

Drupal can automatically aggregate and compress external resources like CSS and JavaScript into a single cached file. This can help reduce both the size and number of requests made to your website. This in turn reduces the server load, the bandwidth used, and the average page loading time for your visitors.

These options are disabled if you have not set up your files directory, or if your download method is set to private.

') ); $directory = file_directory_path(); $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC); $form['bandwidth_optimizations']['preprocess_css'] = array( '#type' => 'radios', - '#title' => t('Aggregate and compress CSS files'), - '#default_value' => intval(variable_get('preprocess_css', FALSE) && $is_writable), + '#title' => t('Optimize CSS files'), + '#default_value' => variable_get('preprocess_css', 0) && $is_writable, '#disabled' => !$is_writable, '#options' => array(t('Disabled'), t('Enabled')), - '#description' => t("Some Drupal modules include their own CSS files. When these modules are enabled, each module's CSS file adds an additional HTTP request to the page, which can increase the load time of each page. These HTTP requests can also slightly increase server load. It is recommended to only turn this option on when your site is in production, as it can interfere with theme development. This option is disabled if you have not set up your files directory, or if your download method is set to private."), + '#description' => t("This option can interfere with theme development. It is recommended to only turn this on when your site is complete."), ); + $form['bandwidth_optimizations']['preprocess_js'] = array( + '#type' => 'radios', + '#title' => t('Optimize JavaScript files'), + '#default_value' => variable_get('preprocess_js', 0) && $is_writable, + '#disabled' => !$is_writable, + '#options' => array(t('Disabled'), t('Enabled')), + '#description' => t("This option can interfere with module development. It is recommended to only turn this on when your site is complete."), + ); $form['#submit']['system_settings_form_submit'] = array(); $form['#submit']['drupal_clear_css_cache'] = array(); + $form['#submit']['drupal_clear_js_cache'] = array(); + return system_settings_form($form); } @@ -738,9 +748,69 @@ function system_file_system_settings() { '#description' => t('If you want any sort of access control on the downloading of files, this needs to be set to private. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.') ); + $form['file_servers'] = array( + '#tree' => TRUE, + '#type' => 'fieldset', + '#title' => t('File servers'), + '#description' => t( + 'This setting is for advanced users.
+ Enables Drupal to serve files from any kind of file server. Drupal will + automatically fall back to file servers that are lower in the list. +
The web server Drupal is running on will always be used as the + default file server.'), + '#collapsible' => FALSE, + ); + + $modules = array(); + foreach (module_implements('file_server', TRUE) as $module) { + $info = _module_parse_info_file(drupal_get_path('module', $module) ."/$module.info"); + $file_server_info = module_invoke($module, 'file_server', 'info'); + + $modules[$module] = array( + 'type' => $file_server_info['type'], + 'module' => (!isset($file_server_info['configuration_page'])) ? $info['name'] : l($info['name'], $file_server_info['configuration_page']), + 'weight' => variable_get("file_server_{$module}_weight", 0), + ); + } + + // Sort file server types by weight. + uasort($modules, create_function('$a, $b', 'return $a["weight"] > $b["weight"];')); + + foreach ($modules as $module => $settings) { + $form['file_servers']['types'][$module] = array('#value' => $settings['type']); + $form['file_servers']['modules'][$module] = array('#value' => $settings['module']); + $form['file_servers']['weights']["file_server_{$module}_weight"] = array('#type' => 'weight', '#default_value' => $settings['weight']); + } + + // The web server Drupal is running on is always available, and it's the + // default server, i.e. a server we can always fall back to. So it must + // always be at the bottom of the list and don't have a configurable weight. + $form['file_servers']['types']['drupal'] = array('#value' => t('Web server')); + $form['file_servers']['modules']['drupal'] = array('#value' => 'Drupal'); + $form['file_servers']['weights']['file_server_drupal_weight'] = array('#value' => t('Default server')); + return system_settings_form($form); } +function theme_system_file_system_settings($form) { + $header = array(t('Type'), t('Module'), t('Weight')); + $rows = array(); + foreach (element_children($form['file_servers']['modules']) as $module) { + // Don't take form control structures + if (is_array($form['file_servers']['modules'][$module])) { + $rows[] = array( + drupal_render($form['file_servers']['types'][$module]), + drupal_render($form['file_servers']['modules'][$module]), + drupal_render($form['file_servers']['weights']["file_server_{$module}_weight"]), + ); + } + } + + $form['file_servers']['#value'] = theme('table', $header, $rows); + + return drupal_render($form); +} + function system_image_toolkit_settings() { $toolkits_available = image_get_available_toolkits(); if (count($toolkits_available) > 1) { @@ -1524,6 +1594,7 @@ function system_modules_submit($form_id, } drupal_clear_css_cache(); + drupal_clear_js_cache(); return 'admin/build/modules'; }