/***************************************************************************
 * NiRF javascript version 1.0.3 -- Native Image Rendered Fonts            *
 *                                                                         *
 * Authors:                                                                *
 *   Kris Bray   <kris.bray@imperium.ca>                                   *
 *   Scott Steil <scott.steil@imperium.ca>                                 *
 *                                                                         *
 * License:                                                                *
 *   This code is licensed under the GPLv3 license.                        *
 *                                                                         *
 * Description:                                                            *
 *   This JavaScript file will identify and replace key elements in your   *
 *   document that require a custom font. This script works in conjunction *
 *   with a back-end script that generates the images. This script will    *
 *   retrieve the CSS styles applied to each element. Then, it will        *
 *   generate a URL with those parameters embedded in it and replace       *
 *   the HTML element with the image. The transition should be seamless.   *
 *                                                                         *
 * Usage:                                                                  *
 *   1) Customize the configuration items below.                           *
 *   2) Something about font...                                            *
 *   3) specify which tags you want to run this script on.                 *
 *      Note: specifying '*' or no tag will run the script on all elements *
 *            to find a matching flag.                                     *
 ***************************************************************************/



/***************************************************************************
 * Configuration for Font Serving                                          *
 ***************************************************************************/

// In some cases, it is more desirable to have your element rendered as an 
// image rather than as the background of the existing element. Setting 
// forceImageRender to true will replace your element with an <img> tag.
var forceImageRender = false;

// Specify the image format: [png|jpg|gif]
var fileType 		 = "png";

// if your using a small size font and it looks funny, try changing scalefirst
// to true. It will draw the font large first and scale down 
// Note: This only applies to NiRF.NET, PHP NiRF already applies anti aliasing
// so scaling is a redundancy that will only increase the rendering time.
var scalefirst 		 = "false" 

// define the variable to tell the nirf js script not to implement a filter
var is_lte_ie7 		= false;

// Set the path to the back-end conversion script
var baseURL 		 = "/convert/";

// Set Trigger Classes to appropriate fonts
// to filter only certain elements with the trigger class you may specify a filter TagName IE 'h1' in the runFonts. To make ALL elements that 
// contain the trigger class convert, leave it blank. This can also speed up performance as it does not need to loop through all elements on the page
window.onload = function ()
{
    //Add our trigger fonts and classes font names must match the font file in the fonts folder 
    addFont("nirfpagetitle");
    
    //Run all elements on the page that contain our trigger classes
	runFonts();
}



/***************************************************************************
 * Font Replacement Code - DO NOT EDIT BELOW THIS LINE                     *
 ***************************************************************************/

var fontReplacers = [];

//hide body until page loads for no flicker reset on window load (runfonts)
document.write("<style type='text/css'> body{visibility:hidden;}</style>") 

function addFont(fontTrigger)
{
    var fontReplacer = {};
    //fontReplacer.fontName = fontName; //moved to CSS to specify font as font-family css attribute
    fontReplacer.fontTrigger = fontTrigger;
    fontReplacers[fontReplacers.length] = fontReplacer;
}


// TODO: modify this to only swap out tags if force image render true
// if force image render false just loop through trigger classes and reset background image on matching class name
// this will also allow for dynamic rollover images using a:hover
function runFonts(tag)
{
	if(!tag){tag = '*'};

    //loop through entire DOM structure and look for class names with our font trigger    
    var doc = document.getElementsByTagName(tag);
    
    for(var i=0; i < doc.length; i++)
    {
        //make sure dom object is an element
        if(doc[i].nodeType == 1)
        {
	        //check if the trigger is in the className
	        for(var e=0; e < fontReplacers.length; e++)
	        {
	            if(doc[i].className.indexOf(fontReplacers[e].fontTrigger) > -1)
	            {
	                //found trigger apply font replacer
	                //check if there are children tags (sometimes spans are placed in H1 tags or A href links)
	                var docChildren = doc[i].childNodes;
	                
	                if(docChildren.length > 1) 
	                {
	                    //loop through children
	                    for (var f=0; f < docChildren.length; f++)
	                    {
	                        if(docChildren[f].nodeType == 1)
	                        {
								elementSwap(docChildren[f], i);
	                        }
	                    }
	                }
	                else
	                {
	                	elementSwap(doc[i], i);
	            	}
	            } 
	    	}
		}
	}
    
    document.body.style.visibility = "visible";
}

/**
 * Retrieve all the necessary styles from any given element.
 */
function getStyles(objRep) 
{
    var fontSwapTrigger = {};
    var fontSwapHover = {};

    //read all CSS attributes from trigger class
    fontSwapTrigger.fontName = getStyle(objRep.className, 'font-family');
    fontSwapTrigger.textAlign = getStyle(objRep.className, 'text-align');
    fontSwapTrigger.fontColor = getStyle(objRep.className, 'color');
    fontSwapTrigger.fontSize = getStyle(objRep.className, 'font-size');
    fontSwapTrigger.fontStyle = getStyle(objRep.className, 'font-weight');
    fontSwapTrigger.bgColor = getStyle(objRep.className, 'background-color');
    fontSwapTrigger.bgImage = getStyle(objRep.className, 'background-image');
    fontSwapTrigger.xOffset = getStyle(objRep.className, 'padding-left');
    fontSwapTrigger.yOffset = getStyle(objRep.className, 'padding-top');
    fontSwapTrigger.fontText = trim(objRep.innerHTML);
    
    //read all CSS attributes for hover class
    fontSwapHover.fontName = getStyle(objRep.parentNode.className + ":hover", 'font-family');
    fontSwapHover.textAlign = getStyle(objRep.parentNode.className + ":hover", 'text-align');
    fontSwapHover.fontColor = getStyle(objRep.parentNode.className + ":hover", 'color');
    fontSwapHover.fontSize = getStyle(objRep.parentNode.className + ":hover", 'font-size');
    fontSwapHover.fontStyle = getStyle(objRep.parentNode.className + ":hover", 'font-weight');
    fontSwapHover.bgColor = getStyle(objRep.parentNode.className + ":hover", 'background-color');
    fontSwapHover.bgImage = getStyle(objRep.parentNode.className + ":hover", 'background-image');
    fontSwapHover.xOffset = getStyle(objRep.parentNode.className + ":hover", 'padding-left');
    fontSwapHover.yOffset = getStyle(objRep.parentNode.className + ":hover", 'padding-top');
    fontSwapHover.fontText = trim(objRep.parentNode.innerHTML);
    
    //safari seems to include the whole absolute path in the background image so check for it before adding it again
    var i = document.location.href.lastIndexOf('/');
    var url = document.location.href.substring(0, i + 1);
    if(fontSwapTrigger.bgImage && fontSwapTrigger.bgImage != '' && fontSwapTrigger.bgImage.indexOf(url) == -1)
    {
    	fontSwapTrigger.bgImage = url + fontSwapTrigger.bgImage;
    }
    if(fontSwapHover.bgImage && fontSwapHover.bgImage != '' && fontSwapHover.bgImage.indexOf(url) == -1)
    {
    	fontSwapHover.bgImage = url + fontSwapHover.bgImage;
    }
    
    return [fontSwapTrigger, fontSwapHover];
}




/**
 * Single element swap
 */
function elementSwap(objRep, uniqueID) 
{
    var fontSwaps = getStyles(objRep);
    var urlEle    = buildURL(fontSwaps[0]);
    var urlHover  = buildURL(fontSwaps[1]);

	objRep.style.display = "block";
	
	//check if font name specified in CSS class
	if(forceImageRender == false)
	{
        var newBG = "";
        
        //set image path for background image
        if(fontSwaps[0].bgColor.toLowerCase() != "transparent" && fontSwaps[0].bgColor != "")
        { 
        	//set color
        	newBG = "#" + fontSwaps[0].bgColor + " "; 
        } 
        newBG += "url(" + urlEle + ") no-repeat top " + fontSwaps[0].textAlign;
        

        var newBGHover = "";

        //set image for background hover if hover class exists
        if(fontSwaps[1].fontName)
        {
            if(fontSwaps[1].bgColor.toLowerCase() != "transparent" && fontSwaps[1].bgColor != "")
            { 
            	newBGHover = "#" + fontSwaps[1].bgColor + " "; 
            }
	        newBGHover += "url(" + urlHover + ") no-repeat top " + fontSwaps[1].textAlign;
        }
        
        //set id for element as will add a CSS rule for it to allow for hovers
        objRep.id = "nf_" + uniqueID;
	   
        //add new css rules
        
        if(is_lte_ie7)
        {
        	//addCSSRule("#nf_" + uniqueID, "filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + urlEle + ", sizingMethod='crop'); text-indent:-6000px;");
        	//addCSSRule("#nf_" + uniqueID + ":hover", "background: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + urlHover + ", sizingMethod='crop'); text-indent:-6000px;");
        }
        else
        {
	        addCSSRule("#nf_" + uniqueID, "background:" + newBG + ";text-indent:-6000px;");
        	//addCSSRule("#nf_" + uniqueID + ":hover", "background:" + newBGHover + ";text-indent:-6000px;");
        }
    }
    if(forceImageRender == true)
    {
        objRep.style.textIndent = ""; //reset text indent
        objRep.innerHTML = "<img src='" + buildURL(fontSwaps[0]) + "' style='border:none;' />";
    }
}

function buildURL(fontSwap)
{
	return baseURL + 
		   "?font=" + 		fontSwap.fontName + 
		   "&text=" + 		Url.encode(fontSwap.fontText) + 
		   "&fontSize=" + 	fontSwap.fontSize + 
		   "&fontColor=" + 	fontSwap.fontColor + 
		   "&bgColor=" + 	fontSwap.bgColor + 
		   "&x=" + 			fontSwap.xOffset + 
		   "&y=" +  		fontSwap.yOffset + 
		   "&bgImg=" + 		fontSwap.bgImage + 
		   "&fontStyle=" + 	fontSwap.fontStyle + 
		   "&textAlign=" + 	fontSwap.textAlign + 
		   "&ftype=" + 		fileType + 
		   "&scalefirst=" + scalefirst;
}

function trim(str) 
{
	return str.replace(/^\s+|\s+$/g,"");
}

function getStyle(className,styleProp)
{
	//loop through all style sheets
	var mysheets=document.styleSheets
	
	for (var s=0; s<mysheets.length; s++)
	{
	    var mysheet=document.styleSheets[s]
        var myrules=mysheet.cssRules? mysheet.cssRules: mysheet.rules
        for (i=0; i<myrules.length; i++)
        {
            if(myrules[i].selectorText.toLowerCase()== "." + className.toLowerCase())
            { 
                targetrule = myrules[i];
                var fndRule = true;
                if(styleProp =='color')
                {
                	return RGBtoHex(targetrule.style.color);
                }
                
                if(styleProp =='background-image')
                {    
                    if(targetrule.style.backgroundImage != 'none' && targetrule.style.backgroundImage != '' && targetrule.style.backgroundImage != 'initial')
                    {
                    	return targetrule.style.backgroundImage.split('url(')[1].replace(')', '');
                    }
                    else
                    {
                    	return '';
                    }
                }
                    
                if(styleProp =='background-color')
                {
                    if(targetrule.style.backgroundColor != 'transparent'){return RGBtoHex(targetrule.style.backgroundColor)}else{return 'transparent'};
                }
                
                if(styleProp =='font-size'){return targetrule.style.fontSize.split("px")[0]};
                if(styleProp =='font-weight'){return targetrule.style.fontWeight};
                if(styleProp =='text-align'){return targetrule.style.textAlign};
                if(styleProp =='font-family'){return targetrule.style.fontFamily};
                if(styleProp =='padding-left'){return targetrule.style.paddingLeft};
                if(styleProp =='padding-top'){return targetrule.style.paddingTop};
            }
        }
    }
    if(!fndRule && className.indexOf('hover') == -1)
    {
    	alert('could not find css rule for font trigger class '+ className);
    }
}

//TODO try setting CSS background for class instead of looping through all elements to change the background image
function setStyle(className,value, prop)
{
	//loop through all style sheets
	var mysheets=document.styleSheets
	
	for (var s=0; s<mysheets.length; s++)
	{
	    
	    var mysheet=document.styleSheets[s]
        var myrules=mysheet.cssRules? mysheet.cssRules: mysheet.rules
        for (i=0; i<myrules.length; i++)
        {
           
            if(myrules[i].selectorText.toLowerCase()== "." + className.toLowerCase())
            { 
                var fndRule = true;
                targetrule=myrules[i]
                if(prop == 'background-image'){ targetrule.style.backgroundImage = value};
                if(prop == 'text-indent'){ targetrule.style.textIndent = value};
                
             }
        }
    }
   if(!fndRule){alert('could not find css rule for font trigger class '+ className)};
}

function addCSSRule(selector, value)
{
	//loop through all style sheets
	var mysheets=document.styleSheets
    var mysheet=document.styleSheets[0] //just get first sheet
    if(mysheet.addRule)
    {
        mysheet.addRule(selector, value, 0)
    }
    else
    {
        mysheet.insertRule(selector + '{' + value + '}', 0); //add new rule other
    }
}

function RGBtoHex(rgbstring) 
{

    if (rgbstring == ''){return ''};
    if (rgbstring.substring(0, 1) == "#"){return rgbstring.substring(1, rgbstring.length) }
    var sp1 = rgbstring.split("(");
    var sp2 = sp1[1].split(")");
    var sp3 = sp2[0].split(",");
    var R, G, B
    R = sp3[0];
    G = sp3[1];
    B = sp3[2];
    
    return toHex(R)+toHex(G)+toHex(B)

}

function toHex(N) 
{
	if (N==null) return "00";
	N=parseInt(N); if (N==0 || isNaN(N)) return "00";
	N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
	return "0123456789ABCDEF".charAt((N-N%16)/16)
      + "0123456789ABCDEF".charAt(N%16);
}


/**
 *
 *  URL encode / decode
 *  http://www.webtoolkit.info/
 *
 **/
 
var Url = {
 
	// public method for url encoding
	encode : function (string) {
		return escape(this._utf8_encode(string));
	},
 
	// public method for url decoding
	decode : function (string) {
		return this._utf8_decode(unescape(string));
	},
 
	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
 
		for (var n = 0; n < string.length; n++) {
 
			var c = string.charCodeAt(n);
 
			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
 
		}
 
		return utftext;
	},
 
	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
 
		while ( i < utftext.length ) {
 
			c = utftext.charCodeAt(i);
 
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
 
		}
 
		return string;
	}
 
}

/**
 * Allow including files
 *
function includeJS(fName) {
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.setAttribute('type','text/javascript');
    script.setAttribute('src',fName);
    head.appendChild(script);
} 

includeJS('nirfConfig.js');
*/