function linksEquivalent (link1, link2) {

	// First, test the easy way.
	if (link1 == link2) return true;

	// Okay, so that was wishful thinking.

	// TODO: Force both links to be absolute.
	return false;
}

/***** some pseudo code...

- Compare the A link (aHref) to a canonical value (photoHref), to determine whether to follow the A link.
- photoHref is defined as a literal value in JavaScript, so the browser has no built-in way of converting it from relative to absolute. So...
- toAbsolute()
  In JavaScript we construct an absolute URL from photoHref (linkText).
-- If linkText is already absolute (has a protocol), then it's DONE.
-- Otherwise linkText needs a new base.

...Little question...
How do we combine id=homeLink with a directory named in siteRoot?
- Options...
-- Option 1: Derive the apparent site root from homeLink, then look for a subdirectory named in siteRoot.
-- Option 2: Try first to use the homeLink; failing that, use the siteRoot.
- Keep in mind: either way it's a pretty rare situation. It only becomes ambiguous when we have a local file system that might look like this: .../files/site.com/files/
- I can't think of why I would go to the trouble of specifying id=homeLink, and then override it with a subdirectory. Simply placing the site into a subdirectory will work without the need for an explicit siteRoot.
- Therefore, let's look first to homeLink, and then to siteRoot as a backup plan. Don't try to combine them.

...Edge case question...
What does it mean when siteRoot doesn't match the current location?
- Example 1: I tested a site in a subdirectory on the server, then moved it to the web root, but forgot to eliminate the old siteRoot from the JavaScript.
- Example 2: I moved a site into a different subdirectory of the server or the local filesystem.
- Example 3: I made a typo entering the siteRoot.
- In all of these examples, but especially #1 and #2, I would ideally like for the links to *fail catastrophically.* That would be better than, say, failing slightly and later causing confusion. I'm thinking something like forcing a subdirectory "OopsWrongSiteRoot/"+ the erroneous siteRoot.

...Summary... [?CHECK]
root-relative + siteRoot = concatenate
root-relative + blank = infer site root from current document, then concatenate
relative + siteRoot = concatenate
relative + blank = use current document

Scenario: A person sits on a web page and starts typing in URLs where they want to go. What do they expect? -- That they all be relative to the current page or site root.
Now, what if we add another parameter, an explicit site root? -- The expectation is that I'm suppose to type something in that is consistent with my current document. I would absolutely expect it to work if the protocol and hostname match my current directory. I would smile if I can type in a path that visibly matches my current document's path (with or without protocol) and it understands it... (In this scenario, I would totally "get it" if it only matches my hostname or first subdirectory)...So now I see a couple of useful things I could do.
- Make a script run in a subdirectory on a server.
- Make a script run on a local file directory, where the directory is named the same as the server. (Sweet! Works on local and remote equally. But seems like "cheating.")
- Test the protocol; if it's "file:" use a special siteRoot. -- This seems better and more reliable than that "cheating" version, so make this the COOKBOOK and anchor siteRoot matches against the beginning of the URL.
...
It's not that useful to explicitly match a hostname. So I'll say this... The siteRoot either must explicitly state a protocol, or else it must skip the hostname and go straight to the directory path.

There's another distracting use case: take a base URL that does not claim to be a web root, and figure a relative URL from it. To do this reliably, you still need to know the web root (to prevent up-directory links) So [FUTURE] use the joinTwoDirectories function; then if it's still relative, run it through toAbsolute(); then if it still has erroneous up-directory links, let browser and the server deal with them.

Cookbook for testing JavaScript which uses literal URLs, on a local filesystem.
- Source this .js file.
- Make sure there is at least one link with id="homeLink". A good way to do this is to add it to the homepage link in your template(s).

*****/

function toAbsolute(linkText) {
	// Take a piece of text 'linkText' which is trying to be a URL, and construct a 
	// complete absolute URL.
	// o If linkText is already absolute, return it unchanged.
	// o If linkText is root-relative, figure out the site root and join them.
	// o Otherwise, treat linkText as relative to the current document.

	// Optional args #2, 3,... are site-root rules. A site root is not necessarily a webroot. It can be a folder in a local filesystem, or a subfolder under the webroot of a server.
	// The format of a site-root rule is
	//     Protocol:SiteRootPath
	// The optional Protocol means 

	// Initialize...
	// MSIE is more tolerant of forward slashes than Mozilla is of backslashes. 
	// With a protocol in front, Microsoft can interpret what gets thrown at it.
	linkText = conformSlashes(linkText);
	constructedLinkText = linkText;

	// Find the linkText protocol, if any (blank if none)
	linkProtocol = '';
	findUrlFragment = linkText.match(/^\w+\:/);
	if (findUrlFragment != null) {
		linkProtocol = '' + findUrlFragment;
	}

	// Construct an absolute URL.
	if (linkProtocol == '') {
		// Without a protocol, we must assume it's some kind of relative reference.
		if (linkText.substr(0,1) == '/') {
			// The link is root-relative.
			// So, figure out the site root.

			// Default if all else fails //XXXX is this reasonable?
			siteRoot = '';

			if(document.getElementById && (theHomeLink = document.getElementById('homeLink'))) {
				// Plan A: Look for a homepage link inside the current document, 
				// identified by id="homeLink".
				siteRoot = toBareDirectory(theHomeLink);
			}
			else {
				// Plan B: Use the current location's protocol and host.
				// Apply site-root rules, if any, to the current location's path.
				siteRoot = location.protocol + '//' + location.host;
				currentLocationPath = conformSlashes(toBareDirectory(location.pathname));
				doneLoop = false;
				for (i = 1; (i < arguments.length) && !doneLoop; i++) {
					thisRule = conformSlashes(arguments[i]);
					ruleProtocol = '';
					findUrlFragment = thisRule.match(/^\w+\:/);
					if (findUrlFragment != null) {
						ruleProtocol = '' + findUrlFragment;
					}
					rulePath = (ruleProtocol == '') ? thisRule : thisRule.substr(thisRule.indexOf(':') + 1);
					if ((ruleProtocol == '') || (ruleProtocol.substr(0,4) == location.protocol.substr(0,4))) {
						// The rule does not specify a protocol,
						// or the rule's protocol matches the current location's protocol.

						// We only want to match directory boundaries. So,
						// make a string from the rule path, with initial and trailing slashes; and
						// make a string from the current location path, with initial and trailing slashes.
						rulePathMatcher = rulePath.replace(/^\/*/, '/').replace(/\/*$/, '/');
						currentLocationPathMatcher = currentLocationPath.replace(/^\/*/, '/').replace(/\/*$/, '/');
						matchPos = currentLocationPathMatcher.indexOf(rulePathMatcher);
						if (matchPos == 0 || (matchPos > 0 && rulePath.substr(0,1) != '/')) {
							// The rule path matches the start of the location path, or 
							// (if the rule path is generic) matches anywhere inside it.
							siteRoot += currentLocationPathMatcher.substr(0, matchPos + rulePathMatcher.length - 1);
							doneLoop = true;
						}
					}
				}
			}
			constructedLinkText = siteRoot + linkText;
		}
		else {
			// The link is document-relative, so base it on the document location.
			siteRoot = conformSlashes(toBareDirectory(location.href));
			constructedLinkText = siteRoot + '/' + linkText;
		}
	}

	return constructedLinkText;
}

function conformSlashes(path) {
	return path.replace(/\\/g, '/');
}

function toBareDirectory(linkText) {
	// Take a string, and trim off anything that looks like
	// o  Trailing whitespace
	// o  A hash (#...)
	// o  A search (?...)
	// o  A filename (xxxx.xxx)
	// o  Trailing slashes
	linkText = '' + linkText;
	result = linkText.replace(/\s+$/, '');
	result = result.replace(/[\#\?].*/, '');
	result = result.replace(/[\/\\][^\/\\]+\.[^\/\\]+$/, '');  // chop x.x but not .., .xx, xx.
	result = result.replace(/[\/\\]+$/, '');
	return result;
}

function photoDetail (thisLink) {

	// The "detail page" is what we usually use, to create a pretty display of photo and caption.
    // It should be root-relative, e.g. '/foo.html'.
	detailPage = '/photo-detail.html';

	// Initialize values.
	theTargetPage = detailPage;
	thePhoto = '';
	theCaption = thisLink.title;

	// Find an image ~inside~ the HTML link,
    // in case we later need its SRC or ALT.
	theInsideImage = null;
	if (thisLink.getElementsByTagName) {
		insideImages = thisLink.getElementsByTagName('img');
		if (insideImages.length > 0) {
			theInsideImage = insideImages[0];
		}
	}

	// Figure out how to rewrite the HTML link.
	if (thisLink.pathname.search(/\.gif$|\.jpg$|\.jpe$|\.jpeg$/i) > 0) {
	    // The HTML link goes to a graphic (to appear when JS is off), 
		// so send it to the detail page.
		theTargetPage = detailPage;
		thePhoto = thisLink.href;
	} else if (thisLink.pathname.replace(/^[\/\.]+/, '') == 
			detailPage.replace(/^[\/\.]+/, '')) {
	    // The HTML link goes to the detail page itself,
		// so append the small-size graphic to it.
		// (Note: The ugly regexp stuff trims leading '.' and '/'.)
		// (DEFER: won't always work when there are same-named detailPage in different directories.)
		// (DEFER: Allow HTML search parms to take priority.)
		theTargetPage = detailPage;
		if (theInsideImage) {
			thePhoto = theInsideImage.src;
		} else {
			thePhoto = '';
		}
	} else {
	    // The HTML link goes to some non-graphic file,
		// so just go there.
		return true;
	}

	// Set the caption. First try the A TITLE, then the IMG ALT.
	theCaption = thisLink.title;
	if (theCaption == '' && (theInsideImage != null)) {
		theCaption = theInsideImage.alt;
	}

	//Go there, and finish up.
	location.href = toAbsolute(detailPage) +
		'?img=' + escape(thePhoto) +
		'&cap=' + escape(theCaption);

	return false;  // Tell the original link not to follow.
}
