? filefield.module.new
Index: filefield.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield/filefield.module,v
retrieving revision 1.23
diff -u -F^f -r1.23 filefield.module
--- filefield.module	30 Mar 2007 03:20:24 -0000	1.23
+++ filefield.module	19 May 2007 12:40:45 -0000
@@ -13,7 +13,16 @@
 function filefield_menu($maycache) {
   $items = array();
 
-  if (!$may_cache && $_SESSION['filefield']) {
+  if ($maycache) {
+    $items[] = array(
+      'path' => 'filefield/js',
+      'callback' => 'filefield_js',
+      //'access' => user_access(),
+      'access' => TRUE,
+      'type' => MENU_CALLBACK
+    );
+  }
+  else if ($_SESSION['filefield']) {
     // Add handlers for previewing new uploads.
     foreach ($_SESSION['filefield'] as $fieldname => $files) {
       if (is_array($files)) {
@@ -276,7 +285,7 @@ function filefield_widget($op, $node, $f
   $fieldname = $field['field_name'];
   switch ($op) {
     case 'prepare form values':
-      _filefield_widget_prepare($node, $field, $node_field);
+      _filefield_widget_prepare_form_values($node, $field, $node_field);
       break;
 
     case 'form':
@@ -288,7 +297,7 @@ function filefield_widget($op, $node, $f
   }
 }
 
-function _filefield_widget_prepare($node, $field, &$node_field) {
+function _filefield_widget_prepare_form_values($node, $field, &$node_field) {
   $fieldname = $field['field_name'];
 
   // @todo split this into its own function. determine if we can make it a form element.
@@ -298,9 +307,9 @@ function _filefield_widget_prepare($node
   // Attach new files 
   if ($file = file_check_upload($fieldname . '_upload')) {
     $file = (array)$file;
-    // test allowed extensions. We do this when the file is uploaded, rather than waiting for the
-    // field itseld to reach op==validate.
-    $ext = array_pop(explode('.',$file['filename']));
+    // test allowed extensions. We do this when the file is uploaded,
+    // rather than waiting for the field itself to reach op==validate.
+    $ext = array_pop(explode('.', $file['filename']));
     $allowed_extensions = array_unique(explode(' ', trim($field['widget']['file_extensions'])));
 
     $valid = in_array($ext, $allowed_extensions);
@@ -359,6 +368,9 @@ function _filefield_widget_prepare($node
 }
 
 function _filefield_widget_form($node, $field, &$node_field) {
+  drupal_add_js('misc/progress.js');
+  drupal_add_js('misc/upload.js');
+
   $fieldname = $field['field_name'];
   drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
  
@@ -370,39 +382,81 @@ function _filefield_widget_form($node, $
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
     '#tree' => TRUE,
-    '#theme' => 'filefield_current',
+    '#prefix' => '<div id="'. form_clean_id($fieldname .'-attach-wrapper') .'">',
+    '#suffix' => '</div>',
   );
-  
-  $form[$fieldname][$fieldname .'_upload'] = array(
+
+  $form[$fieldname]['new'] = array(
+    '#tree' => FALSE,
+    '#prefix' => '<div id="'. form_clean_id($fieldname .'-attach-hide') .'">',
+    '#suffix' => '</div>',
+    '#weight' => 100,
+  );
+
+  // Separate from tree becase of that silly things won't be 
+  // displayed if they are a child of '#type' = form issue
+  $form[$fieldname]['new'][$fieldname .'_upload'] = array(
     '#type'  => 'file',
-    '#description' => $field['widget']['description'] . t('<br />allowed extensions(%ext)', array('%ext' => $field['widget']['file_extensions'])),
-    '#weight' => 9,
+    '#description' => $field['widget']['description'] .
+                      t('<br />allowed extensions(%ext)',
+                        array('%ext' => $field['widget']['file_extensions'])
+                      ),
     '#tree' => FALSE,
+    '#weight' => 9,
   );
 
-  $form[$fieldname]['update'] = array(
+  $form[$fieldname]['new']['upload'] = array(
     '#type' => 'button',
     '#value' => t('Upload'),
-    '#name' => 'cck_filefield_'.$fieldname.'_op',
-    '#attributes' => array('id' => $fieldname.'-attach-button'),
+    '#name' => 'cck_filefield_'. $fieldname .'_op',
+    '#id' => form_clean_id($fieldname .'-attach-button'),
     '#tree' => FALSE,
     '#weight' => 10,
   );
 
   if (is_array($node_field) && count($node_field)) {
+    $form[$fieldname]['files'] = array(
+      '#parents' => array($fieldname),
+      '#theme' => 'filefield_form_current',
+    );
     foreach($node_field as $delta => $file) {
       // @todo: split into its own form and theme functions per file like imagefield
       if ($file['filepath'] && !$file['remove']) {
-        $form[$fieldname][$delta] = _filefield_file_form($node, $field, $file);
+        $form[$fieldname]['files'][$delta] = _filefield_file_form($node, $field, $file);
       }
       elseif ($file['filepath'] && $file['remove']) {
-        $form[$fieldname][$delta]['remove'] = array(
+        $form[$fieldname]['files'][$delta]['remove'] = array(
           '#type' => 'hidden',
           '#value' => $file['remove'],
         );
       }
     }
   }
+
+  // The class triggers the js upload behaviour.
+  $form[$fieldname.'-attach-url'] = array(
+    '#type' => 'hidden',
+    '#value' => url('filefield/js', NULL, NULL, TRUE),
+    '#attributes' => array('class' => 'upload')
+  );
+
+  // Some useful info for our js callback.
+  $form['vid'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->vid,
+    '#tree' => FALSE,
+  );
+  $form['nid'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->nid,
+    '#tree' => FALSE,
+  );
+  $form['type'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->type,
+    '#tree' => FALSE,
+  );
+
   return $form;
 }
 
@@ -422,7 +476,6 @@ function _filefield_file_form($node, $fi
   $form['description'] = array(
       '#type' => 'textfield', 
       '#default_value' => (strlen($file['description'])) ? $file['description'] : $file['filename'], '#maxlength' => 256, 
-      '#title' => t('Description'),
   );
   $form['url'] = array(
     '#type' => 'markup',
@@ -432,19 +485,17 @@ function _filefield_file_form($node, $fi
   );
   $form['size'] = array(
     '#type' => 'markup', 
-    '#value' => t('File Size') .': '. format_size($file['filesize']),
+    '#value' => format_size($file['filesize']),
     '#prefix' => '<div class="filefield-edit-file-size">',
     '#suffix' => '</div>',
   );
   $form['remove'] = array(
     '#type' => 'checkbox', 
     '#default_value' => $file['remove'],
-    '#title' => t('Remove'),
   );
   $form['list'] = array(
     '#type' => 'checkbox', 
     '#default_value' => $file['list'],
-    '#title' => t('List'),
   );
 
   $form['filename'] = array('#type' => 'value',  '#value' => $file['filename']);
@@ -516,6 +567,22 @@ function _filefield_file_load($fid = NUL
   return array();
 }
 
+function theme_filefield_form_current($form) {
+  $header = array(t('Delete'), t('List'), t('Description'), t('Size'));
+
+  foreach (element_children($form) as $key) {
+    $row = array();
+    $row[] = drupal_render($form[$key]['remove']);
+    $row[] = drupal_render($form[$key]['list']);
+    $row[] = drupal_render($form[$key]['icon']). drupal_render($form[$key]['description']). drupal_render($form[$key]['url']);
+    $row[] = drupal_render($form[$key]['size']);
+    $rows[] = $row;
+  }
+  $output = theme('table', $header, $rows);
+  $output .= drupal_render($form);
+  return $output;
+}
+
 function theme_filefield_icon($file) {
   $ext = array_pop(explode('.',$file['filename']));
   $known_extensions = array('0','ace','aif','ai','ani','asf','asp','avi','bak','bat','bin','bmp','bz2','bz','cab','cdr','cfg','com','conf','cpt','css','cur','dat','db','dcr','dic','diff','dir','dll','dmg','doc','dwg','edir','eml','eps','exe','fla','flv','fon','gif','gz','hqx','html','htm','ico','inc','ini','iso','jpeg','jpg','js','lnk','log','m3u','mdb','midi','mid','mov','mp3','mpeg','mpg','nfo','odb','odc','odf','odg','odm','odp','ods','odt','ogg','otg','oth','otp','ots','ott','patch','pdf','php3','php','phtml','pl','png','pps','ppt','psd','pwl','qt','ram','ra','rar','reg','rpm','rtf','sh','shtml','sit','sql','svg','swf','sxc','sxi','sxw','sys','tar','tgz','tiff','tif','tmp','tpl','ttf','txt','wav','wma','wmv','wp','xls','xml','zip');
@@ -609,5 +676,49 @@ function filefield_check_directory($dire
     $path = file_create_path(implode($dirs,'/'));
     file_check_directory($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
   }
-  return true;
+  return TRUE;
+}
+
+/**
+ * Menu callback for JavaScript-based uploads.
+ */
+function filefield_js() {
+  // Parse fieldname from submit button.
+  $matches = array();
+  foreach(array_keys($_POST) as $key) {
+    if (preg_match('/cck_filefield_(.*)_op/', $key, $matches)) {
+      $fieldname = $matches[1];
+      break;
+    }
+  }
+
+  $node = (object)$_POST;
+  $field = content_fields($fieldname, $node->type); // load field data
+
+  // Load fids stored by content.module
+  $node_field = array();
+  $values = content_field('load', $node, $field, $node_field, FALSE, FALSE);
+  $node_field = $values[$fieldname];
+
+  // Load additional field data
+  filefield_field('load', $node, $field, $node_field, FALSE, FALSE);
+
+  // Handle uploads and validation.
+  _filefield_widget_prepare_form_values($node, $field, $node_field);
+  _filefield_widget_validate($node, $field, $node_field);
+
+  // Get our new form baby, yeah tiger, get em!
+  $form = _filefield_widget_form($node, $field, $node_field);
+
+  foreach (module_implements('form_alter') as $module) {
+    $function = $module .'_form_alter';
+    $function('filefield_js', $form);
+  }
+  $form = form_builder('filefield_js', $form);
+
+  $output = theme('status_messages') . drupal_render($form);
+
+  // We send the updated file attachments form.
+  print drupal_to_js(array('status' => TRUE, 'data' => $output));
+  exit();
 }
