Highlight the active link in a navigation menu

I wonder if the script is all right. Please review my code:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Menu</title>
<style>
ul {list-style-type:none; margin:0; padding:0;}
li {display:inline;}
a.active {background:red;}
</style>
</head>
<body>
<ul>
<li><a href="http://www.example.com/home">Home</a></li>
<li><a href="http://www.example.com/news">News</a></li>
<li><a href="http://www.example.com/contact">Contact</a></li>
<li><a href="http://www.example.com/about">About</a></li>
</ul>
<script>
for (var i = 0; i < document.links.length; i++) {
    if (document.links[i].href == document.URL) {
        document.links[i].className = 'active';
    }
}
</script>
</body>
</html>

It should highlight the current page link in the navigation bar.

Works as expected for me.
Is there a particular problem you are having?

[font=calibri]One thing to be careful of is that that kind of matching can only work where the URL is only ever presented in a single format. So it might be that [noparse]example.com/page, www.example.com/page, (www.)example.com/page/ and (www.)example.com/page/index.htm[/noparse] all resolve to the same page … but the script can only go on the basis of what’s in the address bar, so unless you can be certain that no other form of the URL will ever be used, or you have rewrite rules that visibly redirect every request to the preferred format, it is not a sufficiently robust system and is likely to fall over.

There are better ways of doing it![/font]

I would say so, too.
The OP said in a previous thread that his site was on Google Sites and that additional constraints were in play.
Maybe it’s something to do with that?

If the many restrictions on Google Sites are a hindrance, you should consider deploying static pages. There are static sites generators, for different server-side languages. Using those, you will be able to keep the dynamic part when developing and generate static pages for deployment. Obviously, with these solutions, the active page link is not hand coded for each page.

A small thing, but rather than a class of “active”, consider something like “current”, as “active” can end up being confused with the “active” state of a link (a:active), which is quite different.

No specific problem to mention. I’m not good a JavaScript and just wanted my code to be reviewed & checked by a JS expert like you.

Thanks for the tiny point! Google Sites doesn’t support naked domains. The only problem is with the landing/home page, i.e. https://sites.google.com/site/my-site/ and https://sites.google.com/site/my-site/home go to the same page. It’s a problem I need to think about. Maybe:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Menu</title>
<style>
ul {list-style-type:none; margin:0; padding:0;}
li {display:inline;}
a.active {background:red;}
</style>
</head>
<body>
<ul>
<li><a href="http://www.example.com/home">Home</a></li>
<li><a href="http://www.example.com/news">News</a></li>
<li><a href="http://www.example.com/contact">Contact</a></li>
<li><a href="http://www.example.com/about">About</a></li>
</ul>
<script>
for (var i = 0; i < document.links.length; i++) {
    if (document.links[i].href == document.URL) {
        document.links[i].className = 'active';
    } else {document.links[0].className = 'active';}
}
</script>
</body>
</html>

Needs to be reviewed by Pullo.

There are better ways of doing it!

I’d be grateful if you provided an alternative solution!

I read your post a couple of times and am still not sure what you mean: do you mean I should stop using Google Sites due to its limitations?

Very true! Thank you!

:slight_smile:

It’ll work, but it’s brittle.
Besides what Stevie has already pointed out this line:

document.links[0].className = 'active'

will change the class name of the first link it encounters to “active”
What if your home link isn’t the first?

I don’t know much about Google Sites - do you have an include file for your navigation, or what is the reason for trying to use JavaScript to set the styling?

[font=calibri]The easiest way is kinda clunky but works well enough:

Give the <body> of each page a class name that (roughly) matches the name of the page, eg

<body class="news">

then in your navigation list, give each <li> the corresponding class, eg

<ul>
<li class="home"><a href="http://www.example.com/home">Home</a></li>
<li class="news"><a href="http://www.example.com/news">News</a></li>
<li class="contact"><a href="http://www.example.com/contact">Contact</a></li>
<li class="about"><a href="http://www.example.com/about">About</a></li>
</ul>

and finally set your “current” style in the CSS using a list of comma-separated selector pairs, eg

body.home li.home,
body.news li.news,
body.contact li.contact,
body.about li.about 
{background:red;}

Note - commas go between pairs only, not in the middle of a pair and not after the last pair.[/font]

It seems to have a problem even if my home link is the first:
https://googledrive.com/host/0B5jOXzxlxbMhYVF3b0lubjlDWm8/menu.html

I don’t know much about Google Sites - do you have an include file for your navigation, or what is the reason for trying to use JavaScript to set the styling?

As I said you cannot use any scripting language or even CSS stylesheets in your Google Site page content area. However, you can use custom CSS and JavaScript in Google gadgets and embed them to your site as iframes. In Google Sites all you can do is use some inline CSS.
Here’s a sample Google Site and Google gadget:
https://sites.google.com/site/michaelmccolin/test

I can’t. The body class name is fixed by Google. Here’s a Google Site:
https://sites.google.com/site/michaelmccolin/

[font=calibri]Holy guacamole, batman, that is atrocious code :x

Although the body ID is fixed, can you not add an additional class to it? (Discounting any limitations that may imposed by Google Sites, an element can have as many classes as you want)

Although looking at how clunky that code is … is your menu put there by some kind of include, or is it just hard coded into each page? If it’s the latter, you might as well just manually put class="current" on the relevant list item on each page.

Or ditch Google Sites and go for a system that isn’t so utterly cruddy.[/font]

+1. With hosting so incredibly cheap, I don’t see any advantage to such restrictive hosting as this, but many downsides.

Oh dear.
Try this instead:

var active = 0;
for (var i = 0; i < document.links.length; i++) {
    if (document.links[i].href === document.URL) {
        active = i;
    }
}
document.links[active].className = 'active';

Does that help?

Works like a charm! Thank you very much! :slight_smile:

No.

I meant you can circumvent problems like dynamically highlighting the active link in the menu, on client-side, by using the scripting feature, on server-side, in order to dynamically produce static pages that present the same feature…

…or just Google “static site generator”. :slight_smile:

One example is harp: http://harpjs.com/. It’s nodejs related technology. The part I’m talking about is called “compile and deploy”.

The compile process can result in static pages, where each page has the active class attribute added dynamically upon page generation rather then the pages having a JavaScript code included to be executed on client-side in order to determine the active link.

You are basically moving the active link logic from client-side to server-side, or development-side, to be more accurate. After you generate the pages, you simply deploy them on Google Pages server, as static or almost entirely static pages.

I was correcting my previous post when you answered – no I can’t change or add to the parent frame class.