Hi,
there's a bug with tablesort, the colspan attribute and the "active-row-highlighting"

Example:
Some cols in my tableheader have the colspan attribute. Tablesort is enabled.
When I sort the table, tablesort sets only one row to class "active", not all rows which are included in the colspan range.

Here is some example code.

Example Code

/**
 * Buggy tablesort when using colspan
 */
function example_table() {
  $sql = "SELECT * FROM {node}";
  
  $header = array(
            array('data' => t('Title'), 'field' => 'title', 'colspan' => '2')
            , ''
            , array('data' => t('Types'),'field' => 'type', 'colspan' => '3')
            , ''
            , ''
      );
  
  $sql .= tablesort_sql($header);

  $result = db_query(db_rewrite_sql($sql));
  
  $rows = array();
  while ($node = db_fetch_object($result)) {
    $row = array();
    $row[] = 'foo';
    $row[] = $node->title;
    $row[] = 'bar';
    $row[] = $node->type;
    $row[] = 'foobar';
    $row[] = 'barfoo';
    $rows[] = $row;
  }
  $output = theme('table', $header, $rows);
  return $output;
}

I think i can fix the tablesort code, but I am not very fimiliar with the drupal coding guidelines!

I hope someone will fix this soon! :)

Ty,
axe312

Ps.: I hope my english is understandable ;)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

drunken monkey’s picture

FileSize
48.92 KB

Problem exists in HEAD, too. Attached is a screenshot (from 7.x-dev).

Probably related to #557040: theme_table() adds 'active' class for the wrong columns when using rowspan (insofar, that we should be able to fix both at the same time).

drunken monkey’s picture

Title: Problem with tablesort, colspan and the "active"-Class of tablesort » Problem with the "active" class of tablesort
Version: 6.17 » 7.x-dev
Priority: Minor » Normal
Status: Active » Needs review
FileSize
10.62 KB
5.18 KB

Patch attached.
Fixes problems with all sorts of colspan and rowspan weirdness, except one special case were I think even the HTML result would be unspecified – and you'd have to be pretty insane to even try it.
And because I'm a good monkey, there are even tests for it. Rejoice! (The first patch contains only the tests and is there to demonstrate that it previously failed horribly. (Here's to hoping the second one doesn't fail equally horribly!))

Status: Needs review » Needs work

The last submitted patch, tablesort_active.patch, failed testing.

Xano’s picture

Needs screenshot.

drunken monkey’s picture

Needs screenshot, work, and removal of debug() calls, which I left, as always, lying around …

Revised patch attached (only minus three debug() lines and plus one isset()).

drunken monkey’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, tablesort_active-5.patch, failed testing.

drunken monkey’s picture

Status: Needs work » Needs review

#5: tablesort_active-5.patch queued for re-testing.

Test works fine locally, and I couldn't tell what in my patch would influence that test.

drunken monkey’s picture

So, tests pass – anyone wants to set this to RTBC?

bleen’s picture

+++ includes/tablesort.inc	11 Oct 2010 13:04:04 -0000
@@ -186,34 +186,6 @@ function tablesort_header($cell, $header
-function tablesort_cell($cell, $header, $ts, $i) {

I dont know if webchick/dries will be cool with removing a whole function like this after we have released beta.
On the other hand this does seem to be the correct way to fix this bug

+++ modules/simpletest/tests/theme.test	11 Oct 2010 13:04:08 -0000
@@ -157,6 +157,84 @@ class ThemeTableUnitTest extends DrupalW
+
+

extra space

Anyone else want to chime in?

(needs work for the white space)

Powered by Dreditor.

drunken monkey’s picture

FileSize
9.99 KB

I dont know if webchick/dries will be cool with removing a whole function like this after we have released beta.
On the other hand this does seem to be the correct way to fix this bug

You're right, of course, this came up in another issue as well. Even if core doesn't use the function, we can't be sure what contrib modules already do. Removing this now would be a completely unnecessary API change.
So, keeping the function without using it anymore, and adding a @todo for Drupal 8.

Also removed the two superfluous lines.

drunken monkey’s picture

FileSize
8.96 KB

Oops, seems like the DRUPAL_ROOT for the drupal_add_js() call was a stupid idea after all …

drunken monkey’s picture

#12: tablesort_active-12.patch queued for re-testing.

Still seems to work for me, nobody else here interested?

drunken monkey’s picture

#12: tablesort_active-12.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, tablesort_active-12.patch, failed testing.

drunken monkey’s picture

Status: Needs work » Needs review
FileSize
8.47 KB

Weird, test results above show this passed … Also works for me locally.
However, needs a re-roll anyways, since -p0 is now deprecated. See attached.

bleen’s picture

Version: 7.x-dev » 8.x-dev
Issue tags: +Needs backport to D7

This now needs to be fixed in D8 first, so maybe you want to take care of that "todo" for the D8 versin of the patch

Only then will it be backported to D7

drunken monkey’s picture

Ah, you're right, of course.

bleen’s picture

This patch is roughly the same as the patch in #18 but it reduces the amount of code needed by checking that $cell is an array much earlier on. I'm happy with this... lets get one more review for good luck and then we can mark RTBC

Status: Needs review » Needs work
Issue tags: -Needs backport to D7

The last submitted patch, 838096-tablesort_active-D8-18.patch, failed testing.

bleen’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
Issue tags: +Needs backport to D7

The last submitted patch, 838096-tablesort_active-D8-18.patch, failed testing.

drunken monkey’s picture

I can reproduce this locally:
fatal: corrupt patch at line 116
Please re-roll. (Couldn't tell what's wrong with the patch or that line, though.)

bleen’s picture

Status: Needs work » Needs review
FileSize
8.9 KB

hmmm ... try this Mr. Bot

drunken monkey’s picture

+++ b/includes/theme.inc
@@ -1710,6 +1726,7 @@ function theme_table($variables) {
+    $rowspans = array(); // Keeps track of the current column when rowspans are involved.

Comments should go on a separate line and have no more than 80 characters per line.
(Yes, I know, I had that wrong, too, but that was a long time ago …)

+++ b/modules/simpletest/tests/theme.test
@@ -156,6 +156,83 @@ class ThemeTableUnitTest extends DrupalWebTestCase {
+  }
+
 }

While I personally like this style better, core policy seems to be to omit that newline between last method and end of class.

Attached: a patch that should fix this.
(By the way: The "18" (or, now, "25") at the end of the filename stands for the comment number, to easily keep track of what version of the patch that is. Meaning, you should increment that number when creating new patches.)

Powered by Dreditor.

fietserwin’s picture

Issue #1277874: table cells incorrectly get class 'active' seems to target the same code. However, it looks like the patch for this issue may - as an unforeseen but positive side effect - solve that issue as well.

drunken monkey’s picture

Might it, or does it? In the latter case, we could just call the other one a duplicate and maybe make additional efforts to get this one in.

fietserwin’s picture

FileSize
9.19 KB

I changed the patch for the move to /core and reviewed and tested it as well.

Remarks:

  • Reduced a comment to less than 80 characters.
  • I removed some spaces in $this-> assertTrue (...)
  • The assertTrue in the test might/should(?) be replaced by assertEqual(..., 1, ...) as preg_match returns an int or false,
  • In #1277874: table cells incorrectly get class 'active' I talked about 2 headers having the same text, which would go wrong as well. As it turns out, the text of the header is used as argument in the sort parameter, thus that use case is not supported at all. Supporting it would mean exposing (non-translated) field names to users (as part of the query part of the URL in the address bar) which is something we might not want to do.

Considering that my changes have nothing to do with the "real code changes" code changes in the patch itself, I consider this one RTBC, but would like to ask bleen18 or drunken money (or anyone else) to have a last look at it and really set it to RTBC.

bleen’s picture

I'm happy with the changes from #25 & #28 ...

fietserwin’s picture

Status: Needs review » Reviewed & tested by the community

OK, than we set it to RTBC.

xjm’s picture

Status: Reviewed & tested by the community » Needs review

Thanks for your work on this! Please don't mark your own patch RTBC, though. :)

fietserwin’s picture

@bleen18: so you will have to set it to RTBC yourself.

xjm’s picture

Status: Needs review » Needs work
+++ b/core/modules/simpletest/tests/theme.testundefined
@@ -172,6 +172,82 @@ class ThemeTableUnitTest extends DrupalWebTestCase {
+   * Tests if correct sort links are generated for headers where requested and
+   * if the "active" class is set correctly.

Minor thing: This should be just one line, less than 80 chars.

+++ b/core/modules/simpletest/tests/theme.testundefined
@@ -172,6 +172,82 @@ class ThemeTableUnitTest extends DrupalWebTestCase {
+    $header = array(
+      array(
+        'data' => 'Header12',
+        'field' => 'a',
+        'sort' => 'asc',
+        'colspan' => 2,
+      ),
+      'Header3',
+      array(
+        'data' => 'Header4',
+        'field' => 'b',
+      ),
+      array(
+        'data' => 'Header5',
+        'field' => 'c',
+      ),
+    );
+    $rows = array(
+      array(
+        array('data' => 'Column1', 'rowspan' => 2,),
+        'Column2',
+        array('data' => 'Column34', 'colspan' => 2,),
+        'Column5',
+      ),
+      array(
+        'Row2Column2',
+        'Row2Column3',
+        'Row2Column4',
+        'Row2Column5',
+      ),
+    );
+    $this->content = theme('table', array('header' => $header, 'rows' => $rows));
+    $this->assertRaw('sort=desc&order=Header12', t('Correct link for active sort-column.'));
+    $this->assertTrue(preg_match('#<th [^>]*class="active"([^<]|<[^/])+Header12#', $this->content), t('Correct class in header for active sort-column.'));
+    $this->assertNoRaw('order=Header3', t('No link for normal column.'));
+    $this->assertRaw('sort=asc&amp;order=Header4', t('Correct link for inactive sort-column.'));
+    $this->assertFalse(preg_match('#<th [^>]*class="active"([^<]|<[^/])+Header4#', $this->content), t('No class in header for inactive sort-column.'));
+    $this->assertNoRaw(' data="', t('"!attr" not set as HTML attribute.', array('!attr' => 'data')));
+    $this->assertNoRaw(' field="', t('"!attr" not set as HTML attribute.', array('!attr' => 'field')));
+    $this->assertNoRaw(' sort="', t('"!attr" not set as HTML attribute.', array('!attr' => 'sort')));
+    $this->assertRaw(' class="active">Column1</td>', t('Correct class set on active column !num.', array('!num' => 1)));
+    $this->assertRaw(' class="active">Column2</td>', t('Correct class set on active column !num.', array('!num' => 2)));
+    $this->assertRaw(' class="active">Row2Column2</td>', t('Correct class set on active column !num of second row.', array('!num' => 2)));
+    $this->assertNoRaw(' class="active">Row2Column3</td>', t('No class set on inactive column !num of second row.', array('!num' => 3)));
+
+    $_GET['sort'] = 'asc';
+    $_GET['order'] = 'Header4';
+    $this->content = theme('table', array('header' => $header, 'rows' => $rows));
+    $this->assertRaw('sort=asc&amp;order=Header12', t('Correct link for inactive sort-column.'));
+    $this->assertFalse(preg_match('#<th [^>]*class="active"([^<]|<[^/])+Header12#', $this->content), t('No class in header for inactive sort-column.'));
+    $this->assertRaw('sort=desc&amp;order=Header4', t('Correct link for active sort-column.'));
+    $this->assertTrue(preg_match('#<th [^>]*class="active"([^<]|<[^/])+Header4#', $this->content), t('Correct class in header for active sort-column.'));
+    $this->assertNoRaw(' class="active">Column1</td>', t('No class set on inactive column !num.', array('!num' => 1)));
+    $this->assertRaw(' class="active">Column34</td>', t('Correct class set on active column with colspan.', array('!num' => 1)));
+    $this->assertRaw(' class="active">Row2Column4</td>', t('Correct class set on active column !num of second row.', array('!num' => 4)));
+    $this->assertNoRaw(' class="active">Row2Column5</td>', t('No class set on inactive column !num of second row.', array('!num' => 5)));
+
+    $_GET['sort'] = 'desc';
+    $_GET['order'] = 'Header5';
+    $this->content = theme('table', array('header' => $header, 'rows' => $rows));
+    $this->assertRaw('sort=asc&amp;order=Header12', t('Correct link for inactive sort-column.'));
+    $this->assertFalse(preg_match('#<th [^>]*class="active"([^<]|<[^/])+Header12#', $this->content), t('No class in header for inactive sort-column.'));
+    $this->assertRaw('sort=asc&amp;order=Header5', t('Correct link for active sort-column.'));
+    $this->assertTrue(preg_match('#<th [^>]*class="active"([^<]|<[^/])+Header5#', $this->content), t('Correct class in header for active sort-column.'));
+    $this->assertNoRaw(' class="active">Column1</td>', t('No class set on first column.'));
+    $this->assertRaw(' class="active">Column5</td>', t('Correct class set on active column.'));
+    $this->assertNoRaw(' class="active">Row2Column4</td>', t('No class set on inactive column !num of second row.', array('!num' => 4)));
+    $this->assertRaw(' class="active">Row2Column5</td>', t('Correct class set on active column !num of second row.', array('!num' => 5)));
+
+    unset($_GET['sort'], $_GET['order']);

Can we get some inline comments in this wall of assertions? Hard to scan.

Also, I don't think bleen's question from #10 has been addressed yet:

I dont know if webchick/dries will be cool with removing a whole function like this after we have released beta.
On the other hand this does seem to be the correct way to fix this bug.

That bit is not backportable, although it is fine for D8. So it would be good to get a separate D7 patch along with the D8 that does not remove the function.

fietserwin’s picture

- #11 addresses #10, though maybe not very explicitly. In D7 we leave that function as is, it just won't be called anymore by theme_table(). Patch for D7 is foreseen after the patch for D8 gets in.
- Comments could indeed be added. I will see what I can do.

fietserwin’s picture

I will see what I can do.

Well, that was not much I did since then :( Maybe someone else can step up? I'm quite busy with other modules and projects that feed me.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

quietone’s picture

Issue summary: View changes
Status: Needs work » Postponed (maintainer needs more info)
Issue tags: -Needs backport to D7 +Bug Smash Initiative

Triage during a BugSmash group triage meeting.

There has been no activity here for 10 years, so maybe this has been resolved?

Is this issue still a problem?

Since we need more information to move forward with this issue, I am keeping the status at Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.

Thanks!

drunken monkey’s picture

Well, it’s been “fixed” in Drupal 8 insofar as that apparently doesn’t provide the active class on the sorted column anymore, so can’t make mistakes in that regard, either. However, the bug is still present in Drupal 7 – see screenshots. Attached is also a slightly modified re-roll of #16, the last D7 patch.

Status: Needs review » Needs work

The last submitted patch, 48: 838096-48--tablesort_active_class.patch, failed testing. View results