How to identify name/id of named anchor?

D

deko

I use named anchors to take users to specific parts of a long page. But I
want to add some processing and do some things with my nav bar when users go
to certain sections delineated by named anchors. I understand that the
anchors array creates an element for each anchor in the page when the page
is loaded, but how do I identify which anchor is currently being viewed?

Here's some pseudo code:

if (document.anchors.name == "section_B") {

then do this or that

}

But what do I test to determine the current anchor name?

What about using id's instead of names? Can the anchors array return
anchors created with id's as well as names? Would this be of any benefit?

Thanks in advance.
 
M

Michael Winter

[snip]
But what do I test to determine the current anchor name?

Nothing. You can't.

You could parse location.hash, which will return anything from the hash
(#) onwards in the current URI, but if a user scrolled to the location,
that approach is still useless.
What about using id's instead of names? Can the anchors array return
anchors created with id's as well as names? Would this be of any
benefit?

In my tests, no. The anchors collection only returns named (literally) A
elements. Elements, including A, that have id attributes aren't included.

IE was an exception though: it returned A elements with either an id or
name. However, IE is in violation of the DOM 2 HTML Specification when it
does this, so don't expect similar behaviour in other browsers[1].

Depending how you structured your document, you might be able to use other
ways of getting anchors easily, but considering that you can't determine
where the user is with any degree of reliability, I don't see the point.

Mike


[1] Or that day when Hell freezes over and Microsoft actually start
following other people's standards and guidelines.
 
D

deko

You could parse location.hash, which will return anything from the hash
(#) onwards in the current URI, but if a user scrolled to the location,
that approach is still useless.

That sounds like what I'm looking for. I'm not concerned where a user
scrolls, just what link he clicked. One of the things I want to do is
change font color in the nav bar based on what named anchor link the user
clicked - if you can provide any guidance with that, that would be great.
I'll start reading up on location.hash...
 
D

deko

psuedo code attempt.

Here's the function:

function anchorname(n) {
var a=(window.location.hash);
if (document.getElementById(a)=n) {anchorname=true}
}

Here's how I would code my link in the nav list:

<a href="test.php#test01" onClick="anchorname('test01','#currentlink')">
test01</a>

What I'm trying to do is apply css id #currentlink to the link if that's
where the user has navigated to. Am I on the right track?
 
M

Michael Winter

psuedo code attempt.

Here's the function:

function anchorname(n) {
var a=(window.location.hash);
if (document.getElementById(a)=n) {anchorname=true}
}

Here's how I would code my link in the nav list:

<a href="test.php#test01"
onClick="anchorname('test01','#currentlink')">
test01</a>

What I'm trying to do is apply css id #currentlink to the link if that's
where the user has navigated to. Am I on the right track?

The only way you could do precisely that would be to change the id
attribute on each link when they are activated. The only problem with this
is that I'm not entirely sure how well browsers will respond; not all
browsers are as dynamic as others, and may refuse to change the applied
style. Certainly Opera, IE and Mozilla don't like it.

As such, the seemingly most compatible way is to change the className
property (class HTML attribute). Unfortunately, there's one final hack:
when the click event fires, it does so *before* the user agent navigates
to the destination. This means that location.hash won't reflect the
destination when the script runs. There are two solutions:

1) Add a delay between activation and action. Whilst it'll work, problems
can arise from too small, or too large, a delay. With the former,
location.hash may not be accurate (back to square one). With the latter,
the delay before rendering the style changes becomes too obvious.
2) Extract the fragment identifier from the link directly rather than use
location.hash, and continue as normal.

The second is obviously the better choice, so:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">

<title>Test</title>

<script type="text/javascript">
/* Obtain an always-valid function equivalent to
* document.getElementById()
*/
if(document.getElementById) {
var getRefById = function(id) {
return document.getElementById(id);
};
} else if(document.all) {
var getRefById = function(id) {
return document.all[id];
};
} else {
var getRefById = function() {
return null;
};
}

/* activeAnchor - Records a reference to the targeted anchor so
* its style can be restored later.
* oldStyle - The original class for the targeted anchor.
* Makes restoration much easier.
*/
var activeAnchor = null, oldStyle;

function changeStyle(href) {
var d, i;

/* Quit now if no fragment id is present. */
if(-1 == (i = href.indexOf('#'))) {return;}
/* Get reference to destination using extracted fragment id. */
d = getRefById(href.substring(i + 1));

/* Do nothing if we're already at target, or couldn't get
* destination.
*/
if(d && activeAnchor != d) {
/* If there is a currently active link, remove the styling. */
if(activeAnchor) {
activeAnchor.className = oldStyle;
}
/* Apply style to new link. */
if(d) {
oldStyle = d.className;
d.className += ' activeLink';
activeAnchor = d; /* Store reference for next invocation. */
}
}
}
</script>

<style type="text/css" media="screen">
a {
background-color: #ffffff;
color: #0000ff;
}

a.activeLink {
background-color: #ffffbe;
color: #0000ff;
}
</style>
</head>

<body>
<div>
<a id="t1" href="#t2" onclick="changeStyle(this.href);">First</a>
<a id="t2" href="#t1" onclick="changeStyle(this.href);">Second</a>
</div>
</body>
</html>

For this to work, the fragment id contained in the link must match the
value of an id attribute elsewhere in the page. That shouldn't be
difficult though, seeing as that's how anchors should be specified anyway.

Hope that helps,
Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top