#745468 by alevine and Scott Reynolds: Make ajax better able to know what .js/.css...
authorEarl Miles
Fri, 9 Apr 2010 23:15:20 +0000 (23:15 +0000)
committerEarl Miles
Fri, 9 Apr 2010 23:15:20 +0000 (23:15 +0000)
CHANGELOG.txt
ctools.module
includes/ajax.inc
js/ajax-responder.js

index 873ebe8..fce7e9f 100644 (file)
@@ -23,6 +23,7 @@ Initial inclusion of the stylizer plugin to create user customizable styles from
 #723296 by andrewlevine: Generalize more of CTools helpers so they can be used for non-CTools files.
 #726320 by gordon: Allow the CTools wizard to have query strings in the wizard path.
 #711664 by meclimdul: Make the 'hook' version of plugins now optional and improve code around it.
+#745468 by alevine and Scott Reynolds: Make ajax better able to know what .js/.css was already on the page.
 
 ctools 6.x-1.3 (2010-Feb-01)
 ==============
index 7ac338d..2cbb65f 100644 (file)
@@ -114,10 +114,10 @@ function ctools_include($file, $module = 'ctools', $dir = 'includes') {
 /**
  * Provide the proper path to an image as necessary.
  *
- * This helper function is used by ctools but can also be used in other 
- * modules in the same way as explained in the comments of ctools_include. 
+ * This helper function is used by ctools but can also be used in other
+ * modules in the same way as explained in the comments of ctools_include.
  *
- * @param $image 
+ * @param $image
  *   The base file name (with extension)  of the image to be included.
  * @param $module
  *   Optional module containing the include.
@@ -131,8 +131,8 @@ function ctools_image_path($image, $module = 'ctools', $dir = 'images') {
 /**
  * Include css files as necessary.
  *
- * This helper function is used by ctools but can also be used in other 
- * modules in the same way as explained in the comments of ctools_include. 
+ * This helper function is used by ctools but can also be used in other
+ * modules in the same way as explained in the comments of ctools_include.
  *
  * @param $file
  *   The base file name to be included.
@@ -148,8 +148,8 @@ function ctools_add_css($file, $module = 'ctools', $dir = 'css') {
 /**
  * Include js files as necessary.
  *
- * This helper function is used by ctools but can also be used in other 
- * modules in the same way as explained in the comments of ctools_include. 
+ * This helper function is used by ctools but can also be used in other
+ * modules in the same way as explained in the comments of ctools_include.
  *
  * @param $file
  *   The base file name to be included.
@@ -163,6 +163,18 @@ function ctools_add_js($file, $module = 'ctools', $dir = 'js') {
 }
 
 /**
+ * Simple function to add a page id to Drupal.settings.CTools.
+ */
+function ctools_add_page_id() {
+  static $page_id = NULL;
+  if (!isset($page_id)) {
+    $page_id = 'page-' . md5(mt_rand());
+    drupal_add_js(array('CTools' => array('pageId' => $page_id)), 'setting');
+  }
+  return $page_id;
+}
+
+/**
  * Implement hook_init to keep our global CSS at the ready.
  */
 function ctools_init() {
@@ -172,6 +184,10 @@ function ctools_init() {
     ini_set('display_errors', 0);
     register_shutdown_function('ctools_shutdown_handler');
   }
+  else {
+    // Add a setting into the JS that identifies this page.
+    ctools_add_page_id();
+  }
 }
 
 /**
@@ -526,6 +542,57 @@ function ctools_preprocess_page(&$variables) {
     }
     $variables['content'] = strtr($variables['content'], $tokens);
   }
+
+  // Go through all the JS files being added to the page and catalog them.
+  $js_files = array();
+  foreach (drupal_add_js() as $type => $data) {
+    if ($type != 'inline' && $type != 'setting') {
+      foreach ($data as $path => $info) {
+        $js_files[$path] = TRUE;
+      }
+    }
+  }
+
+  // Go through all CSS files that are being added to the page and catalog them.
+  $css_files = array();
+  $css = drupal_add_css();
+  foreach ($css as $media => $types) {
+    // If CSS preprocessing is off, we still need to output the styles.
+    // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones.
+    foreach ($types as $type => $files) {
+      if ($type == 'module') {
+        // Setup theme overrides for module styles.
+        $theme_styles = array();
+        foreach (array_keys($css[$media]['theme']) as $theme_style) {
+          $theme_styles[] = basename($theme_style);
+        }
+      }
+      foreach ($types[$type] as $file => $preprocess) {
+        // If the theme supplies its own style using the name of the module style, skip its inclusion.
+        // This includes any RTL styles associated with its main LTR counterpart.
+        if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
+          // Unset the file to prevent its inclusion when CSS aggregation is enabled.
+          unset($types[$type][$file]);
+          continue;
+        }
+        // Only include the stylesheet if it exists.
+        if (file_exists($file)) {
+          $css_files[$file] = TRUE;
+        }
+      }
+    }
+  }
+
+  // Cache the cataloged JS and CSS so they can be found by an ajax request.
+  $page_id = ctools_add_page_id();
+  $expire = CACHE_TEMPORARY;
+
+  // If the page cache is enabled, respect its cache lifetime.
+  // @TODO: do this for only user_is_anonymous()?
+  if (variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED) {
+    $expire = variable_get('cache_lifetime', 0);
+  }
+  cache_set($page_id, array('js' => $js_files, 'css' => $css_files), 'cache', $expire);
 }
 
 /**
index e1eb270..c79fb3d 100644 (file)
@@ -449,30 +449,34 @@ function ctools_ajax_command_submit($selector) {
 function ctools_ajax_render($commands = array()) {
   // Automatically extract any 'settings' added via drupal_add_js() and make
   // them the first command.
-
   $query_string = '?'. substr(variable_get('css_js_query_string', '0'), 0, 1);
 
   $scripts = drupal_add_js(NULL, NULL);
+  $cached_scripts = cache_get($_POST['page_id'], 'cache')->data;
+
   foreach ($scripts as $type => $data) {
     switch ($type) {
       case 'setting':
         $settings = $data;
         break;
       case 'inline':
-        // presently we ignore inline javascript.
+      case 'theme':
+        // Presently we ignore inline javascript.
+        // Theme JS is already added and because of admin themes, this could add
+        // improper JS to the page.
         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) {
-          $js_files[] = base_path() . $path . ($info['cache'] ? $query_string : '?' . time());
+          if (!isset($cached_scripts['js'][$path])) {
+            $js_files[] = base_path() . $path . ($info['cache'] ? $query_string : '?' . time());
+          }
         }
     }
   }
 
-
   $css = drupal_add_css();
-
   foreach ($css as $media => $types) {
     // If CSS preprocessing is off, we still need to output the styles.
     // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones.
@@ -484,20 +488,24 @@ function ctools_ajax_render($commands = array()) {
           $theme_styles[] = basename($theme_style);
         }
       }
-      foreach ($types[$type] as $file => $preprocess) {
-        // If the theme supplies its own style using the name of the module style, skip its inclusion.
-        // This includes any RTL styles associated with its main LTR counterpart.
-        if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
-          // Unset the file to prevent its inclusion when CSS aggregation is enabled.
-          unset($types[$type][$file]);
-          continue;
-        }
-        // Only include the stylesheet if it exists.
-        if (file_exists($file)) {
-          $css_files[] = array(
-            'file' => base_path() . $file . $query_string,
-            'media' => $media,
-          );
+      // The theme stuff should already be added and because of admin themes,
+      // this could cause different CSS to be added.
+      if ($type != 'theme') {
+        foreach ($types[$type] as $file => $preprocess) {
+          // If the theme supplies its own style using the name of the module style, skip its inclusion.
+          // This includes any RTL styles associated with its main LTR counterpart.
+          if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
+            // Unset the file to prevent its inclusion when CSS aggregation is enabled.
+            unset($types[$type][$file]);
+            continue;
+          }
+          // Only include the stylesheet if it exists.
+          if (file_exists($file) && !isset($cached_scripts['css'][$file])) {
+            $css_files[] = array(
+              'file' => base_path() . $file . $query_string,
+              'media' => $media,
+            );
+          }
         }
       }
     }
index c9016bf..a4d657d 100644 (file)
   Drupal.CTools.AJAX.scripts = {};
   Drupal.CTools.AJAX.css = {};
 
+  Drupal.CTools.AJAX.getPageId = function() {
+    var page_id = '';
+    if (Drupal.settings.CTools && Drupal.settings.CTools.pageId) {
+      page_id = Drupal.settings.CTools.pageId;
+    }
+
+    return page_id;
+  }
+
   /**
    * Success callback for an ajax request.
    *
@@ -53,7 +62,7 @@
       $.ajax({
         type: "POST",
         url: url,
-        data: { 'js': 1, 'ctools_ajax': 1 },
+        data: { 'js': 1, 'ctools_ajax': 1, 'page_id': Drupal.CTools.AJAX.getPageId() },
         global: true,
         success: function (data) {
           Drupal.CTools.AJAX.commandCache[old_url] = data;
       $.ajax({
         type: "POST",
         url: url,
-        data: { 'js': 1, 'ctools_ajax': 1 },
+        data: { 'js': 1, 'ctools_ajax': 1, 'page_id': Drupal.CTools.AJAX.getPageId() },
         global: true,
         success: Drupal.CTools.AJAX.respond,
         error: function(xhr) {
       });
     }
     catch (err) {
+      console.log(err);
       alert("An error occurred while attempting to process " + url);
       $(this).removeClass('ctools-ajaxing');
       return false;
         $.ajax({
           type: "POST",
           url: url,
-          data: { 'js': 1, 'ctools_ajax': 1 },
+          data: { 'js': 1, 'ctools_ajax': 1, 'page_id': Drupal.CTools.AJAX.getPageId() },
           global: true,
           success: Drupal.CTools.AJAX.respond,
           error: function(xhr) {
         $(form).ajaxSubmit({
           type: "POST",
           url: url,
-          data: { 'js': 1, 'ctools_ajax': 1 },
+          data: { 'js': 1, 'ctools_ajax': 1, 'page_id': Drupal.CTools.AJAX.getPageId() },
           global: true,
           success: Drupal.CTools.AJAX.respond,
           error: function(xhr) {