(function () {
    var D, B, x = Math.abs,
        a = Math.sin,
        b = Math.cos,
        n = {},
        p = {},
        q = {
            "0": "0,",
            "1": "17,",
            "2": "34,",
            "3": "51,",
            "4": "68,",
            "5": "85,",
            "6": "102,",
            "7": "119,",
            "8": "136,",
            "9": "153,",
            a: "170,",
            A: "170,",
            b: "187,",
            B: "187,",
            c: "204,",
            C: "204,",
            d: "221,",
            D: "221,",
            e: "238,",
            E: "238,",
            f: "255,",
            F: "255,"
        };
    for (D = 0; D < 256; ++D) {
        B = D.toString(16);
        if (D < 16) {
            B = "0" + B
        }
        p[B] = p[B.toUpperCase()] = D.toString() + ","
    }
    function G(N) {
        var j, M, I, H, L = [],
            J = Math.PI * (3 - Math.sqrt(5)),
            K = 2 / N;
        for (j = 0; j < N; ++j) {
            M = j * K - 1 + (K / 2);
            I = Math.sqrt(1 - M * M);
            H = j * J;
            L.push([b(H) * I, M, a(H) * I])
        }
        return L
    }
    function z(K, i) {
        var J = K,
            I, H, j = (i * 1).toPrecision(3) + ")";
        if (K[0] === "#") {
            if (!n[K]) {
                if (K.length === 4) {
                    n[K] = "rgba(" + q[K[1]] + q[K[2]] + q[K[3]]
                } else {
                    n[K] = "rgba(" + p[K.substr(1, 2)] + p[K.substr(3, 2)] + p[K.substr(5, 2)]
                }
            }
            J = n[K] + j
        } else {
            if (K.substr(0, 4) === "rgb(" || K.substr(0, 4) === "hsl(") {
                J = (K.replace("(", "a(").replace(")", "," + j))
            } else {
                if (K.substr(0, 5) === "rgba(" || K.substr(0, 5) === "hsla(") {
                    I = K.lastIndexOf(",") + 1, H = K.indexOf(")");
                    i *= parseFloat(K.substring(I, H));
                    J = K.substr(0, I) + i.toPrecision(3) + ")"
                } else {
                    J = K
                }
            }
        }
        return J
    }
    function o(i, j) {
        if (window.G_vmlCanvasManager) {
            return null
        }
        var H = document.createElement("canvas");
        H.width = i;
        H.height = j;
        return H
    }
    function h() {
        var j = o(3, 3),
            I, H;
        if (!j) {
            return false
        }
        I = j.getContext("2d");
        I.strokeStyle = "#000";
        I.shadowColor = "#fff";
        I.shadowBlur = "3";
        I.globalAlpha = 0;
        I.strokeRect(2, 2, 2, 2);
        I.globalAlpha = 1;
        H = I.getImageData(2, 2, 1, 1);
        j = null;
        return (H.data[0] > 0)
    }
    function s(O, j) {
        var H = 1024,
            K = O.weightGradient,
            J, M, I, N, L;
        if (O.gCanvas) {
            M = O.gCanvas.getContext("2d")
        } else {
            O.gCanvas = J = o(H, 1);
            if (!J) {
                return null
            }
            M = J.getContext("2d");
            N = M.createLinearGradient(0, 0, H, 0);
            for (I in K) {
                N.addColorStop(1 - I, K[I])
            }
            M.fillStyle = N;
            M.fillRect(0, 0, H, 1)
        }
        L = M.getImageData(~~ ((H - 1) * j), 0, 1, 1).data;
        return "rgba(" + L[0] + "," + L[1] + "," + L[2] + "," + (L[3] / 255) + ")"
    }
    function v(K, J, H, N, L, M, j) {
        var I = (M || 0) + (j && j[0] < 0 ? x(j[0]) : 0),
            i = (M || 0) + (j && j[1] < 0 ? x(j[1]) : 0);
        K.font = J;
        K.textBaseline = "top";
        K.fillStyle = H;
        L && (K.shadowColor = L);
        M && (K.shadowBlur = M);
        j && (K.shadowOffsetX = j[0], K.shadowOffsetY = j[1]);
        K.fillText(N, I, i)
    }
    function l(R, L, P, Q, K, H, N, O, j) {
        var I = Q + x(j[0]) + O + O,
            i = K + x(j[1]) + O + O,
            J, M;
        J = o(I, i);
        if (!J) {
            return null
        }
        M = J.getContext("2d");
        v(M, L, H, R, N, O, j);
        return J
    }
    function m(L, O, P, I) {
        var J = L.width + x(I[0]) + P + P,
            j = L.height + x(I[1]) + P + P,
            M, N, K = (P || 0) + (I && I[0] < 0 ? x(I[0]) : 0),
            H = (P || 0) + (I && I[1] < 0 ? x(I[1]) : 0);
        M = o(J, j);
        if (!M) {
            return null
        }
        N = M.getContext("2d");
        O && (N.shadowColor = O);
        P && (N.shadowBlur = P);
        I && (N.shadowOffsetX = I[0], N.shadowOffsetY = I[1]);
        N.drawImage(L, K, H);
        return M
    }
    function d(T, L, R) {
        var S = parseInt(T.length * R),
            K = parseInt(R * 2),
            I = o(S, K),
            O, j, J, N, Q, P, H, M;
        if (!I) {
            return null
        }
        O = I.getContext("2d");
        O.fillStyle = "#000";
        O.fillRect(0, 0, S, K);
        v(O, R + "px " + L, "#fff", T);
        j = O.getImageData(0, 0, S, K);
        J = j.width;
        N = j.height;
        M = {
            min: {
                x: J,
                y: N
            },
            max: {
                x: -1,
                y: -1
            }
        };
        for (P = 0; P < N; ++P) {
            for (Q = 0; Q < J; ++Q) {
                H = (P * J + Q) * 4;
                if (j.data[H + 1] > 0) {
                    if (Q < M.min.x) {
                        M.min.x = Q
                    }
                    if (Q > M.max.x) {
                        M.max.x = Q
                    }
                    if (P < M.min.y) {
                        M.min.y = P
                    }
                    if (P > M.max.y) {
                        M.max.y = P
                    }
                }
            }
        }
        if (J != S) {
            M.min.x *= (S / J);
            M.max.x *= (S / J)
        }
        if (N != K) {
            M.min.y *= (S / N);
            M.max.y *= (S / N)
        }
        I = null;
        return M
    }
    function y(i) {
        return "'" + i.replace(/(\'|\")/g, "").replace(/\s*,\s*/g, "', '") + "'"
    }
    function C(i, j, H) {
        if (!H) {
            H = document
        }
        if (H.addEventListener) {
            H.addEventListener(i, j, false)
        } else {
            H.attachEvent("on" + i, j)
        }
    }
    function w(I, H, j) {
        if (I.complete) {
            H.w = I.width;
            H.h = I.height;
            j.push(H)
        } else {
            C("load", function () {
                H.w = this.width;
                H.h = this.height;
                j.push(H)
            }, I)
        }
    }
    function u(H, j) {
        var i = 1,
            I;
        if (H.weightFrom) {
            i = 1 * (j.getAttribute(H.weightFrom) || H.textHeight)
        } else {
            if (document.defaultView && document.defaultView.getComputedStyle) {
                I = document.defaultView.getComputedStyle(j, null).getPropertyValue("font-size");
                i = I.replace("px", "") * 1
            } else {
                H.weight = false
            }
        }
        return i
    }
    function g(J) {
        var I, H, j = document.documentElement;
        for (I in E.tc) {
            H = E.tc[I];
            if (J.pageX) {
                H.mx = J.pageX - H.cx;
                H.my = J.pageY - H.cy
            } else {
                H.mx = J.clientX + (j.scrollLeft || document.body.scrollLeft) - H.cx;
                H.my = J.clientY + (j.scrollTop || document.body.scrollTop) - H.cy
            }
        }
    }
    function c(I) {
        var j = E,
            i = document.addEventListener ? 0 : 1,
            H = I.target && I.target.id != undefined ? I.target.id : I.srcElement.parentNode.id;
        if (H && I.button == i && j.tc[H]) {
            g(I);
            j.tc[H].Clicked(I)
        }
    }
    function t() {
        var H = E.tc,
            j;
        for (j in H) {
            H[j].Draw()
        }
    }
    function r(I) {
        var H, j, i;
        H = document.getElementById(I);
        j = {
            x: H.offsetLeft,
            y: H.offsetTop
        };
        while (H.offsetParent) {
            i = H.offsetParent;
            j.x += i.offsetLeft;
            j.y += i.offsetTop;
            H = i
        }
        return j
    }
    function f(H, i) {
        var j = a(i),
            I = b(i);
        return {
            x: H.x,
            y: (H.y * I) + (H.z * j),
            z: (H.y * -j) + (H.z * I)
        }
    }
    function e(H, i) {
        var j = a(i),
            I = b(i);
        return {
            x: (H.x * I) + (H.z * -j),
            y: H.y,
            z: (H.x * j) + (H.z * I)
        }
    }
    function A(I, O, N, L, J, j) {
        var i, K, M, H = I.z1 / (I.z1 + I.z2 + O.z);
        i = O.y * H;
        K = O.x * H;
        M = I.z2 + O.z;
        return {
            x: K,
            y: i,
            z: M
        }
    }
    function F(i) {
        this.ts = new Date().valueOf();
        this.tc = i;
        this.x = this.y = this.w = this.h = this.sc = 1;
        this.z = 0
    }
    F.prototype.Update = function (i, L, j, H, K, I) {
        var J = this.tc.outlineOffset;
        this.x = K * (i - J);
        this.y = K * (L - J);
        this.w = K * (j + J * 2);
        this.h = K * (H + J * 2);
        this.sc = K;
        this.z = I.z
    };
    F.prototype.Draw = function (H) {
        var j = new Date().valueOf() - this.ts,
            i = this.tc;
        H.setTransform(1, 0, 0, 1, 0, 0);
        H.strokeStyle = i.outlineColour;
        H.lineWidth = i.outlineThickness;
        H.shadowBlur = H.shadowOffsetX = H.shadowOffsetY = 0;
        
        if (i.pulsateTo < 1) {
            H.globalAlpha = i.pulsateTo + ((1 - i.pulsateTo) * (0.5 + (b(2 * Math.PI * j / (1000 * i.pulsateTime)) / 2)))
        } else {
            H.globalAlpha = 1
        }
        
        H.strokeRect(this.x , this.y + this.h - 5, this.w, 0)
        
        //this.ctxt = P.getContext("2d");
        //H.strokeRect(this.x -20, this.y, this.w, this.h)
        //H.lineTo(0,100);
        //I.quadraticCurveTo(this.x, this.y, this.w, this.h)
        
        /*
          H.beginPath();
    H.moveTo(this.x,this.Y);
    //H.quadraticCurveTo(25,25,25,62.5);
    H.quadraticCurveTo(25,100,50,100);
    H.quadraticCurveTo(50,120,30,125);
    H.quadraticCurveTo(60,120,65,100);
    H.quadraticCurveTo(125,100,125,62.5);
    H.quadraticCurveTo(125,25,75,25);
    H.stroke();
     */   
    };
    F.prototype.Active = function (H, i, j) {
        return (i >= this.x && j >= this.y && i <= this.x + this.w && j <= this.y + this.h)
    };

    function k(j, K, I, J, H, M) {
        var N = j.ctxt,
            L;
        this.tc = j;
        this.image = K.src ? K : null;
        this.name = K.src ? "" : K;
        this.a = I;
        this.p3d = {
            x: J[0] * j.radius * 1.1,
            y: J[1] * j.radius * 1.1,
            z: J[2] * j.radius * 1.1
        };
        this.x = this.y = 0;
        this.w = H;
        this.h = M;
        this.colour = j.textColour;
        this.weight = this.sc = this.alpha = 1;
        this.weighted = !j.weight;
        this.outline = new F(j);
        if (this.image) {
            if (j.txtOpt && (j.shadowBlur || j.shadowOffset[0] || j.shadowOffset[1])) {
                L = m(this.image, j.shadow, j.shadowBlur, j.shadowOffset);
                if (L) {
                    this.image = L;
                    this.w = L.width;
                    this.h = L.height
                }
            }
        } else {
            this.textHeight = j.textHeight;
            this.extents = d(this.name, j.textFont, this.textHeight);
            this.Measure(N, j)
        }
        this.SetShadowColour = j.shadowAlpha ? this.SetShadowColourAlpha : this.SetShadowColourFixed;
        this.Draw = this.image ? this.DrawImage : this.DrawText
    }
    k.prototype.Measure = function (j, i) {
        this.h = this.extents ? this.extents.max.y + this.extents.min.y : this.textHeight;
        j.font = this.font = this.textHeight + "px " + i.textFont;
        this.w1 = j.measureText(this.name).width;
        if (i.txtOpt) {
            this.image = l(this.name, this.font, this.textHeight, this.w1, this.h, this.colour, i.shadow, i.shadowBlur, i.shadowOffset);
            if (this.image) {
                this.Draw = this.DrawImage
            } else {
                i.txtOpt = false
            }
        }
    };
    k.prototype.SetWeight = function (i) {
        this.weight = i;
        this.Weight(this.tc.ctxt, this.tc);
        this.Measure(this.tc.ctxt, this.tc)
    };
    k.prototype.Weight = function (I, H) {
        var j = this.weight,
            i = H.weightMode;
        this.weighted = true;
        if (i === "colour" || i === "both") {
            this.colour = s(H, (j - H.min_weight) / (H.max_weight - H.min_weight))
        }
        if (i === "size" || i === "both") {
            this.textHeight = j * H.weightSize
        }
        this.extents = d(this.name, H.textFont, this.textHeight)
    };
    k.prototype.SetShadowColourFixed = function (H, j, i) {
        H.shadowColor = j
    };
    k.prototype.SetShadowColourAlpha = function (H, j, i) {
        H.shadowColor = z(j, i)
    };
    k.prototype.DrawText = function (I, M, H) {
        var N = this.tc,
            K = this.x,
            J = this.y,
            L, j, O = this.sc,
            i = this.outline;
        I.globalAlpha = this.alpha;
        I.setTransform(O, 0, 0, O, 0, 0);
        I.fillStyle = this.colour;
        this.SetShadowColour(I, N.shadow, this.alpha);
        I.font = this.font;
        L = this.w1 * O;
        j = this.h * O;
        K += 1 + (M / O) - (L / 2);
        J += 1 + (H / O) - (j / 2);
        I.fillText(this.name, K, J);
        i.Update(K, J, this.w1, this.h, O, this.p3d);
        return i.Active(I, N.mx, N.my) ? i : null
    };
    k.prototype.DrawImage = function (K, O, J) {
        var P = this.tc,
            M = this.x,
            L = this.y,
            N, I, Q = this.sc,
            j = this.outline,
            H = this.image;
        K.globalAlpha = this.alpha;
        K.setTransform(Q, 0, 0, Q, 0, 0);
        K.fillStyle = this.colour;
        P.shadow && this.SetShadowColour(K, P.shadow, this.alpha);
        N = H.width;
        I = H.height;
        M += (O / Q) - (N / 2);
        L += (J / Q) - (I / 2);
        K.drawImage(H, M, L, N, I);
        j.Update(M, L, N, I, Q, this.p3d);
        return j.Active(K, P.mx, P.my) ? j : null
    };
    k.prototype.Calc = function (J, I) {
        var i = e(this.p3d, J),
            j = this.tc,
            K = j.minBrightness,
            H = j.radius;
        this.p3d = f(i, I);
        i = A(j, this.p3d, this.w, this.h, Math.PI / 4, 20);
        this.x = i.x;
        this.y = i.y;
        this.sc = (j.z1 + j.z2 - i.z) / j.z2;
        this.alpha = Math.max(K, Math.min(1, K + 1 - ((i.z - j.z2 + H) / (2 * H))))
    };
    k.prototype.Clicked = function (J) {
        var j = this.a,
            H = j.target,
            I = j.href,
            i;
        if (H != "" && H != "_self") {
            if (self.frames[H]) {
                self.frames[H] = I
            } else {
                if (top.frames[H]) {
                    top.frames[H] = I
                } else {
                    window.open(I, H)
                }
            }
            return
        }
        if (j.fireEvent) {
            if (!j.fireEvent("onclick")) {
                return
            }
        } else {
            i = document.createEvent("MouseEvents");
            i.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            if (!j.dispatchEvent(i)) {
                return
            }
        }
        document.location = I
    };

    function E(N, j, I) {
        var L, J, U, K, H, Q, T, V, P = document.getElementById(N),
            O = ["id", "class", "innerHTML"],
            S, R = [];
        if (!P) {
            throw 0
        }
        if (typeof (window.G_vmlCanvasManager) != "undefined") {
            P = window.G_vmlCanvasManager.initElement(P)
        }
        if (P && (!P.getContext || !P.getContext("2d").fillText)) {
            H = document.createElement("DIV");
            for (L = 0; L < O.length; ++L) {
                H[O[L]] = P[O[L]]
            }
            P.parentNode.insertBefore(H, P);
            P.parentNode.removeChild(P);
            throw 0
        }
        for (L in E.options) {
            this[L] = I && typeof (I[L]) != "undefined" ? I[L] : (typeof (E[L]) != "undefined" ? E[L] : E.options[L])
        }
        this.canvas = P;
        this.ctxt = P.getContext("2d");
        this.z1 = (19800 / (Math.exp(this.depth) * (1 - 1 / Math.E))) + 20000 - 19800 / (1 - (1 / Math.E));
        this.z2 = this.z1 * (1 / this.zoom);
        this.radius = (P.height > P.width ? P.width : P.height) * 0.33 * (this.z2 + this.z1) / (this.z1);
        this.max_weight = 0;
        this.min_weight = 200;
        this.textFont = y(this.textFont);
        this.ctxt.shadowColor = this.shadow;
        this.shadow = this.ctxt.shadowColor;
        this.shadowAlpha = (this.shadowBlur || this.shadowOffset[0] || this.shadowOffset[1]) && h();
        try {
            J = document.getElementById(j || N);
            U = J.getElementsByTagName("a");
            this.taglist = [];
            if (U.length) {
                K = G(U.length);
                for (L = 0; L < U.length; ++L) {
                    Q = U[L].getElementsByTagName("img");
                    if (Q.length) {
                        T = new Image;
                        T.src = Q[0].src;
                        V = new k(this, T, U[L], K[L], 1, 1);
                        w(T, V, this.taglist)
                    } else {
                        this.taglist.push(new k(this, U[L].innerText || U[L].textContent, U[L], K[L], 2, this.textHeight + 2))
                    }
                    if (this.weight) {
                        S = u(this, U[L]);
                        if (S > this.max_weight) {
                            this.max_weight = S
                        }
                        if (S < this.min_weight) {
                            this.min_weight = S
                        }
                        R.push(S)
                    }
                }
                if (this.weight = (this.max_weight > this.min_weight)) {
                    for (L = 0; L < this.taglist.length; ++L) {
                        this.taglist[L].SetWeight(R[L])
                    }
                }
            }
            if (j && this.hideTags) {
                J.style.display = "none"
            }
        } catch (M) {
            M
        }
        this.yaw = this.initial ? this.initial[0] * this.maxSpeed : 0;
        this.pitch = this.initial ? this.initial[1] * this.maxSpeed : 0;
        H = r(P.id);
        this.cx = H.x;
        this.cy = H.y;
        if (!E.started) {
            C("mousemove", g, null);
            C("mouseout", g, null);
            C("mouseup", c, null);
            E.started = setInterval(t, this.interval)
        }
    }
    E.prototype.Draw = function () {
        var I = this.canvas,
            M = 0,
            J, L, N = this.ctxt,
            H, K, j = this.taglist.length;
        N.setTransform(1, 0, 0, 1, 0, 0);
        J = I.width / 2;
        L = I.height / 2;
        this.active = null;
        for (K = 0; K < j; ++K) {
            this.taglist[K].Calc(this.yaw, this.pitch)
        }
        this.taglist = this.taglist.sort(function (O, i) {
            return O.sc - i.sc
        });
        N.textBaseline = "top";
        if (!this.txtOpt && (this.shadowBlur || this.shadowOffset[0] || this.shadowOffset[1])) {
            N.shadowBlur = this.shadowBlur;
            N.shadowOffsetX = this.shadowOffset[0];
            N.shadowOffsetY = this.shadowOffset[1]
        }
        N.clearRect(0, 0, I.width, I.height);
        for (K = 0; K < j; ++K) {
            H = this.taglist[K].Draw(N, J, L);
            if (H && H.sc > M && (!this.frontSelect || H.z <= 0)) {
                this.active = H;
                this.active.index = K;
                M = H.sc
            }
        }
        if (this.freezeActive && this.active) {
            this.yaw = this.pitch = 0
        } else {
            this.Animate(I.width, I.height)
        }
        if (this.active) {
            this.active.Draw(N)
        }
    };
    E.prototype.Animate = function (L, I) {
        var j = this,
            K = j.mx,
            J = j.my,
            N, M, H, i;
        if (K >= 0 && J >= 0 && K < L && J < I) {
            N = j.maxSpeed, i = j.reverse ? -1 : 1;
            this.yaw = i * ((N * 2 * K / L) - N);
            this.pitch = i * -((N * 2 * J / I) - N);
            this.initial = null
        } else {
            if (!j.initial) {
                N = j.minSpeed, M = x(j.yaw), H = x(j.pitch);
                if (M > N) {
                    this.yaw = M > j.z0 ? j.yaw * j.decel : 0
                }
                if (H > N) {
                    this.pitch = H > j.z0 ? j.pitch * j.decel : 0
                }
            }
        }
    };
    E.prototype.Clicked = function (I) {
        var H = this.taglist,
            i = this.active;
        try {
            if (i && H[i.index]) {
                H[i.index].Clicked(I)
            }
        } catch (j) {}
    };
    E.Start = function (H, i, j) {
        E.tc[H] = new E(H, i, j)
    };
    E.tc = {};
    E.options = {
        z1: 20000,
        z2: 20000,
        z0: 0.0002,
        freezeActive: false,
        pulsateTo: 0.15,
        pulsateTime: 3,
        reverse: false,
        depth: 0.5,
        maxSpeed: 0.05,
        minSpeed: 0,
        decel: 0.95,
        interval: 20,
        minBrightness: 0.1,
        outlineColour: "#ffff99",
        outlineThickness: 2,
        outlineOffset: 5,
        textColour: "#ff99ff",
        textHeight: 15,
        textFont: "Helvetica, Arial, sans-serif",
        shadow: "#000",
        shadowBlur: 0,
        shadowOffset: [0, 0],
        initial: null,
        hideTags: true,
        zoom: 1,
        weight: false,
        weightMode: "size",
        weightFrom: null,
        weightSize: 1,
        weightGradient: {
            0: "#f00",
            0.33: "#ff0",
            0.66: "#0f0",
            1: "#00f"
        },
        txtOpt: true,
        frontSelect: false
    };
    for (D in E.options) {
        E[D] = E.options[D]
    }
    window.TagCanvas = E
})();
