diff --git js/modal.js js/modal.js
index 64553b9..fc88b68 100644
--- js/modal.js
+++ js/modal.js
@@ -13,6 +13,7 @@
   // Make sure our objects are defined.
   Drupal.CTools = Drupal.CTools || {};
   Drupal.CTools.Modal = Drupal.CTools.Modal || {};
+  Drupal.CTools.Modal.Cache = Drupal.CTools.Modal.Cache || new Array();
 
   /**
    * Display the modal
@@ -81,6 +82,65 @@
   };
 
   /**
+   * Grab the response from the server and store it.
+   */
+  Drupal.CTools.Modal.warmCache = function () {
+    if ($(this).hasClass('ctools-fetching')) {
+      return false;
+    }
+
+    var url = $(this).attr('href');
+    var object = $(this);
+    $(this).addClass('ctools-fetching');
+    try {
+      url = url.replace(/nojs/g, 'ajax');
+      $.ajax({
+        type: "POST",
+        url: url,
+        data: 'js=1',
+        global: true,
+        success: function (data) {
+          var position = Drupal.CTools.Modal.Cache.push(data);
+          // rel will not be seen by crawlers (they have JS off).
+          object.attr('rel', position - 1);
+        },
+        complete: function() {
+          object.removeClass('ctools-fetching');
+        },
+        dataType: 'json'
+      });
+    }
+    catch (err) {
+      $(this).removeClass('ctools-fetching');
+      return false;
+    }
+
+    return false;
+  };
+
+  /**
+   * Click() function for modals that can be cached.
+   */
+  Drupal.CTools.Modal.clickAjaxCacheLink = function () {
+    var position = $(this).attr('rel');
+    if (position.length != 0 && Drupal.CTools.Modal.Cache[position]) {
+      Drupal.CTools.Modal.show();
+      Drupal.CTools.AJAX.respond(Drupal.CTools.Modal.Cache[position]);
+      return false;
+    }
+    else {
+      // show the empty dialog right away.
+      Drupal.CTools.Modal.show();
+      Drupal.CTools.AJAX.clickAJAXLink.apply(this);
+      if (!$(this).hasClass('ctools-ajaxing')) {
+        Drupal.CTools.Modal.dismiss();
+      }
+
+      return false;
+    }
+  };
+
+  /**
    * Generic replacement click handler to open the modal with the destination
    * specified by the href of the link.
    */
@@ -212,6 +272,16 @@
     }
   };
 
+  /**
+   * Finds all cachable links and binds click and then warms the cache.
+   */
+  Drupal.behaviors.CToolsModalCache = function (context) {
+    $('a.ctools-use-modal-cache:not(.ctools-use-modal-cache-processed)', context)
+    .addClass('ctools-use-modal-cache-processed')
+    .click(Drupal.CTools.Modal.clickAjaxCacheLink)
+    .each(Drupal.CTools.Modal.warmCache);
+  };
+
   // The following are implementations of AJAX responder commands.
 
   /**
