Problem/Motivation
Every pagination link in pagers has the "active" class. The "active" class is automatically added by l() and there is no way to avoid this while using l().
Proposed resolution
As the current page is not rendered as a link, no links in pagers need the "active" class, so stop using l().
Remaining tasks
Reroll backport for D6 and mark as RTBC.
User interface changes
No more "active" class on links in pagers.
API changes
none.
Original report by @Wesley Tanaka
i'm not sure if this behavior is different from 4.6.x
looking at some pager output in 4.7, I noticed that every single link has class=active. This makes no sense. What would make more sense is if only the "current page" link was marked with a different class, but instead it's explicitly set to STRONG.
Comment | File | Size | Author |
---|---|---|---|
#116 | Screen Shot 2014-05-11 at 12.58.45 pm.png | 313.41 KB | thedavidmeister |
#109 | drupal6.pager-active.109.patch | 6.54 KB | sun |
#106 | 41595_106_pager.d8.patch | 5.73 KB | scor |
#104 | 41595.d7.patch | 728 bytes | BTMash |
#100 | drupal6.pager-active.82-D6.patch | 6.54 KB | sun |
Comments
Comment #1
yched CreditAttribution: yched commentedThe "active" class is not set by the pager, but by by the function "l", which formats drupal links, when a link refers to the current page.
That's always the case with pager links (only the query part changes : "page=n".
This patch however proposes a "pager_current" class, that distinguishes the "currently viewed page".
It also removes the hard-coded "" tag, leaving the theme manage the appearence. (maybe is that too "violent ?)
Comment #2
yched CreditAttribution: yched commentedsorry, beginner's mistake - the last line should read :
It also removes the hard-coded "strong" tag, leaving the theme manage the appearence. (maybe is that too "violent" ?)
Comment #3
Stefan Nagtegaal CreditAttribution: Stefan Nagtegaal commentedOur handbook strongly encourages you to diff with:
cvs diff -u -F^f path-name.path
Notice that the difference is in the '-F^f' part... Just a little advise for your next patches... ;-)
Comment #4
yched CreditAttribution: yched commentedWell it is indeed my first patch :-)
I'm on windows, using TortoiseCVS
Problem is i can't find where to specify correct parameters for the "create patch" function
Comment #5
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedshould that be a span instead of a div?
Comment #6
Stefan Nagtegaal CreditAttribution: Stefan Nagtegaal commentedI would even rather see all hardcoded HTML like div's, spans, whatever inside theme_* functions..
Steef
Comment #7
yched CreditAttribution: yched commentedwtanaka : span instead of div ?
making it a div keeps it coherent with the way the other "page number links" are denoted :
div class="previous", div class="next" etc...
but maybe all of them should be spans after all ?
stefan nagtegaal : divs/spans/etc inside theme_* functions :
not sure i understand your point.
the code we're dealing with is inside theme_pager_list
Comment #8
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedGood points.
Another question: Should the l() function be changed to also match the query string? Is there any reason that why it should ignore the query string like it does? I can't think of any pages on my own site where the same node with 2 different query strings would be considered to be the same logical page.
Comment #9
yched CreditAttribution: yched commentedI certainly lack technical and "historical" acquaintance with drupal core to have a definite opiniion about that...
what we call a 'drupal path' (say, 'node/54/edit') is in fact in the 'query' part of the actual matching url ('www.example.com/index.php?q=node/54/edit'), so it might be a little complicated...
and then again, maybe not ?
Comment #10
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedme too.
Comment #11
m3avrck CreditAttribution: m3avrck commentedThis is not a problem just with pager, but with all other links found in core that have parameters attached to their URL. I'm going to mark this one as a duplicate of the issue I just created as I have outlined what the problem is a bit clearer.
http://drupal.org/node/44502
A proposed fix would be a patch to l() because $_GET['q'] isn't compared to the parameters in the URL at all.
Comment #12
yched CreditAttribution: yched commentedAllright.
I'll follow the other issue.
And i'll add a fresh one for my "strictly pager theming" patch - I still think the link for the current page should be accessible for css with an identificated div.
Comment #13
m3avrck CreditAttribution: m3avrck commentedyched, I already have a patch that adds that to pager, along with cleaning up the rest of the markup that pager generates. http://drupal.org/node/44498
Comment #14
m3avrck CreditAttribution: m3avrck commentedleave as duplicate for cross referencing
Comment #15
yched CreditAttribution: yched commentedGreat ! I didn't dare going through all this cleanup. Thanks !
Comment #16
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedm3avrck attached this patch to bug 44502, which has been marked as a duplicate of this one
http://drupal.org/files/issues/common.inc_15.patch
fixing this bug and 44502 so that the earlier reported bug is canonical
Comment #17
m3avrck CreditAttribution: m3avrck commented@wtanaka, the reason I marked this issue as a duplicate of mine (and reversing what you did) was because the other issue *more* clearly defined the problem. By setting this one as the primary, it makes things more difficult since this thread does *not* clearly define the problem as the other one did. Additionally, the other thread was more concise and to the point. This helps *developers* review the problem much easier and faster. Please note this for future. As such, I don't have time to keep moving this issue back and forth and hence I'll leave it here and update accordingly.
Comment #18
m3avrck CreditAttribution: m3avrck commentedAs I was working on the pager in Drupal, I noticed that the l() adds class="active" to *all* of the pager links. This is because each of the links in pager.inc is either node?page=1 or node?page=2, etc...
In l() we have:
If you look above, $_GET['q'] will always be 'node' and hence, *all* pager links will be active. This is most certainly wrong.
We need to fix l() so that it also looks at the parameters in the URL, along with $_GET['q'] itself so it can apply class="active" appropriately. This problem is not just related to pager, but occurs elsewhere in core.
The attached patch fixes this but updating the comparision to make use of the URL parameters.
Comment #19
m3avrck CreditAttribution: m3avrck commentedJust double checked, this query affects all sortable tables too. For example, go on the admin page and look at the source. You'll see that all pager links have class="active", all sortable table links have class="active" and in the admin menu, admin has class="active" too. Doh! This patch fixes that so all of these query links don't have class="active", only the admin menu item has class="active".
Comment #20
m3avrck CreditAttribution: m3avrck commentedBetter readability per chx's recommendation.
Comment #21
moshe weitzman CreditAttribution: moshe weitzman commentedreviewed and tested
Comment #22
yched CreditAttribution: yched commentedThe patch currently doesn't abstract on query params order.
Two urls with the same query params but in a different order should be considered as the same url.
Or am I being too picky ?
Comment #23
m3avrck CreditAttribution: m3avrck commentedI think too picky. I think in most cases in Drupal the arguments are always passed in the same order through the URL, I rarely see this changing and a patch to account for that would be overkill IMO. Simply comparing the path and the query fixes all of the problems I noticed in core so I think that should be sufficient.
Comment #24
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedafter applying that latest patch,
1. go to a page that has a query string set (e.g. /node/somepath?a=b)
2. on that page, make a link with l() to itself, but with no query e.g. l('something', 'node/somepath');
expected behavior: active class is not set
actual behavor: active class is set
Comment #25
m3avrck CreditAttribution: m3avrck commentedwtanaka, that is a good catch, seems that problem only occurs when clean URLs are on, when they are off, that problem wasn't happening. I also discovered another problem, the converse of what you posted, in that if you were on a page with a query, such as /node?page=1 and had a link that was the same, it wasn't being marked as active either.
This new patch should fix both of these problems. Please confirm and set RTC, thanks!
Comment #26
yched CreditAttribution: yched commented+1 : This last patch works OK for me (I'm not using clean urls though)
A little advertisement here : I have proposed a patch on a related subject (node/49181).
It marks any link to a path that is in the current menu trail with the class ="active-trail", which I think is quite usefule for site-navigation awareness.
It only looks at the drupal path, and doesn't take the query part into account (just the way 'active' worked before your patch)
so in the exemples mentionned in the two previous posts, the links would still be marked 'active-trail' (which looks right to me : a page "with queries" can be seen as a child of the same page "without queries")
Comment #27
m3avrck CreditAttribution: m3avrck commentedComment #28
Dries CreditAttribution: Dries commentedIf I remember correctly, QUERY_STRING is a "Apache 2"-ism. It might not work on IIS, Apache 1, or any other webserver. If this is not the case, feel free to switch back the status.
This patch makes me nervous;
l()
is performance critical. This patch might significantly slow down sites that generate a lot of links.Comment #29
m3avrck CreditAttribution: m3avrck commentedDries, I did searching and I don't think QUERY_STRING has any problems, the only problems associated with it are:
And:
Both of which shouldn't affect anything at all.
Now, in terms of performance, I agree. However, right now the l() currently doesn't handle queries at all and wrongly applies "class='active'" which can be problematic to themers. However, code wise, it is minimal and substr() should be very fast with only knocking off the first 2 characters.
Perhaps somebody can benchmark this? I don't have great setup otherwise I would.
Comment #30
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedafter applying common.inc_18.patch (using clean urls) no links that I could see got marked active, even if neither the l() call nor the current page had query parameters
Comment #31
m3avrck CreditAttribution: m3avrck commentedI can't reproduce this with the lastest HEAD. That patch works perfectly for me, with regular and clean URLs, even emptying cache on each of the page views.
Comment #32
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedI have i18n installed -- it could be a bad interaction between the patch and that module
Comment #33
m3avrck CreditAttribution: m3avrck commentedHmm, that shouldn't break it, should it? What if you disable that or test on another clean Drupal install?
Comment #34
yched CreditAttribution: yched commentedBump.
There hasn't been any news on the i18n issue ?
Maybe we can considered it fixed and commit that patch ?
Comment #35
steph CreditAttribution: steph commentedm3avrck proposed me to work on this patch instead of http://drupal.org/node/53926.
I am this modifying a little bit the patch to take care of '' item also.
Comment #36
chx CreditAttribution: chx commentedif (($path . (($query != '') ? '&' . $query : '')) == $_GET['q']) {
my poor head hurts from reading this. Drupal has nice code. This is not nice. I'd daresay it's very ugly.Comment #37
Wesley Tanaka CreditAttribution: Wesley Tanaka commentedThat actually was part of what dissuaded me from looking more into the problem I was having on my site (comment #30)
Comment #38
David Stosik CreditAttribution: David Stosik commentedSteph, it seems that your patch "common.inc.patch.head" doesn't correct the problem I had there: http://drupal.org/node/53926 .
Am I right?
Are there in fact two different problems, or didn't I understand very well?
Comment #39
ricabrantes CreditAttribution: ricabrantes commentedThis bug are fixed in D5.x-dev..
Comment #40
Anonymous (not verified) CreditAttribution: Anonymous commentedAutomatically closed -- issue fixed for two weeks with no activity.
Comment #41
oadaeh CreditAttribution: oadaeh commentedThis was never fixed and is still around in 7.x.
I found this issue trying to create a 6.x theme. All the pager links have class="active" set on them, so I can't theme them the way I want.
I'm setting it to version 8.x, as I know it won't go into 7.x, but I'll be working toward a 6.x version.
Comment #42
oadaeh CreditAttribution: oadaeh commentedAttached is a patch that I believe addresses all concerns brought up in this thread related to the current subject (I did not address the original issue(s) or any of the linked to issues), although in three days of testing and retesting, it's possible I missed something.
The patch is against HEAD, which is still tagged as 7.0. I suspect I'll have to re-create it as soon as 7.0 becomes official and there's a real 8.x.
In order to completely address this, I needed to use both $_GET['q'] and $_SERVER['QUERY_STRING']. I couldn't find any other way to get access to all the correct parts w/o having to create a lot of additional code to remove the unneeded parts of the path.
Also, with the current status of core, I needed to introduce quite a bit more code ($query is now an array and part of $options). In order for that code to not be a burden on the overall function, I attempted to add tests which should fail out on the larger number of links before doing any real computations. I think it will reduce a lot (but probably not all) of unnecessary code execution. Hopefully, it is acceptable.
Comment #43
oadaeh CreditAttribution: oadaeh commentedI'm resetting the version to see if the patch passes the test bot.
Comment #44
oadaeh CreditAttribution: oadaeh commentedComment #45
oadaeh CreditAttribution: oadaeh commentedTrying to see if I can get the patch re-queued, since it seems to not be going anywhere.
Comment #46
oadaeh CreditAttribution: oadaeh commentedNext step.
Comment #47
oadaeh CreditAttribution: oadaeh commentedAll right, never mind. I'll just wait for things to settle down. Sorry for the noise.
Comment #48
oadaeh CreditAttribution: oadaeh commentedAdding a fix for the failed tests and a line I forgot to add in the previous patch. :^(
Comment #49
oadaeh CreditAttribution: oadaeh commentedComment #50
pillarsdotnet CreditAttribution: pillarsdotnet commentedTesting...
Comment #51
pillarsdotnet CreditAttribution: pillarsdotnet commentedThe patch works.
Comment #52
yched CreditAttribution: yched commentedThe issue was stale for 4 years. This cannot be set to RTBC against 7.x within 3 days just on the basis that "it works".
- This could arguably be called an API change - the behavior of the l() function changes, and will impact existing sites out there
- l() is definitely in the critical path, so any change in there needs to be carefully scrutinized for performance impact. Benchmarks.
Comment #53
oadaeh CreditAttribution: oadaeh commentedUpdating the version.
Comment #54
oadaeh CreditAttribution: oadaeh commented#48: active_link_fix.patch queued for re-testing.
Comment #55
Lars Toomre CreditAttribution: Lars Toomre commentedI do not believe that this is an API change but rather a correction of a long-standing problem. Ysched, could you perhaps elaborate on how you fear this behavior change will impact exiting sites negatively?
I do agree with you though that this needs benchmarks before such a frequently used function l() is changed.
One problem I note is that the patch as is does not account for the fact that the path that might use a language other than English. If $options['language']->language is set, it should be used as the second optional parameter to drupal_get_normal_path.
The function also looks like it can be sped up slightly through the storage of intermediate results in static variables. Hence, the $query and $current_page values need only be calculated once across many calls to l() on the same page.
Comment #56
mgiffordThe patch applies nicely to D8 & fixes the problem I identified in this duplicate bug #1170418: All Pagination Links Have Class class="active"
Comment #57
pillarsdotnet CreditAttribution: pillarsdotnet commented#48: active_link_fix.patch queued for re-testing.
Comment #59
pillarsdotnet CreditAttribution: pillarsdotnet commentedRe-rolled with changes suggested in #55 by Lars Toomre.
Comment #61
pillarsdotnet CreditAttribution: pillarsdotnet commentedCorrected.
Comment #63
pillarsdotnet CreditAttribution: pillarsdotnet commentedCorrected.
Comment #65
pillarsdotnet CreditAttribution: pillarsdotnet commentedLet's try removing one of the suggested changes.
Comment #66
pillarsdotnet CreditAttribution: pillarsdotnet commentedComment #68
pillarsdotnet CreditAttribution: pillarsdotnet commentedObviously, the original code identified some paths as active where the patched code does not. Let's combine both approaches.
Comment #70
pillarsdotnet CreditAttribution: pillarsdotnet commentedOkay; let's try remove the caching, instead.
Comment #72
mgiffordLooks like you might need to change a couple of the tests looking at #68's test results. Though #70 just looks like a bad bot. I'm going to try it again and see if that helps.
Comment #73
mgifford#70: identify-active-paths-41595-70.patch queued for re-testing.
Comment #75
pillarsdotnet CreditAttribution: pillarsdotnet commentedOkay, this contains some unrelated changes, but it passes locally. Let's see what the testbot says.
Comment #76
pillarsdotnet CreditAttribution: pillarsdotnet commentedRemoving the unrelated changes.
Comment #77
pillarsdotnet CreditAttribution: pillarsdotnet commentedUnassigning and tagging.
Does anyone care to benchmark this?
Comment #78
xjmThanks for your work on this patch. Note that the Drupal 8.x patch will need to be rerolled, because the core directory structure for Drupal 8 has now changed. (For more information, see #22336: Move all core Drupal files under a /core folder to improve usability and upgrades). When the patch has been rerolled, please set the issue back to "Needs Review."
Tagging as novice for the task of rerolling the Drupal 8.x patch. Also, if anyone wants to help with benchmarking it, that would be cool too.
If you need help rerolling this patch, you can come to core office hours or ask in #drupal-gitsupport on IRC.
Comment #79
musicnode CreditAttribution: musicnode commentedRe-rolled, needs review.
Comment #80
xjmThanks!
Comment #81
sunThe original issue indeed was never fixed. The bug also exists in D6.
The suggested changes for l() in pretty much all patches of this issue are highly debatable and very likely have a serious negative impact on performance, since l() may be called very often in a single request.
We do not have many other areas in which links heavily rely on the 'active' class/styling and are using query strings like pager links anyway yet. This means we want to fix the precise bug in pager.inc first, and in a way that can be easily backported.
Let's resolve the generic issue in #1410574: Make l() respect the URL query string before adding the 'active' CSS class
Attached patch implements a test that proves that the bug exists. Fix forthcoming.
Comment #82
sunAnd the fix.
Amusingly, none of the pager links is supposed to be active at any time, so this could have been fixed very very easily ages ago, as in attached patch.
Comment #83
pillarsdotnet CreditAttribution: pillarsdotnet commentedWow; elegant.
Comment #84
Tor Arne Thune CreditAttribution: Tor Arne Thune commentedLooks like a good solution to me.
Without patch in #82:
With patch in #82:
Comment #85
Tor Arne Thune CreditAttribution: Tor Arne Thune commentedAlso, patch looks good except for a new blank line at EOF.
Comment #86
sunThe blank line at EOF is fine. Only the reverse (no newline at EOF diff warning) would be a reason to reject.
Comment #87
patrickd CreditAttribution: patrickd commented#82 nice and working
Comment #88
Dries CreditAttribution: Dries commentedI wonder if for 8.x we should make l() smarter instead of trying to work around it?
Comment #89
sun@Dries: That's a separate issue: #1410574: Make l() respect the URL query string before adding the 'active' CSS class
Comment #90
Dries CreditAttribution: Dries commentedLet's move this to 7.x then and focus on #1410574 for 8.x.
Comment #91
webchickWell, it probably makes sense to keep the D7 and D8 code bases in sync while we work on a more optimal fix.
Comment #92
xjmYeah, I'd agree that #82 should go into D8 and D7 both now, and we can follow up with #1410574: Make l() respect the URL query string before adding the 'active' CSS class after.
Comment #93
sunMy overly naive hope was to get this trivial fix into D8, D7, and also D6 for the new point releases happening tomorrow. :(
Even though it's utterly unlikely that this is going to happen anymore, here's the full stack of backports. All of them have been manually tested already.
Comment #94
mgiffordJust to say I tested @sun's too patches in #93 against 7.10 & 6.22 and both applied nicely and provided the expected results.
Not sure if we'll get it in to tomorrow's release point, but..
NOTE: I should add that I didn't test the tests, just the results.
Comment #95
catchYeah let's not leave 8.x with known regressions from Drupal 7, additionally we need the test coverage here, even if we're able to clean up the code in the follow-up (which already has a patch).
Committed/pushed to 8.x, moving back to 7.x.
Comment #96
sunSame as #93 for testbot.
Comment #97
fietserwin- Tested on D7.12: works as supposed.
- Reviewed by comparing to the accepted D8 patch: no differences accept for occurrences of /core.
Comment #98
webchickCommitted and pushed to 7.x. Thanks! Marking down to 6.x.
Comment #99
Albert Volkman CreditAttribution: Albert Volkman commentedD6 backport.
Comment #100
sunRe-uploading existing backport including tests from #93.
Comment #101
scor CreditAttribution: scor commentedThe test introduced by #96 (Pager functionality) fails on a tesbot instance, my MAMP localhost and also on btmash's machine.
Comment #102
xjm8.x will have the same problem. Guess so far is that this might be related to Drupal being installed in a subdirectory.
Comment #103
sunSo the href contains a potential subdirectory already, so this should have been $GLOBALS['base_root'] instead.
Comment #104
BTMash CreditAttribution: BTMash commentedFor now, I am submitting a D7 patch because apparently, there is not pager.test file for D8 :/
Comment #105
scor CreditAttribution: scor commentedRTBC'ing D7 patch in #104, fixes the test on both localhost and testbot.
Comment #106
scor CreditAttribution: scor commentedpatch for D8 (includes pager.test from #96 and fix from #104).
Comment #107
BTMash CreditAttribution: BTMash commentedI'm going to be marking 8.x as rtbc since this is basically a reroll of what was supposed to go in from #93, has the change from #104 , and the tests pass locally.
Comment #108
webchickGreat, thanks all! Committed/pushed #106 to D8, #104 to D7.
Back to 6.x for #100.
Comment #109
sunAdjusted the D6 backport identically.
Comment #110
xjm#109 looks like a thorough backport (and the test coverage!).
Tagging for manual testing as well since I know Gábor prefers to see confirmation that the patch works well in production. Please test #109 on your D6 sites and report the results here in the issue.
Comment #111
danillonunes CreditAttribution: danillonunes commentedI have applied the patch from #109 in a site running Drupal 6.20 and it works fine at home page, but not at any of admin pages. Later I saw the admin theme I was using (Rubik, based on Tao), has a custom theme_pager function which uses theme_links instead of theme_pager_link to render the pager links.
Also, the patch creates a new file modules/system/tests/pager.test. I don't know if test files like that are being used anywhere in D6.
Comment #112
mgiffordYa, sounds like the pager.test should be removed..
@danillonunes want to re-roll the patch for D6?
Comment #113
sunI don't see why we'd want to remove the test coverage. The test results for #109 nicely show that the test was executed and passes.
Comment #114
mgiffordGood point.. Thanks @sun!
Comment #115
Danny_Joris CreditAttribution: Danny_Joris commentedSo this is fixed for all pagers, but what about any other links that have the same ?q, but different query parameters? They all get an active class. Is there an open issue for that?
Comment #116
thedavidmeister CreditAttribution: thedavidmeister commented#115 - l() has gone through a lot of changes between D6 and D8, so I'm reasonably sure that issue is fixed in the latest version at least.
I've attached a patch from simplytest.me showing that the active classes do not show up for links in pagers with this patch attached, so I'd say the manual testing has been done for this.
I was getting some whitespace errors when applying the patch locally, so I've marked it as "needs reroll".
Comment #117
thedavidmeister CreditAttribution: thedavidmeister commentedComment #118
timmillwood