? 451928-file-uploads.patch
? TODO.txt
? ctools-multiversion.diff
? ctools_modal_file_uploads_0.patch
Index: includes/ajax.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/includes/ajax.inc,v
retrieving revision 1.6
diff -u -p -r1.6 ajax.inc
--- includes/ajax.inc	20 Apr 2009 21:29:46 -0000	1.6
+++ includes/ajax.inc	5 May 2009 19:56:01 -0000
@@ -315,7 +315,15 @@ function ctools_ajax_command_restripe($s
  * to the AJAX requester.
  */
 function ctools_ajax_render($commands = array()) {
-  drupal_json($commands);
+  if (!empty($_REQUEST['ctools_multipart'])) {
+    // We don't use drupal_json here because the header is not true. We're not really
+    // returning JSON, strictly-speaking, but rather JSON content wrapped in a <textarea>
+    // as per the "file uploads" example here: http://malsup.com/jquery/form/#code-samples
+    echo '<textarea>' . drupal_to_js($commands) . '</textarea>';
+  }
+  else {
+    drupal_json($commands);
+  }
   exit;
 }
 
Index: js/modal.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/js/modal.js,v
retrieving revision 1.9
diff -u -p -r1.9 modal.js
--- js/modal.js	24 Apr 2009 00:08:51 -0000	1.9
+++ js/modal.js	5 May 2009 19:56:03 -0000
@@ -136,8 +136,9 @@ Drupal.CTools.Modal.submitAjaxForm = fun
   var object = $(this);
   try {
     url.replace('/nojs/', '/ajax/');
-    $(this).ajaxSubmit({
-      type: "POST",
+
+    var ajaxOptions = {
+      type: 'POST',
       url: url,
       data: '',
       global: true,
@@ -150,18 +151,38 @@ Drupal.CTools.Modal.submitAjaxForm = fun
         $('.ctools-ajaxing', object).removeClass('ctools-ajaxing');
       },
       dataType: 'json'
-    });
+    };
+
+    // If the form requires uploads, use an iframe instead and add data to
+    // the submit to support this and use the proper response.
+    if ($(this).attr('enctype') == 'multipart/form-data') {
+      ajaxOptions = {
+        success: Drupal.CTools.AJAX.iFrameJsonRespond,
+        iframe: true,
+        data: {'ctools_multipart': '1'}
+      } + ajaxOptions;
+    }
+
+    $(this).ajaxSubmit(ajaxOptions);
   }
   catch (err) {
     alert("An error occurred while attempting to process " + url); 
     $(this).removeClass('ctools-ajaxing');
-    $('.ctools-ajaxing', this).removeClass('ctools-ajaxing');
+    $('div.ctools-ajaxing', this).remove();
     return false;
   }
   return false;
 }
 
 /**
+ * Wrapper for handling JSON responses from an iframe submission
+ */
+Drupal.CTools.AJAX.iFrameJsonRespond = function(data) {
+  var myJson = eval(data);
+  Drupal.CTools.AJAX.respond(myJson);
+}
+
+/**
  * Bind links that will open modals to the appropriate function.
  */
 Drupal.behaviors.CToolsModal = function(context) {
@@ -187,8 +208,10 @@ Drupal.behaviors.CToolsModal = function(
       .addClass('ctools-use-modal-processed')
       .click(function() {
         // Make sure it knows our button.
-        this.form.clk = this;
-        $(this).after('<div class="ctools-ajaxing"> &nbsp; </div>');
+        if (!$(this.form).hasClass('ctools-ajaxing')) {
+          this.form.clk = this;
+          $(this).after('<div class="ctools-ajaxing"> &nbsp; </div>');
+        }
       });
 
   }
