//  Prototip 1.3.5.1 - 18-05-2008
//  Copyright (c) 2008 Nick Stakenburg (http://www.nickstakenburg.com)
//
//  Licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License
//  http://creativecommons.org/licenses/by-nc-nd/3.0/

//  More information on this project:
//  http://www.nickstakenburg.com/projects/prototip/

var Prototip = {
  Version: '1.3.5.1'
};

var Tips = {
  options: {
    className: 'default',      // default class for all tips
	closeButtons: false,       // true | false
	zIndex: 6000               // raise if required
  }
};
Object.extend(Prototip, {
    REQUIRED_Prototype: "1.6.0.2",
    REQUIRED_Scriptaculous: "1.8.1",
    start: function() {
        this.require("Prototype");
        Tips.initialize();
        Element.observe(window, "unload", this.unload)
    },
    require: function(A) {
        if ((typeof window[A] == "undefined") || (this.convertVersionString(window[A].Version) < this.convertVersionString(this["REQUIRED_" + A]))) {
            throw ("Lightview requires " + A + " >= " + this["REQUIRED_" + A]);
        }
    },
    convertVersionString: function(A) {
        var B = A.replace(/_.*|\./g, "");
        B = parseInt(B + "0".times(4 - B.length));
        return A.indexOf("_") > -1 ? B - 1 : B
    },
    capture: function(A) {
        if (!Prototype.Browser.IE) {
            A = A.wrap(function(E, D) {
                var C = Object.isElement(this) ? this: this.element,
                B = D.relatedTarget;
                if (B != C && !$A(C.select("*")).member(B)) {
                    E(D)
                }
            })
        }
        return A
    },
    getHiddenDimensions: function(B) {
        B = $(B);
        var A = B.ancestors(),
        C = [],
        E = [];
        A.push(B);
        A.each(function(F) {
            if (F != B && F.visible()) {
                return
            }
            C.push(F);
            E.push({
                display: F.getStyle("display"),
                position: F.getStyle("position"),
                visibility: F.getStyle("visibility")
            });
            F.setStyle({
                display: "block",
                position: "absolute",
                visibility: "visible"
            })
        });
        var D = {
            width: B.clientWidth,
            height: B.clientHeight
        };
        C.each(function(G, F) {
            G.setStyle(E[F])
        });
        return D
    },
    unload: function() {
        Tips.removeAll()
    }
});
Object.extend(Tips, {
    tips: [],
    visible: [],
    initialize: function() {
        this.zIndexTop = this.zIndex
    },
    useEvent: (function(A) {
        return {
            mouseover: (A ? "mouseenter": "mouseover"),
            mouseout: (A ? "mouseout": "mouseout"),
            mouseenter: (A ? "mouseenter": "mouseover"),
            mouseout: (A ? "mouseout": "mouseout")
        }
    })(Prototype.Browser.IE),
    fixIE: (function(B) {
        var A = new RegExp("MSIE ([\\d.]+)").exec(B);
        return A ? (parseFloat(A[1]) < 7) : false
    })(navigator.userAgent),
    add: function(A) {
        this.tips.push(A)
    },
    remove: function(A) {
        var B = this.tips.find(function(C) {
            return C.element == $(A)
        });
        if (B) {
            B.deactivate();
            if (B.tooltip) {
                B.wrapper.remove();
                if (Tips.fixIE) {
                    B.iframeShim.remove()
                }
            }
            this.tips = this.tips.without(B)
        }
    },
    removeAll: function() {
        this.tips.each(function(A) {
            this.remove(A.element)
        }.bind(this))
    },
    raise: function(B) {
        if (B.highest) {
            return
        }
        if (this.visible.length == 0) {
            this.zIndexTop = this.options.zIndex;
            for (var A = 0; A < this.tips.length; A++) {
                this.tips[A].wrapper.setStyle({
                    zIndex: this.options.zIndex
                })
            }
        }
        B.wrapper.setStyle({
            zIndex: this.zIndexTop++
        });
        if (B.loader) {
            B.loader.setStyle({
                zIndex: this.zIndexTop
            })
        }
        for (var A = 0; A < this.tips.length; A++) {
            this.tips[A].highest = false
        }
        B.highest = true
    },
    addVisibile: function(A) {
        this.removeVisible(A);
        this.visible.push(A)
    },
    removeVisible: function(A) {
        this.visible = this.visible.without(A)
    },
    hook: function(B, E) {
        B = $(B),
        E = $(E);
        var I = Object.extend({
            element: "bottomLeft",
            target: "topLeft",
            offset: {
                x: 0,
                y: 0
            }
        },
        arguments[2] || {});
        var D = E.cumulativeOffset();
        D.left += I.offset.x;
        D.top += I.offset.y;
        var C = E.cumulativeScrollOffset(),
        A = document.viewport.getScrollOffsets();
        D.left += ( - 1 * (C[0] - A[0]));
        D.top += ( - 1 * (C[1] - A[1]));
        var G = {
            element: Prototip.getHiddenDimensions(B),
            target: Prototip.getHiddenDimensions(E)
        },
        H = {
            element: Object.clone(D),
            target: Object.clone(D)
        };
        for (var F in H) {
            switch (I[F]) {
            case "topRight":
                H[F][0] += G[F].width;
                break;
            case "topMiddle":
                H[F][0] += (G[F].width / 2);
                break;
            case "rightMiddle":
                H[F][0] += G[F].width;
                H[F][1] += (G[F].height / 2);
                break;
            case "bottomLeft":
                H[F][1] += G[F].height;
                break;
            case "bottomRight":
                H[F][0] += G[F].width;
                H[F][1] += G[F].height;
                break;
            case "bottomMiddle":
                H[F][0] += (G[F].width / 2);
                H[F][1] += G[F].height;
                break;
            case "leftMiddle":
                H[F][1] += (G[F].height / 2);
                break
            }
        }
        D.left += -1 * (H.element[0] - H.target[0]);
        D.top += -1 * (H.element[1] - H.target[1]);
        B.setStyle({
            left: D.left + "px",
            top: D.top + "px"
        })
    }
});
Tips.initialize();
var Tip = Class.create({
    initialize: function(C, D) {
        this.element = $(C);
        Tips.remove(this.element);
        var A = (Object.isString(D) || Object.isElement(D)),
        B = A ? arguments[2] || [] : D;
        this.content = A ? D: null;
        this.options = Object.extend({
            ajax: false,
            className: Tips.options.className,
            closeButton: Tips.options.closeButtons,
            delay: !(B.showOn && B.showOn == "click") ? 0.12 : false,
            duration: 0.3,
            effect: false,
            hideAfter: false,
            hideOn: "mouseout",
            hook: B.hook,
            offset: B.hook ? {
                x: 0,
                y: 0
            }: {
                x: 16,
                y: 16
            },
            fixed: B.hook ? true: false,
            showOn: "mousemove",
            target: this.element,
            title: false,
            viewport: B.hook ? false: true
        },
        B);
        this.target = $(this.options.target);
        if (this.options.ajax) {
            this.options.ajax.options = Object.extend({
                onComplete: Prototype.emptyFunction
            },
            this.options.ajax.options || {})
        }
        this.setup();
        if (this.options.effect) {
            Prototip.require("Scriptaculous");
            this.queue = {
                position: "end",
                limit: 1,
                scope: this.wrapper.identify()
            }
        }
        Tips.add(this);
        this.activate()
    },
    setup: function() {
        this.wrapper = new Element("div", {
            className: "prototip"
        }).setStyle({
            display: "none",
            zIndex: Tips.options.zIndex
        });
        this.wrapper.identify();
        if (Tips.fixIE) {
            this.iframeShim = new Element("iframe", {
                className: "iframeShim",
                src: "javascript:false;",
                frameBorder: 0
            }).setStyle({
                display: "none",
                zIndex: Tips.options.zIndex - 1,
                opacity: 0
            })
        }
        if (this.options.ajax) {
            this.showDelayed = this.showDelayed.wrap(this.ajaxShow)
        }
        this.tip = new Element("div", {
            className: "content"
        });
        this.title = new Element("div", {
            className: "title"
        }).hide();
        if (this.options.closeButton || (this.options.hideOn.element && this.options.hideOn.element == "closeButton")) {
            this.closeButton = new Element("a", {
                href: "#",
                className: "close"
            })
        }
    },
    build: function() {
        if (Tips.fixIE) {
            $(document.body).insert(this.iframeShim)
        }
        if (this.options.ajax) {
            $(document.body).insert(this.loader = new Element("div", {
                className: "prototipLoader"
            }).hide())
        }
        var A = "wrapper";
        if (this.options.effect) {
            A = "effectWrapper";
            this.wrapper.insert(this.effectWrapper = new Element("div", {
                className: "effectWrapper"
            }))
        }
        this[A].insert(this.tooltip = new Element("div", {
            className: "tooltip " + this.options.className
        }).insert(this.toolbar = new Element("div", {
            className: "toolbar"
        }).insert(this.title)));
        this.tooltip.insert(this.tip).insert(new Element("div").setStyle("clear:both"));
        $(document.body).insert(this.wrapper);
        if (!this.options.ajax) {
            this.update({
                title: this.options.title,
                content: this.content
            })
        }
    },
    update: function(E) {
        var A = this.tooltip.getStyle("visibility"),
        B = this.wrapper.setStyle("height:auto;width:auto;").getStyle("visibility");
        [this.tooltip, this.wrapper].invoke("setStyle", "visibility:hidden;");
        this.toolbar.setStyle("width: auto;");
        if (this.options.effect) {
            this.effectWrapper.setStyle("height:auto;width:auto;")
        }
        if (E.title) {
            this.title.show().update(E.title);
            this.toolbar.show()
        } else {
            if (!this.closeButton) {
                this.title.hide();
                this.toolbar.hide()
            }
        }
        if (Object.isString(E.content) || Object.isElement(E.content)) {
            this.tip.update(E.content).insert(new Element("div").setStyle("clear:both;"))
        }
        var C = {
            width: Prototip.getHiddenDimensions(this.wrapper).width + "px"
        },
        D = [this.wrapper];
        if (this.options.effect) {
            D.push(this.effectWrapper)
        }
        if (Tips.fixIE) {
            D.push(this.iframeShim)
        }
        if (this.closeButton) {
            this.title.show().insert({
                top: this.closeButton
            });
            this.toolbar.show()
        }
        this.toolbar.setStyle("width: 100%;");
        C.height = null;
        this.wrapper.setStyle({
            visibility: B
        });
        this.tooltip.setStyle({
            visibility: A
        });
        D.invoke("setStyle", C)
    },
    activate: function() {
        this.eventShow = this.showDelayed.bindAsEventListener(this);
        this.eventHide = this.hide.bindAsEventListener(this);
        if (this.options.fixed && this.options.showOn == "mousemove") {
            this.options.showOn = "mouseover"
        }
        if (this.options.showOn == this.options.hideOn) {
            this.eventToggle = this.toggle.bindAsEventListener(this);
            this.element.observe(this.options.showOn, this.eventToggle)
        }
        var C = {
            element: this.eventToggle ? [] : [this.element],
            target: this.eventToggle ? [] : [this.target],
            tip: this.eventToggle ? [] : [this.wrapper],
            closeButton: [],
            none: []
        };
        var A = this.options.hideOn.element;
        this.hideElement = A || (!this.options.hideOn ? "none": "element");
        this.hideTargets = C[this.hideElement];
        if (!this.hideTargets && A && Object.isString(A)) {
            this.hideTargets = this.tip.select(A)
        }
        var D = {
            mouseenter: "mouseover",
            mouseout: "mouseout"
        };
        $w("show hide").each(function(H) {
            var G = H.capitalize(),
            F = (this.options[H + "On"].event || this.options[H + "On"]);
            this[H + "Action"] = F;
            if (["mouseenter", "mouseout", "mouseover", "mouseout"].include(F)) {
                this[H + "Action"] = (Tips.useEvent[F] || F);
                this["event" + G] = Prototip.capture(this["event" + G])
            }
        }.bind(this));
        if (!this.eventToggle) {
        if(this.element) {
            this.element.observe(this.options.showOn, this.eventShow)
            }
        }
        if (this.hideTargets) {
            this.hideTargets.invoke("observe", this.hideAction, this.eventHide)
        }
        if (!this.options.fixed && this.options.showOn == "click") {
            this.eventPosition = this.position.bindAsEventListener(this);
            this.element.observe("mousemove", this.eventPosition)
        }
        this.buttonEvent = this.hide.wrap(function(G, F) {
            var E = F.findElement(".close");
            if (E) {
                F.stop();
                E.blur();
                G(F)
            }
        }).bindAsEventListener(this);
        if (this.closeButton) {
            this.wrapper.observe("click", this.buttonEvent)
        }
        if (this.options.showOn != "click" && (this.hideElement != "element")) {
            this.eventCheckDelay = Prototip.capture(function() {
                this.clearTimer("show")
            }).bindAsEventListener(this);
            this.element.observe(Tips.useEvent.mouseout, this.eventCheckDelay)
        }
        var B = [this.element, this.wrapper];
        this.activityEnter = Prototip.capture(function() {
            Tips.raise(this);
            this.cancelHideAfter()
        }).bindAsEventListener(this);
        this.activityLeave = Prototip.capture(this.hideAfter).bindAsEventListener(this);
        B.invoke("observe", Tips.useEvent.mouseover, this.activityEnter).invoke("observe", Tips.useEvent.mouseout, this.activityLeave);
        if (this.options.ajax && this.options.showOn != "click") {
            this.ajaxHideEvent = Prototip.capture(this.ajaxHide).bindAsEventListener(this);
            this.element.observe(Tips.useEvent.mouseout, this.ajaxHideEvent)
        }
    },
    deactivate: function() {
        if (this.options.showOn == this.options.hideOn) {
        if(this.element) {
            this.element.stopObserving(this.options.showOn, this.eventToggle)
            }
        } else {
            this.element.stopObserving(this.options.showOn, this.eventShow);
            if (this.hideTargets) {
                this.hideTargets.invoke("stopObserving")
            }
        }
        if (this.eventPosition) {
            this.element.stopObserving("mousemove", this.eventPosition)
        }
        if (this.eventCheckDelay) {
            this.element.stopObserving("mouseout", this.eventCheckDelay)
        }
        this.wrapper.stopObserving();
        this.element.stopObserving(Tips.useEvent.mouseover, this.activityEnter).stopObserving(Tips.useEvent.mouseout, this.activityLeave);
        if (this.ajaxHideEvent) {
            this.element.stopObserving(Tips.useEvent.mouseout, this.ajaxHideEvent)
        }
    },
    ajaxShow: function(C, B) {
        if (!this.tooltip) {
            this.build()
        }
        this.position(B);
        if (this.ajaxContentLoaded) {
            C(B);
            return
        } else {
            if (this.ajaxContentLoading) {
                return
            }
        }
        var D = {
            ajaxPointer: {
                pointerX: Event.pointerX(B),
                pointerY: Event.pointerY(B)
            }
        };
        var A = Object.clone(this.options.ajax.options);
        A.onComplete = A.onComplete.wrap(function(F, E) {
            this.update({
                title: this.options.title,
                content: E.responseText
            });
            this.position(D);
            if (this.loader && !this.loader.visible()) {
                this.ajaxContentLoaded = true;
                this.ajaxContentLoading = false;
                return
            } (function() {
                F(E);
                if (this.loader && this.loader.visible()) {
                    this.show()
                }
                this.clearTimer("loader");
                this.loader.remove();
                this.ajaxContentLoaded = true;
                this.ajaxContentLoading = false
            }.bind(this)).delay(0.3)
        }.bind(this));
        this.loaderTimer = Element.show.delay(this.options.delay, this.loader);
        this.wrapper.hide();
        this.ajaxContentLoading = true;
        (function() {
            this.ajaxTimer = new Ajax.Request(this.options.ajax.url, A)
        }.bind(this)).delay(this.options.delay)
    },
    ajaxHide: function() {
        this.clearTimer("loader")
    },
    showDelayed: function(A) {
        if (!this.tooltip) {
            this.build()
        }
        if (!this.options.ajax) {
            this.position(A)
        }
        if (this.wrapper.visible()) {
            return
        }
        this.clearTimer("show");
        this.showTimer = this.show.bind(this).delay(this.options.delay)
    },
    clearTimer: function(A) {
        if (this[A + "Timer"]) {
            clearTimeout(this[A + "Timer"])
        }
    },
    show: function() {
        if (this.wrapper.visible() && this.options.effect != "appear") {
            return
        }
        if (Tips.fixIE) {
            this.iframeShim.show()
        }
        Tips.addVisibile(this.wrapper);
        if (this.options.effect) {
            this.effectWrapper.setStyle({
                height: Prototip.getHiddenDimensions(this.effectWrapper).height + "px"
            });
            this.tooltip.hide();
            this.effectWrapper.hide();
            this.wrapper.show();
            if (this.activeEffect) {
                Effect.Queues.get(this.queue.scope).remove(this.activeEffect)
            }
            this.activeEffect = Effect[Effect.PAIRS[this.options.effect][0]](this.effectWrapper, {
                beforeStart: Element.show.curry(this.tooltip),
                duration: this.options.duration,
                queue: this.queue,
                afterFinish: function() {
                    this.effectWrapper.setStyle({
                        height: "auto"
                    });
                    this.element.fire("prototip:shown")
                }.bind(this)
            })
        } else {
            this.tooltip.show();
            this.wrapper.show();
            this.element.fire("prototip:shown")
        }
    },
    hideAfter: function(A) {
        if (this.options.ajax) {
            if (this.loader && this.options.showOn != "click") {
                this.loader.hide()
            }
            this.clearTimer("ajax");
            this.ajaxContentLoading = null
        }
        if (!this.options.hideAfter) {
            return
        }
        this.cancelHideAfter();
        this.hideAfterTimer = this.hide.bind(this).delay(this.options.hideAfter)
    },
    cancelHideAfter: function() {
        if (this.options.hideAfter) {
            this.clearTimer("hideAfter")
        }
    },
    hide: function() {
        this.clearTimer("show");
        this.clearTimer("loader");
        if (!this.wrapper.visible()) {
            return
        }
        if (this.options.effect) {
            if (this.activeEffect) {
                Effect.Queues.get(this.queue.scope).remove(this.activeEffect)
            }
            this.activeEffect = Effect[Effect.PAIRS[this.options.effect][1]](this.effectWrapper, {
                duration: this.options.duration,
                queue: this.queue,
                afterFinish: this.afterHide.bind(this)
            })
        } else {
            this.afterHide()
        }
    },
    afterHide: function() {
        if (Tips.fixIE) {
            this.iframeShim.hide()
        }
        if (this.loader) {
            this.loader.hide()
        }
        this.wrapper.hide();
        Tips.removeVisible(this.wrapper);
        this.element.fire("prototip:hidden")
    },
    toggle: function(A) {
        if (this.wrapper && this.wrapper.visible()) {
            this.hide(A)
        } else {
            this.showDelayed(A)
        }
    },
    position: function(A) {
        Tips.raise(this);
        if (this.options.effect) {
            var D = this.effectWrapper.getStyle("visibility"),
            E = this.effectWrapper.getStyle("display");
            this.effectWrapper.setStyle({
                visibility: "visible"
            }).show()
        }
        if (this.options.hook) {
            var L = Object.extend({
                offset: this.options.offset
            },
            {
                element: this.options.hook.tip,
                target: this.options.hook.target
            });
            Tips.hook(this.wrapper, this.target, L);
            if (this.loader) {
                Tips.hook(this.loader, this.target, L)
            }
            if (Tips.fixIE) {
                Tips.hook(this.iframeShim, this.target, L)
            }
        } else {
            var G = this.target.cumulativeOffset(),
            K = Prototip.getHiddenDimensions(this.wrapper),
            C = A.ajaxPointer || {},
            H = {
                left: ((this.options.fixed) ? G[0] : C.pointerX || Event.pointerX(A)) + this.options.offset.x,
                top: ((this.options.fixed) ? G[1] : C.pointerY || Event.pointerY(A)) + this.options.offset.y
            };
            if (!this.options.fixed && this.element !== this.target) {
                var B = this.element.cumulativeOffset();
                H.left += -1 * (B[0] - G[0]);
                H.top += -1 * (B[1] - G[1])
            }
            if (!this.options.fixed && this.options.viewport) {
                var M = document.viewport.getScrollOffsets(),
                I = document.viewport.getDimensions(),
                F = {
                    left: "width",
                    top: "height"
                };
                for (var J in F) {
                    if ((H[J] + K[F[J]] - M[J]) > I[F[J]]) {
                        H[J] = H[J] - K[F[J]] - 2 * this.options.offset[J == "top" ? "x": "y"]
                    }
                }
            }
            H = {
                left: H.left + "px",
                top: H.top + "px"
            };
            this.wrapper.setStyle(H);
            if (this.loader) {
                this.loader.setStyle(H)
            }
            if (Tips.fixIE) {
                this.iframeShim.setStyle(H)
            }
        }
        if (this.options.effect) {
            this.effectWrapper.setStyle({
                visibility: D,
                display: E
            })
        }
    }
});
Prototip.start();
