/**
 * FontEffect - jQuery plugin for font effect
 *
 * @author Alessandro Uliana (fonteffect@iofo.it)
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Demo and examples on
 * http://www.iofo.it/jquery/fonteffect/
 *
 * @requires jQuery v1.3.2
 * @version: 1.0.0 - 30/3/2009
 */
(function(JQ){
    //* Global Variables *************************************************************
    var FE={};
    FE.divcounter=0; // div counter for debug
    //* Tabella posizioni layer *************************************************************
    FE.tabpos = ["", "0001021020212212", "00010203041020304041424344142434", "000102030405061020304050606162636465162636465666"];
    //* Most common typeface(from http: //www.codestyle.org/css/font-family/index.shtml) **********
    FE.font = {
        serif:       "Georgia, 'Times New Roman', 'Century Schoolbook L', serif",
        sans_serif:  "Verdana, Helvetica, Arial, 'URW Gothic L', sans-serif",
        monospace:   "'Courier New', Courier, 'DejaVu Sans Mono', monospace",
        fantasy:     "Impact, Papyrus, fantasy",
        cursive:     "'Comic Sans MS' cursive"
        };
    //* Main Function *******************************************************************************
    jQuery.fn.FontEffect = function(o){
        //* Defaults *********************************************************************
        var d = jQuery.extend({
            outline             :false,
            outlineColor1       :"",
            outlineColor2       :"",
            outlineWeight       :1,    // 1=light, 2=normal, 3=bold
            mirror              :false,
            mirrorColor         :"#000",
            mirrorOffset        :-10,
            mirrorHeight        :50,
            mirrorDetail        :1,    // 1=high, 2=medium, 3=low
            mirrorTLength       :50,
            mirrorTStart        :0.2,
            shadow              :false,
            shadowColor         :"#aaa",
            shadowOffsetTop     :5,
            shadowOffsetLeft    :5,
            shadowBlur          :1,    // 1=none, 2=low, 3=high
            shadowOpacity       :0.1,
            gradient            :false,
            gradientColor       :"",
            gradientFromTop     :true,
            gradientPosition    :20,
            gradientLength      :50,
            gradientSteps       :20,
            proportional        :false,
            hideText            :false,
            debug               :false
        },  o);
        //* Main Loop ********************************************************************
        this.not(".JQFE").each(function(){
            //* Check and correct options ********************************************************************
            if(!d.outline &&
                !d.shadow  &&
                !d.mirror  &&
                !d.gradient) {d.outline=true;};
            if(d.outline){
                if(d.outlineColor1 == "" && d.outlineColor2 == ""){
                    d.outlineColor1=pickcontrast(JQ(this).css("color"));
                    };
                if(d.outlineColor2 == "") d.outlineColor2=d.outlineColor1;
                };
            if(d.gradient && d.gradientColor == ""){d.gradientColor=pickcontrast(JQ(this).css("color"));};
            //* get the element display option and change to inline ********************************************************************
            var userdisplay=JQ(this).css("display");
            var userposition=JQ(this).css("position");
            JQ(this).css({
                display: "inline",
                position:((userposition == "absolute")?"absolute": "relative")
                });
            //* Local Variables ********************************************************************
            var h=JQ(this).height();
            var w=JQ(this).width()*1.04;
            var W=w+"px";
            var H=h+"px";
            //var W=w.pxToEm({scope: this});
            //var H=h.pxToEm({scope: this});
            var t=JQ(this).html();
            //* Set Class and Options ********************************************************
            JQ(this)
                .data("options", d)
                .addClass("JQFE")
                .css({
                    width: W,
                    height: H,
                    display: userdisplay,
                    position:((JQ(this).css("position")!= "absolute")?"relative": "absolute"),
                    zoom: 1
                    });
            //* Create the MyContainer structure ***********************************************
            var MyContainer=JQ("<div></div>").css({ // need extra div for IE zindex bug
                width: W,
                height: H,
                position: "relative"
            });
            //* MyContainer For the central layer ***********************************************
            MyContainer.append(
                JQ("<div class='JQFEText'>"+t+"</div>").css({
                    display:  d.hideText ? "none" :  "inline" ,
                    width: W,
                    height: H,
                    position: "relative",
                    zIndex:   100
                })
            );
            //* MyContainer For the Upper Effect layer ***********************************************
            var alldivsup=JQ("<div></div>").css({
                width: W,
                height: H,
                left: "0px",
                position: "absolute",
                top:      parseInt(JQ(this).css("paddingTop"))*0+"px",
                zIndex:   110
            });
            //* MyContainer For the Lower Effect layer ***********************************************
            var alldivsdown=JQ(alldivsup).clone().css({zIndex: 90});
            FE.divounter+= 4;
            JQ(this).html("");
            //* Mirror Effect ****************************************************************
            if(d.mirror){
                for(i=0;i<h*(d.mirrorHeight/100);i++){
                    if(d.proportional){
                        var css_top1    =(h+d.mirrorOffset+i*d.mirrorDetail).pxToEm({scope: this});
                        var css_height  =d.mirrorDetail.pxToEm({scope: this});
                        var css_top2    =((h*-1)+i*(100/d.mirrorHeight)).pxToEm({scope: this});
                    }
                    else{
                        var css_top1    =(h+d.mirrorOffset+i*d.mirrorDetail)+"px";
                        var css_height  =d.mirrorDetail+"px";
                        var css_top2    =((h*-1)+i*(100/d.mirrorHeight))+"px";
                    };
                    var css_opacity=d.mirrorTStart-(i*(d.mirrorTStart/((d.mirrorHeight/100)*d.mirrorTLength)));
                    var appo=JQ("<div class='JQFEMirror'></div>").css({
                        position: "absolute",
                        top:      css_top1,
                        height:   css_height,
                        width:    W,
                        overflow: "hidden"
                    }).append(JQ("<div>"+t+"</div>").css({
                            position: "absolute",
                            color:    d.mirrorColor,
                            top:      css_top2,
                            opacity:  css_opacity
                        })
                        );
                    FE.divounter+= i*2;
                    // Skip Non Visible Layers ************************************************
                    if(css_opacity<0.01) break;
                    alldivsdown.append(appo);
                };
            };
            //* Outline Effect ***************************************************************
            if(d.outline){
                var totdiv =(d.outlineWeight)*8;
                var to=FE.tabpos[d.outlineWeight];
                for(i=0;i<totdiv;i++){
                    appo=JQ("<div class='JQFEOutline'>"+t+"</div>").css({
                        position: "absolute",
                        top:     (to.charAt(i*2)  -d.outlineWeight)+"px",
                        left:    (to.charAt(i*2+1)-d.outlineWeight)+"px",
                        width:    W,
                        color:   ((i<totdiv/2+d.outlineWeight)?d.outlineColor1: d.outlineColor2),
                        zIndex:  ((i>totdiv-totdiv/3)?20: 30)
                    });
                    FE.divounter+= i;
                    alldivsdown.append(appo);
                };
            };
            //* Shadow Effect ****************************************************************
            if(d.shadow){
                var totdiv =(d.shadowBlur)*8;
                var to=FE.tabpos[d.shadowBlur];
                for(i=0;i<totdiv;i++){
                    appo=JQ("<div class='JQFEShadow'>"+t+"</div>").css({
                        opacity:  d.shadowOpacity,
                        position: "absolute",
                        top:     (to.charAt(i*2)  -d.shadowBlur)+d.shadowOffsetTop +"px",
                        left:    (to.charAt(i*2+1)-d.shadowBlur)+d.shadowOffsetLeft+"px",
                        width:    W,
                        height:   H,
                        color:    d.shadowColor,
                        zIndex:   10
                    });
                    FE.divounter+= i;
                    alldivsdown.append(appo);
                };
            };
            //* Gradient Effect *************************************************************
            if(d.gradient){
                var step    = Math.round((h*(d.gradientLength*0.01))/d.gradientSteps);
                var postop  = h*(d.gradientPosition*0.01);
                var opa     =(1/d.gradientSteps);
                var gcolor  = d.gradientColor;
                /*
                if(!d.gradientFromTop){
                    gcolor=JQ(this).css("color");
                    JQ(this).css("color", d.gradientColor);
                }
                */
                for(i=0;i<d.gradientSteps;i++){
                    if(d.proportional){
                        css_top1   = (((i == 0)?0: postop)+i*step).pxToEm({scope: this});
                        css_height = (((i == 0)?postop: 0)+step  ).pxToEm({scope: this});
                        css_top2   = ((((i == 0)?0: postop)+i*step)*-1).pxToEm({scope: this});
                    }
                    else{
                        css_top1   = (((i == 0)?0: postop)+i*step)+"px";
                        css_height = (((i == 0)?postop: 0)+step  )+"px";
                        css_top2   = ((((i == 0)?0: postop)+i*step)*-1)+"px";
                    };
                    appo=JQ("<div class='JQFEGradient'></div>").css({
                        position: "absolute",
                        top:      css_top1,
                        height:   css_height,
                        left:     "0px",
                        width:    W,
                        overflow: "hidden"
                    }).append(JQ("<div>"+t+"</div>").css({
                            width:    "100%",
                            position: "absolute",
                            top:      css_top2,
                            color:    gcolor,
                            opacity:  1-opa*i
                        })
                        );
                    FE.divounter+= i*2;
                    alldivsup.append(appo);
                };
            };
            //* End Effects ******************************************************************
            MyContainer.append(alldivsdown);
            MyContainer.append(alldivsup);
            //* Draw Effect ******************************************************************
            JQ(this).append(MyContainer);
        });//* Main Loop End *******************************************************************************
        //* Internal Functions ******************************************************************************
        function hex2rgb(hexcolor){
            hexcolor=hexcolor.substring(1);
            if(hexcolor.length == 3) hexcolor=hexcolor.charAt(0)+hexcolor.charAt(0)+hexcolor.charAt(1)+hexcolor.charAt(1)+hexcolor.charAt(2)+hexcolor.charAt(2);
            var rgbcolor="rgb("+parseInt(hexcolor.substring(0, 2), 16)+", "+parseInt(hexcolor.substring(2, 4), 16)+", "+parseInt(hexcolor.substring(4, 6), 16)+")";
            return(rgbcolor);
        };
        function chkColorString(col){
            // test if "col" is a valid html color definition string(rgb(n, n, n)||#fff|#ffffff)
            return(/(#([0-9A-Fa-f]{3,6})\b)|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\))/.test(col));
        };
        function pickcontrast(col){ //(try to) find the contrasting color
            if(chkColorString(col)){
                col = col.toUpperCase();
                if(col.charAt(0) == "#") col=hex2rgb(col);
                var appo=col.substring(4, col.length-1).split(", ");
                var g=255-parseInt(appo[0]);
                var b=255-parseInt(appo[1]);
                var r=255-parseInt(appo[2]);
                col="rgb("+r+", "+g+", "+b+")";
            };
        return(col);
        };
        return this; // chain...
    }; //* Main Function End *******************************************************************************
    //* External Functions *******************************************************************************
    jQuery.fn.changeOptionsFE = function(newoptions){
        if(this){
            var oldoptions=JQ(this).data("options") || {};
            jQuery.extend(oldoptions, newoptions);
            JQ(this).data("options", oldoptions);
        };
    };
    jQuery.fn.redrawFE = function(newoptions){
        if(this){
            if(newoptions) JQ(this).changeOptionsFE(newoptions);
            JQ(this).removeFE();
            JQ(this).FontEffect(JQ(this).data("options"));
        };
    };
    jQuery.fn.removeFE = function(removeoptions){
        if(this && JQ(this).hasClass("JQFE")){
            var t=JQ(this).find("div[class='JQFEText']").html();
            JQ(this).removeClass("JQFE");
            if(removeoptions) JQ(this).data("options", {});
            JQ(this).find("div[class^='JQFE']").remove();
            JQ(this).html(t);
        };
    };
    //* External Functions End *******************************************************************************
})(jQuery);
//* End FontEffect Plugin ******************************************************************************
/*--------------------------------------------------------------------
 * javascript method:  "pxToEm"
 * by:
   Scott Jehl(scott@filamentgroup.com)
   Maggie Wachs(maggie@filamentgroup.com)
   http: //www.filamentgroup.com
 *
 * Copyright(c) 2008 Filament Group
 * Dual licensed under the MIT(filamentgroup.com/examples/mit-license.txt) and GPL(filamentgroup.com/examples/gpl-license.txt) licenses.
 *
--------------------------------------------------------------------*/
Number.prototype.pxToEm = String.prototype.pxToEm = function(settings){
    settings = jQuery.extend({
        scope:  'body',
        reverse:  false
},  settings);
    var pxVal =(this  ==  '') ? 0 :  parseFloat(this);
    var scopeVal;
    var getWindowWidth = function(){
        var de = document.documentElement;
        return self.innerWidth ||(de && de.clientWidth) || document.body.clientWidth;
};
    if(settings.scope  ==  'body' && jQuery.browser.msie &&(parseFloat(JQ('body').css('font-size')) / getWindowWidth()).toFixed(1) > 0.0){
        var calcFontSize = function(){
            return(parseFloat(JQ('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16;
    };
        scopeVal = calcFontSize();
}
    else { scopeVal = parseFloat(JQ(settings.scope).css("font-size")); };
    var result =(settings.reverse  ==  true) ?(pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em';
    return result;
};

