Keyboard navigation: how to go to the next and pre

2019-08-12 18:57发布

问题:

I am trying to build a site with keyboard navigation. I want the user to be able to navigate through a menu of five or six pages using the left and right arrows. No matter on which page is the user, I want him/her to go back/forward in the menu when the left/right arrow is pressed.

Let's say the horizontal menu is built this way :
[Home / Random page / Some page / Another page / And so on]

Apparently it is not working. Here is what I have so far :

document.onkeyup = KeyCheck;       

var pages = ["index.php", "random-page.php", "some-page.php", "another-page.php", "and-so-on.php"];

function leftarrowpressed() {
    location.href = pages[0]-1;
}

function rightarrowpressed() {
    location.href = pages[0]+1;
    }
} 

function KeyCheck(e)
    {
       var KeyID = (window.event) ? event.keyCode : e.keyCode;

       switch(KeyID)
       {

 // left arrow key
         case 37:
         leftarrowpressed()    
          break;

//  right arrow key
          case 39:
          rightarrowpressed() 
          break;

       }
    }

Thank you all for your help.

回答1:

pages[0]-1 will evaluate to "index.php"-1 which is NaN. You don't want to subtract 1 from the page URL (you basically cannot subtract from strings) - rather subtract 1 from the index to get the previous page. Also, guard for the bounds:

location.href = pages[ Math.max(0, 0 - 1) ];

and:

location.href = pages[ Math.min(pages.length - 1, 0 + 1) ];

I guess you replace the 0 with the index of the current page automatically.

Secondly, you have an extraneous } in rightarrowpressed it seems.



回答2:

okay, I checked out your site and modified/extended my code slightly to try to (almost) achieve what it is I think you want to do. I'm going to leave the other answer unedited because it shows what is probably a better method for doing this... This solution is rather hack-y, and just a way to illustrate the concept.

To see it, go to any of your pages (except the blog page), then open up webkit inspector (my code will only work in WebKit(chrome/safari), although it would be REALLY easy to make it work in any browser) and enter the following into the javascript console:

    document.querySelector("footer").setAttribute("style","position:fixed;bottom:0px;width:100%;");
    document.querySelector("header").setAttribute("style","position:fixed;top:0px;width:100%;");

    var pages           =       ["accueil","references","cv","contact","aide","blog"],
    classNames          =       ["accueil","ref","cv","contact","aide","blog"],
    pageUrls            =       ["","references.php","cv.php","contact.php","aide.php","blog/"]
    baseUrl             =       "http://maximelaforet.com/",
    currentPageIndex    =       pageUrls.indexOf(window.location.href.replace(baseUrl,"")),
    pageDivs            =       [1,1,1,1,1,1];

    pageDivs[currentPageIndex] = document.querySelector("div.content");
    pageDivs[currentPageIndex].id = pages[currentPageIndex]+"Page";
    pageDivs[currentPageIndex].setAttribute("style","-webkit-transition:all 1s ease-in-out;position:fixed;top:63px;width:100%;height:"+(window.innerHeight - 270)+"px;overflow:scroll;");

    for (var i=0; i<pageUrls.length;i++)
    {
        if (i!=currentPageIndex)
        {
            var pageGrabber = new XMLHttpRequest();
            pageGrabber.open("GET","http://maximelaforet.com/" + pageUrls[i], false);
            pageGrabber.send(null);

            if (pageGrabber.status==200)
            {
                var temp = document.createElement("div");
                temp.innerHTML = pageGrabber.response;

                if (pages[i]!="blog")
                pageDivs[i] = temp.querySelector("div.content").cloneNode(true);
                else
                pageDivs[i] = temp.querySelector("div#page").cloneNode(true);
            }

            pageDivs[i].id = pages[i]+"Page";
            pageDivs[i].setAttribute("style","-webkit-transition:-webkit-transform 1s ease-in-out;position:fixed;top:63px;width:100%;height:"+(window.innerHeight - 270)+"px;overflow:scroll;");
            if (i<currentPageIndex)
            pageDivs[i].style.webkitTransform = "translate3d(-100%,0,0)";
            else
            pageDivs[i].style.webkitTransform = "translate3d(100%,0,0)";

            document.body.appendChild(pageDivs[i]);
        }
    }

    window.addEventListener("keyup", KeyCheck, true);
    function KeyCheck(e)
    {
        e.preventDefault();
        e.stopPropagation();
        var KeyID = (window.event) ? event.keyCode : e.keyCode;

        switch(KeyID)
        {
            // left arrow key
            case 37:
            if (currentPageIndex == 0)//we're at the first page, go to the last
            currentPageIndex = pages.length - 1;//-1 to account for first index being "0"
            else//go to the previous page
            pageDivs[currentPageIndex].style.webkitTransform = "translate3d(100%,0,0)";
            pageDivs[currentPageIndex-1].style.webkitTransform = "translate3d(0,0,0)";
            document.querySelector("header").classList.remove(classNames[currentPageIndex]);
            document.querySelector("header").classList.add(classNames[currentPageIndex-1]);

            if (classNames[currentPageIndex] == "accueil")
            document.querySelector("li > a[class~='"+classNames[currentPageIndex]+"']").classList.toggle("current_acc");
            else
            document.querySelector("li > a[class~='"+classNames[currentPageIndex]+"']").classList.toggle("current_"+classNames[currentPageIndex]);
            if (classNames[currentPageIndex] == "accueil")
            document.querySelector("li > a[class~='"+classNames[currentPageIndex-1]+"']").classList.toggle("current_acc");
            else
            document.querySelector("li > a[class~='"+classNames[currentPageIndex-1]+"']").classList.toggle("current_"+classNames[currentPageIndex-1]);

            currentPageIndex--;
            break;
            //  right arrow key
            case 39:
            if (currentPageIndex == (pages.length - 1))//if we're at the last page, go to the first
            currentPageIndex = 0;
            else//go to the next page
            pageDivs[currentPageIndex].style.webkitTransform = "translate3d(-100%,0,0)";
            pageDivs[currentPageIndex+1].style.webkitTransform = "translate3d(0,0,0)";

            document.querySelector("header").classList.remove(classNames[currentPageIndex]);
            document.querySelector("header").classList.add(classNames[currentPageIndex+1]);

            if (classNames[currentPageIndex] == "accueil")
            document.querySelector("li > a[class~='"+classNames[currentPageIndex]+"']").classList.toggle("current_acc");
            else
            document.querySelector("li > a[class~='"+classNames[currentPageIndex]+"']").classList.toggle("current_"+classNames[currentPageIndex]);
            if (classNames[currentPageIndex] == "accueil")
            document.querySelector("li > a[class~='"+classNames[currentPageIndex+1]+"']").classList.toggle("current_acc");
            else
            document.querySelector("li > a[class~='"+classNames[currentPageIndex+1]+"']").classList.toggle("current_"+classNames[currentPageIndex+1]);

            currentPageIndex++;
            break;
            default:
            var noChange = true;//just so we can ignore the rest if a boring key
        }

    }

Keep in mind, though, this is a really hack-y way to do it, but it should point you in the right direction. Let me know if you have more questions.



回答3:

Well, seems to me you'll need to know which page you're currently on each time for it to work. For this I'd recommend window.localStorage if (and only if) A) all of the pages are served from the same domain, and B) You don't need to support older browsers. If either of those are untrue, this method won't work, and you'll need to do something else like parse the URL string.

I took your code and modified it slightly to show how you might use localStorage. I added some comments, but it should be relatively self-explanatory. Here 'tis:

//if current index don't exist, make it
if (!window.localStorage.currentPageIndex)
{
    window.localStorage.currentPageIndex = 0;//frustratingly, it gets stringified anyway - you have to parseInt later
}

//set up vars
var pages        = ["index.php", "random-page.php", "some-page.php", "another-page.php", "and-so-on.php"],
currentPageIndex = parseInt(window.localStorage.currentPageIndex);//as promised

//set event listener on window
window.addEventListener("keyup", KeyCheck);
function KeyCheck(e)
{
    var KeyID = (window.event) ? event.keyCode : e.keyCode;

    switch(KeyID)
    {
            // left arrow key
        case 37:
            if (currentPageIndex == 0)//we're at the first page, go to the last
                currentPageIndex = pages.length - 1;//-1 to account for first index being "0"
            else//go to the previous page
                currentPageIndex--;   
            break;
            //  right arrow key
        case 39:
            if (currentPageIndex == (pages.length - 1))//if we're at the last page, go to the first
                currentPageIndex = 0;
            else//go to the next page
                currentPageIndex++;
            break;
        default:
            var noChange = true;//just so we can ignore the rest if a boring key
    }

    if (!noChange)//haha, I love double negatives
    {
        //now dump the new current page index back into localStorage
        window.localStorage.currentPageIndex = currentPageIndex;

        //first, try it in your javascript console to make sure it works (refresh the page!)
        console.log(pages[currentPageIndex],currentPageIndex);
        //then use real urls and uncomment the next line to go to the new current page!
        //location.href = pages[currentPageIndex]
    }
}

But - I've gotta ask - do you really want to do it this way? that's a lot of HTTP requests and refreshing the page - are the pages small enough that you could just load them all together at once, and simply only display one at a time? (you could even do a cool sliding or crazy 3d effect between pages - again, assuming you only need to support newer browsers...)