Split from #303889: Impossible to update D6 -> D7
GBain22 summarized it pretty well:

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!)

Comments

JohnAlbin’s picture

Subscribing while I digest the idea of having a #skip_to_nav link inside an actual drupal menu.

pwolanin’s picture

Priority: Normal » Minor

Well, as pointed out in the other thread, seems like there might be a number of cases where there would be a consistent anchor or query string that when appended to the current URL would give a useful result.

catch’s picture

Priority: Minor » Normal

I should clarify that I've got no real interest in this issue either way, just keeping the queue tidy, and this was actually split from #123103: Retain #anchors during path alias -> normal path saving

catch’s picture

Priority: Normal » Minor

cross-posted

mgifford’s picture

Why would you put a 'Skip to content' in a menu? Generally it's something you'd want to put into a theme and treat differently than other menu items. You're not wanting to have the user change it all that often. Wouldn't want it to be as visible as the other menus usually.

This isn't a challenge for your request as much as it is for the example.

Gomez_in_the_South’s picture

I think this is a reasonable request. In my case I wanted to put a link to the top of the page in a bottom menu. It wasn't an option to place a link in the template as the link needed to be one of the middle menu items (where it made the most sense from a usability point of view).

For those looking for a solution in the meantime, this is what I did, which worked for me in Drupal 6:
1. Create a menu item with the path as http://anchor_top
2. I copied the function theme_menu_item (see the API) into the template.php of my current theme (replacing 'theme' with the name of my theme).
3. In this theme_menu_item function I added the following lines of code:

// if the menu item should actually be an anchor, replace part with #

if (!(strpos($link, "http://anchor_") === false)) {  
  $link = str_replace("http://anchor_","#",$link);
}

This causes the http://anchor_ in the link to be replaced with just a '#' which renders my final link as #top.

GBain22’s picture

@Gomez_in_the_South - I tried your code in Drupal 6 but it made no difference to the menu item itself - could you possibly show me another example instead of using "http://anchor" as I'm not sure what I should be entering for the menu item.

I also found that in Drupal 6 you receive a "The path '' is either invalid or you do not have access to it." error if you enter a Path like '#content' - Drupal 5 would allow this behaviour - which I didn't notice due to only recently upgrading to Drupal 6.

@mgifford - the reason this is needed, is simply to go with other items in the same menu, you're right - the user won't be editing it - because I won't be giving the user access to edit their menu's anyway - hence why it would be ideal to work - not to mention the huge importance in improving accessibility for screen reader users.

Garry.

pwolanin’s picture

Version: 7.x-dev » 8.x-dev
Everett Zufelt’s picture

Issue tags: +Accessibility

tagging

alpirrie’s picture

Just followed the thread all the way here. For accessibility, I could really use the feature suggested. Does the switch to 8.x-dev mean it's being pushed way into the future?

Subscribe.

AdrianB’s picture

Subscribing. (This would be useful for adding javascript fragment links as well.)

robonoob’s picture

Subscribing. (This would be very useful. I am finding way to implement this on theme level but without much success.)

Thanks @Gomez_in_the_South. Now I can add a menu item to link to part of the current page. I am using a Zen sub-theme on D6-16.

Garrett Albright’s picture

See: #123103: Retain #anchors during path alias -> normal path saving and subscribing. JohnAlbin, would you consider this a bug as well, just as you considered that one a bug? If so, I say we set the version back to 7.x and get to work.

Garrett Albright’s picture

RedTop’s picture

subscribing.

I'm hitting a wall adding a 'Top of page' link to a menu I've put into the footer.

Garrett Albright’s picture

RedTop, #759808: Disallow # character in path aliases is blocking this issue. If you can run Drupal 7, please test the patch in that issue and report back if it works.

jason.fisher’s picture

Just wanted to share how we are handling this problem (6.x) ..

Add this to your theme's template.php:

/* Allow #fragment links to be placed in menus via http://current/#fragment */                                                                                    
function THEMENAME_menu_item_link($link) {	
  if (strpos($link['href'], 'http://current/') !== FALSE) {
    $link['href'] = str_replace('http://current/', '', $link['href']);
    $fragment = true;
  }

  return $fragment ? str_replace('/%2523', '#', l($link['title'], $link['href'], $link['localized_options'])) : l($link['title'], $link['href'], $link['localized_options']);                   	
}

Then use http://current/#fragment as your menu path. Make sure to flush your theme registry cache.

mgifford’s picture

Can this be brought into D7 using the Accessible Helper Module?

KoshaK’s picture

it's works for me Well, except one thing...
It's only works for Default language!

I have two languages on my site, Russian - as Default and English.

The link in English pages looks like this http://www.photoexpedition.eu/en#top - it's loosing the node/[ID] part

If I set English as Default Language then it's works fine for English pages, but not for Russian.

any suggestions?

tejaspmehta’s picture

Hi,

Method posted in #17 by jason.fisher works well for home page only. Now i have url something like http://domain.com/content/abc then at time of using this method it take me to home page with following method http://domain.com/#aaa

It replace $link['href'] properly but not setting up menus properly. Anyidea why ?

Thank you
Tejas Mehta

sorensong’s picture

Do I have to rename/replace anything in this snippet?

sorensong’s picture

Issue tags: +anchor, +anchor fragments

This is seriously disappointing, such a basic option is unavailable in Drupal.

Zach Harkey’s picture

There are a lot of reasons to use a path like: <current>#fragment.

For example, it is a clean semantic way to implement an extremely flexible mega menu from content regions.

Just create a content region for each mega-menu item you want.

  regions[mega_1] = Mega 1
  regions[mega_2] = Mega 2

Then output these regions somewhere at the bottom of your page.tpl.php.

<?php if ($mega_1): ?>
  <div class="mega" id="mega-1"><?php print $mega_1 ?></div>  
<?php endif ?>
<?php if ($mega_2): ?>
  <div class="mega" id="mega-2"><?php print $mega_2 ?></div>
<?php endif ?>

Then we could use jquery to append each #mega-id content div up into the menu item with the appropriate href="#mega-id".

So if I was able to create menu items for "Mega-1" and "Mega-2" with paths of <current>#mega-1 and <current>#mega-2 respectively, the resultant output would be something like:

<div class="mega-menu">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about">About</a></li>
    <li><a href="#mega-1">Mega-1</a><div id="#mega-1">mega-1 blocks here</div></li>
    <li><a href="#mega-2">Mega-2</a><div id="#mega-2">mega-2 blocks here</div></li>    
    <li><a href="/contact">Contact</a></li>
  </ul>
</div>

The flexibility to create mega menu items containing blocks, mini-panels, forms, menus, nodes, views, etc. are endless.

--

Incidentally, I tried using the theme function workaround as described in #17 but it triggers the following error:

Fatal error: Unsupported operand types in /.../includes/common.inc on line 1593

Zach Harkey’s picture

Here is a modified version of the function in #17 that avoids Fatal errors and works well with other modules that need to modify link attributes, e.g., menu_attributes.

/* Allow #fragment links to be placed in menus via `http://current/#fragment`  */
function THEMENAME_menu_item_link($link) {
  if (empty($link['localized_options'])) {
    $link['localized_options'] = array();
  }
  if (strpos($link['href'], 'http://current/#') === 0) {
    $fragment = str_replace('http://current/#', '', $link['href']);
    $link['localized_options']['fragment'] = $fragment;
    $link['localized_options']['external'] = TRUE;
    $link['href'] = '';
  }
  return l($link['title'], $link['href'], $link['localized_options']);
}

dcmouyard’s picture

The code in #24 doesn’t work in D7. I was able to get the following to work:

/**
 * Override HTML for links.
 */
function THEMENAME_link($vars) {
  // Allow #fragment links to be used via 'http://current/#fragment'
  if (strpos($vars['path'], 'http://current/#') === 0) {
    $vars['options']['fragment'] = str_replace('http://current/#', '', $vars['path']);
    $vars['path'] = '';
  }

  return '<a href="' . check_plain(url($vars['path'], $vars['options'])) . '"' . drupal_attributes($vars['options']['attributes']) . '>' . ($vars['options']['html'] ? $vars['text'] : check_plain($vars['text'])) . '</a>';
}
aklump’s picture

Here is another Drupal 7 Solution that uses hook_preprocess_menu_link() and a slightly different menu link format. It has the advantage of maintaining the render array format and the link fragment format is potentially more intuitive, and at least shorter.

My use case for this is as listed above, which is to add a Top link to a footer menu, and the admin can still modify the word Top if they so choose.

Here's what to do...

The link you enter in the menu form is
:# + FRAGMENT NAME, e.g. :#top

And in your theme or module you need to add the following code:

/**
 * Implements hook_preprocess_menu_link().
 */
function THEMENAME_preprocess_menu_link(&$vars) {

  // Allow fragements as menu items
  if (substr($vars['element']['#href'], 0, 2) === ':#') {
    $vars['element']['#localized_options']['fragment'] = substr($vars['element']['#href'], 2);
    $vars['element']['#href'] = drupal_is_front_page() ? '<front>' : drupal_get_path_alias();
    $vars['element']['#attributes']['class'][] = 'fragment';
  }
}

I've also added a class 'fragment' so you can turn off any styling you may have on a.active, since it is odd to have an active fragment.

bowersox’s picture

+1 for allowing menu link paths to include anchors (/foo/bar#myanchor). There are cases where users want to build links that go directly to an anchor deep into a long page.

mgifford’s picture

Issue tags: +Responsive Design

There is a good use case to add links to the top of the page in the footer for menus in the new responsive themes. Being able to add a footer menu with links up to sections higher up the page would be a good user pattern that you can't presently do with the menus right now.

This will be useful for mobile sites.

TinaRey’s picture

After hours of searching #25 worked for me, thanks a ton! D7, link in main menu to contact form footer.

Also tried #26 but that didn't work: I put in :#webform-client-form-2, which after saving kind of doubled (:#webform-client-form-2#webform-client-form-2) and the link it produced was :#webform-client-form-2 so a page not found failure came up...

wrg20’s picture

Here's a workaround I did to make anchors available in menus.

1. Install and enable the module "Redirects" for D7. I'm using version 7.x-1.0-beta4+3-dev
2. In your menu use "node/nodenumber-anchorname" for the path (i.e. node/100-myanchorwithoutpoundsign).
3. Go to the page where the anchor lives (node/nodenumber).
4. Select URL Redirect ->Add URL redirect to this content.
5. Put "node/nodenumber-myanchorpoundsign" in the FROM section
6. Put "node/nodenumber#anchorname" in the TO section
7. Optional: Change the advanced options and change the status to 302

Now when you click on the item in the menu it will redirect to the anchor within the page. This will also help ensure that relative paths still work when you move from development to production. I know it's not pretty because it shows the node # in the link but I figured I would share this with you.

Garrett Albright’s picture

Hash tag. Oh God, you called it a hash tag…

wrg20’s picture

too much Twitter on the brain...

mgifford’s picture

Can someone propose a patch?

mgifford’s picture

Status: Active » Closed (duplicate)

I'd like to direct this to #1543750: Allow menu items without path

IELTS_REGISTRATION’s picture

To create a link(e.g. http://www.bigrock.in/transfer/domain-transfer.php) to a named anchor (e.g. "#domaintransfer"), you will need to use a small work-around.

l('linktext', '', array('fragment' => 'namedanchor', 'external' => TRUE));

To create a hash-only link (to "#"), you'll need to adapt it to:

l('linktext', '', array('fragment' => ' ', 'external' => TRUE));

(Note that the fragment does contain a space.)

rooby’s picture

Issue summary: View changes
Related issues: +#1543750: Allow menu items without path
apaderno’s picture

Issue tags: -anchor fragments

I am removing the tags used in just few issues. I apologize for bumping this issue.