Fx.Elements = new Class({
    Extends: Fx.CSS,
    initialize: function (a, b) {
        this.elements = this.subject = $$(a);
        this.parent(b)
    },
    compute: function (a, b, d) {
        var c = {};
        for (var g in a) {
            var i = a[g],
                e = b[g],
                h = c[g] = {};
            for (var f in i) h[f] = this.parent(i[f], e[f], d)
        }
        return c
    },
    set: function (a) {
        for (var b in a) {
            var d = a[b];
            for (var c in d) this.render(this.elements[b], c, d[c], this.options.unit)
        }
        return this
    },
    start: function (a) {
        if (!this.check(a)) return this;
        var b = {},
            d = {};
        for (var c in a) {
            var g = a[c],
                i = b[c] = {},
                e = d[c] = {};
            for (var h in g) {
                var f =
                this.prepare(this.elements[c], h, g[h]);
                i[h] = f.from;
                e[h] = f.to
            }
        }
        return this.parent(b, d)
    }
});
var Loop = new Class({
    loopCount: 0,
    isStopped: true,
    isLooping: false,
    loopMethod: $empty,
    setLoop: function (a, b) {
        if (this.isLooping) {
            this.stopLoop();
            var d = true
        } else d = false;
        this.loopMethod = a;
        this.loopDelay = b || 3E3;
        d && this.startLoop();
        return this
    },
    stopLoop: function () {
        this.isStopped = true;
        this.isLooping = false;
        $clear(this.periodical);
        return this
    },
    startLoop: function (a) {
        if (this.isStopped) {
            a = a ? a : this.loopDelay;
            this.isStopped = false;
            this.isLooping = true;
            this.periodical = this.looper.periodical(a, this)
        }
        return this
    },
    resetLoop: function () {
        this.loopCount =
        0;
        return this
    },
    looper: function () {
        this.loopCount++;
        this.loopMethod(this.loopCount);
        return this
    }
}),
    SlideShow = new Class({
        Implements: [Options, Events, Loop],
        options: {
            delay: 7E3,
            transition: "crossFade",
            duration: "500",
            autoplay: false
        },
        initialize: function (a, b) {
            this.setOptions(b);
            this.setLoop(this.showNext, this.options.delay);
            this.element = document.id(a);
            this.slides = this.element.getChildren();
            this.current = this.slides[0];
            this.transitioning = false;
            this.setup();
            this.options.autoplay && this.play()
        },
        setup: function () {
            this.setupElement().setupSlides(true);
            return this
        },
        setupElement: function () {
            var a = this.element;
            a.getStyle("position") != "absolute" && a != document.body && a.setStyle("position", "relative");
            return this
        },
        setupSlides: function (a) {
            this.slides.each(function (b, d) {
                this.storeTransition(b).reset(b);
                a && d != 0 && b.setStyle("display", "none")
            }, this);
            return this
        },
        storeTransition: function (a) {
            var b = a.get("class"),
                d = /transition:[a-zA-Z]+/,
                c = /duration:[0-9]+/;
            d = b.match(d) ? b.match(d)[0].split(":")[1] : this.options.transition;
            b = b.match(c) ? b.match(c)[0].split(":")[1] : this.options.duration;
            a.store("ssTransition", d).store("ssDuration", b);
            return this
        },
        resetOptions: function (a) {
            this.options = $merge(this.options, a);
            this.setupSlides(false);
            return this
        },
        getTransition: function (a) {
            return a.retrieve("ssTransition")
        },

        getDuration: function (a) {
            return a.retrieve("ssDuration")
        },
        show: function (a, b) {
            a = typeof a == "number" ? this.slides[a] : a;
            if (a != this.current && !this.transitioning) {
                this.transitioning = true;
                var d = b && b.transition ? b.transition : this.getTransition(a),
                    c = b && b.duration ? b.duration : this.getDuration(a),
                    g = this.current.setStyle("z-index", 1),
                    i = this.reset(a),
                    e = {
                        previous: {
                            element: g,
                            index: this.slides.indexOf(g)
                        },
                        next: {
                            element: i,
                            index: this.slides.indexOf(i)
                        }
                    };
                this.fireEvent("show", e);
                this.transitions[d](g, i, c, this);
                (function () {
                    g.setStyle("display", "none");
                    this.fireEvent("showComplete", e);
                    this.transitioning = false
                }).bind(this).delay(c);
                this.current = i
            }
            return this
        },
        reset: function (a) {
            return a.setStyles({
                position: "absolute",
                "z-index": 0,
                display: "block",
                left: 0,
                top: 0
            }).fade("show")
        },
        nextSlide: function () {
            var a =
            this.current.getNext();
            return a ? a : this.slides[0]
        },
        previousSlide: function () {
            var a = this.current.getPrevious();
            return a ? a : this.slides.getLast()
        },
        showNext: function (a) {
            this.show(this.nextSlide(), a);
            return this
        },
        showPrevious: function (a) {
            this.show(this.previousSlide(), a);
            return this
        },
        play: function () {
            this.startLoop();
            this.fireEvent("play");
            return this
        },
        pause: function () {
            this.stopLoop();
            this.fireEvent("pause");
            return this
        },
        reverse: function () {
            this.setLoop(this.loopMethod == this.showNext ? this.showPrevious : this.showNext, this.options.delay);
            this.fireEvent("reverse");
            return this
        },
        toElement: function () {
            return this.element
        }
    });
Element.Properties.slideshow = {
    set: function (a) {
        var b = this.retrieve("slideshow");
        b && b.pause();
        return this.eliminate("slideshow").store("slideshow:options", a)
    },
    get: function (a) {
        if (a || !this.retrieve("slideshow")) {
            if (a || !this.retrieve("slideshow:options")) this.set("slideshow", a);
            this.store("slideshow", new SlideShow(this, this.retrieve("slideshow:options")))
        }
        return this.retrieve("slideshow")
    }
};
Element.implement({
    playSlideShow: function (a) {
        this.get("slideshow", a).play();
        return this
    },
    pauseSlideShow: function (a) {
        this.get("slideshow", a).pause();
        return this
    }
});
SlideShow.adders = {
    transitions: {},
    add: function (a, b) {
        this.transitions[a] = b;
        this.implement({
            transitions: this.transitions
        })
    },
    addAllThese: function (a) {
        $A(a).each(function (b) {
            this.add(b[0], b[1])
        }, this)
    }
};
$extend(SlideShow, SlideShow.adders);
SlideShow.implement(SlideShow.adders);
SlideShow.add("fade", function (a, b, d) {
    a.set("tween", {
        duration: d
    }).fade("out");
    return this
});
SlideShow.addAllThese([
    ["none", function (a) {
        a.setStyle("display", "none");
        return this
    }],
    ["crossFade", function (a, b, d) {
        a.set("tween", {
            duration: d
        }).fade("out");
        b.set("tween", {
            duration: d
        }).fade("in");
        return this
    }],
    ["fadeThroughBackground", function (a, b, d) {
        d = d / 2;
        b.set("tween", {
            duration: d
        }).fade("hide");
        a.set("tween", {
            duration: d,
            onComplete: function () {
                b.fade("in")
            }
        }).fade("out")
    }],
    ["pushLeft", function (a, b, d, c) {
        c = c.element.getSize().x;
        b.setStyle("left", c);
        (new Fx.Elements([a, b], {
            duration: d
        })).start({
            0: {
                left: [-c]
            },
            1: {
                left: [0]
            }
        });
        return this
    }],
    ["pushRight", function (a, b, d, c) {
        c = c.element.getSize().x;
        b.setStyle("left", -c);
        (new Fx.Elements([a, b], {
            duration: d
        })).start({
            0: {
                left: [c]
            },
            1: {
                left: [0]
            }
        });
        return this
    }],
    ["pushUp", function (a, b, d, c) {
        c = c.element.getSize().y;
        b.setStyle("top", c);
        (new Fx.Elements([a, b], {
            duration: d
        })).start({
            0: {
                top: [-c]
            },
            1: {
                top: [0]
            }
        });
        return this
    }],
    ["pushDown", function (a, b, d, c) {
        c = c.element.getSize().y;
        b.setStyle("top", -c);
        (new Fx.Elements([a, b], {
            duration: d
        })).start({
            0: {
                top: [c]
            },
            1: {
                top: [0]
            }
        });
        return this
    }],
    ["blindRight", function (a, b, d, c) {
        a = c.element.getSize().x;
        b.setStyles({
            left: -a,
            "z-index": 2
        }).set("tween", {
            duration: d
        }).tween("left", 0);
        return this
    }],
    ["blindLeft", function (a, b, d, c) {
        a = c.element.getSize().x;
        b.setStyles({
            left: a,
            "z-index": 2
        }).set("tween", {
            duration: d
        }).tween("left", 0);
        return this
    }],
    ["blindUp", function (a, b, d, c) {
        a = c.element.getSize().y;
        b.setStyles({
            top: a,
            "z-index": 2
        }).set("tween", {
            duration: d
        }).tween("top", 0);
        return this
    }],
    ["blindDown", function (a, b, d, c) {
        a = c.element.getSize().y;
        b.setStyles({
            top: -a,
            "z-index": 2
        }).set("tween", {
            duration: d
        }).tween("top", 0);
        return this
    }],
    ["blindDownFade", function (a, b, d, c) {
        this.blindDown(a, b, d, c).fade(a, b, d, c)
    }],
    ["blindUpFade", function (a, b, d, c) {
        this.blindUp(a, b, d, c).fade(a, b, d, c)
    }],
    ["blindLeftFade", function (a, b, d, c) {
        this.blindLeft(a, b, d, c).fade(a, b, d, c)
    }],
    ["blindRightFade", function (a, b, d, c) {
        this.blindRight(a, b, d, c).fade(a, b, d, c)
    }]
]);
var Tabs = new Class({
    Extends: SlideShow,
    options: {
        transition: "none",
        currentClassName: "current"
    },
    initialize: function (a, b, d) {
        this.navs = $$(b);
        this.parent(a, d);
        this.bound = {
            navClick: this.navClick.bind(this),
            onShow: this.onShow.bind(this)
        };
        this.attach()
    },
    attach: function () {
        var a = this;
        this.navs.each(function (b, d) {
            b.store("tabs:handler", function () {
                a.navClick(d)
            }).addEvent("click", b.retrieve("tabs:handler"))
        }, this);
        this.addEvent("show", this.bound.onShow);
        return this
    },
    detach: function () {
        this.navs.each(function (a) {
            a.removeEvent("click", a.retrieve("tabs:handler"))
        }, this);
        return this
    },
    navClick: function (a) {
        this.show(a);
        return this
    },
    onShow: function (a) {
        this.navs[a.previous.index].removeClass(this.options.currentClassName);
        this.navs[a.next.index].addClass(this.options.currentClassName)
    }
});
(function (a) {
    a.store("hashchange:interval", 300);
    a.store("hashchange:ieframe-src", "./blank.html");
    a.store("hashchange:implemented", !! ("onhashchange" in a));
    Element.Events.hashchange = {
        onAdd: function (b) {
            Element.Events.hashchange.onAdd = $empty;
            var d = $(this),
                c = $empty;
            if (d == $(a)) {
                a.store("hashchange:changed", false);
                var g = function (e, h) {
                    a.store("hashchange:current", h || e);
                    if (a.retrieve("hashchange:changed")) {
                        e = e.trim();
                        if (e.length == 0) if ((new String(a.location)).indexOf("#") >= 0) e = "#";
                        a.fireEvent("hashchange", [e])
                    } else a.store("hashchange:changed", true)
                };
                if (typeof a.onhashchange == "function" && b !== a.onhashchange) {
                    a.addEvent("hashchange", a.onhashchange);
                    a.onhashchange = null
                }
                if (Browser.Engine.trident4 || Browser.Engine.trident5) {
                    c = function (e, h) {
                        var f = a.retrieve("hashchange:checker"),
                            l = a.retrieve("hashchange:timer");
                        $clear(l);
                        var j = h && e.length == 0,
                            k = e == "#";
                        l = unescape(new String(a.location));
                        if (k) k = j = "#";
                        else if (j) k = j = "";
                        else {
                            j = e = e != null ? e : l;
                            if (e.length > 0) {
                                k = e.indexOf("#");
                                if (k >= 0) j = e.substr(k)
                            }
                            k = j.toLowerCase()
                        }
                        var m =
                        a.retrieve("hashchange:current");
                        if (m != k) {
                            if (h) {
                                e = l;
                                if (m) e = e.replace(m, j);
                                else e += j;
                                a.location = e
                            }
                            l = !h && a.retrieve("hashchange:changed");
                            g(j, k);
                            l && a.retrieve("hashchange:ieframe").setPath(j)
                        }
                        l = f.delay(a.retrieve("hashchange:interval"));
                        a.store("hashchange:timer", l)
                    };
                    var i = a.retrieve("hashchange:ieframe-src");
                    b = new IFrame({
                        id: "hashchange-ie-frame",
                        src: i + "?start",
                        styles: {
                            width: 0,
                            height: 0,
                            position: "absolute",
                            top: -9999,
                            left: -9999
                        },
                        onload: function () {
                            var e = $("hashchange-ie-frame");
                            if (e.retrieve("loaded")) {
                                e =
                                unescape(new String(e.contentWindow.location));
                                var h = e.indexOf("?");
                                if (h >= 0) {
                                    var f = "";
                                    if (e.indexOf("?empty") >= 0) f = "#";
                                    else {
                                        h = e.indexOf("?!");
                                        if (h >= 0) {
                                            f = e.substr(h + 2);
                                            f = "#" + f
                                        }
                                    }
                                    a.retrieve("hashchange:checker")(f, true)
                                }
                            } else e.store("loaded", true)
                        }.bind(a)
                    });
                    a.store("hashchange:ieframe", b);
                    b.injectInside(document.body);
                    b.setPath = function (e) {
                        if (e.charAt(0) == "#") {
                            e = e.substr(1);
                            if (e.length == 0) {
                                this.contentWindow.location = i + "?empty";
                                return
                            }
                        }
                        this.contentWindow.location = i + "?!" + escape(e)
                    }.bind(b)
                } else if (a.retrieve("hashchange:implemented")) c =
                a.onhashchange = function (e) {
                    e = e && typeof e == "string" ? e : new String(a.location.hash);
                    g.delay(1, a, [e])
                };
                else {
                    if (Browser.Engine.presto) history.navigationMode = "compatible";
                    c = function (e) {
                        var h = a.retrieve("hashchange:checker"),
                            f = a.retrieve("hashchange:timer");
                        $clear(f);
                        e = e || new String(a.location.hash);
                        f = e.toLowerCase();
                        if (e.length == 0 && (new String(a.location)).indexOf("#") >= 0) f = "#";
                        a.retrieve("hashchange:current") != f && g(e, f);
                        f = h.delay(a.retrieve("hashchange:interval"));
                        a.store("hashchange:timer", f)
                    }
                }
                a.store("hashchange:checker", c);
                c();
                a.sethash = function (e) {
                    if (e.charAt(0) != "#") e = "#" + e;
                    a.hashcheck(e)
                }
            }
        },
        onDelete: function () {
            if ($(this) == $(a)) {
                var b = a.retrieve("hashchange:timer");
                if (b) {
                    $clear(b);
                    a.store("hashchange:timer", null)
                }
            }
        }
    }
})(window, undefined);
var HashEvents = new Class({
    Implements: [Options, Events],
    initialize: function (a) {
        this.setOptions(a);
        this.pairs = {};
        this.lastPairs = {};
        this.bound = this.check.bind(this);
        this.attach()
    },
    attach: function () {
        window.addEvent("hashchange", this.bound);
        return this
    },
    detach: function () {
        window.removeEvent("hashchange", this.bound);
        return this
    },
    check: function () {
        this.fireEvent("change");
        this.pairs = window.location.hash.substr(1).parseHashEvents();
        for (key in this.pairs) if (this.lastPairs[key] && this.lastPairs[key] != this.pairs[key]) this.fireEvent(key + ":change", this.pairs[key]);
        else this.lastPairs[key] || this.fireEvent(key, this.pairs[key]);
        for (key in this.lastPairs)!this.pairs[key] && this.fireEvent(key + ":remove", this.lastPairs[key]);
        this.lastPairs = this.pairs;
        return this
    },
    handleBlankKeys: function (a) {
        $type(a) == "array" ? a.each(function (b) {
            console.log(b + " added!")
        }, this) : console.log(a + " added!")
    }
});
String.implement({
    parseHashEvents: function () {
        var a = this.split(/[&;]/),
            b = {};
        a.length && a.each(function (d) {
            var c = d.split("=");
            d = c[0];
            c = c[1] || true;
            var g = $type(c) == "string" ? c.split(",") : false;
            b[d] = g && g.length > 1 ? g : c
        });
        return b
    }
});
