Tuesday, November 18, 2008

Helpful Hyperlinks with JavaScript

Which links will receive an icon?

To define what type of file the link goes to, we’ll look at the file extension. The file types are split out into two groups: those that have unique icons, such as torrent files, and those that will share the same icon, but have different file extensions, such as Flash files (.fla and .swf).

Grouping file extensions that share the same icon saves you having hundreds of CSS classes and icons. To achieve this I have created two arrays.

The first array, IndividualClassArray, holds the file extensions of all the links with individual icons. The base of the CSS class name is the same as the file extension. That is, a text file is referenced with ‘txt’ and the CSS class name is the classPrefix (set earlier) and ‘txt’ the base CSS class name, making a CSS class called ‘iKon_txt’ in this case.

IndividualClassArray = Array('txt', 'xls', 'css', 'torrent');

The second array, classArray, is actually a multidimensional array, but don’t let that put you off. Basically, it’s a group of individual arrays grouped according to the kind of icon we’d like to use. The first item in this array is IndividualClassArray (this array must always be the first array). The following arrays are similar to the previous array with one important difference: the first item in each of the arrays is the name of the CSS class that will be used, and the following items are the file extensions which need that class. In the following example the .swf and .fla file extensions will be associated with the ‘flash’ CSS class.

classArray = Array(
IndividualClassArray,
Array('flash', 'swf', 'fla')
);

Note: File extensions exclude the dot, that is, xls not .xls.

For maximum portability, the actual CSS class name used will have a prefix such as ‘iKon_’, which we configured earlier—but in these arrays we always exclude the prefix. So a Flash CSS class is always referred to as ‘flash’ rather than ‘iKon_flash’.

External Links

To figure out whether a link is an external site, we need to know the host name of the current page.

For this we use:

url = parseURL(qualifyHREF(document.location.href)).hostname;

This takes the current document’s location and gets the domain name using the qualifyHREF function to make sure we have a fully qualified address and the parseURL function to get the host name. (Both of these functions were written by our resident JavaScript guru, Brothercake, and covered in his blog post). Later, when we add the classes for the external links, we’ll use this host name to work out whether the link is external to our site.

The Code That Actually Does the Work

Now we need to get all the links from the page using document.getElementsByTagName("a"), and determine the file extension of the link.

We do this by using the functions parseURL and qualifyHREF again.

First, take the href value of the a element:
linkHref = aElements[iv].href;

Next, parse the value to gain more information about the link:
oUrl = parseURL(qualifyHREF(linkHref));

Then get the extension for the link:
fileExt = oUrl.extension;

Then, we need to loop through these links and work out whether they need an icon. This is where it starts to become a little bit trickier. We need to loop through classArray and each of the arrays it contains. We do this by running a loop within a loop. Yes, that’s a loop, in a loop, in a loop! This hairy piece of code looks like this:

aElements = document.getElementsByTagName("a");
iElements = aElements.length;

for (iv = 0; iv < iElements; iv++) {
iLen = classArray.length;
for (ii = 0; ii < iLen; ii++) {
iArr = classArray[ii].length;
for (i = 0; i < iArr; i++) {
// Do we need to add an icon?
}
}
}

Does this link require an icon?

To find out if we need to add an icon, we’ll compare the file extension of the link with each of the extensions listed in our arrays.

if (fileExt == classArray[ii][i]) {
if (ii === 0) {
linkClass = fileExt;
}
else {
linkClass = classArray[ii][0];
}
bFound = true;

Now we know if the link needs an icon, and which class it needs. We’ll add that class using the addClass function we’ve grabbed from the Core JavaScript Library.

if (bFound && linkClass !== '') {
addClass(aElements[iv], classPrefix + linkClass);
}

Links to External Sites

Working out if the link is to an external site is just a case of comparing the URL host name we determined earlier with the URL we set in the configuration area.

if (oUrl.hostname.indexOf(url) == -1) { // not our url
bExternal = true;
}

If it’s true, we’ll append a new image element in the anchor, add a source and ID, and then add an alt and title attribute for the image. We add the extra icon rather than just assigning a class to clearly show that this link goes to another site, as well as adding title and alt attributes to the icon.

if (bExternal) { // an external link
img = document.createElement('img');
img.id = 'Newimg' + iv;
img.src = externalIconLoc;
img.alt = 'external site';
img.title = 'links to an external web site';
void (aElements[iv].appendChild(img));
oimg = document.getElementById("Newimg" + iv);
addClass(oimg, classExternal);
}

The CSS Classes

Let’s move back to the CSS file now.

Here is our CSS class to add the icon to .doc files. Notice the class name is prefixed with ‘iKon_’ and then the file extension ‘doc’. This class basically puts a bit of padding in the top and bottom, and to the right of the link. It then adds a background image of the icon into that space.

.iKon_doc {
padding: 5px 20px 5px 0;
background: transparent url(icons/icon_doc.gif) no-repeat center right;
}

For our external link icons, we’ll use a slightly different class structure. We add some padding top and bottom to make sure our icon is borderless.

.iKon_external{
padding: 5px 0 0 5px;
border: 0;
}

If you changed the classPrefix variable, don’t forget to alter these class names to match.

Limitations

The link must have a file extension to have an icon assigned to the link (unless it’s an external site). The script also doesn’t recognize query string- based navigation links. If CSS is disabled, then only the external link icon will display and if JavaScript is disabled, then there are no visible changes to the page.

Conclusion

iKonize is a quick and easy way to add visually meaningful icons after links. The script works in IE5.5+ and can work independent of CSS3 attribute selectors. As you might expect, the script degrades well and is easily configured. I hope you find it useful!

0 comments: