Dorward's Ramblings

Fragment Highlight

First published on

Updated on

Deprecated

In light of improvements to browsers, I consider this code redundant and deprecated. I no longer maintain it.

Introduction

Fragment Highlight aids a user in locating the section of a document they linked to, by highlighting the relevant heading. This functionality is equivalent to the proposed :target selector for CSS 3 but works in earlier browsers and conforms to current (i.e. not proposed) standards.

It is written in JavaScript, with a strong focus on the separation of content, presentation, and logic. It is designed to gracefully degrade so that it works in supporting browsers and causes no problems in unsupporting browsers.

The script can be seen in action on this site, try the table of contents for this page (above) if you have a supporting browser.

Browser Support

This data assumes browsers with JavaScript and CSS enabled. It is assumed that a later version of the same browser will support the script. If a browser is not listed, it has not been tested (reports of support in other browsers would be welcome).

Support for Fragment Highlight
Browser Version Support
Netscape4No
Mozilla1.3Yes
Konqueror3.1.1Yes
Opera7.1Yes
Internet Explorer for Windows6Yes

Download

You can download the script from Github.

Install

The script is designed to work with minimal changes to the HTML code. The HTML must be suitably semantic, a style sheet must be written, then the script can be dumped in.

HTML

Links to specific parts of an HTML document take the form: <a href="#fragment">text</a>.

This script functions only on:

  • Links from external documents
  • Links in which the first character of the href is "#"

The script will not function on links of the form: <a href="currentPage.html#fragment">text</a>.

Targets

In modern HTML, document fragments are identified with an id attribute on arbitrary elements. For example: <h3 id="fragment">text</h3>. The script will recognise any target taking this form.

Previously, links including fragment identifiers took the form: <a name="fragment">text</a>.

This form has been deprecated and the script will not recognise them. It is possible that the script will recognise fragment identifiers of this form in future, but it seems unlikely.

CSS

The script works by changing the class of targeted elements, a style must be defined to describe how targeted elements (with the class "fragment") should look.

I have the following code in my style sheet:

.fragment {
  background-color: yellow;
  color: black;
}

JS

The JavaScript can be included in an existing script, or included separately.

<script type="text/javascript" src="hi.js"></script>

If you have existing scripts activated in the onload event, it is very important that you merge the onload event handler from the highlight script with your existing script.

You may wish to edit other parts of the script, notably the definition of "var fragExclude".

How it works

Declarations

As the document loads, the script defines a couple of variables.

fragHLed stores the value of the currently targeted fragment (which is blank, at least until the document has finished loading and the onload event is triggered.

You should edit fragExclude to be a list of ids that you do not wish to be highlighted. In this case <foo id="header"> is excluded as it is used by the Skip navigation link.

var fragHLed = '';
var fragExclude = ('header');

This is used to search the array to make sure that the fragment being visited isn't on the "do not highlight" list.

Array.prototype.search = function(myVariable) { 
  for(x in this) if (x == myVariable) return true; return false;
}

fragHL()

This unhighlights any existing elements that have been highlighted, then highlights the specified one.

function fragHL(frag) {
    if (fragHLed.length > 0 && document.getElementById(fragHLed)) {
    KillClass(document.getElementById(fragHLed),'fragment');
    }
    if (frag.length > 0 && document.getElementById(frag)) {
    fragHLed = frag;
    AddClass (document.getElementById(frag),'fragment');
    }
}

fragHLload()

This is called by the onload event handler, it extracts the value after the "#" in the requested URL and calls fragHL

function fragHLload() {
    fragHL(location.hash.substring(1));
}

This scans the document for links that have href attributes with values starting with a "#". It then adds onclick events to each to call fragHL().

function fragHLlink() {
    if (document.getElementsByTagName) {
        var an = document.getElementsByTagName('a');
        for (i=0; i<an.length; i++) {
            if (an.item(i).getAttribute('href').indexOf('#') >= 0) {
                var fragment = an.item(i).getAttribute('href').substring(
                    an.item(i).getAttribute('href').indexOf('#') + 1
                );
                if (fragExclude.search(fragment)) {
                    var evn = "fragHL('" + fragment + "')";
                    var fun = new Function('e',evn);
                    an.item(i).onclick = fun;
                }
            } 
        }
    }
}

Onload

This calls the relevant functions needed at load time, should there be an existing onload handler, this will overwrite it - so the two should be merged.

window.onload = function(){
    fragHLload();
    fragHLlink();
};