/*	sJIR (scalable Jens Image Replacement) Version 0.1
	Copyright 2004 Jens Persson
	Based on
	sIFR (Scalable Inman Flash Replacement) Version 2.0 RC1
	Copyright 2004 Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben

	This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
*/

String.prototype.normalize = function(){
	return this.replace(/\s+/g, " ");
};

/* IE 5.0 does not support the push method, so here goes */
if(Array.prototype.push == null){
	Array.prototype.push = function(item){
		this[this.length] = item;
		return this.length;
	};
};

/*	Implement function.apply for browsers which don't support it natively
	Courtesy of Aaron Boodman - http://youngpup.net */
if (!Function.prototype.apply){
	Function.prototype.apply = function(oScope, args) {
		var sarg = [];
		var rtrn, call;

		if (!oScope) oScope = window;
		if (!args) args = [];

		for (var i = 0; i < args.length; i++) {
			sarg[i] = "args["+i+"]";
		};

		call = "oScope.__applyTemp__(" + sarg.join(",") + ");";

		oScope.__applyTemp__ = this;
		rtrn = eval(call);
		oScope.__applyTemp__ = null;
		return rtrn;
	};
};


/*	The following code parses CSS selectors.
	This script however is not the right place to explain it,
	please visit the documentation for more information. */
	var reParseSelector = /^([^#\.>\`]*)(#|\.|\>|\`)(.+)$/;
	function parseSelector(sSelector, oParentNode, sMode){
		sSelector = sSelector.replace(" ", "`");
		var selector = sSelector.match(reParseSelector);
		var node, listNodes, listSubNodes, subselector;
		var listReturn = [];

		if(selector == null){ selector = [sSelector, sSelector]	};
		if(selector[1] == ""){ selector[1] = "*" };
		if(sMode == null){ sMode = "`" };

		switch(selector[2]){
			case "#":
				subselector = selector[3].match(reParseSelector);
				if(subselector == null){ subselector = [null, selector[3]] };
				node = 	document.getElementById(subselector[1]);
				if(node == null || (selector[1] != "*" && node.nodeName.toLowerCase() != selector[1].toLowerCase())){
					return listReturn;
				};
				if(subselector.length == 2){
					listReturn.push(node);
					return listReturn;
				};
				return parseSelector(subselector[3], node, "#");
			case ".":
				if(sMode == "`"){
					listNodes = getElementsByTagName(oParentNode, selector[1]);
				} else {
					listNodes = oParentNode.childNodes;
				};

				for(var i = 0; i < listNodes.length; i++){
					node = listNodes[i];
					if(node.nodeType != 1){
						continue;
					};

					subselector = selector[3].match(reParseSelector);
					if(subselector != null){
						if(node.className.match("\\b" + subselector[1] + "\\b") == null){
							continue;
						};
						listSubNodes = parseSelector(subselector[3], node, subselector[2]);
						listReturn = listReturn.concat(listSubNodes);
					} else if(node.className.match("\\b" + selector[3] + "\\b") != null){
						listReturn.push(node);
					};
				};
				return listReturn;
			case ">":
				if(sMode == "`"){
					listNodes = getElementsByTagName(oParentNode, selector[1]);
				} else {
					listNodes = oParentNode.childNodes;
				};
				for(var i = 0; i < listNodes.length; i++){
					node = listNodes[i];
					if(node.nodeType != 1){
						continue;
					};
					if(node.nodeName.toLowerCase() != selector[1].toLowerCase()){
						continue;
					};
					listSubNodes = parseSelector(selector[3], node, ">");
					listReturn = listReturn.concat(listSubNodes);
				};
				return listReturn;
			case "`":
				listNodes = getElementsByTagName(oParentNode, selector[1]);
				for(var i = 0; i < listNodes.length; i++){
					node = listNodes[i];
					listSubNodes = parseSelector(selector[3], node, "`");
					listReturn = listReturn.concat(listSubNodes);
				};
				return listReturn;
			default:
				listNodes = getElementsByTagName(oParentNode, selector[0]);
				for(var i = 0; i < listNodes.length; i++){
					listReturn.push(listNodes[i]);
				};
				return listReturn;
		};
	};

	function getElementsByTagName(oParentNode, sTagName){
		/*	IE5.x does not support document.getElementsByTagName("*")
			therefore we're resorting to element.all */
		if(sTagName == "*" && oParentNode.all != null){
			return oParentNode.all;
		};
		return oParentNode.getElementsByTagName(sTagName);
	};

/*	Executes an anonymous function which returns the function sJIR (defined inside the function).
	You can replace elements using sJIR.replaceElement()
	All other variables and methods you see are private. If you want to understand how this works you should
	learn more about the variable-scope in JavaScript. */

var sJIR = function(){
	if(!document.createElement || !document.getElementById){ return function(){return false} };

	function fetchContent(oNode, oNewNode, sCase){
		var sContent = "";
		var oSearch = oNode.firstChild;
		var oRemove, oRemovedNode, oTarget;

		while(oSearch){
			if(oSearch.nodeType == 3){
				switch(sCase){
					case "lower":
						sContent += oSearch.nodeValue.toLowerCase();
						break;
					case "upper":
						sContent += oSearch.nodeValue.toUpperCase();
						break;
					default:
						sContent += oSearch.nodeValue;
				};
			} else if(oSearch.nodeType == 1){
				if(oSearch.nodeName.toLowerCase() == "a"){
					if(oSearch.getAttribute("target")){
						oTarget = oSearch.getAttribute("target");
					} else {
						oTarget = "";
					};
					sContent += '<a href="' + oSearch.getAttribute("href") + '" target="' + oTarget + '">';
				};
				if(oSearch.hasChildNodes){
					sContent += fetchContent(oSearch, null, sCase);
				};
				if(oSearch.nodeName.toLowerCase() == "a"){
					sContent += "</a>";
				};
			};
			oRemove = oSearch;
			oSearch = oSearch.nextSibling;
			if(oNewNode != null){
				oRemovedNode = oRemove.parentNode.removeChild(oRemove);
				oNewNode.appendChild(oRemovedNode);
			};
		};
		return sContent;
	};

	function getStyle(node, style,styleCC) {
		var value = node.style[styleCC];

		if(!value)
			if(document.defaultView)
				value = document.defaultView.getComputedStyle(node, "").getPropertyValue(style);
			else if(node.currentStyle)
				value = node.currentStyle[styleCC];

		return value;
	}

	function replaceElement(sSelector, sCase){
		var listNodes = parseSelector(sSelector, document);
		for(var i = 0; i < listNodes.length; i++){
			node = listNodes[i];

			/* Prevents elements from being replaced multiple times. */
			if(node.className.match(/\bsJIR\-replaced\b/) != null){ continue; };
			node.className = node.className.normalize() + (node.className == ""  ? "" : " ") + "sJIR-replaced";

			color = getStyle(node,"color","color");
			backgroundcolor = "transparent";
			n = node;
			while (backgroundcolor == "transparent") {
				backgroundcolor = getStyle(n, "background-color","backgroundColor");
				n = n.parentNode;
			}
			
			sFont = getStyle(node, "font-family","fontFamily");

			sWidth = node.offsetWidth;
			sHeight = node.offsetHeight;

			nodeAlternate = document.createElement("span");
			nodeAlternate.className = "sJIR-alternate";

			sText = fetchContent(node, nodeAlternate, sCase);
			sText = sText.replace(/<[^>]*>/g, "");
			sText = sText.replace(/%\d{0}/g, "%25");
			sText = sText.replace(/\+/g, "%2B");
			sText = sText.replace(/&/g, "%26");
			sText = sText.replace(/\"/g, "%22");
			sText = sText.normalize();

			newImg=document.createElement('img');
			newImg.setAttribute('alt',sText);
			newImg.setAttribute('width',sWidth);
			newImg.setAttribute('height',sHeight);
			newImg.setAttribute('src',"sjir/?f=" +escape(sFont)
			                         +"&w=" + escape(sWidth)
						 +"&h=" + escape(sHeight)
						 +"&bg=" + escape(backgroundcolor)
						 +"&fg=" + escape(color)
						 +"&t="+ escape(sText));
			node.appendChild(newImg,node);
		}


	};

	function sJIR(e){
		if((!sJIR.bAutoInit && (window.event || e) != null) || !mayReplace(e)){
			return;
		};
		bIsInitialized = true;

		for(var i = 0; i < stackReplaceElementArguments.length; i++){
			replaceElement.apply(null, stackReplaceElementArguments[i]);
		};
		stackReplaceElementArguments = [];
	};

	sJIR.replaceElement = replaceElement;
	sJIR.bAutoInit = true;

	if(window.attachEvent){
		window.attachEvent("onload", sJIR);
	} else if(document.addEventListener || window.addEventListener){
		if(document.addEventListener){
			document.addEventListener("load", sJIR, false);
		};
		if(window.addEventListener){
			window.addEventListener("load", sJIR, false);
		};
	} else {
		if(typeof window.onload == "function"){
			var fOld = window.onload;
			window.onload = function(){ fOld(); sJIR(); };
	} else {
			window.onload = sJIR;
		};
	};

	return sJIR;
}();


