How can I give the current page's link a disabled look?

僤鯓⒐⒋嵵緔 提交于 2019-12-07 15:41:31
Michael_B

UPDATED

On second thought, your problem is that when you click the link to a new page, you are refreshing the javascript...so the click event fires but then is immediately replaced by the original DOM elements for whatever page you browse to.

Use this instead:

HTML/Razor

<nav>
    <ul id="menu">
        <li><a href="/">Home</a></li>
        <li><a href="/About">About</a></li>
        <li><a href="/Contact">Contact</a></li>
    </ul>
</nav>

jQuery

$(document).ready(function () {
        $("#menu a").each(function(){
            //set all menu items to 'black
            $(this).css("color","black");

            var linkPath=$(this).attr("href");
            var relativePath=window.location.pathname.replace('http://'+window.location.hostname,'');

            //set the <a> with the same path as the current address to blue
            if(linkPath==relativePath)
                $(this).css("color","blue");
        });
});

I think this is pretty close to what you are looking for here:

http://jsfiddle.net/qmHeF/1/

JS:

 $("#menu a").each(
    function(index)
        {
            if(window.location.href==this.href)
            {
                $(this).parent().remove();
            }
        }
    );

I remove it from the DOM here (my personal preference) but you can just add a class or custom CSS if you like.

http://jsfiddle.net/qmHeF/2/

Updated: Changed it to add a class instead of remove it.

    $("#menu a").each(
function(index)
    {
        if(window.location.href==this.href)
        {
            $(this).addClass("current");
        }
    }
);

using window.location.href instead of the jquery href will give you the full URL instead of the relative url. That way you don't need to parse either url and you can just compare the two.

You have to create a CSS class for this active state, like suggested in the comment, I use current in this example.

.current {
text-decoration: none;
/* here you style the seemingly disabled link as you please */
}

As for the HTML, the active menu page would look like this:

If you are in the About page

   <nav>
        <ul id="menu">
            <li><a href="~/">Home</a></li>
            <li><a class="current" href="~/About">About</a></li>
            <li><a href="~/Contact">Contact</a></li>
        </ul>
    </nav>

If you want the link to be disabled, using only html, here goes the code. Fiddle was updated to show this code. An elegant solution using Javascript was provided below in the comments.

<nav>
    <ul id="menu">
        <li><a href="~/">Home</a></li>
        <li><span class="current" >About</span></li>
        <li><a href="~/Contact">Contact</a></li>
    </ul>
</nav>

I made a quick example here so you can see if this is what you're looking for: Example in jsFiddle.net

Best wishes

You can either check with some server-side language (e.g. PHP) to see if the current page is Home, About, or Contact, and apply a "current" class accordingly. Or, if you'd prefer, you can do this with JavaScript. I'm not sure how your absolute URLs look, but I would do something like this:

$(document).ready(function() {
     $('a[href="' + window.location.pathname + '"]').addClass('current');
});

You may have to add some forward slashes in there, depending upon how your URLs look.

There are three sets of solutions to this universal development task: 1) server-side scripting alters menu/links for you, 2) CSS styling using something like a "current" class, or 3) javascript/css hybrid solutions.

It really all depends on your system and scope of development. For large dynamic sites, obviously one might as well use server-side code if it's already being used anyway. But for most projects where one isn't already using such scripting, one can manually add in a 'current' class to links and style them as you please with CSS or even more the anchor wrapping the text entirely (depending on your style of link/menus).

For a more robust javascript solution, you might try this: automatic link hightler/styling

function extractPageName(hrefString)
{
    var arr = hrefString.split('/');
    return  (arr.length < 2) ? hrefString : arr[arr.length-2].toLowerCase() + arr[arr.length-1].toLowerCase();
}

function setActiveMenu(arr, crtPage)
{
    for (var i=0; i < arr.length; i++)
    {
        if(extractPageName(arr[i].href) == crtPage)
        {
            if (arr[i].parentNode.tagName != "DIV")
            {
                arr[i].className = "current";
                arr[i].parentNode.className = "current";
            }
        }
    }
}

function setPage()
{
    hrefString = document.location.href ? document.location.href : document.location;

    if (document.getElementById("nav") !=null )
    setActiveMenu(document.getElementById("nav").getElementsByTagName("a"), extractPageName(hrefString));
}

Then run setPage onload, such as with:

window.onload=function()
{
    setPage();
}

As far as usability goes, it's generally accepted that just styling a nav link to look less interesting, lower contrast, grayer, not underlined, etc, is sufficient to help people know here they are. The cost of clicking a link where you already are is pretty low, but it's a nice design touch for most sites anyway.

to programmatically change my links, based on current url, i would prefer jquery:

<style type="text/css">
.current {
   color: #cccccc;
}
</style>

...

<nav>
   <ul id="menu">
      <li><a href="~/">Home</a></li>
      <li><a href="~/About">About</a></li>
      <li><a href="~/Contact">Contact</a></li>
   </ul>
</nav>

...

<script type="text/javascript">
   $(document).ready(function() {
      var href = $("#menu li a").prop("href");
      $("a[href$='"+href.substr( href.lastIndexOf("/") )+"']").addClass("current");
   });
</script>

..the jquery code adds the "current" class to any a link that has its href property set to last part of address (after last /). Thats not perfect anyway if your links are somewhat like /Contact/More..

Your "Update 2" version is close to working - you just need to add the class to #home, not home

Something like:

.current {
    color: blue;
}

.current a {
      text-decoration: none;
}

with:

// ...
$("#home").addClass('current');
// ...

How about something like this?

What we are doing here is that we call updateMenu with a string contained in the href attribute of a menu anchor. If the string and the anchor.href match, then we hide the anchor and copy it's text content to a new text node which we then append to the li element.

If we don't have a match then we unhide the menu anchor and check to see if the li element's (the parentNode in this case) last child is a text node, if it is we remove it because it was added by us.

You requested:

I want the current page's link to give some visual indication that clicking the corresponding link would be senseless as the user is already on that page.

This solution does that and also renders the link unclickable.

Of course it doesn't have to be exactly this formulation, but can be some other variant, and of course you can achieve this using jquery rather than vanilla javascript if you prefer.

HTML

<nav>
    <ul id="menu">
        <li><a href="/">Home</a></li>
        <li><a href="/About">About</a></li>
        <li><a href="/Contact">Contact</a></li>
    </ul>
</nav>

Javascript

(function () {
    var updateMenu = (function () {
        var anchors = document.getElementById("menu").getElementsByTagName("a");

        return function (page) {
            Array.prototype.forEach.call(anchors, function (anchor) {
                var last;

                if (anchor.pathname === page) {
                    anchor.style.display = "none";
                    anchor.parentNode.appendChild(document.createTextNode(anchor.textContent));
                } else {
                    last = anchor.parentNode.lastChild;
                    anchor.style.display = "block";
                    if (last.nodeType === 3) {
                        anchor.parentNode.removeChild(last);
                    }
                }
            });
        }
    }());

    setTimeout(function () {
        updateMenu("/");
        setTimeout(function () {
            updateMenu("/About");
            setTimeout(function () {
                updateMenu("/Contact");
                setTimeout(function () {
                    updateMenu("");
                }, 5000);
            }, 5000);
        }, 5000);
    }, 5000);
}());

On jsfiddle

I you want to use hrefs like in your example i.e. "~/About", then you will need to formulate your string to be passed to updateMenu, like so for my example;

HTML

<a href="~/About">About</a>

Javascript

console.log(document.getElementsByTagName("a")[0].pathname);
console.log(window.location.pathname + "~/About");

Outputs

/Xotic750/G5YuV/show/~/About
/Xotic750/G5YuV/show/~/About 

On jsfiddle

See window.location for it's other properties

Returns a location object with information about the current location of the document.

For a purely css solution to this you could try pointer-events, here is a jsfiddle showing it in use.

Warning: The use of pointer-events in CSS for non-SVG elements is experimental. The feature used to be part of the CSS3 UI draft specification but, due to many open issues, has been postponed to CSS4.

CSS

.current {
    pointer-events: none;
    cursor: default;
    text-decoration: none;
    color: black;
}

HTML

<nav>
    <ul id="menu">
        <li><a href="/">Home</a></li>
        <li><a class="current" href="/About">About</a></li>
        <li><a href="/Contact">Contact</a></li>
    </ul>
</nav>

Your update #2 should work, but you forgot to put "#" ($('#home').addClass...).

But if again it's not working, pay a particular attention to your CSS

If you have, for example, a css like

#home{color : blue;}
.current{color : orange;}

The text will be blue since #home is "stronger"

If we put values to selector: id=10 class=5 node selector (div) = 1

so #home = 10 and is higher than .current wich equal 5, #homestyles will override.

you could use li.current but again, 5+1=6 wich is lower than an id.

But #home.current will equal 15! Wich will overide #home styles!

But if your color style is on the node itself with the attribute style="" you have to remove it with jquery or use !important :

.current{
    color: blue !important;
}

It will override EVERY css but it is not recommended.

Your update #3 was close.

give your body an ID whatever name you want the page to be and give your links ids like so

<body id="about">
    <nav>
        <ul id="menu">
            <li class="home"><a href="~/">Home</a></li>
            <li class="about"><a href="~/About">About</a></li>
            <li class="contact"><a href="~/Contact">Contact</a></li>
        </ul>
    </nav>
</body

Then your CSS can look somewhat like your update #3 example:

li a {color:blue}
#home .home{color:red !important}
#about .about{color:red !important}
#contact .contact{color:red !important}

This should ignore any classes that are not being used and only color the selected one red.

mikeyUX

I hate to point out that the reason your css color is not being applied to your link is because css colors for links must be set on the anchor tag (an anchor tag will not inherit a color from a wrapping LI element). Try

.current a {color:#123456;} 

or leave your css as is, but change your markup so the "current" class is applied to the < a > tag instead of the < li >.

EDIT: The reason your jsfiddle works when attempting to change colors (while your production code doesn't) is because the fiddle text is not inside of an A tag.

If you wish to automatically detect which page you are currently on, simply compare the HREF value of each link to the document.URL string:

$('nav').find('a').each(function(){
    if ( document.URL.indexOf( $(this).attr('href') ) !== -1 ){
        $(this).parent().addClass('current');
    }
});

Detailed description & test available here: -> http://jsfiddle.net/vV4h5/26/

EDIT #2: One more thing... your asp.net links are going to mess with this a bit as the document.URL will not contain the ~ character... simply remove the first character from your href value as follows:

 var href = $(this).attr('href').split(1); //
 if ( document.URL.indexOf( href[1] ) !== -1 ){
      ...

I'd just remove the linkyness from the one you are currently on. You can control the styling by targeting li and li a differently in your CSS. The only slightly tricky thing is to get the actual href value right for the links you are using, but that shouldn't be too hard. And it's not a lot of code.

$(function(){
    var href = window.location.pathname.replace(/.*\//, "/"),
        $active = $("nav ul#menu a[href='"+href+"']");
    $active.replaceWith($active.text());
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!