Index: edge.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/edge/edge.module,v
retrieving revision 1.4
diff -u -p -r1.4 edge.module
--- edge.module	9 Nov 2010 23:50:40 -0000	1.4
+++ edge.module	7 Dec 2010 15:01:37 -0000
@@ -7,6 +7,19 @@
  */
 
 /**
+ * Implements hook_element_info().
+ */
+function edge_element_info() {
+  $types['table'] = array(
+    '#header' => array(),
+    '#rows' => array(),
+    '#pre_render' => array('edge_pre_render_table'),
+    '#theme' => 'table',
+  );
+  return $types;
+}
+
+/**
  * Implements hook_theme_registry_alter().
  */
 function edge_theme_registry_alter(&$callbacks) {
@@ -71,3 +84,95 @@ function edge_css_alter(&$css) {
   }
 }
 
+/**
+ * #pre_render callback to transform children of an element into #rows suitable for theme_table().
+ *
+ * This function converts sub-elements of an element of #type 'table' to be
+ * suitable for theme_table():
+ * - The first level of sub-elements are table rows. Only the #attributes
+ *   property is taken into account.
+ * - The second level of sub-elements is converted into columns for the
+ *   corresponding first-level table row.
+ *
+ * Simple example usage:
+ * @code
+ * $form['table'] = array(
+ *   '#type' => 'table',
+ *   '#header' => array(t('Title'), array('data' => t('Operations'), 'colspan' => '1')),
+ *   // Optionally, to add tableDrag support:
+ *   '#attached' => array(
+ *     'tabledrag' => array(array('order', 'sibling', 'thing-weight')),
+ *   ),
+ * );
+ * foreach ($things as $row => $thing) {
+ *   $form['table'][$row]['#weight'] = $thing['weight'];
+ *
+ *   $form['table'][$row]['title'] = array(
+ *     '#type' => 'textfield',
+ *     '#default_value' => $thing['title'],
+ *   );
+ *
+ *   // Optionally, to add tableDrag support:
+ *   $form['table'][$row]['#attributes'] = array('class' => array('draggable'));
+ *   $form['table'][$row]['weight'] = array(
+ *     '#type' => 'textfield',
+ *     '#title' => t('Weight for @title', array('@title' => $thing['title'])),
+ *     '#title_display' => 'invisible',
+ *     '#size' => 4,
+ *     '#default_value' => $thing['weight'],
+ *     '#attributes' => array('class' => array('thing-weight')),
+ *   );
+ *
+ *   // The amount of link columns should be identical to the 'colspan'
+ *   // attribute in #header above.
+ *   $form['table'][$row]['edit'] = array(
+ *     '#type' => 'link',
+ *     '#title' => t('Edit'),
+ *     '#href' => 'thing/' . $row . '/edit',
+ *   );
+ * }
+ * @endcode
+ *
+ * @param $element
+ *   A structured array containing two sub-levels of elements.
+ *
+ * @see system_element_info()
+ * @see theme_table()
+ * @see drupal_process_attached()
+ * @see drupal_add_tabledrag()
+ */
+function edge_pre_render_table($element) {
+  foreach (element_children($element) as $first) {
+    $row = array('data' => array());
+    // Apply attributes of first-level elements as table row attributes.
+    if (isset($element[$first]['#attributes'])) {
+      $row += $element[$first]['#attributes'];
+    }
+    // Turn second-level elements into table row columns.
+    foreach (element_children($element[$first]) as $second) {
+      // Assign the element by reference, so any potential changes to the
+      // original element are taken over.
+      $row['data'][] = array('data' => &$element[$first][$second]);
+    }
+    $element['#rows'][] = $row;
+  }
+
+  // Take over $element['#id'] as HTML ID attribute, if not already set.
+  if (!isset($element['#attributes']['id']) && !empty($element['#id'])) {
+    $element['#attributes']['id'] = $element['#id'];
+  }
+
+  // If the custom #attached][tabledrag] is set and there is a HTML ID, convert
+  // it into #attached][drupal_add_tabledrag] and inject the HTML ID as first
+  // callback argument.
+  if (isset($element['#attached']['tabledrag']) && isset($element['#attributes']['id'])) {
+    $element['#attached']['drupal_add_tabledrag'] = $element['#attached']['tabledrag'];
+    foreach ($element['#attached']['drupal_add_tabledrag'] as &$args) {
+      array_unshift($args, $element['#attributes']['id']);
+    }
+    unset($element['#attached']['tabledrag']);
+  }
+
+  return $element;
+}
+
