Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Somehow the <tfoot>
element of a table never got into core. While not commonly used, it still is a necessary component on some sites. Themes have to add this functionality when it's optional use should be provided by core.
Proposed resolution
Add optional #footer
variable in theme hook and corresponding <tfoot>
markup in table template.
Remaining tasks
None
User interface changes
None
API changes
None
Original report by @sreynen
Comment | File | Size | Author |
---|---|---|---|
#121 | 806982.patch | 6.05 KB | Pol |
#86 | Screen Shot 2014-06-09 at 10.24.57 AM.png | 38.13 KB | JohnAlbin |
Comments
Comment #1
sreynen CreditAttribution: sreynen commentedThis patch is against HEAD, which is currently D7. I hope that's the right way to do this.
The new tfoot code is basically just a copy of the existing thead code. Ideally both thead and tfoot would take rows rather than cells, as both can contain multiple rows in HTML, but that's probably a separate issue. I also took out the check if body rows exist. I'm not really sure why that's in thead (shouldn't we be semantically identifying the table head whether or not there are body rows?), but it seems to be thead-specific in any case.
Comment #2
Jaypan CreditAttribution: Jaypan commentedBump. This needs to be added to D6 and D7 as well.
Comment #4
bfroehle CreditAttribution: bfroehle commentedOne immediate bug is that tfoot should come BEFORE tbody in the rendered HTML.
From the HTML 4 specifications:
Comment #5
sreynen CreditAttribution: sreynen commentedWell shoot, I've been doing tfoot after tbody all these years.
Comment #6
minorOffense CreditAttribution: minorOffense commentedThere's also a syntax error in the patch here:
That trailing bracket shouldn't be there.
Comment #7
kathyh CreditAttribution: kathyh commented#D8 /core upgrade, address #4 and #6
Comment #8
kathyh CreditAttribution: kathyh commentedGetting the following notice:
Notice: Undefined index: footer in theme_table() (line 1771 of \core\include\theme.inc).
from the line declaring: $footer = $variables['footer'];
Comment #9
claudiu.cristeaYou should also document the new
$variables['footer']
by adding explanation in the function doxygen part. See http://drupal.org/node/1354 for details.Comment #10
bfroehle CreditAttribution: bfroehle commentedUntested, but documentation added and warning in #8 fixed. Not how this patch needs to relate to theme_tablesort, in general more testing is required.
Comment #11
bfroehle CreditAttribution: bfroehle commentedComment #12
zhangtaihao CreditAttribution: zhangtaihao commentedI may just be missing the obvious. In the following lines in the patch:
I presume the reference to
$header
is meant to be$footer
?Comment #13
bfroehle CreditAttribution: bfroehle commentedYes, of course. "Untested, ..." Good catch.
Comment #14
miqmago CreditAttribution: miqmago commentedVery good!!
Is it possible to add to D7 future upgrades?
Comment #15
miqmago CreditAttribution: miqmago commentedAtthached the patch corrected changing $header => $footer
Comment #17
mitchell CreditAttribution: mitchell commented#14: Yes. After 8.x is committed, a backport is possible.
Comment #18
miqmago CreditAttribution: miqmago commentedOk thanks,
Attached patch for D7.18
Comment #20
miqmago CreditAttribution: miqmago commentedIs there any pre-test tool?
Comment #21
bfroehle CreditAttribution: bfroehle commentedComment #23
willvincent CreditAttribution: willvincent commentedI've started a separate issue for a D7 backport: #1892654: D7 Backport: theme_table() should take an optional footer variable and produce <tfoot>
Comment #24
floydm CreditAttribution: floydm commentedRerolled patch from #15 against current 8.x branch.
Comment #25
zhangtaihao CreditAttribution: zhangtaihao commentedThanks, @Floydm, for rerolling it. Now, onto details:
tablesort_cell()
on a footer cell?colspan
> 1?In general, I think the previous patch (prior to reroll) might be a bit out of date, considering that
theme_table()
in D8 has changed considerably since this issue originally started. The D7 backport issues (i.e. being non-responsive) can be dealt with separately, especially given the patch in #24 is pretty much D7-ready.It would be great if someone with expertise in the D8 responsive table implementation could chime in (from #1276908: Administrative tables are too wide for smaller screens).
Comment #26
jimmyko CreditAttribution: jimmyko commented#24: theme_table_tfoot-806982-24.patch queued for re-testing.
Comment #27
claudiu.cristea#24: theme_table_tfoot-806982-24.patch queued for re-testing.
Comment #29
shashikant_chauhan CreditAttribution: shashikant_chauhan commentedComment #30
shashikant_chauhan CreditAttribution: shashikant_chauhan commentedComment #32
markhalliwellComment #33
lokapujyaJust a start. There is more to do. Basically, I directly copied header.
Comment #35
Alan D. CreditAttribution: Alan D. commentedWith zero knowledge of this, "- $ts = array();" should not be removed or it would probably trigger PHP notices latter (without looking at the code). All references to table sort should probably be removed from the footer section imho, unless the intent is to allow footer based sorting.
Comment #36
lokapujyaFixed a missing bracket.
Comment #37
markhalliwellVery quick review:
Agreed. Do not remove this.
This function doesn't even exist and is not needed.
Unnecessary space.
Should be footer.
Comment #38
lokapujyaComment #39
lokapujyaAdding back in the footer parameter documentation. Leaving out the example: doesn't seem like the right place for it.
Comment #40
markhalliwellThe template itself should also have documentation for footer, not just this PHP function.
This chunk shouldn't exist (missing space).
tfoot
should come after<tbody>
.Comment #41
markhalliwellComment #42
lokapujyaI will update the template.
I thought we wanted tfoot before tbody according to comment #4.
Comment #43
lokapujyaMinor updates. Changed to hardcoded td tags in the footer, since a footer won't have th tags.
Comment #45
markhalliwellThat is the old HTML 4.01 spec. From HTML5 (which can be before or after
<tbody>
now):Also, please don't hard code the tags. Just use the same format as the header.
Comment #46
markhalliwellComment #47
lokapujyaImplemented the above review.
Comment #48
markhalliwellWe should probably default to
FALSE
here. You'll see the test fail now because it's outputtingth
by default. Speaking of tests, we should probably add a test for this "header" configuration too.Again, needs proper indenting and no field.
Comment #49
lokapujyaI'm not seeing the indentation problem.
Comment #50
markhalliwellAh, nm about the indention. The context lines before made it look a bit off.
Comment #52
lokapujyaComment #53
markhalliwellRemove this.
By changing this to an array, we've lost the test case that a simple string works. I would add a simple string:
'Footer 3'
at the bottom.Comment #54
lokapujyaChanges from #53.
Comment #55
markhalliwellAwesome! This looks good to me. I'd like to get some manual testing with some screenshots in before I RTBC it. Thanks @lokapujya for all your work! This went by quickly. I'm also going to see if I can't get some others to review.
Comment #56
sunGiven Mark's reference to the HTML5 spec above, the proposed implementation does not actually respect the standard.
In case we intentionally do not support the full standard, we not only need to document that we do not, we also need to document why we do not.
2) All of the code that follows this condition has been copied from the 'rows' code path → duplicate code.
Pending a clarification on why we don't support the full HTML5 standard, at minimum we should look into ways to de-duplicate the code in this function.
Actually, I was wrong:
The code was copied from 'header', not 'rows'.
In particular the quoted lines here are reversed — instead of consuming the data from the table header columns, they are re-setting the responsive classes for each column (without applying the expected classes to the table footer columns).
→ Most likely the best possible demonstration for why code duplication is bad. ;-)
Similar to Mark's documentation remarks, let's also place the new 'footer' variable after 'rows' here.
This test class is a "semi-unit" test — the test method you've added to is named
testThemeTableWithEmptyMessage()
If you want to cover the case of an empty table with header + footer, that's fine — but you're additionally changing the table column layout here: the footer contains one more column than the header + the empty row.
Varying amount of columns in header + rows + footer is a separate test.
In any case, we need one (or more) new test methods in this class to cover the actual expectations for table footers.
Speaking of expectations...
Is it sane to expect a table footer to appear where no table rows are?
Outputting the header makes (some leve of) sense to me, but why the footer?
We need to cover all permutations/expectations in the test, and next to comments in the functional code, the test is also a good place to document why we do expect what we expect. :)
Can TFOOT contain a TH?
Lastly, why are we doing this? Can we think of use-case for a table footer in core + actually use this feature?
In case we cannot, what's the use-case? :)
Comment #57
lokapujya2. Removed Duplication.
4. Partially implemented: Separated the unit test.
6. Yes, see core/assets/vendor/normalize-css/test.html for an example.
Comment #58
gnugetAlright.
I just attached the interdiff between #54 and #57 just in case.
Also, i think tfoot can contain a TH
accord with the definition:
(http://www.w3.org/TR/html5/tabular-data.html#the-tfoot-element)
there is not any clarification about if there is any special restriction related with what kind of rows can contain the tfoot tag
Comment #59
jimmyko CreditAttribution: jimmyko commented+1 to @gnuget
There is another proof for that in https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot.
Comment #60
markhalliwellHere are my responses/questions to @sun's review in #56:
#empty
doesn't have anything to do with headers or footers, it simply adds empty text when#rows
is... empty. Implementation logic must be left to code actually constructing the render array (ie: add/don't add footer elements if rows are empty, etc).<th>
element is only a child of<tr>
. It has no context or relationship to<thead>, <tbody>, or <tfoot>
. http://www.w3.org/TR/html5/tabular-data.html#the-th-element. FWIW, I have used header cells in the footer before, granted it's extremely rare, but it does happen (especially when dealing with complex tables/data).Also, should we really be asking "where do we use it in core?". This element has existed since HTML 4.01. I'd like to stop asking these types of questions when it's simply just part of the table spec. Core may not be using it, but clients do and contrib could. Instead, we should be following the spec and providing a native way for anyone to implement this in Drupal. As stated above, this element has more semantic use for data based tables (totaling). It also prevents class-itis on body rows to determine which is a "footer" element.
Comment #61
gnugetI will work on this.
Comment #62
gnugetOk.
I've been working on this but i have some questions/thoughts.
While i was working on this patch, i read again the HTML5 spec and i found something to we miss in the previous patches.
Accord with the HTML5 spec: tbody and tfoot have the same structure:
http://www.w3.org/TR/html5/tabular-data.html#the-tbody-element
http://www.w3.org/TR/html5/tabular-data.html#the-tfoot-element
That means to tfoot element actually can have more than one row just like tbody.
So... instead to put the logic of the footer apart, i did a little change in the rows because accord with the spec tbody and tfoot work in the same way.
But while there is not an important change in the code, this changes the way we want to test the footer and the way how we will use it.
So, if we really want to follow the spec, i think this is the way the footer should work.
If you are agree with this new approach i have some questions:
I attached the patch, i didn't add an interdiff because i didn't start from #57 because with this new approach i think a lot of things could change.
I will continue working on this, i just want a little feedback.
Comment #63
c4rl CreditAttribution: c4rl commentedRegarding #62, seems to me that we should just have
$variables['rows']
and$variables['footer_rows']
and they effectively work the same.Seems to me that we can just leave
$no_striping
asFALSE
for consistency's sake with tbody rows, and that the odd/even count should persist across both -- people can override this in CSS if they please.Test-wise, having something identical for the rows test that just makes sure
$footer_rows
appears in a<footer>
seems fine to me.Comment #64
markhalliwellPlease for the love of all things lets just keep it
$variables['footer']
, not$variables['footer_rows']
.I'm not at my computer right now, but I'll take a look at #62 tomorrow.
Comment #65
c4rl CreditAttribution: c4rl commentedRe: $footer vs $footer_rows, seems fine, though seems like behavior should be relatively identical to $rows.
Comment #66
c4rl CreditAttribution: c4rl commentedI think I changed my mind about multiple rows :) I checked out the spec for thead and it can also take multiple rows.
Given that we've built $header to only support one row, it seems like keeping $footer to one row is also okay.
Personally I haven't really used tfoot much in my web career.
Comment #67
markhalliwellI'd rather just use
$sections
and$section
. I don't think it's necessary to prefix with "table" as we're already in the table's preprocess function and know what context we're in. This is really just a personal preference and very trivial though ;)We shouldn't be adding any striping anyway since #1649780: Remove first/last/odd/even classes in favor of CSS3 pseudo selectors landed. This should be a separate issue though, for now use:
$no_striping = isset($row['no_striping']) ? $row['no_striping'] : ($table_part === 'rows' ? FALSE : TRUE);
footer
is simpler and cleaner. Yes, it should behave identically torows
.Yes,
thead
can also technically contain multiple rows, however changing this to be spec would require much more work and should be a separate issue as well.header
already exists and was constructed based on simple use, not per spec. We're adding in a new variable here to complete thetable
spec, we shouldn't constrict our addition with legacy cruft.Understood. It's a rare element for sure, but it is part of the spec. That is kind of the whole point of this issue is to flush out the table theme hook and be more in-line with the spec instead of assuming what people need. Not many will use it, but the last client I worked for needed it extensively (and I also utilized multiple
tfoot
rows). Havingtfoot
can be extremely helpful when dealing with tons of tabular data and constructing interactive tables that utilize lots of JS/AJAX.This is why I put #2224487: Support "footer" in tables in Bootstrap. Themes shouldn't have to do this, it should just be provided by core naturally.
Comment #68
gnugetI attached a patch with the suggested changes of #67
Also i added a test for check the footer and the documentation based in $rows.
Comment #69
gnugetReroll because of this #2247991: [May 27] Move all module code from …/lib/Drupal/… to …/src/… for PSR-4.
Comment #70
gnugetI just remove an extra space
Comment #71
gnugetI did a little modification into the test.
The idea is make sure the order of the rows is respected in the footer.
Comment #72
markhalliwellNeeds
.
.Minor nitpick. Really shouldn't have quotes around
no_striping
.This should be expanded into multiple lines.
This can be simplified to:
$no_striping = $section === 'footer'
Comment #73
gnugetHi Mark.
Thanks for your review.
The documentation of
footer
comes fromrows
so, the problems in 1,2,3 are also presented in rows. Should i change that in the documentation of rows too?About 4 i will change that.
Comment #74
markhalliwellWe might as well since we're in there. They're just minor documentation/coding standards nitpicks. I don't think that really qualifies as scope creep.
Comment #75
joelpittetno_striping and data don't need quotes around them as @Mark Carver mentioned. @gnuget looking good, thanks for the minor test change too to foo.
Comment #76
gnugetOk.
Here a new version of the patch with the suggestions of #72
Thank you for your reviews guys!
Comment #77
markhalliwellThis looks great! In retrospect, I would actually like to get @jhodgdon's feedback on the documentation bits. We are essentially duplicating and I wonder if there is a way to consolidate this so we only have to update it once and not in both sections.
I'll leave her a tell to review.
Comment #78
jhodgdonI think the docs look mostly great too!
My suggestion for the footer area would be something like this:
I agree that duplication is not desirable.
There are also a couple of minor formatting glitches:
b)
Text in the 2nd and 3rd line should line up directly under the word sort (2 space indentation). It is indented an extra space. This is true of some, but not all, of the rest of the list.
c)
After : in a list item, the next word should be capitalized.
d)
Boolean should be capitalized. It is a proper noun.
e) In this code section:
You've gone to the trouble to partially split out the one-line array into multiple lines... but it's not fully split. Can we format it the way we would in actual code? I think it would be clearer?
f) Why are we repeating this documentation in the Twig file and in the preprocess function? That doesn't make any sense to me. I think it should just be in the Twig file, which is where most people would look for it. Let's just take it out of the preprocess function and make sure that function links to the twig template for docs on the variable input?
Comment #79
gnugetHI jhodgdon!
Thanks for your time reviewing this patch.
I fixed a,b,c,d.
In the
e
i just restore the code as it was before, which is the way i would do it, i hope that's is ok for you.and for
f
i just want to be sure about what i have to do, because while the documentation is almost the same, is not exactly the same.The documentation in the preprocess function is focused in the format what type => table expect the variables, the documentation in
table.html.twig
file is focused in all the available variables in that twig template.If you are sure about this, should i remove the documentation from the preprocess and overwrite the documentation of the twig template and link the preprocess to the twig template?
Comment #80
jhodgdonI guess we can leave the duplicated documentation. Probably out of scope for this issue anyway.
Thanks for making the other clean-ups; the documentation looks good to me now. I'm not going to mark the patch RTBC though since I did not look at the code or tests.
Comment #81
markhalliwellI manually tested this and it works wonderfully. Here's a screenshot of the output (render array used at the bottom).
In hindsight, there could be some whitespace cleanup done, but it's very... very trivial:
Comment #82
alexpottCommitted 580fd45 and pushed to 8.x. Thanks!
Comment #84
markhalliwellThis needs to be backported to 7.x (not sure why there wasn't a label).
Comment #85
markhalliwellCreated a draft change notice at https://drupal.org/node/2282663
It will need a review before it can be published.
Comment #86
JohnAlbinCritical? regression. Responsive tables are no longer responsive.
Since we don't have any simple tests that check that the responsive table classes get applied correctly, this was bound to happen eventually. :-p
As you can see from the screenshot only the header is properly hiding columns on small and medium sized screens. The table data is not hidden and causes a horizontal scrollbar.
Comment #88
alexpottCommitted f3a0ffa and pushed to 8.x to revert.
The patch is not critical so lets rollback to fix.
Comment #89
markhalliwellBlocked on #2282683: Responsive tables do not have tests
Comment #91
markhalliwell@JohnAlbin, turns out this was actually happening before this patch and is still passes tests after applying the patch after #2282683: Responsive tables do not have tests got in.
It turns out that this is actually a regression from #1939008: Convert theme_table() to Twig.
I've created #2296859: [regression] Responsive classes not always added to table rows to address this (which this issue is now/still postponed on).
Comment #92
joelpittet@Mark Carver, where in theme_table conversion did the regression happen? If I recall we moved the responsive stuff to type table preprocess outside of that conversion issue, if my memory serves right it was to do with the removal of theme() calls or drupal_add_js() removals.
I could be wrong but this could be your regression issue you are looking for? #2171071: Rename drupal_add_library() to _drupal_add_library() and remove its uses
Comment #93
markhalliwellFrom the patch in #1939008-133: Convert theme_table() to Twig. It was previously using an incremental
$i
variable as the index, instead it was changed to use the associative array key, which can differ greatly between some table headers/rows:Comment #94
joelpittetWell I can see where you would see that, though I still fail to see where those keys won't match... I'm probably missing something still, sorry.
Comment #95
markhalliwellNow that #2296859: [regression] Responsive classes not always added to table rows is in, this will need a reroll.
Comment #96
gnugetA updated version attached.
Comment #97
markhalliwellSetting this back to RTBC since the regression wasn't caused by this issue.
Comment #98
alexpottCommitted 1c7cf17 and pushed to 8.x. Thanks!
Comment #100
guschilds CreditAttribution: guschilds commentedHey all,
Thanks for the work on this.
Hate to post on a Fixed issue, but I just (successfully) used the patch from #1 of #1892654: D7 Backport: theme_table() should take an optional footer variable and produce <tfoot> for D7 (came from #23 here). I noticed multiple mentions and tags to backport to D7 after committing to 8.x. Are there plans to address that? Is this the place to bring that up? FWIW, the linked backport issue was closed as a dupe in favor of this one.
Thanks again,
Gus
Comment #101
markhalliwellYep, good catch! Normally we just re-open this issue and change the version when we see a "needs backport to D7" tag. Unfortunately, there was never such a tag on this issue and it was forgotten. I would love to help move this forwards, however I do not have time to write the conversion myself. If someone wants to start working on the 7.x version of this patch I, would be happy to review and get it to an RTBC state.
Comment #102
guschilds CreditAttribution: guschilds commentedAttached is a backport to D7.
It follows the changes made in the 8.x commit (1c7cf17) rather than the previous 7.x approach all the way back from #23.
Could you review this, Mark Carver? Thanks!
Comment #103
markhalliwellFrom first glance it looks ok. I really haven't reviewed it manually yet though. The test should also be backported: http://cgit.drupalcode.org/drupal/tree/modules/simpletest/tests/theme.te...
Comment #104
potop CreditAttribution: potop commentedWhile this is not fixed yet in D7 core one can use FooBar Table module to render table with footer.
Comment #105
lokapujyaAdding the test.
Comment #107
lokapujyaretest
Comment #113
PolLet try to get this thing done.
Retriggering the tests.
Comment #114
PolRe-uploading patch from #105 because I'm unable to trigger tests on that one.
Comment #117
apotek CreditAttribution: apotek commentedIs this issue meant to supersede https://www.drupal.org/node/1892654?If so, maybe 1892654 should be closed and we point people to this one, since that issue seems dormant.:facepalm:
Comment #118
PolHere's an updated patch with fixed tests.
Comment #119
PolComment #121
PolUpdating patch to solve last failing test.
Comment #122
PolAny update on this ?
Comment #123
PolComment #124
joseph.olstadThere already is a D7 backport issue open for this.
#1892654: D7 Backport: theme_table() should take an optional footer variable and produce <tfoot>
Let's copy the Pol patch from here to there and mark this issue as fixed.