Index: fieldgroup_table.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fieldgroup_table/fieldgroup_table.module,v
retrieving revision 1.1
diff -u -u -p -r1.1 fieldgroup_table.module
--- fieldgroup_table.module	28 Dec 2006 21:33:46 -0000	1.1
+++ fieldgroup_table.module	15 Jul 2008 04:07:09 -0000
@@ -24,8 +24,13 @@ function fieldgroup_table_form_alter($fo
     foreach (fieldgroup_groups($form['type']['#value']) as $group_name => $group) {
       // Are we allowed to touch this fieldgroup?
       if (isset($group['settings']['multiple']) && $group['settings']['multiple']) {
+
+        // get all the deltas for all fields
+        $deltas = _fieldgroup_get_deltas( $group['fields'], $form[$group_name] );
+
         $fields = array();
         $header = array();
+        $rows = array();
         // Hijack the fields with multiple values enabled.
         foreach ($group['fields'] as $field_name => $field) {
           if (isset($form[$group_name][$field_name])) {
@@ -38,25 +43,28 @@ function fieldgroup_table_form_alter($fo
             }
           }
         }
-        $rows = array();
-        $delta = 0;
-        // Rewrite the array.
-        while (TRUE) {
-          $row = array();
-          foreach ($fields as $field_name => $field) {
-            if (isset($field[$delta])) {
-              $row[$field_name] = $field[$delta];
+
+        $node = $form["#node"];
+        foreach( $deltas as $delta ) {
+          if( is_int( $delta ) ) {
+            $row = array();
+            foreach( $fields as $field_name => $field ) {
+              $items = array();
+              $items[0] = $node->{$field_name}[$delta];
+              
+              // prepare the widgets as a grid of single widgets rather than one multi-select widget
+              // this is only needed for select fields etc.
+              _fieldgroup_table_widget_invoke( 'prepare form values', $node, $field_name, $items, $delta );
+              $tempform = _fieldgroup_table_widget_invoke('form', $node, $field_name, $items, $delta );
+              $row[$field_name] = $tempform[$field_name];
+              
               // Enable tree.
               $row[$field_name]['#tree'] = TRUE;
               // Override the parents with the "normal" path.
-              $row[$field_name]['#parents'] = array($field_name,$delta);
+              $row[$field_name]['#parents'] = array($group_name,$field_name,$delta);
             }
+            $rows[] = $row;
           }
-          if (empty($row)) {
-            break;
-          }
-          $rows[] = $row;
-          $delta++;
         }
 
         $form[$group_name]['fieldgroup_table'] = array(
@@ -74,6 +82,71 @@ function fieldgroup_table_form_alter($fo
 }
 
 /**
+ * Implementation of hook_nodeapi
+ */
+function fieldgroup_table_nodeapi(&$node, $op, $teaser, $page) {
+  switch ($op) {
+    case 'submit':
+      // post process the forms to turn a list of single input widgets into a one multiple field
+      foreach (fieldgroup_groups($node->type) as $group_name => $group) {
+        if (isset($group['settings']['multiple']) && $group['settings']['multiple']) {
+          $deltas = _fieldgroup_get_deltas( $group['fields'], $node->{$group_name} );
+          
+          // save the fields
+          foreach( $deltas as $delta ) {
+            foreach( $group['fields'] as $field_name => $field ) {
+              $items = array();
+              $items = $node->{$group_name}[$field_name][$delta];
+              
+              _fieldgroup_table_widget_invoke( 'submit', $node, $field_name, $items, $delta );
+              _fieldgroup_table_widget_invoke( 'process form values', $node, $field_name, $items, $delta );
+              $node->{$field_name}[$delta] = $items[0];
+            }
+          }
+          
+          _content_field_invoke('submit', $node);
+          _content_field_invoke_default('submit', $node);
+        }
+      }
+      
+      break;
+  }
+}
+
+/**
+ * get a list of deltas
+ */
+function _fieldgroup_get_deltas( $fields, $data ) {
+//  dpr(func_get_args(), FALSE, '_fieldgroup_get_deltas($fields, $data)');
+  $deltas = array();
+  foreach ( $fields as $field_name => $field ) {
+    if (fieldgroup_table_check_field_multiple($field_name)) {
+      $deltas = array_unique( array_merge( $deltas, array_keys($data[$field_name]) ) );
+    }
+  }
+  return $deltas;
+}
+
+/**
+ * Invoke widget hook on a single widget but make the widget not multiple first
+ */
+function _fieldgroup_table_widget_invoke( $op, $node, $field_name, &$items, $delta ) {
+  static $widget_types = NULL;
+  if( !$widget_types ) {
+    $widget_types = _content_widget_types();
+  }
+  $type = content_types($node->type);        
+  $module = $widget_types[$type['fields'][$field_name]['widget']['type']]['module'];
+  $function = $module .'_widget';
+  if (function_exists($function)) {
+    $field_info = $type['fields'][$field_name];
+    $field_info['multiple'] = FALSE;
+    $field_info['required'] = ($delta==0) ? $field_info['required'] : FALSE;
+    return $function( $op, $node, $field_info, $items );
+  }
+}
+
+/**
  * Implementation of hook_elements().
  */
 function fieldgroup_table_elements() {
