8

I have a site that is built as a single-page and all requests are made with AJAX. The pages are like site.com/#Page or site.com/#Page/Other.

Now, I need to implement the a Skip Navigation link in the site, but because the URLs start with # I cannot use a simple anchor. Is there any way to do it without changing all the URLs? Thanks.

Note: the skip navigation does at least 3 things: scrolls to that part of the page, focus on the element where the content starts (it can even be a not focusable element, such as an H1 title) and lets the screen readers know about the change.

Diego Jancic
  • 7,280
  • 7
  • 52
  • 80
  • Are you using a SPA framework? It would be helpful to know details on how you handle routing. There's some [possible solutions for angular](http://stackoverflow.com/questions/14712223/how-to-handle-anchor-hash-linking-in-angularjs) users, for example. – Jasen Nov 11 '15 at 18:09
  • @Jasen No, I'm not. I'm using a simple JS library for handling browser history, but that's it. What I can see in the example you put is that it only scrolls, but doesn't work well with keyboard navigation or screen readers. – Diego Jancic Nov 11 '15 at 18:18

3 Answers3

3

You have two things to do:

  • have a focusable element (use tabindex="-1" for the elements which are not focusable by default like h1)

  • focus it using javascript/jQuery focus() method

Example:

document.getElementById("myEle").focus();

or

jQuery("#myEle").focus();
Adam
  • 17,838
  • 32
  • 54
0

To achieve what you want, you can take a look at scrollTop() in JQuery : https://api.jquery.com/scrollTop/

Raphaël Vigée
  • 2,048
  • 14
  • 27
  • 1
    `scrollTop` only scrolls the window, it doesn't do the other things I've mentioned in the _Note:_. The main problem is that it doesn't focus on the element, so the screen readers don't start reading from there. – Diego Jancic Nov 11 '15 at 18:14
0

I finally figured it out. I basically had to

  1. Disable the framework/script used for handling the hash changes
  2. Change the URL to point to the main content
  3. Restore the original URL and re-enable what I disabled in #1.

For example, I had an event like this:

var onPageChange = function (newLocation, historyData) {
    // load page
};

First, I changed it to:

var pageChangeEnabled = true;
var onPageChange = function (newLocation, historyData) {
    if (pageChangeEnabled) {
        // load page
    }
};

And then, the Skip Navigation link looks like this:

<a href="javascript:pageChangeEnabled=false;var oh=location.hash;location.hash='#content';location.hash=oh;pageChangeEnabled=true;void(0);" id='skipNav'>Skip Navigation</a>

For easier understanding, this is the code in the href:

// disable navigation
pageChangeEnabled=false;

// save current hash
var oldHash=location.hash;

// update the hash/anchor, make everything work
location.hash = '#content';

// restore the old hash, as there are no elements that have the same
// name of the URL, it works
location.hash = oldHash;

// re-enable page navigation
pageChangeEnabled=true;

// void(0); is just to avoid the navigation of the link
void(0);

UPDATE: As explained by Adam, this does not fully work as keyboard navigation does not change. I ended up doing: $('#content').attr('tabindex', '-1').focus();

Diego Jancic
  • 7,280
  • 7
  • 52
  • 80
  • this won't give keyboard focus to the element. (pressing tab will lead you to the very first link of the page) – Adam Nov 12 '15 at 08:13
  • @Adam you're right. I though I have tried your answer and didn't work. I tried it (again?) now and it works perfect on Chrome with NVDA :) Thanks. – Diego Jancic Nov 12 '15 at 16:50
  • If you put this in a function and attach it to the link with `link_elem.onclick=scroll_top_function` it will be more readable and maintainable – Daniel F Dec 24 '15 at 18:11