﻿var FontReplacer = {
	_url:  'http://www.almega.com.hk/cc/fontwriter/fontwriter.ashx?font=[font]&text=[text]&height=[height]&color=[color]&bcolor=[bcolor]&size=[size]',
	_enableTransparency: true,
	_forceHeight: false,
	_forceWidth: false,

	replace: function(tag, className, font) {
		this.replaceIn(document, tag, className, font);
	},

	replaceIn: function(root, tag, className, font) {
		var elements = this.getElementsByClassName(root, tag, className);
		
		// added by Simon Lock on 2008/10/23
		for (var counter=0; counter<1; counter++)
			if (this.replaceElements(elements, font)) break;
	},

	replaceElements: function(elements, font) {
	
		var delimiters = " ,.!?";
		var skippers = String.fromCharCode(9, 10);

		for (var i=0; i<elements.length; i++) {
			var el = elements[i];           

			// only handle text nodes
			if (!el.firstChild) continue; // added by Simon Lock on 2008/5/30
			if (el.firstChild.nodeType != 3) continue; // If not Text node

			// get attributes of elements                    
			var text = el.firstChild.nodeValue;
			var color = this.getStyle(el, 'color');
			var bcolor = this.getStyle(el, 'backgroundColor');
			var height = this.getStyle(el, 'height');
			var width = this.getStyle(el, 'width');
			var size = this.getStyle(el, 'fontSize');
			var spacing = this.getStyle(el, 'letterSpacing');
			if (spacing=="normal") spacing = "0";
			
			color = this.getColorByName(color);
			if (color.indexOf('rgb') != -1) 
				color = this.cssRgb2Hex(color);

			bcolor = this.getColorByName(bcolor);
			if (bcolor == 'transparent' && !this._enableTransparency)
				bcolor = '';

			if (bcolor.indexOf('rgb') != -1) 
				bcolor = this.cssRgb2Hex(bcolor);  
			 
			color = color.replace('#','');
			bcolor = bcolor.replace('#',''); 

			var s = text;
			var obj = document.createElement("span");
			el.replaceChild(obj, el.firstChild);
			
			for (var j=0; j<s.length; j++) {
				text = "";
				while (j<s.length) {
					if (skippers.indexOf(s.charAt(j))<0) {
						text += s.charAt(j);
						if (s.charCodeAt(j)>=256 || delimiters.indexOf(s.charAt(j))>=0) break;
					}
					j++;
				}
				if (!isNaN(text.charCodeAt(0))) {
					// create image for replacement
					var url = this._url.replace('[text]',text).replace('[font]',font).replace('[bcolor]',bcolor).replace('[color]',color).replace('[size]',size);
					if (this._forceWidth)
					    url = url.replace('[width]',width);
					if (this._forceHeight)
					    url = url.replace('[height]',height);

					var img = new Image();
					obj.appendChild(img);
					img.src = url;
					//img.title = text;
					//img.title = j + "/" + text.charCodeAt(0);
					//img.title = color;
					img.style.paddingRight = spacing;
				}
				// test code by passing the event handler
				//el.replaceChild(img, el.firstChild);				   
			}
		}

		// Check if all text nodes are replaced
		for (var i=0; i<elements.length; i++)
		{ var n = elements[i].firstChild;
			if (!n) continue;
			if (n.nodeType==3) return false;
		}
		return true;
	},

	// this doesn't always work for font sizes, so we're using it for colors mostly
	getStyle: function(el, prop) {
		if (document.defaultView && document.defaultView.getComputedStyle) {
			return document.defaultView.getComputedStyle(el, null)[prop];
		} else if (el.currentStyle) {
			return el.currentStyle[prop];
		} else {
			return el.style[prop];
		}
	},

	cssRgb2Hex: function(color)
	{
		var c = color.replace('rgb(','').replace(')','').split(',');
		return this.rbg2hex(parseInt(c[0]), parseInt(c[1]), parseInt(c[2]));
	},

	rbg2hex: function(red, green, blue)
	{
		var r = red.toString(16);
		var g = green.toString(16);
		var b = blue.toString(16);
						  
		var c =             
		( (r.toString().length == 1) ? '0' : '') + r +
		( (g.toString().length == 1) ? '0' : '') + g + 
		( (b.toString().length == 1) ? '0' : '') + b;
			   
		return c;
	},
	
	getColorByName: function(color) 
	{
		switch (color.toLowerCase()) {
			case 'aliceblue': return '#f0f8ff';
			case 'antiquewhite': return '#faebd7';
			case 'aqua': return '#00ffff';
			case 'aquamarine': return '#7fffd4';
			case 'azure': return '#f0ffff';
			case 'beige': return '#f5f5dc';
			case 'bisque': return '#ffe4c4';
			case 'black': return '#000000';
			case 'blanchedalmond': return '#ffebcd';
			case 'blue': return '#0000ff';
			case 'blueviolet': return '#8a2be2';
			case 'brown': return '#a52a2a';
			case 'burlywood': return '#deb887';
			case 'cadetblue': return '#5f9ea0';
			case 'chartreuse': return '#7fff00';
			case 'chocolate': return '#d2691e';
			case 'coral': return '#ff7f50';
			case 'cornflowerblue': return '#6495ed';
			case 'cornsilk': return '#fff8dc';
			case 'crimson': return '#dc143c';
			case 'cyan': return '#00ffff';
			case 'darkblue': return '#00008b';
			case 'darkcyan': return '#008b8b';
			case 'darkgoldenrod': return '#b8860b';
			case 'darkgray': return '#a9a9a9';
			case 'darkgreen': return '#006400';
			case 'darkkhaki': return '#bdb76b';
			case 'darkmagenta': return '#8b008b';
			case 'darkolivegreen': return '#556b2f';
			case 'darkorange': return '#ff8c00';
			case 'darkorchid': return '#9932cc';
			case 'darkred': return '#8b0000';
			case 'darksalmon': return '#e9967a';
			case 'darkseagreen': return '#8fbc8f';
			case 'darkslateblue': return '#483d8b';
			case 'darkslategray': return '#2f4f4f';
			case 'darkturquoise': return '#00ced1';
			case 'darkviolet': return '#9400d3';
			case 'deeppink': return '#ff1493';
			case 'deepskyblue': return '#00bfff';
			case 'dimgray': return '#696969';
			case 'dodgerblue': return '#1e90ff';
			case 'firebrick': return '#b22222';
			case 'floralwhite': return '#fffaf0';
			case 'forestgreen': return '#228b22';
			case 'fuchsia': return '#ff00ff';
			case 'gainsboro': return '#dcdcdc';
			case 'ghostwhite': return '#f8f8ff';
			case 'gold': return '#ffd700';
			case 'goldenrod': return '#daa520';
			case 'gray': return '#808080';
			case 'green': return '#008000';
			case 'greenyellow': return '#adff2f';
			case 'honeydew': return '#f0fff0';
			case 'hotpink': return '#ff69b4';
			case 'indianred': return '#cd5c5c';
			case 'indigo': return '#4b0082';
			case 'ivory': return '#fffff0';
			case 'khaki': return '#f0e68c';
			case 'lavender': return '#e6e6fa';
			case 'lavenderblush': return '#fff0f5';
			case 'lawngreen': return '#7cfc00';
			case 'lemonchiffon': return '#fffacd';
			case 'lightblue': return '#add8e6';
			case 'lightcoral': return '#f08080';
			case 'lightcyan': return '#e0ffff';
			case 'lightgoldenrodyellow': return '#fafad2';
			case 'lightgreen': return '#90ee90';
			case 'lightgrey': return '#d3d3d3';
			case 'lightpink': return '#ffb6c1';
			case 'lightsalmon': return '#ffa07a';
			case 'lightseagreen': return '#20b2aa';
			case 'lightskyblue': return '#87cefa';
			case 'lightslategray': return '#778899';
			case 'lightsteelblue': return '#b0c4de';
			case 'lightyellow': return '#ffffe0';
			case 'lime': return '#00ff00';
			case 'limegreen': return '#32cd32';
			case 'linen': return '#faf0e6';
			case 'magenta': return '#ff00ff';
			case 'maroon': return '#800000';
			case 'mediumaquamarine': return '#66cdaa';
			case 'mediumblue': return '#0000cd';
			case 'mediumorchid': return '#ba55d3';
			case 'mediumpurple': return '#9370db';
			case 'mediumseagreen': return '#3cb371';
			case 'mediumslateblue': return '#7b68ee';
			case 'mediumspringgreen': return '#00fa9a';
			case 'mediumturquoise': return '#48d1cc';
			case 'mediumvioletred': return '#c71585';
			case 'midnightblue': return '#191970';
			case 'mintcream': return '#f5fffa';
			case 'mistyrose': return '#ffe4e1';
			case 'moccasin': return '#ffe4b5';
			case 'navajowhite': return '#ffdead';
			case 'navy': return '#000080';
			case 'oldlace': return '#fdf5e6';
			case 'olive': return '#808000';
			case 'olivedrab': return '#6b8e23';
			case 'orange': return '#ffa500';
			case 'orangered': return '#ff4500';
			case 'orchid': return '#da70d6';
			case 'palegoldenrod': return '#eee8aa';
			case 'palegreen': return '#98fb98';
			case 'paleturquoise': return '#afeeee';
			case 'palevioletred': return '#db7093';
			case 'papayawhip': return '#ffefd5';
			case 'peachpuff': return '#ffdab9';
			case 'peru': return '#cd853f';
			case 'pink': return '#ffc0cb';
			case 'plum': return '#dda0dd';
			case 'powderblue': return '#b0e0e6';
			case 'purple': return '#800080';
			case 'red': return '#ff0000';
			case 'rosybrown': return '#bc8f8f';
			case 'royalblue': return '#4169e1';
			case 'saddlebrown': return '#8b4513';
			case 'salmon': return '#fa8072';
			case 'sandybrown': return '#f4a460';
			case 'seagreen': return '#2e8b57';
			case 'seashell': return '#fff5ee';
			case 'sienna': return '#a0522d';
			case 'silver': return '#c0c0c0';
			case 'skyblue': return '#87ceeb';
			case 'slateblue': return '#6a5acd';
			case 'slategray': return '#708090';
			case 'snow': return '#fffafa';
			case 'springgreen': return '#00ff7f';
			case 'steelblue': return '#4682b4';
			case 'tan': return '#d2b48c';
			case 'teal': return '#008080';
			case 'thistle': return '#d8bfd8';
			case 'tomato': return '#ff6347';
			case 'turquoise': return '#40e0d0';
			case 'violet': return '#ee82ee';
			case 'wheat': return '#f5deb3';
			case 'white': return '#ffffff';
			case 'whitesmoke': return '#f5f5f5';
			case 'yellow': return '#ffff00';
			case 'yellowgreen': return '#9acd32';
			default: return color;
		}
	},

	// credit: http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
	getElementsByClassName: function(oElm, strTagName, strClassName){
		var arrElements = (strTagName == "*" && oElm.all) ? oElm.all : oElm.getElementsByTagName(strTagName);
		var arrReturnElements = new Array();
		strClassName = strClassName.replace(/\-/g, "\\-");
		var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
		var oElement;
		for (var i=0; i<arrElements.length; i++){
			oElement = arrElements[i];
			if (oRegExp.test(oElement.className)){
				arrReturnElements.push(oElement);
			}
		}
		return (arrReturnElements)
	}     
};