function com_stewartspeak_replacement() {
/*
	Dynamic Heading Generator
    By Stewart Rosenberger
    http://www.stewartspeak.com/headings/

	This script searches through a web page for specific or general elements
	and replaces them with dynamically generated images, in conjunction with
	a server-side script.
*/

/* When the page first loads, the script will attempt to load a small (1x1 pixel) test image. If this test is successful, we can conclude that the visitor’s browser supports the display of images, otherwise it would not have wasted bandwidth downloading it. This is the crux of JIR: By testing for image support, we can immediately determine whether or not our visitors have any use for stylized headings. If they do not, the script will stop right there.

Assuming the visitor’s browser supports images, the script then waits until the page is entirely finished loading, because it can’t replace text that hasn’t been downloaded yet. Once the HTML is finished loading, our script will search it for specified elements (<h1>, <span>, etc.) and replace the text inside of them with an <img> tag. This dynamic <img> tag has its alt attribute set to the original text, and its src attribute set to the URL of the PHP script that we just installed. The PHP script then sends back a custom PNG image, and voila: custom headings.

Weighing in at a hefty eight kilobytes, there’s a lot of stuff going on in this corner of the ring, but there are only two lines that need to be customized before the script will work.

  replaceSelector("h1","heading.php",true);
  var testURL = "test.png";

The replaceSelector function accepts three parameters: The first is the CSS-style selector that indicates which elements should be replaced. This selector may be almost any valid CSS selector, including id, class, element and attribute selectors.

The second parameter is the URL of our custom PHP script.

The third parameter is a true/false value that indicates whether word-wrap should be turned on for this replacement. When this flag is set to true, headings are broken into multiple images, one for each word. When it is false, only a single, non-breaking image is generated for each heading.

replaceSelector should be called once for each group of elements you want replaced by a custom image. The URLs in these lines can be absolute (http://…) or relative to our HTML file (path/filename).

The testURL variable needs to be set to the URL of a small (1x1 pixel) test image.

Once these lines are set correctly, you can upload the JavaScript file to your web server, and apply it to your web pages by adding the following line to their <head> tags.

  <script
    type="text/JavaScript"
    src="replacement.js">
  </script>

Make sure the src attribute in that line points to the location that you uploaded the JavaScript file to.  */


replaceSelector("h2","../languages/font_changer/fontscript_h2.php",false);
var testURL = "../languages/font_changer/test.png" ;

/* Print Versions

As previously seen here in ALA, many sites are now employing specialized printer style sheets to give their visitors better hard copies of their content. In many cases this involves reversing the process of image replacement so that the printed copy of a page uses actual fonts rather than graphics, which often look poor on high-resolution printers. Unfortunately, JavaScript falls short of solving this problem. Once we’ve replaced our text with an image, it’s impossible to reverse that process specifically for printing purposes, so we need to find another solution.

Instead of trying to reverse our replacement process, we can do a little planning ahead. Along with inserting an <img> tag into our headings, we can also insert a <span> tag that contains the original heading text. And we can set that span’s display property to none, so that it doesn’t show up onscreen. Now we have two copies of our original text: One in a visible image, and one in an un-displayed span. By giving each of these elements identifiable class attributes (“replacement”, and “print-text,” respectively), and by adding in a print-specific style sheet, we can swap their display properties when they’re printed.

The following style sheet (download a sample CSS file here) could be used to generate an appropriate print version of your page:

  span.print-text {
    display: inline !important;
  }
  img.replacement {
    display: none;
  }

Once we’ve uploaded this style sheet -to our web server, we only need to change two lines in our JavaScript to make it work:

  var doNotPrintImages = false;
  var printerCSS = "replacement-print.css";

By setting doNotPrintImages to true, and printerCSS to the URL of the print style sheet we just created, the script will automatically insert the appropriate CSS <link> into our document’s <head> tag.  */


var doNotPrintImages = false;
var printerCSS = "../css/replacement.css";

/* Flicker Free

Because our script can’t begin replacing elements until after the entire document has loaded, there will often be a quick flash of unstyled content as the browser waits for the replacement process to begin. This is less of a problem than it is a minor annoyance, but since it’s avoidable we might as well fix it. With the help of another small style sheet, we can do just that.

Before the document’s body begins loading we can dynamically insert a style sheet that will hide these elements entirely. Since linked CSS files are applied even as the document is rendering, no content will be visible during this period. Once our replacement technique is finished executing we can disable this style sheet and our newly stylized headings will be visible once more.

For example, if your page was set up to replace <h1> tags, the following style sheet (available here) would hide them until our replacement technique was finished:

  h1 {
    visibility: hidden;
  }

There is a slight problem with this approach, however. Our entire technique depends on the loading of a test picture to indicate whether the browser supports images. If the image never loads, our technique will never activate. And if our technique never activates, the style sheet that hides our unstyled headings will never be deactivated. Because of this, visitors who have disabled image support in their browsers, but who are still capable of using JavaScript and CSS, will see nothing but empty space where our headings should have been.

We’ll do our part to improve this poor minority’s already-difficult browsing experience by adding a short timeout value to the script. If the test image hasn’t been successfully loaded after one or two seconds (or however long you see fit), the script will automatically disable this style sheet, and the headings will reappear. Those one or two seconds are a slight inconvenience for this exceptionally rare person, but it solves the flicker problem for the other 99.99% of our visitors. What’s important is that we maintain accessibility for everyone.

To enable this optional customization, and to remove the brief flash of unstyled content, you must edit three lines in the JavaScript source:

  var hideFlicker = false;
  var hideFlickerCSS = "replacement-screen.css";
  var hideFlickerTimeout = 1000;

Set hideFlicker = true, and hideFlickerCSS to the URL of the CSS file that you just created to hide your headers.

hideFlickerTimeout should be set to the maximum number of milliseconds (i.e. 1/1000 seconds) that the script will let pass before disabling that style sheet.   */

var hideFlicker = true;
var hideFlickerCSS = "../css/dement.css";
var hideFlickerTimeout = 100;


/* ---------------------------------------------------------------------------
    For basic usage, you should not need to edit anything below this comment.
    If you need to further customize this script's abilities, make sure
	you're familiar with Javascript. And grab a soda or something.
*/

var items;
var imageLoaded = false;
var documentLoaded = false;

function replaceSelector(selector,url,wordwrap)
{
	if(typeof items == "undefined")
		items = new Array();

	items[items.length] = {selector: selector, url: url, wordwrap: wordwrap};
}

if(hideFlicker)
{		
	document.write('<link id="hide-flicker" rel="stylesheet" media="screen" href="' + hideFlickerCSS + '" />');		
	window.flickerCheck = function()
	{
		if(!imageLoaded)
			setStyleSheetState('hide-flicker',false);
	};
	setTimeout('window.flickerCheck();',hideFlickerTimeout)
}

if(doNotPrintImages)
	document.write('<link id="print-text" rel="stylesheet" media="print" href="' + printerCSS + '" />');

var test = new Image();
test.onload = function() { imageLoaded = true; if(documentLoaded) replacement(); };
test.src = testURL + "?date=" + (new Date()).getTime();

addLoadHandler(function(){ documentLoaded = true; if(imageLoaded) replacement(); });


function documentLoad()
{
	documentLoaded = true;
	if(imageLoaded)
		replacement();
}

function replacement()
{
	for(var i=0;i<items.length;i++)
	{
		var elements = getElementsBySelector(items[i].selector);
		if(elements.length > 0) for(var j=0;j<elements.length;j++)
		{
			if(!elements[j])
				continue ;
		
			var text = extractText(elements[j]);
    		while(elements[j].hasChildNodes())
				elements[j].removeChild(elements[j].firstChild);

			var tokens = items[i].wordwrap ? text.split(' ') : [text] ;
			for(var k=0;k<tokens.length;k++)
			{
				var url = items[i].url + "?text="+escape(tokens[k]+' ')+"&selector="+escape(items[i].selector);
				var image = document.createElement("img");
				image.className = "replacement";
				image.alt = tokens[k] ;
				image.src = url;
				elements[j].appendChild(image);
			}

			if(doNotPrintImages)
			{
				var span = document.createElement("span");
				span.style.display = 'none';
				span.className = "print-text";
				span.appendChild(document.createTextNode(text));
				elements[j].appendChild(span);
			}
		}
	}

	if(hideFlicker)
		setStyleSheetState('hide-flicker',false);
}

function addLoadHandler(handler)
{
	if(window.addEventListener)
	{
		window.addEventListener("load",handler,false);
	}
	else if(window.attachEvent)
	{
		window.attachEvent("onload",handler);
	}
	else if(window.onload)
	{
		var oldHandler = window.onload;
		window.onload = function piggyback()
		{
			oldHandler();
			handler();
		};
	}
	else
	{
		window.onload = handler;
	}
}

function setStyleSheetState(id,enabled) 
{
	var sheet = document.getElementById(id);
	if(sheet)
		sheet.disabled = (!enabled);
}

function extractText(element)
{
	if(typeof element == "string")
		return element;
	else if(typeof element == "undefined")
		return element;
	else if(element.innerText)
		return element.innerText;

	var text = "";
	var kids = element.childNodes;
	for(var i=0;i<kids.length;i++)
	{
		if(kids[i].nodeType == 1)
		text += extractText(kids[i]);
		else if(kids[i].nodeType == 3)
		text += kids[i].nodeValue;
	}

	return text;
}

/*
	Finds elements on page that match a given CSS selector rule. Some
	complicated rules are not compatible.
	Based on Simon Willison's excellent "getElementsBySelector" function.
	Original code (with comments and description):
		http://simon.incutio.com/archive/2003/03/25/getElementsBySelector
*/
function getElementsBySelector(selector)
{
	var tokens = selector.split(' ');
	var currentContext = new Array(document);
	for(var i=0;i<tokens.length;i++)
	{
		token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');
		if(token.indexOf('#') > -1)
		{
			var bits = token.split('#');
			var tagName = bits[0];
			var id = bits[1];
			var element = document.getElementById(id);
			if(tagName && element.nodeName.toLowerCase() != tagName)
				return new Array();
			currentContext = new Array(element);
			continue;
		}

		if(token.indexOf('.') > -1)
		{
			var bits = token.split('.');
			var tagName = bits[0];
			var className = bits[1];
			if(!tagName)
				tagName = '*';

			var found = new Array;
			var foundCount = 0;
			for(var h=0;h<currentContext.length;h++)
			{
				var elements;
				if(tagName == '*')
					elements = currentContext[h].all ? currentContext[h].all : currentContext[h].getElementsByTagName('*');
				else
					elements = currentContext[h].getElementsByTagName(tagName);

				for(var j=0;j<elements.length;j++)
					found[foundCount++] = elements[j];
			}

			currentContext = new Array;
			var currentContextIndex = 0;
			for(var k=0;k<found.length;k++)
			{
				if(found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b')))
					currentContext[currentContextIndex++] = found[k];
			}

			continue;
	    }

		if(token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/))
		{
			var tagName = RegExp.$1;
			var attrName = RegExp.$2;
			var attrOperator = RegExp.$3;
			var attrValue = RegExp.$4;
			if(!tagName)
				tagName = '*';

			var found = new Array;
			var foundCount = 0;
			for(var h=0;h<currentContext.length;h++)
			{
				var elements;
	        	if(tagName == '*')
					elements = currentContext[h].all ? currentContext[h].all : currentContext[h].getElementsByTagName('*');
				else
					elements = currentContext[h].getElementsByTagName(tagName);

				for(var j=0;j<elements.length;j++)
					found[foundCount++] = elements[j];
			}

			currentContext = new Array;
			var currentContextIndex = 0;
			var checkFunction;
			switch(attrOperator)
			{
				case '=':
					checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
					break;
				case '~':
					checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
					break;
				case '|':
					checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
					break;
				case '^':
					checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
					break;
				case '$':
					checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
					break;
				case '*':
					checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
					break;
				default :
					checkFunction = function(e) { return e.getAttribute(attrName); };
			}

			currentContext = new Array;
			var currentContextIndex = 0;
			for(var k=0;k<found.length;k++)
			{
				if(checkFunction(found[k]))
					currentContext[currentContextIndex++] = found[k];
			}

			continue;
		}

		tagName = token;
		var found = new Array;
		var foundCount = 0;
		for(var h=0;h<currentContext.length;h++)
		{
			var elements = currentContext[h].getElementsByTagName(tagName);
			for(var j=0;j<elements.length; j++)
				found[foundCount++] = elements[j];
		}

		currentContext = found;
	}

	return currentContext;
}


}// end of scope, execute code
if(document.createElement && document.getElementsByTagName && !navigator.userAgent.match(/opera\/?6/i))
	com_stewartspeak_replacement();