Issue #806982 by lokapujya, gnuget, miqmago, shashi1028, Floydm, bfroehle, kathyh, sreynen: Tables should take an optional footer variable and produce <tfoot>.
parent
135ca1c04f
commit
1c7cf17980
|
@ -1428,32 +1428,32 @@ function drupal_pre_render_table(array $element) {
|
||||||
* - header: An array containing the table headers. Each element of the array
|
* - header: An array containing the table headers. Each element of the array
|
||||||
* can be either a localized string or an associative array with the
|
* can be either a localized string or an associative array with the
|
||||||
* following keys:
|
* following keys:
|
||||||
* - "data": The localized title of the table column.
|
* - data: The localized title of the table column.
|
||||||
* - "field": The database field represented in the table column (required
|
* - field: The database field represented in the table column (required
|
||||||
* if user is to be able to sort on this column).
|
* if user is to be able to sort on this column).
|
||||||
* - "sort": A default sort order for this column ("asc" or "desc"). Only
|
* - sort: A default sort order for this column ("asc" or "desc"). Only
|
||||||
* one column should be given a default sort order because table sorting
|
* one column should be given a default sort order because table sorting
|
||||||
* only applies to one column at a time.
|
* only applies to one column at a time.
|
||||||
* - "class": An array of values for the 'class' attribute. In particular,
|
* - class: An array of values for the 'class' attribute. In particular,
|
||||||
* the least important columns that can be hidden on narrow and medium
|
* the least important columns that can be hidden on narrow and medium
|
||||||
* width screens should have a 'priority-low' class, referenced with the
|
* width screens should have a 'priority-low' class, referenced with the
|
||||||
* RESPONSIVE_PRIORITY_LOW constant. Columns that should be shown on
|
* RESPONSIVE_PRIORITY_LOW constant. Columns that should be shown on
|
||||||
* medium+ wide screens should be marked up with a class of
|
* medium+ wide screens should be marked up with a class of
|
||||||
* 'priority-medium', referenced by with the RESPONSIVE_PRIORITY_MEDIUM
|
* 'priority-medium', referenced by with the RESPONSIVE_PRIORITY_MEDIUM
|
||||||
* constant. Themes may hide columns with one of these two classes on
|
* constant. Themes may hide columns with one of these two classes on
|
||||||
* narrow viewports to save horizontal space.
|
* narrow viewports to save horizontal space.
|
||||||
* - Any HTML attributes, such as "colspan", to apply to the column header
|
* - Any HTML attributes, such as "colspan", to apply to the column header
|
||||||
* cell.
|
* cell.
|
||||||
* - rows: An array of table rows. Every row is an array of cells, or an
|
* - rows: An array of table rows. Every row is an array of cells, or an
|
||||||
* associative array with the following keys:
|
* associative array with the following keys:
|
||||||
* - "data": an array of cells
|
* - data: An array of cells.
|
||||||
* - Any HTML attributes, such as "class", to apply to the table row.
|
* - Any HTML attributes, such as "class", to apply to the table row.
|
||||||
* - "no_striping": a boolean indicating that the row should receive no
|
* - no_striping: A Boolean indicating that the row should receive no
|
||||||
* 'even / odd' styling. Defaults to FALSE.
|
* 'even / odd' styling. Defaults to FALSE.
|
||||||
* Each cell can be either a string or an associative array with the
|
* Each cell can be either a string or an associative array with the
|
||||||
* following keys:
|
* following keys:
|
||||||
* - "data": The string to display in the table cell.
|
* - data: The string to display in the table cell.
|
||||||
* - "header": Indicates this cell is a header.
|
* - header: Indicates this cell is a header.
|
||||||
* - Any HTML attributes, such as "colspan", to apply to the table cell.
|
* - Any HTML attributes, such as "colspan", to apply to the table cell.
|
||||||
* Here's an example for $rows:
|
* Here's an example for $rows:
|
||||||
* @code
|
* @code
|
||||||
|
@ -1465,9 +1465,11 @@ function drupal_pre_render_table(array $element) {
|
||||||
* // Row with attributes on the row and some of its cells.
|
* // Row with attributes on the row and some of its cells.
|
||||||
* array(
|
* array(
|
||||||
* 'data' => array('Cell 1', array('data' => 'Cell 2', 'colspan' => 2)), 'class' => array('funky')
|
* 'data' => array('Cell 1', array('data' => 'Cell 2', 'colspan' => 2)), 'class' => array('funky')
|
||||||
* )
|
* ),
|
||||||
* );
|
* );
|
||||||
* @endcode
|
* @endcode
|
||||||
|
* - footer: An array of table rows which will be printed within a <tfoot>
|
||||||
|
* tag, in the same format as the rows element (see above).
|
||||||
* - attributes: An array of HTML attributes to apply to the table tag.
|
* - attributes: An array of HTML attributes to apply to the table tag.
|
||||||
* - caption: A localized string to use for the <caption> tag.
|
* - caption: A localized string to use for the <caption> tag.
|
||||||
* - colgroups: An array of column groups. Each element of the array can be
|
* - colgroups: An array of column groups. Each element of the array can be
|
||||||
|
@ -1612,77 +1614,81 @@ function template_preprocess_table(&$variables) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($variables['rows'])) {
|
// Rows and footer have the same structure.
|
||||||
$flip = array('even' => 'odd', 'odd' => 'even');
|
$sections = array('rows' , 'footer');
|
||||||
$class = 'even';
|
foreach ($sections as $section) {
|
||||||
foreach ($variables['rows'] as $row_key => $row) {
|
if (!empty($variables[$section])) {
|
||||||
// Check if we're dealing with a simple or complex row
|
$flip = array('even' => 'odd', 'odd' => 'even');
|
||||||
if (isset($row['data'])) {
|
$class = 'even';
|
||||||
$cells = $row['data'];
|
foreach ($variables[$section] as $row_key => $row) {
|
||||||
$no_striping = isset($row['no_striping']) ? $row['no_striping'] : FALSE;
|
|
||||||
|
|
||||||
// Set the attributes array and exclude 'data' and 'no_striping'.
|
|
||||||
$row_attributes = $row;
|
|
||||||
unset($row_attributes['data']);
|
|
||||||
unset($row_attributes['no_striping']);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$cells = $row;
|
$cells = $row;
|
||||||
$row_attributes = array();
|
$row_attributes = array();
|
||||||
$no_striping = FALSE;
|
$no_striping = $section === 'footer';
|
||||||
}
|
|
||||||
|
|
||||||
// Add odd/even class.
|
// Check if we're dealing with a simple or complex row
|
||||||
if (!$no_striping) {
|
if (isset($row['data'])) {
|
||||||
$class = $flip[$class];
|
$cells = $row['data'];
|
||||||
$row_attributes['class'][] = $class;
|
$no_striping = isset($row['no_striping']) ? $row['no_striping'] : $no_striping;
|
||||||
}
|
|
||||||
|
|
||||||
// Build row.
|
// Set the attributes array and exclude 'data' and 'no_striping'.
|
||||||
$variables['rows'][$row_key] = array();
|
$row_attributes = $row;
|
||||||
$variables['rows'][$row_key]['attributes'] = new Attribute($row_attributes);
|
unset($row_attributes['data']);
|
||||||
$variables['rows'][$row_key]['cells'] = array();
|
unset($row_attributes['no_striping']);
|
||||||
if (!empty($cells)) {
|
}
|
||||||
// Reset the responsive index.
|
|
||||||
$responsive_index = -1;
|
|
||||||
foreach ($cells as $col_key => $cell) {
|
|
||||||
// Increase the responsive index.
|
|
||||||
$responsive_index++;
|
|
||||||
|
|
||||||
if (!is_array($cell)) {
|
// Add odd/even class.
|
||||||
$cell_content = $cell;
|
if (!$no_striping) {
|
||||||
$cell_attributes = array();
|
$class = $flip[$class];
|
||||||
$is_header = FALSE;
|
$row_attributes['class'][] = $class;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
$cell_content = '';
|
|
||||||
if (isset($cell['data'])) {
|
// Build row.
|
||||||
$cell_content = $cell['data'];
|
$variables[$section][$row_key] = array();
|
||||||
unset($cell['data']);
|
$variables[$section][$row_key]['attributes'] = new Attribute($row_attributes);
|
||||||
|
$variables[$section][$row_key]['cells'] = array();
|
||||||
|
if (!empty($cells)) {
|
||||||
|
// Reset the responsive index.
|
||||||
|
$responsive_index = -1;
|
||||||
|
foreach ($cells as $col_key => $cell) {
|
||||||
|
// Increase the responsive index.
|
||||||
|
$responsive_index++;
|
||||||
|
|
||||||
|
if (!is_array($cell)) {
|
||||||
|
$cell_content = $cell;
|
||||||
|
$cell_attributes = array();
|
||||||
|
$is_header = FALSE;
|
||||||
}
|
}
|
||||||
// Flag the cell as a header or not and remove the flag.
|
else {
|
||||||
$is_header = !empty($cell['header']);
|
$cell_content = '';
|
||||||
unset($cell['header']);
|
if (isset($cell['data'])) {
|
||||||
|
$cell_content = $cell['data'];
|
||||||
|
unset($cell['data']);
|
||||||
|
}
|
||||||
|
|
||||||
$cell_attributes = $cell;
|
// Flag the cell as a header or not and remove the flag.
|
||||||
|
$is_header = !empty($cell['header']);
|
||||||
|
unset($cell['header']);
|
||||||
|
|
||||||
if (is_array($cell_content)) {
|
$cell_attributes = $cell;
|
||||||
$cell_content = drupal_render($cell_content);
|
|
||||||
|
if (is_array($cell_content)) {
|
||||||
|
$cell_content = drupal_render($cell_content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Add active class if needed for sortable tables.
|
||||||
|
if (isset($variables['header'][$col_key]['data']) && $variables['header'][$col_key]['data'] == $ts['name'] && !empty($variables['header'][$col_key]['field'])) {
|
||||||
|
$cell_attributes['class'][] = 'active';
|
||||||
|
}
|
||||||
|
// Copy RESPONSIVE_PRIORITY_LOW/RESPONSIVE_PRIORITY_MEDIUM
|
||||||
|
// class from header to cell as needed.
|
||||||
|
if (isset($responsive_classes[$responsive_index])) {
|
||||||
|
$cell_attributes['class'][] = $responsive_classes[$responsive_index];
|
||||||
|
}
|
||||||
|
$variables[$section][$row_key]['cells'][$col_key]['tag'] = $is_header ? 'th' : 'td';
|
||||||
|
$variables[$section][$row_key]['cells'][$col_key]['attributes'] = new Attribute($cell_attributes);
|
||||||
|
$variables[$section][$row_key]['cells'][$col_key]['content'] = $cell_content;
|
||||||
}
|
}
|
||||||
// Add active class if needed for sortable tables.
|
|
||||||
if (isset($variables['header'][$col_key]['data']) && $variables['header'][$col_key]['data'] == $ts['name'] && !empty($variables['header'][$col_key]['field'])) {
|
|
||||||
$cell_attributes['class'][] = 'active';
|
|
||||||
}
|
|
||||||
// Copy RESPONSIVE_PRIORITY_LOW/RESPONSIVE_PRIORITY_MEDIUM
|
|
||||||
// class from header to cell as needed.
|
|
||||||
if (isset($responsive_classes[$responsive_index])) {
|
|
||||||
$cell_attributes['class'][] = $responsive_classes[$responsive_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
$variables['rows'][$row_key]['cells'][$col_key]['tag'] = $is_header ? 'th' : 'td';
|
|
||||||
$variables['rows'][$row_key]['cells'][$col_key]['attributes'] = new Attribute($cell_attributes);
|
|
||||||
$variables['rows'][$row_key]['cells'][$col_key]['content'] = $cell_content;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2561,7 +2567,7 @@ function drupal_common_theme() {
|
||||||
'template' => 'breadcrumb',
|
'template' => 'breadcrumb',
|
||||||
),
|
),
|
||||||
'table' => array(
|
'table' => array(
|
||||||
'variables' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL, 'colgroups' => array(), 'sticky' => FALSE, 'responsive' => TRUE, 'empty' => ''),
|
'variables' => array('header' => NULL, 'rows' => NULL, 'footer' => NULL, 'attributes' => array(), 'caption' => NULL, 'colgroups' => array(), 'sticky' => FALSE, 'responsive' => TRUE, 'empty' => ''),
|
||||||
'template' => 'table',
|
'template' => 'table',
|
||||||
),
|
),
|
||||||
'tablesort_indicator' => array(
|
'tablesort_indicator' => array(
|
||||||
|
|
|
@ -110,6 +110,28 @@ class TableTest extends DrupalUnitTestBase {
|
||||||
$this->assertNoRaw('no_striping', 'No invalid no_striping HTML attribute was printed.');
|
$this->assertNoRaw('no_striping', 'No invalid no_striping HTML attribute was printed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the 'footer' option works correctly.
|
||||||
|
*/
|
||||||
|
function testThemeTableFooter() {
|
||||||
|
$footer = array(
|
||||||
|
array(
|
||||||
|
'data' => array(1),
|
||||||
|
),
|
||||||
|
array('Foo'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$table = array(
|
||||||
|
'#type' => 'table',
|
||||||
|
'#rows' => array(),
|
||||||
|
'#footer' => $footer,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->render($table);
|
||||||
|
$this->removeWhiteSpace();
|
||||||
|
$this->assertRaw('<tfoot><tr><td>1</td></tr><tr><td>Foo</td></tr></tfoot>', 'Table footer found.');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that the 'header' option in cells works correctly.
|
* Tests that the 'header' option in cells works correctly.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
* - attributes: Any HTML attributes, such as "colspan", to apply to the
|
* - attributes: Any HTML attributes, such as "colspan", to apply to the
|
||||||
* table cell.
|
* table cell.
|
||||||
* - content: The string to display in the table cell.
|
* - content: The string to display in the table cell.
|
||||||
|
* - footer: Table footer rows, in the same format as the rows variable.
|
||||||
* - empty: The message to display in an extra row if table does not have
|
* - empty: The message to display in an extra row if table does not have
|
||||||
* any rows.
|
* any rows.
|
||||||
*
|
*
|
||||||
|
@ -78,4 +79,17 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if footer %}
|
||||||
|
<tfoot>
|
||||||
|
{% for row in footer %}
|
||||||
|
<tr{{ row.attributes }}>
|
||||||
|
{% for cell in row.cells %}
|
||||||
|
<{{ cell.tag }}{{ cell.attributes }}>
|
||||||
|
{{- cell.content -}}
|
||||||
|
</{{ cell.tag }}>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tfoot>
|
||||||
|
{% endif %}
|
||||||
</table>
|
</table>
|
||||||
|
|
Loading…
Reference in New Issue