diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 7400017..59c95f2 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -866,6 +866,7 @@ function template_preprocess_table(&$variables) { if (!is_array($cell)) { $header_columns++; $cell_content = $cell; + $cell_label = $cell; $cell_attributes = new Attribute(); $is_header = TRUE; } @@ -897,6 +898,7 @@ function template_preprocess_table(&$variables) { $responsive_classes[$responsive_index] = RESPONSIVE_PRIORITY_LOW; } } + $cell_label = $cell_content; tablesort_header($cell_content, $cell, $variables['header'], $ts); @@ -907,6 +909,9 @@ function template_preprocess_table(&$variables) { $variables['header'][$col_key]['tag'] = $is_header ? 'th' : 'td'; $variables['header'][$col_key]['attributes'] = $cell_attributes; $variables['header'][$col_key]['content'] = $cell_content; + if (!empty($cell_label)) { + $variables['header'][$col_key]['label'] = $cell_label; + } } } $variables['header_columns'] = $header_columns; @@ -971,6 +976,10 @@ function template_preprocess_table(&$variables) { $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; + if (!empty($variables['header'][$col_key]['label'])) { + $variables[$section][$row_key]['cells'][$col_key]['label'] = $variables['header'][$col_key]['label']; + $variables[$section][$row_key]['cells'][$col_key]['attributes']->setAttribute('data-th', $variables['header'][$col_key]['label']); + } } } } diff --git a/core/misc/tableresponsive.js b/core/misc/tableresponsive.js index f2ebd18..6b82014 100644 --- a/core/misc/tableresponsive.js +++ b/core/misc/tableresponsive.js @@ -55,7 +55,7 @@ // Attach a resize handler to the window. $(window) - .on('resize.tableresponsive', $.proxy(this, 'eventhandlerEvaluateColumnVisibility')) + .on('resize.tableresponsive', $.proxy(this, 'eventhandlerCollapseColumns')) .trigger('resize.tableresponsive'); } @@ -79,6 +79,17 @@ * or priority-medium. */ $.extend(TableResponsive.prototype, /** @lends Drupal.TableResponsive# */{ + eventhandlerCollapseColumns: function (e) { + var $table = this.$table; + var $parent = $table.parent(); + var parentWidth = $parent.width(); + var tableWidth = $table.width(); + // If table is wider than or equal to its parent element width, + // add class is-collapsed to avoid overflowing. + if (parentWidth <= tableWidth) { + $table.addClass('is-collapsed'); + } + }, /** * @param {jQuery.Event} e diff --git a/core/modules/filter/src/Tests/FilterAdminTest.php b/core/modules/filter/src/Tests/FilterAdminTest.php index 7e6a2d3..2aa6726 100644 --- a/core/modules/filter/src/Tests/FilterAdminTest.php +++ b/core/modules/filter/src/Tests/FilterAdminTest.php @@ -377,10 +377,10 @@ function testFilterTipHtmlEscape() { $this->drupalGet('filter/tips'); - $this->assertRaw('' . $link_as_code . ''); - $this->assertRaw('' . $link . ''); - $this->assertRaw('' . $ampersand_as_code . ''); - $this->assertRaw('' . $ampersand . ''); + $this->assertRaw('' . $link_as_code . ''); + $this->assertRaw('' . $link . ''); + $this->assertRaw('' . $ampersand_as_code . ''); + $this->assertRaw('' . $ampersand . ''); } } diff --git a/core/modules/system/css/system.module.css b/core/modules/system/css/system.module.css index b38c5e5..eba6809 100644 --- a/core/modules/system/css/system.module.css +++ b/core/modules/system/css/system.module.css @@ -105,6 +105,11 @@ tr.add-new .tabledrag-changed { a.tabledrag-handle:hover { text-decoration: none; } + +/* If inside of a collapsible table, float the handle to the right side */ +.responsive-enabled.is-collapsed a.tabledrag-handle { + float: right; +} a.tabledrag-handle .handle { background: url(../../../misc/icons/787878/move.svg) no-repeat 6px 7px; height: 14px; diff --git a/core/modules/system/src/Tests/Theme/TableTest.php b/core/modules/system/src/Tests/Theme/TableTest.php index e65037c..6d54d03 100644 --- a/core/modules/system/src/Tests/Theme/TableTest.php +++ b/core/modules/system/src/Tests/Theme/TableTest.php @@ -232,8 +232,8 @@ public function testThemeTableResponsivePriority() { $this->assertRaw('1', 'Header 1: the priority-medium class was applied correctly.'); $this->assertRaw('2', 'Header 2: the priority-low class was applied correctly.'); $this->assertRaw('3', 'Header 3: no priority classes were applied.'); - $this->assertRaw('4', 'Cell 1: the priority-medium class was applied correctly.'); - $this->assertRaw('5', 'Cell 2: the priority-low class was applied correctly.'); + $this->assertRaw('4', 'Cell 1: the priority-medium class was applied correctly.'); + $this->assertRaw('5', 'Cell 2: the priority-low class was applied correctly.'); $this->assertRaw('6', 'Cell 3: no priority classes were applied.'); } @@ -305,7 +305,7 @@ public function testThemeTableRowRenderArray() { ); $this->render($table); $this->removeWhiteSpace(); - $this->assertRaw('1-one1-two1-three', 'Table row 1 found.'); - $this->assertRaw('2-one2-two2-three', 'Table row 2 found.'); + $this->assertRaw('1-one1-two1-three', 'Table row 1 found.'); + $this->assertRaw('2-one2-two2-three', 'Table row 2 found.'); } } diff --git a/core/modules/system/templates/table.html.twig b/core/modules/system/templates/table.html.twig index f6b32e4..4ac9639 100644 --- a/core/modules/system/templates/table.html.twig +++ b/core/modules/system/templates/table.html.twig @@ -30,6 +30,7 @@ * - content: The string to display in the table cell. * - active_table_sort: A boolean indicating whether the cell is the active table sort. + - label: The value of the related table header of this column. * - 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 * any rows. diff --git a/core/modules/views/templates/views-view-table.html.twig b/core/modules/views/templates/views-view-table.html.twig index fe6be75..25dcd0d 100644 --- a/core/modules/views/templates/views-view-table.html.twig +++ b/core/modules/views/templates/views-view-table.html.twig @@ -22,6 +22,7 @@ * - columns: Row column items. Columns are keyed by column number. * - attributes: HTML classes to apply to each column. * - content: The column content. + * - label: The value of the related table header of this column. * - default_classes: A flag indicating whether default classes should be * used. * - responsive: A flag indicating whether table is responsive. diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc index fbe962e..a637b3d 100644 --- a/core/modules/views/views.theme.inc +++ b/core/modules/views/views.theme.inc @@ -558,6 +558,11 @@ function template_preprocess_views_view_table(&$variables) { $column_reference['attributes'] = array(); } + if (!empty($label)) { + $data_th = SafeMarkup::checkPlain(!empty($fields[$field]) ? $fields[$field]->label() : ''); + $column_reference['label'] = $data_th; + } + if ($classes = $fields[$field]->elementClasses($num)) { $column_reference['attributes']['class'][] = $classes; } diff --git a/core/themes/bartik/css/components/table.css b/core/themes/bartik/css/components/table.css index 18aedbc..c226244 100644 --- a/core/themes/bartik/css/components/table.css +++ b/core/themes/bartik/css/components/table.css @@ -59,12 +59,60 @@ tr th { td.priority-medium { display: none; } + .mobile-table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + } + .mobile-table th { + display: none; + } + .mobile-table td { + display: block; + border: none; + } + .mobile-table td:before { + content: attr(data-th)" "; + font-weight: bold; + width: 8em; + display: inline-block; + } } @media screen and (max-width: 60em) { /* 920px */ th.priority-low, td.priority-low { display: none; } + .responsive-enabled.is-collapsed { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + } + .responsive-enabled.is-collapsed th { + display: none; + } + .responsive-enabled.is-collapsed td { + display: block; + border: none; + } + .responsive-enabled.is-collapsed td:before { + content: attr(data-th)" "; + font-weight: bold; + width: 8em; + display: inline-block; + } + + /* A few overrides to cover some edge cases. */ + .responsive-enabled.is-collapsed .form-item { + display: inline-block; + } + .responsive-enabled.is-collapsed .dropbutton-wrapper { + width: auto; + display: inline-block + } + .touch .responsive-enabled.is-collapsed .draggable td { + padding: 10px 12px; + } } table ul.links { margin: 0; diff --git a/core/themes/seven/css/components/tables.css b/core/themes/seven/css/components/tables.css index afc9301..47f5db9 100644 --- a/core/themes/seven/css/components/tables.css +++ b/core/themes/seven/css/components/tables.css @@ -134,10 +134,59 @@ th.select-all { td.priority-medium { display: none; } + .mobile-table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + } + .mobile-table th { + display: none; + } + .mobile-table td { + display: block; + border: none; + } + .mobile-table td:before { + content: attr(data-th)" "; + font-weight: bold; + width: 8em; + display: inline-block; + } } @media screen and (max-width: 60em) { /* 920px */ th.priority-low, td.priority-low { display: none; } + .responsive-enabled.is-collapsed { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + } + .responsive-enabled.is-collapsed th { + display: none; + } + .responsive-enabled.is-collapsed td { + display: block; + border: none; + } + .responsive-enabled.is-collapsed td:before { + content: attr(data-th)" "; + font-weight: bold; + width: 8em; + display: inline-block; + } + + /* A few overrides to cover some edge cases. */ + .responsive-enabled.is-collapsed .form-item { + display: inline-block; + } + .responsive-enabled.is-collapsed .dropbutton-wrapper { + width: auto; + display: inline-block + } + .touch .responsive-enabled.is-collapsed .draggable td { + padding: 10px 12px; + } } +