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 1 | Header 2 |
', 'Table header found.');
+ $this->assertRaw('Footer 1 | Footer 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 -}}
+ {{ cell.tag }}>
+ {% endfor %}
+
+
+ {% endif %}