Index: edge.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/edge/edge.module,v
retrieving revision 1.5
diff -u -p -r1.5 edge.module
--- edge.module	7 Dec 2010 15:09:37 -0000	1.5
+++ edge.module	3 Jan 2011 20:39:02 -0000
@@ -13,8 +13,17 @@ function edge_element_info() {
   $types['table'] = array(
     '#header' => array(),
     '#rows' => array(),
+    '#empty' => '',
     '#pre_render' => array('edge_pre_render_table'),
     '#theme' => 'table',
+    // Properties for tableselect support.
+    '#tableselect' => FALSE,
+    '#input' => TRUE,
+    '#value_callback' => 'edge_type_table_value',
+    '#tree' => TRUE,
+    '#process' => array('edge_process_table'),
+    '#multiple' => TRUE,
+    '#js_select' => TRUE,
   );
   return $types;
 }
@@ -85,6 +94,121 @@ function edge_css_alter(&$css) {
 }
 
 /**
+ * Helper function to determine the value of a table form element.
+ *
+ * @param $element
+ *   The form element whose value is being populated.
+ * @param $input
+ *   The incoming input to populate the form element. If this is FALSE,
+ *   the element's default value should be returned.
+ *
+ * @return
+ *   The data that will appear in the $element_state['values'] collection
+ *   for this element. Return nothing to use the default.
+ */
+function edge_type_table_value($element, $input = FALSE) {
+  // If #multiple is FALSE, the regular default value of radio buttons is used.
+  if (!empty($element['#multiple'])) {
+    // @todo Why?
+    // Contrary to #type 'checkboxes', the default value of checkboxes in a
+    // table is built from the array keys (instead of array values) of the
+    // #default_value property.
+    if ($input === FALSE) {
+      $element += array('#default_value' => array());
+      return drupal_map_assoc(array_keys(array_filter($element['#default_value'])));
+    }
+    else {
+      return is_array($input) ? drupal_map_assoc($input) : array();
+    }
+  }
+}
+
+/**
+ * #process callback for #type 'table' to add tableselect support.
+ *
+ * @see form_process_tableselect()
+ * @see theme_tableselect()
+ */
+function edge_process_table($element, &$form_state) {
+  if ($element['#tableselect']) {
+    if ($element['#multiple']) {
+      $value = is_array($element['#value']) ? $element['#value'] : array();
+    }
+    // Advanced selection behaviour make no sense for radios.
+    else {
+      $element['#js_select'] = FALSE;
+    }
+    // Add a "Select all" checkbox column to the header.
+    if ($element['#js_select']) {
+      $element['#attached']['js'][] = 'misc/tableselect.js';
+      array_unshift($element['#header'], array('class' => array('select-all')));
+    }
+    // Add an empty header column for radio buttons or a "Select all" checkbox
+    // is not desired.
+    else {
+      array_unshift($element['#header'], '');
+    }
+
+    // @todo FIXME
+    if (!isset($element['#default_value']) || $element['#default_value'] === 0) {
+      $element['#default_value'] = array();
+    }
+    // Create a checkbox or radio for each row in a way that the value of the
+    // tableselect element behaves as if it had been of #type checkboxes or
+    // radios.
+    foreach (element_children($element) as $key) {
+      // Do not overwrite manually created children.
+      if (!isset($element[$key]['select'])) {
+        // Determine option label; either an assumed 'title' column, or the
+        // first available column containing a #title or #markup.
+        $title = '';
+        if (!empty($element[$key]['title']['#title'])) {
+          $title = $element[$key]['title']['#title'];
+        }
+        else {
+          // @todo Performance-optimization.
+          foreach (element_children($element[$key]) as $column) {
+            if (isset($element[$key][$column]['#title'])) {
+              $title = $element[$key][$column]['#title'];
+              break;
+            }
+            if (isset($element[$key][$column]['#markup'])) {
+              $title = $element[$key][$column]['#markup'];
+              break;
+            }
+          }
+        }
+        if ($title !== '') {
+          $title = t('Update !title', array('!title' => $title));
+        }
+
+        // Prepend the select column to existing columns.
+        $element[$key] = array('select' => array()) + $element[$key];
+        $element[$key]['select'] += array(
+          '#type' => $element['#multiple'] ? 'checkbox' : 'radio',
+          '#title' => $title,
+          '#title_display' => 'invisible',
+          '#return_value' => $key,
+          '#attributes' => $element['#attributes'],
+        );
+        $element_parents = array_merge($element['#parents'], array($key));
+        if ($element['#multiple']) {
+          $element[$key]['select']['#default_value'] = isset($value[$key]) ? $key : NULL;
+          $element[$key]['select']['#parents'] = $element_parents;
+        }
+        else {
+          $element[$key]['select']['#default_value'] = ($element['#default_value'] == $key ? $key : NULL);
+          $element[$key]['select']['#parents'] = $element['#parents'];
+          $element[$key]['select']['#id'] = drupal_html_id('edit-' . implode('-', $element_parents));
+        }
+      }
+    }
+  }
+
+  return $element;
+}
+
+/**
  * #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
