/**
 * 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($) {
    //* 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 *******************************************************************************
    $.fn.FontEffect = function(o) {
        //* Defaults *********************************************************************
        var d = $.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($(this).css("color"));
                };
                if (d.outlineColor2 == "") d.outlineColor2 = d.outlineColor1;
            };
            if (d.gradient && d.gradientColor == "") { d.gradientColor = pickcontrast($(this).css("color")); };
            //* get the element display option and change to inline ********************************************************************
            var userdisplay = $(this).css("display");
            var userposition = $(this).css("position");
            $(this).css({
                display: "inline",
                position: ((userposition == "absolute") ? "absolute" : "relative")
            });
            //* Local Variables ********************************************************************
            var h = $(this).height();
            var w = $(this).width() * 1.04;
            var W = w + "px";
            var H = h + "px";
            var fontSize = $(this).css("font-size");
            var fontColor = $(this).css("color");
            //var W=w.pxToEm({scope: this});
            //var H=h.pxToEm({scope: this});
            var t = $(this).html();
            //* Set Class and Options ********************************************************
            $(this)
                .data("options", d)
                .addClass("JQFE")
                .css({
                    width: W,
                    height: H,
                    display: userdisplay,
                    position: (($(this).css("position") != "absolute") ? "relative" : "absolute"),
                    zoom: 1,
                    fontSize: fontSize
                    
                });
            //* Create the MyContainer structure ***********************************************
            var MyContainer = $("<div></div>").css({ // need extra div for IE zindex bug
                width: W,
                height: H,
                position: "relative",
                fontSize: fontSize
            });
            //* MyContainer For the central layer ***********************************************
            MyContainer.append(
                $("<div class='JQFEText'>" + t + "</div>").css({
                    display: d.hideText ? "none" : "inline",
                    width: W,
                    height: H,
                    position: "relative",
                    zIndex: 100,
                    fontSize: fontSize,
                    color: fontColor
                })
            );
            //* MyContainer For the Upper Effect layer ***********************************************
            var alldivsup = $("<div></div>").css({
                width: W,
                height: H,
                left: "0px",
                position: "absolute",
                top: parseInt($(this).css("paddingTop")) * 0 + "px",
                zIndex: 110,
                fontSize: fontSize
            });
            //* MyContainer For the Lower Effect layer ***********************************************
            var alldivsdown = $(alldivsup).clone().css({ zIndex: 90 });
            FE.divounter += 4;
            $(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 = $("<div class='JQFEMirror'></div>").css({
                        position: "absolute",
                        top: css_top1,
                        height: css_height,
                        width: W,
                        overflow: "hidden"
                    }).append($("<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 = $("<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),
                        fontSize: fontSize
                    });
                    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 = $("<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=$(this).css("color");
                $(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 = $("<div class='JQFEGradient'></div>").css({
                        position: "absolute",
                        top: css_top1,
                        height: css_height,
                        left: "0px",
                        width: W,
                        overflow: "hidden"
                    }).append($("<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 ******************************************************************
            $(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 *******************************************************************************
    $.fn.changeOptionsFE = function(newoptions) {
        if (this) {
            var oldoptions = $(this).data("options") || {};
            $.extend(oldoptions, newoptions);
            $(this).data("options", oldoptions);
        };
    };
    $.fn.redrawFE = function(newoptions) {
        if (this) {
            if (newoptions) $(this).changeOptionsFE(newoptions);
            $(this).removeFE();
            $(this).FontEffect($(this).data("options"));
        };
    };
    $.fn.removeFE = function(removeoptions) {
        if (this && $(this).hasClass("JQFE")) {
            var t = $(this).find("div[class='JQFEText']").html();
            $(this).removeClass("JQFE");
            if (removeoptions) $(this).data("options", {});
            $(this).find("div[class^='JQFE']").remove();
            $(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 = $.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' && $.browser.msie && (parseFloat($('body').css('font-size')) / getWindowWidth()).toFixed(1) > 0.0) {
        var calcFontSize = function() {
            return (parseFloat($('body').css('font-size')) / getWindowWidth()).toFixed(3) * 16;
        };
        scopeVal = calcFontSize();
    }
    else { scopeVal = parseFloat($(settings.scope).css("font-size")); };
    var result = (settings.reverse == true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em';
    return result;
};

