diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 4230087..8a77595 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1460,6 +1460,13 @@ function drupal_pre_render_table(array $element) { * ) * ); * @endcode + * - footer: An array containing the table footers. Each element of the array + * can be either a localized string or an associative array with the + * following keys: + * - "data": The localized summary information of the table column. + * - "header": Indicates this cell is a header. + * - Any HTML attributes, such as "colspan", to apply to the column footer + * cell. * - attributes: An array of HTML attributes to apply to the table tag. * - caption: A localized string to use for the tag. * - colgroups: An array of column groups. Each element of the array can be @@ -1598,6 +1605,49 @@ function template_preprocess_table(&$variables) { } } + // Format the table footer: + if (!empty($variables['footer'])) { + + foreach ($variables['footer'] as $col_key => $cell) { + if (!is_array($cell)) { + $cell_content = $cell; + $cell_attributes = new Attribute(); + } + else { + $cell_content = ''; + if (isset($cell['data'])) { + $cell_content = $cell['data']; + unset($cell['data']); + } + // Flag the cell as a header or not and remove the flag. + $is_header = isset($cell['header']) ? $cell['header'] : TRUE; + unset($cell['header']); + + // Track responsive classes for each column as needed. Only the footer + // cells for a column are marked up with the responsive classes by a + // module developer or themer. The responsive classes on the footer cells + // must be transferred to the content cells. + if (!empty($cell['class']) && is_array($cell['class'])) { + if (in_array(RESPONSIVE_PRIORITY_MEDIUM, $cell['class'])) { + $responsive_classes[$col_key] = RESPONSIVE_PRIORITY_MEDIUM; + } + elseif (in_array(RESPONSIVE_PRIORITY_LOW, $cell['class'])) { + $responsive_classes[$col_key] = RESPONSIVE_PRIORITY_LOW; + } + } + + if (is_array($cell_content)) { + $cell_content = drupal_render($cell_content); + } + $cell_attributes = new Attribute($cell); + } + $variables['footer'][$col_key] = array(); + $variables['header'][$col_key]['tag'] = $is_header ? 'th' : 'td'; + $variables['footer'][$col_key]['attributes'] = $cell_attributes; + $variables['footer'][$col_key]['content'] = $cell_content; + } + } + if (!empty($variables['rows'])) { $flip = array('even' => 'odd', 'odd' => 'even'); $class = 'even'; @@ -2553,7 +2603,7 @@ function drupal_common_theme() { 'template' => 'breadcrumb', ), 'table' => array( - 'variables' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL, 'colgroups' => array(), 'sticky' => FALSE, 'responsive' => TRUE, 'empty' => ''), + 'variables' => array('header' => NULL, 'footer' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL, 'colgroups' => array(), 'sticky' => FALSE, 'responsive' => TRUE, 'empty' => ''), 'template' => 'table', ), 'tablesort_indicator' => array( diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php index 6b9c5ef..80f5f90 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php @@ -86,15 +86,24 @@ function testThemeTableWithEmptyMessage() { 'colspan' => 2, ), ); + $footer = array( + 'Footer 1', + array( + 'data' => 'Footer 2', + 'colspan' => 2, + ), + ); $table = array( '#type' => 'table', '#header' => $header, + '#footer' => $footer, '#rows' => array(), '#empty' => 'Empty row.', ); $this->render($table); $this->removeWhiteSpace(); $this->assertRaw('Header 1Header 2', 'Table header found.'); + $this->assertRaw('Footer 1Footer 2', 'Table footer found.'); $this->assertRaw('Empty row.', 'Colspan on #empty row found.'); } diff --git a/core/modules/system/templates/table.html.twig b/core/modules/system/templates/table.html.twig index ce69286..884349a 100644 --- a/core/modules/system/templates/table.html.twig +++ b/core/modules/system/templates/table.html.twig @@ -28,6 +28,11 @@ * - attributes: Any HTML attributes, such as "colspan", to apply to the * table cell. * - content: The string to display in the table cell. + * - footer: Table footer cells. Each cell contains the following properties: + * - tag: The HTML tag name to use; either TH or TD. + * - attributes: HTML attributes to apply to the tag. + * - content: A localized string for the title of the column. + * - field: Field name (required for column sorting). * - empty: The message to display in an extra row if table does not have * any rows. * @@ -40,7 +45,6 @@ {% if caption %} {{ caption }} {% endif %} - {% for colgroup in colgroups %} {% if colgroup.cols %} @@ -52,7 +56,6 @@ {% endif %} {% endfor %} - {% if header %} @@ -64,7 +67,6 @@ {% endif %} - {% if rows %} {% for row in rows %} @@ -78,4 +80,15 @@ {% endfor %} {% endif %} + {% if footer %} + + + {% for cell in footer %} + <{{ cell.tag }}{{ cell.attributes }}> + {{- cell.content -}} + + {% endfor %} + + + {% endif %}