//	safesend.js
//
//	AUTHOR:   Rob Zako
//
//	DATE:     Version 2.0: December 13, 2009
//	          Version 1.0: March 3, 2008
//
//	SUMMARY:  Defines the function safeSendRewrite() to rewrite obscured mailto links.
//
//	USAGE:    To protect mailto links from Web-harvesting robots, you should:
//
//	          1) Include the following code in the HEAD of an (X)HTML file:
//
//	               <script src=".../safesend.js" type="text/javascript" charset="utf-8"></script>
//	               <style type="text/css" media="all">
//	                 span.safesend { display: none; }
//	               </style>
//
//	          2) Insert obscured mailto links using the following syntax:
//
//	               <a><span class="safesend">address#name#display</span>noscript</a>
//
//	             where
//
//	               'address' is the email address split at each '@', '+' and '.', in reverse order,
//	                 and with each '@' replaced with '!',  '+' with '^' and '.' with '/'.
//
//	               'name" is the OPTIONAL full name of the addressee. The special value '*'
//	                 indicates the noscript text should be used.
//
//	               'display' is the OPTIONAL text to be displayed. The special value '*' indicates
//	                 the full name should be displayed; the special value '@' indicates the email
//	                 address should be displayed.
//
//	               'noscript' is the OPTIONAL text to be displayed when scripting is disabled.
//
//	              In addition, any text in the <span>...</span> after '%', '(', '[' or '{' and
//	              before '%', ')', ']' or '}' ("lint") is discarded before other processing.
//
//	          3) Insert the following code at the very end of the BODY of an (X)HTML file:
//
//	               <script type="text/javascript">safeSendRewrite();</script>
//
//	EXAMPLES:    For example,
//
//	               <a><span class="safesend">com/acme!beta/alpha</span>click here</a>
//
//	             is rewritten to
//
//	               <a href="mailto:alpha.beta@acre.com">click here</a>
//
//	             For example,
//
//	               <a><span class="safesend">com/acme!beta/alpha#*</span>Alpha Beta</a>
//
//	             is rewritten to
//
//	               <a href="mailto:Alpha Beta <alpha.beta@acre.com>">Alpha Beta</a>
//
//	             For example,
//
//	               <a><span class="safesend">com/acme!beta/alpha#Alpha Beta</span>click here</a>
//
//	             is rewritten to
//
//	               <a href="mailto:Alpha Beta <alpha.beta@acre.com>">click here</a>
//
//	             For example,
//
//	               <a><span class="safesend">com/acme!beta/alpha#Alpha Beta#*</span>click here</a>
//
//	             is rewritten to
//
//	               <a href="mailto:Alpha Beta <alpha.beta@acre.com>">Alpha Beta</a>
//
//	             For example,
//
//	               <a><span class="safesend">com/acme!beta/alpha#Alpha Beta#@</span>click here</a>
//
//	             is rewritten to
//
//	               <a href="mailto:Alpha Beta <alpha.beta@acre.com>">alpha.beta@acre.com</a>
//
//	             For example,
//
//	               <a><span class="safesend">com/acme!beta/alpha#Alpha Beta#email</span>click here</a>
//
//	             is rewritten to
//
//	               <a href="mailto:Alpha Beta <alpha.beta@acre.com>">email</a>
//
//	BUGS:     The script produces incorrect results when the full name contains a comma (,).
//
//	NOTE:     The approach, based on JavaScript and the DOM model, should work with older HTML
//	          files and newer XHTML files. In particular, the approach avoids calling the
//	          depricated document.write() function.
//
//	SOURCE:   Modeled after setMailtoLinks() by Milo Vermeulen.
//	          See <http://milov.nl/2330> and <http://milov.nl/milov.js>

function safeSendRewrite()
{
	if (! document.getElementsByTagName) { return; }
	var anchorElementArray = document.getElementsByTagName('A');
	for (var i = 0; i < anchorElementArray.length ; i++) {
		var anchorElement = anchorElementArray[i];
		var safesendElementArray = new Array();
		for (var j = 0; j < anchorElement.childNodes.length; j++) {
			var childNode = anchorElement.childNodes[j];
			if (childNode.nodeType == Node.ELEMENT_NODE && childNode.tagName == 'SPAN' && childNode.className.match(/(^| )safesend($| )/)) {
				safesendElementArray.push(childNode);
			}
		}
		for (var j = 0; j < safesendElementArray.length; j++) {
			anchorElement.removeChild(safesendElementArray[j]);
		}
		var noscript =
			anchorElement.childNodes.length == 1 && anchorElement.firstChild.nodeType == Node.TEXT_NODE ?
				anchorElement.firstChild.nodeValue :
				undefined;
		if (safesendElementArray.length == 1) {
			var safesendElement = safesendElementArray[0];
			if (safesendElement.childNodes.length == 1 && safesendElement.firstChild.nodeType == Node.TEXT_NODE) {
				// discard lint, get arguments
				var args = safesendElement.firstChild.nodeValue.replace(/[%(\[{][^%)\]}]*[%)\]}]/gi, '').split('#');
				if (args.length >= 1) {
					// split at '!' -> '@'
					var addressParts1 = args[0].split('!').reverse();
					for (var k1 = 0; k1 < addressParts1.length; k1++) {
						// split at '^' -> '+'
						var addressParts2 = addressParts1[k1].split('^').reverse();
						for (var k2 = 0; k2 < addressParts2.length; k2++) {
							// split at '/' -> '.'
							addressParts2[k2] = addressParts2[k2].split('/').reverse().join('.');
						}
						addressParts1[k1] = addressParts2.join('+');
					}
					var address = addressParts1.join('@');
					var name =
						args.length < 2  || ! args[1] ?
							undefined :
							args[1] == '*' ?
								noscript :
								args[1];
					var display =
						args.length < 3 || ! args[2] ?
							(anchorElement.hasChildNodes() ? undefined : name ? name : address) :
							(args[2] == '*' ? name : args[2] == '@' ? address : args[2]);
					anchorElement.href = 'mailto:' + (name ? name + ' <' + address + '>' : address);
					if (display) {
						while (anchorElement.hasChildNodes()) {
							anchorElement.removeChild(anchorElement.lastChild);
						}
						anchorElement.appendChild(document.createTextNode(display));
					}
				}
			}
		}
	}
}
