/**
 * MooScroll beta [for mootools 1.2]
 * @author Jason J. Jaeger | greengeckodesign.com
 * @version 0.56
 * @license MIT-style License
 *			Permission is hereby granted, free of charge, to any person obtaining a copy
 *			of this software and associated documentation files (the "Software"), to deal
 *			in the Software without restriction, including without limitation the rights
 *			to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *			copies of the Software, and to permit persons to whom the Software is
 *			furnished to do so, subject to the following conditions:
 *	
 *			The above copyright notice and this permission notice shall be included in
 *			all copies or substantial portions of the Software.
 *	
 *			THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *			IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *			FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *			AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *			LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *			OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *			THE SOFTWARE.
 **/
 

var MooScroll=new Class({
    Implements: Options,
    options: {
        selector: ".scroll",
        increment: 10,
        upBtnClass: "upBtn",
        downBtnClass: "downBtn",
        scrollBarClass: "scrollBar",
        scrollHandleClass: "scrollHandle",
        scrollHandleBGClass: "scrollHandleBG",
        scrollHandleTopClass: "scrollHandleTop",
        scrollHandleMiddleClass: "scrollHandleMiddle",
        scrollHandleBottomClass: "scrollHandleBottom",
        scrollControlsYClass: "scrollControlsY",
        handleOpacity: 1,
        handleActiveOpacity: 0.85,
        disabledOpacity: 0.5,
        fullWindowMode: false,
        restrictedBrowsers: [Browser.Engine.presto925, Browser.Platform.ipod, Browser.Engine.webkit419]
    },
    initialize: function(A) {
        if (this.options.restrictedBrowsers.contains(true)) {
            return
        }
        this.setOptions(A);
        this.mooScrollAreas = [];
        $(document.body).getElements(this.options.selector).each(function(C, B) {
            var D = new MooScrollArea(this.options, C);
            this.mooScrollAreas.include(D)
        }.bind(this))
    },
    loadContent: function(A) {
        this.mooScrollAreas.each(function(C, B) {
            C.loadContent(A)
        })
    }
});
var MooScrollArea = new Class({
    Implements: Options,
    initialize: function(A, B) {
        this.setOptions(A);
        this.parentEl = B;
        this.viewPort = {
            x: $(window).getSize().x,
            y: $(window).getSize().y
        };
        this.parentElPadding = this.parentEl.getStyles("padding-top", "padding-right", "padding-bottom", "padding-left");
        this.paddingHeight = parseFloat(this.parentEl.getStyle("padding-top")) + parseFloat(this.parentEl.getStyle("padding-bottom"));
        this.paddingWidth = parseFloat(this.parentEl.getStyle("padding-left")) + parseFloat(this.parentEl.getStyle("padding-right"));
        this.contentEl = new Element("div", {
            "class": "contentEl"
        }).adopt(this.parentEl.getChildren()).inject(this.parentEl, "top");
        this.parentEl.setStyles({
            padding: 0,
            overflow: "hidden",
            width: parseFloat(this.parentEl.getStyle("width")) + this.paddingWidth,
            height: parseFloat(this.parentEl.getStyle("height")) + this.paddingHeight
        });
        this.borderHeight = parseFloat(this.parentEl.getStyle("border-top-width")) + parseFloat(this.parentEl.getStyle("border-bottom-width"));
        this.contentEl.setStyles({
            height: this.parentEl.getSize().y - this.borderHeight,
            overflow: "hidden",
            padding: 0
        });
        this.paddingEl = new Element("div", {
            "class": "paddingEl"
        }).adopt(this.contentEl.getChildren()).inject(this.contentEl, "top").setStyles(this.parentElPadding);
        if (this.options.fullWindowMode) {
            $(document).getElement("html").setStyle("overflow", "hidden");
            this.parentEl.setStyles({
                height: "100%",
                width: "100%",
                position: "absolute"
            });
            this.contentEl.setStyles({
                height: "100%",
                width: "100%",
                position: "absolute"
            })
        }
        this.scrollControlsYWrapper = new Element("div", {
            "class": this.options.scrollControlsYClass
        }).inject(this.parentEl, "bottom");
        this.upBtn = new Element("div", {
            "class": this.options.upBtnClass
        }).inject(this.scrollControlsYWrapper, "bottom");
        this.downBtn = new Element("div", {
            "class": this.options.downBtnClass
        }).inject(this.scrollControlsYWrapper, "bottom");
        this.scrollBar = new Element("div", {
            "class": this.options.scrollBarClass
        }).inject(this.scrollControlsYWrapper, "bottom");
        this.scrollHandle = new Element("div", {
            "class": this.options.scrollHandleClass
        }).inject(this.scrollBar, "inside");
        this.scrollHandleTop = new Element("div", {
            "class": this.options.scrollHandleTopClass
        }).inject(this.scrollHandle, "inside");
        this.scrollHandleBG = new Element("div", {
            "class": this.options.scrollHandleBGClass
        }).inject(this.scrollHandle, "inside");
        this.scrollHandleMiddle = new Element("div", {
            "class": this.options.scrollHandleMiddleClass
        }).inject(this.scrollHandle, "inside");
        this.scrollHandleBottom = new Element("div", {
            "class": this.options.scrollHandleBottomClass
        }).inject(this.scrollHandle, "inside");
        this.coverUp = new Element("div").inject(this.scrollControlsYWrapper, "bottom");
        this.fixIE6CSSbugs();
        this.overHang = this.paddingEl.getSize().y - this.parentEl.getSize().y;
        this.setHandleHeight();
        if (this.overHang <= 0) {
            this.greyOut();
            return
        }
        this.initSlider();
        this.parentEl.addEvents({
            mousewheel: function(C) {
                C = new Event(C).stop();
                if (C.wheel > 0) {
                    this.scrollUp(true)
                } else {
                    if (C.wheel < 0) {
                        this.scrollDown(true)
                    }
                }
            }.bind(this),
            keydown: function(C) {
                if (C.key === "up") {
                    C = new Event(C).stop();
                    this.scrollUp(true)
                } else {
                    if (C.key === "down" || C.key === "space") {
                        C = new Event(C).stop();
                        this.scrollDown(true)
                    }
                }
            }.bind(this),
            click: function(C) {
                this.hasFocus = true;
                this.hasFocusTimeout = (function() {
                    $clear(this.hasFocusTimeout);
                    this.hasFocus = true
                }.bind(this)).delay(50)
            }.bind(this)
        });
        this.contentEl.addEvents({
            scroll: function(C) {
                this.slider.set(this.contentEl.getScroll().y)
            }.bind(this)
        });
        this.scrollHandle.addEvents({
            mousedown: function(C) {
                this.scrollHandle.addClass(this.options.scrollHandleClass + "-Active").setStyle("opacity", this.options.handleActiveOpacity)
            }.bind(this)
        });
        document.addEvents({
            mouseup: function(C) {
                this.scrollHandle.removeClass(this.options.scrollHandleClass + "-Active").setStyle("opacity", this.options.handleOpacity);
                this.upBtn.removeClass(this.options.upBtnClass + "-Active");
                this.downBtn.removeClass(this.options.downBtnClass + "-Active")
            }.bind(this),
            keydown: function(C) {
                if ((this.hasFocus || this.options.fullWindowMode) && (C.key === "down" || C.key === "space" || C.key === "up")) {
                    this.parentEl.fireEvent("keydown", C)
                }
            }.bind(this),
            click: function(C) {
                this.hasFocus = false
            }.bind(this)
        });
        window.addEvent("resize",
        function() {
            $clear(this.refreshTimeout);
            if (this.options.fullWindowMode) {
                this.refreshTimeout = (function() {
                    $clear(this.refreshTimeout);
                    if (this.viewPort.x != $(window).getSize().x || this.viewPort.y != $(window).getSize().y) {
                        this.refresh();
                        this.viewPort.x = $(window).getSize().x;
                        this.viewPort.y = $(window).getSize().y
                    }
                }.bind(this)).delay(250)
            }
        }.bind(this));
        this.upBtn.addEvents({
            mousedown: function(C) {
                $clear(this.upInterval);
                $clear(this.downInterval);
                this.upInterval = this.scrollUp.periodical(10, this);
                this.upBtn.addClass(this.options.upBtnClass + "-Active")
            }.bind(this),
            mouseup: function(C) {
                $clear(this.upInterval);
                $clear(this.downInterval)
            }.bind(this),
            mouseout: function(C) {
                $clear(this.upInterval);
                $clear(this.downInterval)
            }.bind(this)
        });
        this.downBtn.addEvents({
            mousedown: function(C) {
                $clear(this.upInterval);
                $clear(this.downInterval);
                this.downInterval = this.scrollDown.periodical(10, this);
                this.downBtn.addClass(this.options.downBtnClass + "-Active")
            }.bind(this),
            mouseup: function(C) {
                $clear(this.upInterval);
                $clear(this.downInterval)
            }.bind(this),
            mouseout: function(C) {
                $clear(this.upInterval);
                $clear(this.downInterval)
            }.bind(this)
        })
    },
    initSlider: function() {
        this.slider = new Slider(this.scrollBar, this.scrollHandle, {
            range: [0, Math.round(this.overHang)],
            mode: "vertical",
            onChange: function(A) {
                this.contentEl.scrollTo(0, A);
                this.webKitKludge(A)
            }.bind(this)
        }).set(0)
    },
    webKitKludge: function(A) {
        if (!Browser.Engine.webkit) {
            return
        }
        if (this.step > A) {
            this.step = A;
            return
        }
        $clear(this.sliderTimeout);
        this.sliderTimeout = (function() {
            $clear(this.sliderTimeout);
            var B = (1 * this.paddingEl.getSize().y) / 100;
            if ((B + A) >= this.overHang) {
                if (this.paddingElTopMargin == null) {
                    this.paddingElTopMargin = parseFloat(this.paddingEl.getStyle("margin-top"))
                }
                this.paddingEl.setStyle("margin-top", this.paddingElTopMargin - B);
                if (!this.scrollHandleTopMargin) {
                    this.scrollHandleTopMargin = parseFloat(this.scrollHandle.getStyle("margin-top"))
                }
                this.scrollHandle.setStyle("margin-top", this.scrollHandleTopMargin + 2);
                this.contentEl.scrollTo(0, this.overHang);
                this.step = this.overHang
            } else {
                this.paddingEl.setStyle("margin-top", this.paddingElTopMargin);
                this.scrollHandle.setStyle("margin-top", this.scrollHandleTopMargin);
                this.contentEl.scrollTo(0, A);
                this.step = A
            }
        }.bind(this)).delay(10)
    },
    scrollUp: function(A) {
        var B = this.contentEl.getScroll().y - 30;
        this.slider.set(B);
        if (this.contentEl.getScroll().y <= 0 && A) {
            document.window.scrollTo(0, document.window.getScroll().y - this.options.increment)
        }
    },
    scrollDown: function(C) {
        var D = this.contentEl.getScroll().y + this.options.increment;
        this.slider.set(D);
        var A = (1 * this.paddingEl.getSize().y) / 100;
        var B = (this.paddingEl.getSize().y - this.parentEl.getSize().y) <= (this.contentEl.getScroll().y + A);
        if (B && C) {
            document.window.scrollTo(0, document.window.getScroll().y + this.options.increment)
        }
    },
    fixIE6CSSbugs: function() {
        if (Browser.Engine.trident4) {
            this.parentEl.setStyle("height", this.parentEl.getStyle("height"));
            this.contentEl.setStyle("height", this.parentEl.getStyle("height"));
            var C = this.scrollBar.getStyle("top").toInt();
            var A = this.scrollBar.getStyle("bottom").toInt();
            var B = this.parentEl.getSize().y - this.borderHeight;
            this.scrollControlsYWrapper.setStyles({
                height: B
            });
            this.scrollBar.setStyles({
                height: B - C - A
            })
        }
    },
    setHandleHeight: function() {
        var A = (100 - ((this.overHang * 100) / this.paddingEl.getSize().y));
        this.handleHeight = ((A * this.parentEl.getSize().y) / 100) - (this.scrollHandleTop.getSize().y + this.scrollHandleBottom.getSize().y);
        if ((this.handleHeight + this.scrollHandleTop.getSize().y + this.scrollHandleBottom.getSize().y) >= this.scrollBar.getSize().y) {
            this.handleHeight -= (this.scrollHandleTop.getSize().y + this.scrollHandleBottom.getSize().y) * 2
        }
        if (this.scrollHandle.getStyle("min-height") && this.handleHeight < parseFloat(this.scrollHandle.getStyle("min-height"))) {
            this.handleHeight = parseFloat(this.scrollHandle.getStyle("min-height")) + this.scrollHandleBottom.getSize().y + this.scrollHandleTop.getSize().y
        }
        this.scrollHandle.setStyles({
            height: this.handleHeight
        })
    },
    greyOut: function() {
        this.scrollControlsYWrapper.setStyles({
            display: "none"
        });
    },
    unGrey: function() {
        this.scrollHandle.setStyles({
            display: "block",
            height: "auto"
        });
        this.upBtn.setStyles({
            opacity: 1
        });
        this.downBtn.setStyles({
            opacity: 1
        });
        this.scrollBar.setStyles({
            opacity: 1
        });
        this.coverUp.setStyles({
            display: "none",
            width: 0,
            height: 0
        });
        this.setHandleHeight()
    },
    loadContent: function(A) {
        this.slider.set(0);
        this.paddingEl.empty().set("html", A);
        this.refresh()
    },
    refresh: function() {
        var A = Math.round(((100 * this.step) / this.overHang));
        if (this.options.fullWindowMode) {
            var B = $(window).getSize();
            this.parentEl.setStyles({
                width: "100%",
                height: "100%"
            })
        }
        this.fixIE6CSSbugs();
        this.overHang = this.paddingEl.getSize().y - this.parentEl.getSize().y;
        this.setHandleHeight();
        if (this.overHang <= 0) {
            this.greyOut();
            return
        } else {
            this.unGrey()
        }
        this.scrollHandle.removeEvents();
        var C = Math.round((A * this.overHang) / 100);
        this.initSlider();
        this.slider.set(C)
    }
}
);
