diff options
author | Angie Byron <webchick@24967.no-reply.drupal.org> | 2009-01-28 07:43:26 +0000 |
---|---|---|
committer | Angie Byron <webchick@24967.no-reply.drupal.org> | 2009-01-28 07:43:26 +0000 |
commit | ad99dd761a7e11256200d959f10c9898befa8176 (patch) | |
tree | be658215f4af3a0a3fb56126fb11b829ce8f3b9a | |
parent | f16eccbe9d0199385e0334b1692d6a1ec7225917 (diff) | |
download | brdo-ad99dd761a7e11256200d959f10c9898befa8176.tar.gz brdo-ad99dd761a7e11256200d959f10c9898befa8176.tar.bz2 |
#242962 by Heine: Add a 'tablesort' Form API element to unify various places we use a big table with JS-enabled checkboxes next to each item (with tests).
-rw-r--r-- | includes/common.inc | 8 | ||||
-rw-r--r-- | includes/form.inc | 111 | ||||
-rw-r--r-- | includes/tablesort.inc | 11 | ||||
-rw-r--r-- | modules/comment/comment.admin.inc | 87 | ||||
-rw-r--r-- | modules/comment/comment.module | 3 | ||||
-rw-r--r-- | modules/simpletest/tests/form.test | 203 | ||||
-rw-r--r-- | modules/simpletest/tests/form_test.info | 8 | ||||
-rw-r--r-- | modules/simpletest/tests/form_test.module | 182 | ||||
-rw-r--r-- | modules/system/system.module | 9 |
9 files changed, 548 insertions, 74 deletions
diff --git a/includes/common.inc b/includes/common.inc index 3e5d0c383..95bc9fc33 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -3354,7 +3354,10 @@ function drupal_render(&$elements) { } $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : ''; $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : ''; - return $prefix . $content . $suffix; + $content = $prefix . $content . $suffix; + // Store the rendered content, so higher level elements can reuse it. + $elements['#content'] = $content; + return $content; } } @@ -3609,6 +3612,9 @@ function drupal_common_theme() { 'file' => array( 'arguments' => array('element' => NULL), ), + 'tableselect' => array( + 'arguments' => array('element' => NULL), + ), 'form_element' => array( 'arguments' => array('element' => NULL, 'value' => NULL), ), diff --git a/includes/form.inc b/includes/form.inc index 8ce4563cd..f5e1a61de 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -2037,6 +2037,117 @@ function form_process_checkboxes($element) { } /** + * Format a table with radio buttons or checkboxes. + * + * @param $element + * An associative array containing the properties and children of the + * tableselect element. + * Properties used: header, options, empty, js_select. + * + * @return + * A themed HTML string representing the table. + * + * @ingroup themeable + */ +function theme_tableselect($element) { + $rows = array(); + if (!empty($element['#options'])) { + // Generate a table row for each selectable item in #options. + foreach ($element['#options'] as $key => $value) { + $row = array(); + + // Render the checkbox / radio element. + $row[] = $element[$key]['#content']; + + // As theme_table only maps header and row columns by order, create the + // correct order by iterating over the header fields. + foreach ($element['#header'] as $fieldname => $title) { + $row[] = $element['#options'][$key][$fieldname]; + } + $rows[] = $row; + } + // Add an empty header or a "Select all" checkbox to provide room for the + // checkboxes/radios in the first table column. + $first_col = $element['#js_select'] ? array(theme('table_select_header_cell')) : array(''); + $header = array_merge($first_col, $element['#header']); + } + else { + // If there are no selectable options, display the empty text over the + // entire width of the table. + $header = $element['#header']; + $rows[] = array(array('data' => $element['#empty'], 'colspan' => count($header))); + } + return theme('table', $header, $rows); +} + +/** + * Create the correct amount of checkbox or radio elements to populate the table. + * + * @param $element + * An associative array containing the properties and children of the + * tableselect element. + * + * @return + * The processed element. + */ +function form_process_tableselect($element) { + + if ($element['#multiple']) { + $value = is_array($element['#value']) ? $element['#value'] : array(); + } + else { + // Advanced selection behaviour make no sense for radios. + $element['#js_select'] = FALSE; + } + + $element['#tree'] = TRUE; + + if (count($element['#options']) > 0) { + if (!isset($element['#default_value']) || $element['#default_value'] === 0) { + $element['#default_value'] = array(); + } + + // Create a checkbox or radio for each item in #options in such a way that + // the value of the tableselect element behaves as if it had been of type + // checkboxes or radios. + foreach ($element['#options'] as $key => $choice) { + // Do not overwrite manually created children. + if (!isset($element[$key])) { + if ($element['#multiple']) { + $element[$key] = array( + '#type' => 'checkbox', + '#title' => '', + '#return_value' => $key, + '#default_value' => isset($value[$key]), + '#attributes' => $element['#attributes'], + '#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL, + ); + } + else { + // Generate the parents as the autogenerator does, so we will have a + // unique id for each radio button. + $parents_for_id = array_merge($element['#parents'], array($key)); + $element[$key] = array( + '#type' => 'radio', + '#title' => '', + '#return_value' => $key, + '#default_value' => ($element['#default_value'] == $key) ? $key : NULL, + '#attributes' => $element['#attributes'], + '#parents' => $element['#parents'], + '#id' => form_clean_id('edit-' . implode('-', $parents_for_id)), + '#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL, + ); + } + } + } + } + else { + $element['#value'] = array(); + } + return $element; +} + +/** * Theme a form submit button. * * @ingroup themeable diff --git a/includes/tablesort.inc b/includes/tablesort.inc index 3c2068e1b..36f01607f 100644 --- a/includes/tablesort.inc +++ b/includes/tablesort.inc @@ -165,13 +165,14 @@ function tablesort_get_order($headers) { return $default; } else { - // The first column specified is initial 'order by' field unless otherwise specified - if (is_array($headers[0])) { - $headers[0] += array('data' => NULL, 'field' => NULL); - return array('name' => $headers[0]['data'], 'sql' => $headers[0]['field']); + // The first column specified is the initial 'order by' field unless otherwise specified. + $first = current($headers); + if (is_array($first)) { + $first += array('data' => NULL, 'field' => NULL); + return array('name' => $first['data'], 'sql' => $first['field']); } else { - return array('name' => $headers[0]); + return array('name' => $first, 'sql' => ''); } } } diff --git a/modules/comment/comment.admin.inc b/modules/comment/comment.admin.inc index a2103d301..2ed783808 100644 --- a/modules/comment/comment.admin.inc +++ b/modules/comment/comment.admin.inc @@ -58,43 +58,37 @@ function comment_admin_overview($type = 'new', $arg) { // Load the comments that need to be displayed. $status = ($arg == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED; - $form['header'] = array( - '#type' => 'value', - '#value' => array( - theme('table_select_header_cell'), - array('data' => t('Subject'), 'field' => 'subject'), - array('data' => t('Author'), 'field' => 'name'), - array('data' => t('Posted in'), 'field' => 'node_title'), - array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'), - array('data' => t('Operations')), - )); - $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid, n.title as node_title FROM {comment} c INNER JOIN {users} u ON u.uid = c.uid INNER JOIN {node} n ON n.nid = c.nid WHERE c.status = %d' . tablesort_sql($form['header']['#value']), 50, 0, NULL, $status); + $header = array( + 'subject' => array('data' => t('Subject'), 'field' => 'subject'), + 'author' => array('data' => t('Author'), 'field' => 'name'), + 'posted_in' => array('data' => t('Posted in'), 'field' => 'node_title'), + 'time' => array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'), + 'operations' => array('data' => t('Operations')), + ); + + $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid, n.title as node_title FROM {comment} c INNER JOIN {users} u ON u.uid = c.uid INNER JOIN {node} n ON n.nid = c.nid WHERE c.status = %d' . tablesort_sql($header), 50, 0, NULL, $status); // Build a table listing the appropriate comments. + $options = array(); $destination = drupal_get_destination(); + while ($comment = db_fetch_object($result)) { - $comments[$comment->cid] = ''; - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - $form['subject'][$comment->cid] = array( - '#markup' => l($comment->subject, 'node/' . $comment->nid, array('attributes' => array('title' => truncate_utf8($comment->comment, 128)), 'fragment' => 'comment-' . $comment->cid)) - ); - $form['username'][$comment->cid] = array( - '#markup' => theme('username', $comment) - ); - $form['node_title'][$comment->cid] = array( - '#markup' => l($comment->node_title, 'node/' . $comment->nid) - ); - $form['timestamp'][$comment->cid] = array( - '#markup' => format_date($comment->timestamp, 'small') - ); - $form['operations'][$comment->cid] = array( - '#markup' => l(t('edit'), 'comment/edit/' . $comment->cid, array('query' => $destination)) + $options[$comment->cid] = array( + 'subject' => l($comment->subject, 'node/' . $comment->nid, array('attributes' => array('title' => truncate_utf8($comment->comment, 128)), 'fragment' => 'comment-' . $comment->cid)), + 'author' => theme('username', $comment), + 'posted_in' => l($comment->node_title, 'node/' . $comment->nid), + 'time' => format_date($comment->timestamp, 'small'), + 'operations' => l(t('edit'), 'comment/edit/' . $comment->cid, array('query' => $destination)), ); } + $form['comments'] = array( - '#type' => 'checkboxes', - '#options' => isset($comments) ? $comments: array() + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + '#empty' => t('No comments available.'), ); + $form['pager'] = array( '#markup' => theme('pager', NULL, 50, 0) ); @@ -146,41 +140,6 @@ function comment_admin_overview_submit($form, &$form_state) { } /** - * Theme the comment admin form. - * - * @param $form - * An associative array containing the structure of the form. - * @ingroup themeable - */ -function theme_comment_admin_overview($form) { - $output = drupal_render($form['options']); - if (isset($form['subject']) && is_array($form['subject'])) { - foreach (element_children($form['subject']) as $key) { - $row = array(); - $row[] = drupal_render($form['comments'][$key]); - $row[] = drupal_render($form['subject'][$key]); - $row[] = drupal_render($form['username'][$key]); - $row[] = drupal_render($form['node_title'][$key]); - $row[] = drupal_render($form['timestamp'][$key]); - $row[] = drupal_render($form['operations'][$key]); - $rows[] = $row; - } - } - else { - $rows[] = array(array('data' => t('No comments available.'), 'colspan' => '6')); - } - - $output .= theme('table', $form['header']['#value'], $rows); - if ($form['pager']['#markup']) { - $output .= drupal_render($form['pager']); - } - - $output .= drupal_render($form); - - return $output; -} - -/** * List the selected comments and verify that the admin wants to delete them. * * @param $form_state diff --git a/modules/comment/comment.module b/modules/comment/comment.module index a92b96a45..a69fba641 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -118,9 +118,6 @@ function comment_theme() { 'comment_block' => array( 'arguments' => array(), ), - 'comment_admin_overview' => array( - 'arguments' => array('form' => NULL), - ), 'comment_preview' => array( 'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1), ), diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test index 64311a9c3..8d376bfb7 100644 --- a/modules/simpletest/tests/form.test +++ b/modules/simpletest/tests/form.test @@ -110,3 +110,206 @@ class FormsTestTypeCase extends DrupalWebTestCase { } } +/** + * Test the tableselect form element for expected behavior. + */ +class FormsElementsTableSelectFunctionalTest extends DrupalWebTestCase { + + function getInfo() { + return array( + 'name' => t('Tableselect form element type test'), + 'description' => t('Test the tableselect element for expected behavior'), + 'group' => t('Form API'), + ); + } + + function setUp() { + parent::setUp('form_test'); + } + + + /** + * Test the display of checkboxes when #multiple is TRUE. + */ + function testMultipleTrue() { + + $this->drupalGet('form_test/tableselect/multiple-true'); + + $this->assertNoText(t('Empty text.'), t('Empty text should not be displayed.')); + + // Test for the presence of the Select all rows tableheader. + $this->assertFieldByXPath('//th[@class="select-all"]', NULL, t('Presence of the "Select all" checkbox.')); + + $rows = array('row1', 'row2', 'row3'); + foreach($rows as $row) { + $this->assertFieldByXPath('//input[@type="checkbox"]', $row, t('Checkbox for value @row.', array('@row' => $row))); + } + } + + /** + * Test the display of radios when #multiple is FALSE. + */ + function testMultipleFalse() { + $this->drupalGet('form_test/tableselect/multiple-false'); + + $this->assertNoText(t('Empty text.'), t('Empty text should not be displayed.')); + + // Test for the absence of the Select all rows tableheader. + $this->assertNoFieldByXPath('//th[@class="select-all"]', '', t('Absence of the "Select all" checkbox.')); + + $rows = array('row1', 'row2', 'row3'); + foreach($rows as $row) { + $this->assertFieldByXPath('//input[@type="radio"]', $row, t('Radio button for value @row.', array('@row' => $row))); + } + } + + /** + * Test the display of the #empty text when #options is an empty array. + */ + function testEmptyText() { + $this->drupalGet('form_test/tableselect/empty-text'); + $this->assertText(t('Empty text.'), t('Empty text should be displayed.')); + } + + /** + * Test the submission of single and multiple values when #multiple is TRUE. + */ + function testMultipleTrueSubmit() { + + // Test a submission with one checkbox checked. + $edit = array(); + $edit['tableselect[row1]'] = TRUE; + $this->drupalPost('form_test/tableselect/multiple-true', $edit, 'Submit'); + + $this->assertText(t('Submitted: row1 = row1'), t('Checked checkbox row1')); + $this->assertText(t('Submitted: row2 = 0'), t('Unchecked checkbox row2.')); + $this->assertText(t('Submitted: row3 = 0'), t('Unchecked checkbox row3.')); + + // Test a submission with multiple checkboxes checked. + $edit['tableselect[row1]'] = TRUE; + $edit['tableselect[row3]'] = TRUE; + $this->drupalPost('form_test/tableselect/multiple-true', $edit, 'Submit'); + + $this->assertText(t('Submitted: row1 = row1'), t('Checked checkbox row1.')); + $this->assertText(t('Submitted: row2 = 0'), t('Unchecked checkbox row2.')); + $this->assertText(t('Submitted: row3 = row3'), t('Checked checkbox row3.')); + + } + + /** + * Test submission of values when #multiple is FALSE. + */ + function testMultipleFalseSubmit() { + $edit['tableselect'] = 'row1'; + $this->drupalPost('form_test/tableselect/multiple-false', $edit, 'Submit'); + $this->assertText(t('Submitted: row1'), t('Selected radio button')); + } + + /** + * Test the #js_select property. + */ + function testAdvancedSelect() { + // When #multiple = TRUE a Select all checkbox should be displayed by default. + $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-default'); + $this->assertFieldByXPath('//th[@class="select-all"]', NULL, t('Display a "Select all" checkbox by default when #multiple is TRUE.')); + + // When #js_select is set to FALSE, a "Select all" checkbox should not be displayed. + $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-no-advanced-select'); + $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, t('Do not display a "Select all" checkbox when #js_select is FALSE.')); + + // A "Select all" checkbox never makes sense when #multiple = FALSE, regardless of the value of #js_select. + $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-default'); + $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, t('Do not display a "Select all" checkbox when #multiple is FALSE.')); + + $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-advanced-select'); + $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, t('Do not display a "Select all" checkbox when #multiple is FALSE, even when #js_select is TRUE.')); + } + + + /** + * Test the whether the option checker gives an error on invalid tableselect values for checkboxes. + */ + function testMultipleTrueOptionchecker() { + + list($header, $options) = _form_test_tableselect_get_data(); + + $form['tableselect'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + ); + + // Test with a valid value. + list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'row1')); + $this->assertFalse(isset($errors['tableselect']), t('Option checker allows valid values for checkboxes.')); + + // Test with an invalid value. + list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'non_existing_value')); + $this->assertTrue(isset($errors['tableselect']), t('Option checker disallows invalid values for checkboxes.')); + + } + + + /** + * Test the whether the option checker gives an error on invalid tableselect values for radios. + */ + function testMultipleFalseOptionchecker() { + + list($header, $options) = _form_test_tableselect_get_data(); + + $form['tableselect'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + '#multiple' => FALSE, + ); + + // Test with a valid value. + list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'row1')); + $this->assertFalse(isset($errors['tableselect']), t('Option checker allows valid values for radio buttons.')); + + // Test with an invalid value. + list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'non_existing_value')); + $this->assertTrue(isset($errors['tableselect']), t('Option checker disallows invalid values for radio buttons.')); + } + + + /** + * Helper function for the option check test to submit a form while collecting errors. + * + * @param $form_element + * A form element to test. + * @param $edit + * An array containing post data. + * + * @return + * An array containing the processed form, the form_state and any errors. + */ + private function formSubmitHelper($form_element, $edit) { + $form_id = $this->randomName(); + + $form = $form_state = array(); + + $form = array_merge($form, $form_element); + $form['op'] = array('#type' => 'submit', '#value' => t('Submit')); + + $form['#post'] = $edit; + $form['#post']['form_id'] = $form_id; + + drupal_prepare_form($form_id, $form, $form_state); + + drupal_process_form($form_id, $form, $form_state); + + $errors = form_get_errors(); + + // Clear errors and messages. + drupal_get_messages(); + form_set_error(NULL, '', TRUE); + + // Return the processed form together with form_state and errors + // to allow the caller lowlevel access to the form. + return array($form, $form_state, $errors); + } + +} + diff --git a/modules/simpletest/tests/form_test.info b/modules/simpletest/tests/form_test.info new file mode 100644 index 000000000..d138f15cc --- /dev/null +++ b/modules/simpletest/tests/form_test.info @@ -0,0 +1,8 @@ +; $Id$ +name = "FormAPI Test" +description = "Support module for Form API tests." +package = Testing +version = VERSION +core = 7.x +files[] = form_test.module +hidden = TRUE diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module new file mode 100644 index 000000000..a1eee25b2 --- /dev/null +++ b/modules/simpletest/tests/form_test.module @@ -0,0 +1,182 @@ +<?php +// $Id$ + +/** + * @file + * Helper module for the form API tests. + */ + +/** + * Implementation of hook_menu(). + */ +function form_test_menu() { + $items = array(); + + $items['form_test/tableselect/multiple-true'] = array( + 'title' => 'Tableselect checkboxes test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_multiple_true_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/tableselect/multiple-false'] = array( + 'title' => 'Tableselect radio button test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_multiple_false_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/tableselect/empty-text'] = array( + 'title' => 'Tableselect empty text test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_empty_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/tableselect/advanced-select'] = array( + 'title' => 'Tableselect js_select tests', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_js_select_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Create a header and options array. Helper function for callbacks. + */ +function _form_test_tableselect_get_data() { + $header = array( + 'one' => t('One'), + 'two' => t('Two'), + 'three' => t('Three'), + 'four' => t('Four'), + ); + + $options['row1'] = array( + 'one' => 'row1col1', + 'two' => t('row1col2'), + 'three' => t('row1col3'), + 'four' => t('row1col4'), + ); + + $options['row2'] = array( + 'one' => 'row2col1', + 'two' => t('row2col2'), + 'three' => t('row2col3'), + 'four' => t('row2col4'), + ); + + $options['row3'] = array( + 'one' => 'row3col1', + 'two' => t('row3col2'), + 'three' => t('row3col3'), + 'four' => t('row3col4'), + ); + + return array($header, $options); +} + +/** + * Build a form to test the tableselect element. + * + * @param $form_state + * The form_state + * @param $element_properties + * An array of element properties for the tableselect element. + * + * @return + * A form with a tableselect element and a submit button. + */ +function _form_test_tableselect_form_builder($form_state, $element_properties) { + $form = array(); + + list($header, $options) = _form_test_tableselect_get_data(); + + $form['tableselect'] = $element_properties; + + $form['tableselect'] += array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + '#multiple' => FALSE, + '#empty' => t('Empty text.'), + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Submit'), + ); + + return $form; +} + +/** + * Test the tableselect #multiple = TRUE functionality. + */ +function _form_test_tableselect_multiple_true_form($form_state) { + return _form_test_tableselect_form_builder($form_state, array('#multiple' => TRUE)); +} + +/** + * Process the tableselect #multiple = TRUE submitted values. + */ +function _form_test_tableselect_multiple_true_form_submit($form, &$form_state) { + $selected = $form_state['values']['tableselect']; + foreach ($selected as $key => $value) { + drupal_set_message(t('Submitted: @key = @value', array('@key' => $key, '@value' => $value))); + } +} + +/** + * Test the tableselect #multiple = FALSE functionality. + */ +function _form_test_tableselect_multiple_false_form($form_state) { + return _form_test_tableselect_form_builder($form_state, array('#multiple' => FALSE)); +} + +/** + * Process the tableselect #multiple = FALSE submitted values. + */ +function _form_test_tableselect_multiple_false_form_submit($form, &$form_state) { + drupal_set_message(t('Submitted: @value', array('@value' => $form_state['values']['tableselect']))); +} + +/** + * Test functionality of the tableselect #empty property. + */ +function _form_test_tableselect_empty_form($form_state) { + return _form_test_tableselect_form_builder($form_state, array('#options' => array())); +} + +/** + * Test functionality of the tableselect #js_select property. + */ +function _form_test_tableselect_js_select_form($form_state, $action) { + + switch ($action) { + + case 'multiple-true-default': + $options = array('#multiple' => TRUE); + break; + + case 'multiple-false-default': + $options = array('#multiple' => FALSE); + break; + + case 'multiple-true-no-advanced-select': + $options = array('#multiple' => TRUE, '#js_select' => FALSE); + break; + + case 'multiple-false-advanced-select': + $options = array('#multiple' => FALSE, '#js_select' => TRUE); + break; + } + + return _form_test_tableselect_form_builder($form_state, $options); +} diff --git a/modules/system/system.module b/modules/system/system.module index 581ae0aab..a7ac5d319 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -354,7 +354,14 @@ function system_elements() { '#input' => TRUE, '#size' => 60, ); - + $type['tableselect'] = array( + '#input' => TRUE, + '#js_select' => TRUE, + '#multiple' => TRUE, + '#process' => array('form_process_tableselect'), + '#options' => array(), + '#empty' => '', + ); /** * Form structure. |