Retain #anchors during path alias -> normal path saving

nasi - February 27, 2007 - 11:40
Project:Drupal
Version:7.x-dev
Component:menu system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:active
Description

It is often desirable to create a menu item that links to a particular place on a page, e.g. /node/xx#name

In the menu system the # character is translated into %2523 and the link fails.

There is a hack, documented at http://drupal.org/node/106821, whereby you can specify a complete url to avoid this translation. This is an inelegant workaround and not a solution as it leads to management problems when the base url is not constant throughout the life of a site (e.g. when migrating between test/live sites or when it runs concurrently on two domains: xx.com, xx.co.uk).

I can't see any reason why the # character cannot be escaped. It doesn't pose any security threat and only users with admin privileges can define menu paths.

#1

JohnAlbin - June 8, 2007 - 00:20
Category:feature request» bug report
Status:active» needs review

Named anchors are a standard part of the URL scheme. So not properly handling them in the menu system is a bug, IMO.

The attached patch allows admins to add custom menu items with relative URLs and anchor fragments.

(Also, I’ve updated the above handbook page to show a better workaround then having to enter full URLs.)

AttachmentSize
fragment.patch 2.22 KB

#2

Steven - June 11, 2007 - 06:30
Status:needs review» needs work

Tweaks like this will not work afaik, since normal menu paths can contain the # character.

If we want to change the menu system to support fragments and/or query strings, this needs to be added properly, without introducing forbidden characters in the menu paths.

This could mean that you enter menu paths in urlencoded form (i.e; what this patch tries to do) in the UI, but that would need to be integrated cleanly with the current unencoded, module-generated paths.

#3

catch - June 11, 2007 - 14:51

The path_redirect module adds an extra field in for named anchors

_____________ # _____________

or similar. That makes the distinction pretty clear, not sure how it stores it though.

#4

JohnAlbin - June 12, 2007 - 15:54
Status:needs work» needs review

From section 3.3 of RFC 3986 (Uniform Resource Identifier (URI): Generic Syntax):

The path is terminated by the first question mark ("?") or number sign ("#") character, or by the end of the URI.

So the # and ? characters, according to the RFC, are already forbidden in the path. Right now, Drupal encodes all characters in the path (including the #), but I can’t think of any real-world examples of using an encoded # in the path of a URL.

Steven, the above patch doesn’t change the way Drupal handles url encoding. You would still enter URLs in unencoded form. It just splits the path at the first # and puts the parts back in $item->path and $item->fragment.

#5

Steven - June 12, 2007 - 17:33
Status:needs review» needs work

I'm not talking about URL path components, but about Drupal menu paths. They are not the same.

#6

Steven - June 12, 2007 - 17:35

As for a real world example... any search that includes a # in the keyword box.

#7

Ryan Palmer - August 7, 2007 - 20:06

Any progress on this lately?? Was there a group consensus reached on a course of action??

#8

seanr - September 10, 2007 - 17:33

I've needed this for a very long time and am amazed it's still not possible. This is a pretty basic thing to want to do in a web site. The example I need it for right now is a political candidate's bio page with targets to each section (why I'm running, voice of the voters, etc.). I'd like to not have to break the bio up into three pages simply because the menu won;t let me use targets.

#9

Hinrich - September 22, 2007 - 18:43

Anchors are necessary. We using them to separate paragraphs in a long article. As I create my own theme, I do not have any problems to insert a simple str_replace, but the time I used for the search.

I cannot imagine, why an url cannot have an anchor in the menu system. It is like an article without a title.

#10

sumgai - December 11, 2007 - 17:06

It's crazy not to support this.

I have lots of pages with a <a name='top'></a> at the top and a <a href='#top'>Top</a> at the bottom.

I can't do this in Drupal.

In v5.x, I hacked the url and menu_path_is_external functions so it worked, by just adding:

  if(strpos($path, '#') === 0) return $path;

as the first line in each of the functions, but in 6.x, the changes to the menu system break that simple hack.

#11

rickauer - January 12, 2008 - 12:44

Can we revive this thread? There seems to be a consensus that enabling # and ? in the menu system does make sense (I just wanted to link to a Drupal page like "my/url?page=2", which is not allowed unless you specify the FQDN). Can some developer look at this, please?

Thanks,
Stephan

#12

webernet - January 12, 2008 - 18:21
Version:5.x-dev» 6.x-dev
Status:needs work» fixed

I believe this is fixed in 6.x.

#13

Anonymous (not verified) - January 26, 2008 - 18:21
Status:fixed» closed

Automatically closed -- issue fixed for two weeks with no activity.

#14

mikegulline - February 29, 2008 - 22:00

i have 6 and i am having the same prob. i dont think its fixed yet. anyone figure this out yet?

mike

#15

tanc - May 1, 2008 - 01:14

Yeah, this seems kind of strange. What about the fairly usual case where a menu item should point to something with a url redirect after in the form of: ?destination=

At the moment in Drupal 5 (haven't tested 6) it wont work. In many other modules and situations we can specify a destination in the url, why not in a menu item?

#16

Ryan Palmer - June 28, 2008 - 00:02
Status:closed» needs work

I don't think this was fixed in 6.

Relative paths using named anchor links in menu items do not work. The menu system won't accept them as a valid path.

#17

pwolanin - June 30, 2008 - 15:58
Status:needs work» postponed (maintainer needs more info)

@Ryan - if you really think this needs to be re-open, please more details of how you'd solve this. For example, we might think about a feature where a menu link could use <current> the same way it uses (at the moment) <front>

#18

Ryan Palmer - July 1, 2008 - 08:36

I realize the menu navigation is attached at the hip with hook_menu and the page serving mechanisms of Drupal, and that the needs of this cannot be ignored when requesting an issue that seems to relate to only adding menu items to the tree, not defining paths in the first place. My question is, is it really practical for hash symbols to be used in paths, and should this character become a non-eligible character altogether for the purposes of Drupal?

Assuming we must have hashes in paths without them being links to anchors (ie, encoded), how about:
- another column in the menu_links table (fragment)
- another field for fragment in menu_edit_item form, or some means of denoting a fragment (eg. "node/123bottom")

This would let everything else (# symbols and the rest) be properly encoded, and fragments could be built into the links when the menus are build.

I may not have the insight to suggest such radical changes to Drupal core at this point, though.

#19

pwolanin - July 1, 2008 - 11:57

@Ryan - for Drupal 6, anchors should already work for "normal" links. I thought the only issue to be addressed here was named anchors for the current page.

#20

Ryan Palmer - July 1, 2008 - 21:06

To my knowledge, with the exception of comment #17, this issue has been regarding menu items containing named anchors, WITH Drupal paths as well. Being able to leave the pre-anchor part of the path blank to have it always apply to the current page would be a bonus, IMHO.

Example: When adding a menu item with a path "buy#1", I get the following response:

The path 'buy' is either invalid or you do not have access to it.

#21

pwolanin - July 2, 2008 - 17:52
Category:bug report» support request

um, then I would expect you get the same error message inserting a link with the path "buy", right?

I can add a link to the path "node/4#hello" and it works fine.

#22

Ryan Palmer - July 3, 2008 - 06:34

Interesting.

For me, "buy" was an alias to node/40. Normally, when entering an alias to a menu item path, it replaces it with the node/# equivalent and notifies the user of the change, but in this case it says the "buy#1" path is not valid.

The menu item accepted a path of node/40#1 and the menu item ends up being buy#1 which is great.

Does anyone know, is this by design? And if so, should something be added to the description of the menu path field specifying this feature/limitation?

#23

pwolanin - July 3, 2008 - 12:06

hmm, accepting aliases at all was added late, so this may indeeed be a bug - please investigate and refocus the issue.

#24

troublehelix - September 20, 2008 - 20:38

I can confirm I have what looks like the same issue as Ryan, where the named anchor will work only if referencing it via node name, but not the alias.

#25

TheRec - October 20, 2008 - 07:56
Category:support request» bug report

I agree with pwolanin (#19 and #23), the only issue left 6.x is anchor for path aliases.

  • node/1#anchor works just fine.
  • my-nice-alias-to-node-one#anchor does not work. Error given when trying to save the menu item with this path :
    • The path 'test' is either invalid or you do not have access to it. When I remove the anchor from this path, the menu item is created well (because the path does exists).

And while fixing this I also think there are some thought to put in path menu items consiting only of an anchor (starting with #) which should "point" to the current path. I don't think a "link" (working like ) is useful, it is possible to just check if the path starts with # and if it does just use the specified path as the link (as it would do with an external link), then for browsers the link would be a relative link to an anchor on the current page.

#26

catch - October 20, 2008 - 12:56

When you add a menu item for node/1#anchor - does the path get aliased when you view it in the menu?

#27

TheRec - October 20, 2008 - 13:39

Yes it does get aliased and the anchor is working. Then, maybe it needs to be documented, although I know that this "translation" would certainly occur it didn't come to my mind to do it this way. Thanks for the solution.

Seeing that I am not the only one who thought that using directly the alias with an anchor, and not the nid, maybe it would not be such a bad idea to offer both solution for anchors.

Lastly, that leaves us with the feature request, the "relative anchor" I talked about before, maybe we should create a feature request for this ?

#28

catch - October 20, 2008 - 14:17
Version:6.x-dev» 7.x-dev
Status:postponed (maintainer needs more info)» active

OK, marking this back to active and bumping to 7.x. I can see two issues here here:

1. allowing a menu item with only a fragment, i.e. #anchor
2. When drupal_get_normal_path is called as part of the menu item validation, if the alias has an anchor appended, ignore this, then add it back to the normal path (so alias#anchor gets split to alias + #anchor which eventually gets saved as node/1#anchor).

I'm not sure how the first one should work - which use cases are there for having the same #anchor on every page a menu might show up on? #2 sounds like a decent usability improvement to me.

#29

TheRec - October 24, 2008 - 07:24
Category:bug report» feature request

About 1., an example would be "skip links" to improve accessibility. At the top of the page you offer links which point to named anchors like "#content" (if you have a named anchor or even an element with id called "content") and it will help people using a screenreader to skipping all the navigation links (for example). They will reach the content way more quickly. Of course this can be done directly in the page.tpl, but then you loose all the menu features. For example the ability to translate those. Well, it is possible to make this last part (transaltion) with the t() function and the interface translation system too.

If it is implemented, I doubt it would require much more efforts than it took to support external links... but with that kind of paths the "#" should not be encoded otherwise it will just not work of course.
Another problem we would run into is that the link_path field would be empty in the menu_links table since fragments (anchors) are stored in the options field, if I understood how it works, so after all the " <current>" placeholder wouldn't be such a bad idea. It could also be useful with querystring (which is stored in the same field, options) instead of anchor, the principle is the same for both (we would just need to respect the order, ?query=string#anchor (and not the opposite).

About 2., I would also see it as usability improvement more than a real "bug fix" (well, the feature is here, it just does not work as I expected, but it works), thus I changed the category. I think that your reasoning is right about how it should be done, it makes perfect sense since it basically how it works right now with not aliased paths (according to what I read this afternoon, so I might not have catched the whole picture but that's my understanding).

#30

catch - October 20, 2008 - 17:18
Category:feature request» bug report

I left it as a bug, because usability issues are bugs ;) It either needs more documentation there, or the behaviour should be changed.

#31

GBain22 - October 23, 2008 - 13:53

Hi Guys,

Just to echo a few points that people have already made, about why this is important.

In terms of accessibility, a "skip to content" link is extremely useful for blind users (using screen readers) as it gives them the ability to skip through all of your links and go straight to your main content. Here I would usually use

<a href="#maincontent">Skip to content</a>

but when this is published in a drupal menu the '#' becomes encoded as '%23' (don't quote me on that exact encode!)

The sooner this is sorted, the sooner I can stop worrying about hard coding in this skip links into my page.tpl.php file! I'm sure many of you feel the same.

Just thought I'd add a comment anyway!
Garry

#32

pwolanin - October 23, 2008 - 16:21

This sounds like a new feature - we have a <front> special symbol now - maybe we need something like a <current> tag to make clear the intent?

#33

catch - October 24, 2008 - 08:53
Title:Allow named anchor links (#) in menu path» Retain #anchors during path alias -> normal path saving

As far as I can see there's two issues:

1. If you save a normal path with a fragment, this is handled fine in the menu. When you enter a path alias, drupal_get_normal_path() doesn't validate it as an alias, so you can't save it. Since the end result would be the same, this seems like a UI inconsistency to me and it's clearly caused some confusion. (I haven't tested this, going on the reports above).

2. Being able to enter a fragment for the current path. <current> sounds like a reasonable way to do that. Although I can't think of a situation where you'd want to add anything other than a #fragment for the current path, so maybe just validation of the string might work?

These seem like different issues to me, so I've split current path handling to a new issue #325533: Allow <current>#fragment as a menu path

#34

TheRec - October 24, 2008 - 10:09

About 2., the only other occasion I see would be adding a querystring (as I said previously)... the use of it would also be limited but might still be useful, it can be handy to pass a parameter to the current page (i.e. like offering a link to the same page with a parameter telling the user does not have Javascript... indeed very limited, not that many other examples come to my mind right now ;)), but as I said it should not take that much more time to implement since it is done exactly the same way for #fragment and querystring (stored in options field in the menu_links table). The <current> would make it possible to handle both, as it is already done with <front>.

#35

pwolanin - October 24, 2008 - 18:44

@catch - thanks for clarifying and splitting the 2 issues.

#36

pwolanin - October 24, 2008 - 18:49

For those who really want to append an anchor, etc, in D6 to the current page, I suggest you'll need to implement/use a trivial module that implements hook_translated_menu_link_alter(). If I get bored I'll write it in the mini module section of the handbook.

#37

sumgai - May 22, 2009 - 16:55

I would like to create a menu item (using the admin interface) in a menu, say secondary-links, with the "Menu Link Title" as "Top" and the "Path" as "#top".
It would generate

<a href="#top">Top</a>

as the menu item. In this way, every page can have a "Top" link that works as expected.

But this is not possible today.

This seems to be linked to this whole discussion.

I've tried to raise this seemingly simple issue before, but have not gotten anything resembling a reasonable solution.

So, I thought I'd try posting this issue in this thread for you consideration.

Thanks,

Mitch

 
 

Drupal is a registered trademark of Dries Buytaert.