/*\
 JS-Cumulus - WP-Cumulus in JavaScript (codenamed jscumulus)
 Based on Stratus plugin by Dawid Fatyga (fatyga@student.agh.edu.pl)
 Based on WP-Cumulus by Roy Tanck (http://www.roytanck.com)
 @author Jeroen van Warmerdam (aka jerone or jeronevw) (http://www.jeroenvanwarmerdam.nl)
 @date 05-02-2010 13:00:00
 @version 0.2
 Copyright 2010, Jeroen van Warmerdam
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 \*/
(function(a, v){
    var m = {
        ID: "tagCloud",
        Class: "tagCloud",
        Width: 400,
        Heigth: 400,
        Consistent: true,
        Rank: 30,
        Url: "#",
        FontMin: 10,
        FontMax: 24,
        Depth: 150,
        AnimationTime: 1,
        HoverStop: true,
        OverWrite: false
    };
    var e = a, j = e.document, k = e.TagCloud, i = e.Tag, t = e.Vector, g = e.Surface, h = 1, f = Object.prototype.toString, d = "[object Object]", o = function(z){
        return f.call(z) === d
    }, c = function(z){
        return !!z.nodeType
    }, y = Math.PI / 180, q = [], l = [], x = (function(){
        var A = 0, z = 3600;
        while (A < z) {
            q[A] = Math.sin(A / 10 * y);
            A++
        }
        return function B(C){
            while (C < 0) {
                C += 360
            }
            return q[Math.round(C * 10) % z]
        }
    })(), n = (function(){
        var A = 0, z = 3600;
        while (A < z) {
            l[A] = Math.cos(A / 10 * y);
            A++
        }
        return function(B){
            return l[Math.round(Math.abs(B) * 10) % z]
        }
    })(), r = {
        Add: (function(){
            if (j.addEventListener) {
                return function(B, A, z){
                    z = r.Fix.call(this, A === "mouseenter" || A === "mouseleave" ? r.mouseEnter(z) : z);
                    A = A === "mouseenter" && "mouseover" || A === "mouseleave" && "mouseout" || A;
                    B.addEventListener(A, z, false);
                    return function(){
                        B.removeEventListener(A, z, false);
                        return true
                    }
                }
            }
            else {
                if (j.attachEvent) {
                    return function(B, A, z){
                        z = r.Fix.call(this, z);
                        B.attachEvent("on" + A, z);
                        return function(){
                            B.detachEvent("on" + A, z);
                            return true
                        }
                    }
                }
            }
        })(),
        Fix: function(z){
            return function(C){
                if (!C.target) {
                    C.target = C.srcElement || j
                }
                if (C.target.nodeType === 3) {
                    C.target = C.target.parentNode
                }
                if (!C.relatedTarget && C.fromElement) {
                    C.relatedTarget = C.fromElement === C.target ? C.toElement : C.fromElement
                }
                if (C.pageX == null && C.clientX != null) {
                    var B = j.documentElement, A = j.body;
                    C.pageX = C.clientX + (B && B.scrollLeft || A && A.scrollLeft || 0) - (B && B.clientLeft || A && A.clientLeft || 0);
                    C.pageY = C.clientY + (B && B.scrollTop || A && A.scrollTop || 0) - (B && B.clientTop || A && A.clientTop || 0)
                }
                z.call(this, C)
            }
        },
        mouseEnter: function(z){
            var A = function(B, C){
                if (B === C) {
                    return false
                }
                while (C && C !== B) {
                    C = C.parentNode
                }
                return C === B
            };
            return function(C){
                var B = C.relatedTarget;
                if (this === B || A(this, B)) {
                    return
                }
                z.call(this, C)
            }
        }
    };
    var p = function(A, B, C){
        this.set = function(D, E, F){
            this.x = D || 0;
            this.y = E || 0;
            this.z = F || 0
        };
        if (A !== v && o(A)) {
            this.set(A.x, A.y, A.z)
        }
        else {
            this.set(A, B, C)
        }
        this.Multiply = function(z){
            this.x *= z;
            this.y *= z;
            this.z *= z;
            return this
        };
        this.Done = function(){
            return Math.abs(this.x) > 0.01 || Math.abs(this.y) > 0.01 || Math.abs(this.z) > 0.01
        }
    };
    var w = function(A, z){
        this.set = function(C, B){
            this.width = C || 0;
            this.height = B || 0
        };
        if (A !== v && o(A)) {
            this.set(A.width, A.height)
        }
        else {
            this.set(A, z)
        }
    };
    var u = function(z, B, A){
        this.id = B;
        this.className = A;
        this.active = false;
        this.mouse = new p();
        this.position = new p();
        this.size = new w({
            width: z.size.width || m.Width / 2,
            height: z.size.height || m.Heigth / 2
        });
        this.element = j.createElement("div");
        this.element.setAttribute("id", this.id);
        this.element.setAttribute("class", this.className);
        this.element.style.width = this.size.width + "px";
        this.element.style.height = this.size.height + "px";
        this.element.style.display = "block";
        this.Update = function(){
            this.position = new p({
                x: this.element.offsetLeft,
                y: this.element.offsetTop
            });
            return this
        };
        this.Activate = function(){
            var C = this;
            r.Add(this.element, "mousemove", function(D){
                return function(E){
                    if (!z.active) {
                        z.Animate()
                    }
                    if (!(m.HoverStop && !this.active)) {
                        this.Update();
//
//						alert('E.pageX: ' + E.pageX + "\r\n" +
//									   'this.position.x: ' + this.position.x + "\r\n" +
//									   'this.size.width: ' + this.size.width + "\r\n");


//						console.log('myVar: ', findPos(this.element));
var pos = findPos(this.element);
						
                        this.mouse.set(((-E.pageY + pos[1]) * 2 / this.size.height + 1) * 4, ((E.pageX - pos[0]) * 2 / this.size.width - 1) * 4)
                    }
                }
.call(C, D)
            });
            r.Add(this.element, "mouseenter", function(){
                C.active = true
            });
            r.Add(this.element, "mouseleave", function(){
                C.active = false
            });
            return this
        };
        return this
    };
    var s = function(A, z, C){
        this.id = h++;
        this.title = A;
        this.rank = ((!isNaN(z) && z >= 0 && z <= 100) ? z : m.Rank) / 100;
        this.url = C || (isNaN(z) ? z : false) || m.Url;
        this.position = new p();
        var D = j.createElement("a"), B = j.createElement("li");
        D.setAttribute("id", "jsCumulus" + this.id);
        D.setAttribute("href", this.url);
        D.innerHTML = this.title;
        B.setAttribute("class", "tagClass");
        B.style.position = "absolute";
        B.appendChild(D);
        this.element = B;
        B = D = null;
        this.Activate = function(E){
            r.Add(this.element, "mouseenter", function(){
                E.active = false
            });
            r.Add(this.element, "mouseleave", function(){
                E.active = true
            });
            return this
        }
    };
var findPos = function(obj){
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		do {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
			
		}
		while (obj = obj.offsetParent);
		
		return [curleft, curtop];
	}
}
	
    var b = function(A, B, z, C){
        if (c(arguments[0])) {
            this.element = arguments[0];
            A = arguments[1];
            B = arguments[2];
            z = arguments[3];
            C = arguments[4]
        }
        var C = C || o(z) && z || o(B) && B || {};
        this.active = false;
        this.delta = new p(-2, -2);
        this.size = new w({
            width: parseFloat(!!parseFloat(B) && B || !!parseFloat(C.width) && C.width || m.Width),
            height: parseFloat(!!parseFloat(z) && z || !!parseFloat(C.height) && C.height || B || m.Height)
        });
        this.font = {
            min: parseFloat(C.fontMin) || m.FontMin,
            max: parseFloat(C.fontMax) || m.FontMax
        };
        this.radius = C.radius || Math.min(this.size.width, this.size.height) / 4;
        this.consistent = C.consistent !== v ? !!C.consistent : m.Consistent;
        this.overwrite = C.overwrite !== v ? !!C.overwrite : m.OverWrite;
        this.items = A && A.length && A.slice(0) || (function(){
            var E = 50, F = 0, D = [];
            for (; E >= F; --E) {
                D[E] = new s("+", 100)
            }
            return D
        })();
        this.attractor = new u(this, C.id || m.ID + Math.floor(Math.random() * 10000 + 1), C.className || m.Class);
        C = null;
        this.Distribute = function(H){
            var H = H || this.element || j.body, E = j.createElement("ul"), D = this.items.length - 1, K = 0, F;
            if (this.overwrite) {
                while (H.firstChild) {
                    H.removeChild(H.firstChild)
                }
            }
            for (; D >= K; --D) {
                F = this.items[D];
                if (F instanceof s && F.title) {
                    E.appendChild(F.element);
                    F.Activate(this.attractor)
                }
                else {
                    this.items.splice(D, 1)
                }
            }
            this.attractor.element.appendChild(E);
            H.appendChild(this.attractor.element);
            this.attractor.Activate();
            E = null;
            var J = 0, L = 0, M = this.items, D = 0, G = M.length, I = this.radius;
            for (; D < G; D++) {
                J = this.consistent ? Math.acos(-1 + (2 * D) / G) : Math.random() * (Math.PI);
                L = this.consistent ? Math.sqrt(G * Math.PI) * J : Math.random() * (2 * Math.PI);
                M[D].position.set(I * Math.sin(J) * Math.cos(L), I * Math.sin(J) * Math.sin(L), I * Math.cos(J))
            }
            J = L = M = D = G = I = null;
            this.Update();
            return this
        };
        this.Update = function(F){
            var U = this.items, G = this.attractor.Update(), F = F || new p(), Q = F.x || 0, O = F.y || 0, K = x(Q), P = n(Q), M = x(O), S = n(O), L = this.font.max - this.font.min, H = 0, I = U.length;
            this.position = new p({
                x: this.size.width / 2 + G.position.x,
                y: this.size.height / 2 + G.position.y
            });
            for (; H < I; H++) {
                var T = U[H], V = T.position, J = T.element, N = J.firstChild, W = V.x * S + (V.y * K + V.z * P) * M, D = V.y * P + V.z * (-K), E = V.x * (-M) + (V.y * K + V.z * P) * S, R = m.Depth / (m.Depth + E);
                V.set(W, D, E);
                N.style.opacity = Math.max(R - 0.7, 0) / 0.5 + 0.2;
                N.style.fontSize = T.rank * R * L + this.font.min + "px";
                J.style.left = (this.position.x + W * R) - (J.clientWidth / 2) + "px";
                J.style.top = (this.position.y + D * R) - (J.clientHeight / 2) + "px"
            }
            U = G = F = Q = O = K = P = M = S = L = H = I = null;
            return this
        };
        this.Pause = function(){
            if (this.animation) {
                this.active = false;
                e.clearInterval(this.animation);
                this.animation = null
            }
            return this
        };
        this.Stop = function(){
            this.delta = new p();
            if (this.animation) {
                this.active = false;
                e.clearInterval(this.animation);
                this.animation = null
            }
            return this
        };
        this.Animate = function(E){
            this.active = true;
            this.delta = E || this.delta || new p();
            var D = this;
            this.animation = e.setInterval(function(){
                return function(){
                    if (this.attractor.active) {
                        this.delta = this.attractor.mouse
                    }
                    else {
                        this.delta = this.delta.Multiply(0.98)
                    }
                    if (this.delta.Done()) {
                        this.Update(this.delta)
                    }
                    else {
                        this.Stop()
                    }
                }
.call(D)
            }, m.AnimationTime);
            return this
        };
        if (this.element) {
            this.Distribute(this.element)
        }
        return this
    };
    e.JSCumulus = JSCumulus = {};
    e.TagCloud = b;
    e.Tag = s;
    e.Vector = p;
    e.Surface = w;
    JSCumulus.noConflict = function(){
        e.TagCloud = k;
        e.JSCumulus.TagCloud = b;
        e.Tag = i;
        e.JSCumulus.Tag = s;
        e.Vector = t;
        e.JSCumulus.Vector = p;
        e.Surface = g;
        e.JSCumulus.Surface = w
    }
})(window);

