/*
ProtoScrollBar - it«s ScrollBars!!, based on prototype and script.aculo.us.

Copyright Andreas Gotfredsen (andreas@holviks.se), 2008 Holviks Marketing AB
All rights reserved.
 
VERSION 1.0.0

Developed for CapTech AB Webshop
*/

if (typeof Effect == 'undefined')
    throw ("protoscrollbar.js requires including script.aculo.us' effects.js library!");

var ProtoScrollBar = Class.create();
ProtoScrollBar.prototype = {

    initialize: function(container, options) {
        if (!$(container)) {
            throw (container + " doesn't exist!");
            return false;
        }

        this.visible = true;
        this.content = $(container);
        //this.content.setStyle({ height: (120) + 'px' });

        this.currentValue = 0;

        var self = this;

        /* Slider-options */
        this.options = Object.extend({

            axis: 'vertical',
            onChange: function(value) {
                self.updateView(value);
            },
            onSlide: function(value) {
                self.updateView(value);
            }
        }, options);

        /* Scroller-options */
        this.options = Object.extend({
            scrollOnHover: false,
            classNames: {
                psbcontainer: 'PSB_container',
                psbbuttonup: 'PSB_buttonup',
                psbbuttondown: 'PSB_buttondown',
                psbtrack: 'PSB_track',
                psbhandle: 'PSB_handle'
            },
            visibleHeight: this.isVertical() ? 100 : this.content.offsetHeight,
            visibleWidth: this.isVertical() ? this.content.offsetWidth : 300,
            delta: 1,
            autoHide: true,
            interval: 100,
            enableOnClickScroll: false,
            enableKeyboard: true,
            enableMouse: true,
            //enableScrollWheel: true, // Denna används ju ingenstans...
            offseter: 35,
            debug: false,
            containerScroller: null,
            minifix: 0
        }, this.options);

        this.PSBcontainer = new Element("div", { 'class': this.options.classNames.psbcontainer });
        this.PSBbuttonup = new Element("div", { 'class': this.options.classNames.psbbuttonup });
        this.PSBbuttondown = new Element("div", { 'class': this.options.classNames.psbbuttondown });

        this.PSBtrack = new Element("div", { 'class': this.options.classNames.psbtrack }).update(
			this.PSBhandle = new Element("div", { 'class': this.options.classNames.psbhandle })
		);

        this.PSBcontainer.insert({ 'top': this.PSBbuttondown });
        this.PSBcontainer.insert({ 'top': this.PSBtrack });
        this.PSBcontainer.insert({ 'top': this.PSBbuttonup });

        var insertTo = this.content.up();
        insertTo.insert({ 'bottom': this.PSBcontainer });

        this.maxValue = 20;
        this.options.range = $R(0, this.maxValue);

        this.buttons = {
            up: this.PSBbuttonup,
            down: this.PSBbuttondown
        };

        if (this.options.enableMouse) {
            var eventType = Prototype.Browser.Gecko ? "DOMMouseScroll" : "mousewheel";
            Event.observe(this.content, eventType, (function(e) {
                this.enableMouse(e);
            }).bind(this), false);

            Event.observe(this.PSBtrack, eventType, (function(e) {
                this.enableMouse(e);
            }).bind(this), false);
        }


        this.eventMouseAction = this.buttonAction.bindAsEventListener(this);
        $H(this.buttons).values().each(function(button) {
            if (self.options.scrollOnHover) {
                Event.observe(button, "mouseover", self.eventMouseAction);
                Event.observe(button, "mouseout", self.eventMouseAction);
            } else {
                Event.observe(button, "mousedown", self.eventMouseAction);
                Event.observe(button, "mouseup", self.eventMouseAction);
            }
        });

        this.slider = new Control.Slider(this.PSBhandle, this.PSBtrack, this.options);

    },

    isVertical: function() {
        return this.options.axis == 'vertical';
    },


    scroll: function() {
        var oldValue = this.currentValue;

        this.updateWheelDelta();
        this.slider.setValue(this.currentValue + this.options.delta * this.multiplier, 0);

        var newValue = this.currentValue;

        // Om man skrollar någon miniskroller i botten, så skall den fortsätta att skrolla den
        // omgivande skrollen, om det finns nåon angiven.
        if (oldValue == newValue && this.options.containerScroller != null) {
            this.options.containerScroller.multiplier = this.multiplier;
            this.options.containerScroller.scroll();
        }
    },
    buttonAction: function(e) {

        this.multiplier = Event.element(e) == this.buttons.up ? -1 : 1;
        switch (e.type) {
            case "mouseover":
            case "mousedown":
                this.scroll();
                this.updateResize();
                var self = this;
                if (this.timer) clearTimeout(this.timer);
                this.timer = setInterval(function() { self.scroll() }, self.options.interval);
                break;
            case "mouseout":
            case "mouseup":
                clearTimeout(this.timer);
                break;
        }
    },
    enableMouse: function(e) {
        this.multiplier = Event.wheel(e) < 0 ? 1 : -1;
        Event.stop(e);

        this.scroll();
    },

    updateResize: function() {

        this.PSBcontainer.setStyle({ height: (this.content.getHeight() - this.options.offseter) + 'px' });

        this.slider.trackLength = this.PSBtrack.getHeight() - this.options.minifix; //use only for mini scrollers because they have different css		

        this.handleHeight = Math.round((this.content.offsetHeight * this.content.offsetHeight) / this.content.scrollHeight) - this.options.offseter;

        if (this.handleHeight > this.slider.trackLength) this.handleHeight = this.slider.trackLength;

        if (this.handleHeight < 10) this.handleHeight = 10;
        this.PSBhandle.style.height = this.handleHeight + "px";

        this.slider.handleLength = this.handleHeight;

        if (this.content.offsetHeight >= this.content.scrollHeight) {
            if (this.visible) {
                setTimeout(function() {
                    this.slider.setValue(0);
                    this.PSBcontainer.hide();
                    this.visible = false;
                } .bind(this), 1);
            }
        }
        else {
            if (!this.visible) {
                setTimeout(function() {
                    this.PSBcontainer.show();
                    this.slider.trackLength = this.PSBtrack.getHeight();

                    this.handleHeight = Math.round((this.content.offsetHeight * this.content.offsetHeight) / this.content.scrollHeight) - this.options.offseter;

                    if (this.handleHeight > this.slider.trackLength) this.handleHeight = this.slider.trackLength;

                    if (this.handleHeight < 10) this.handleHeight = 10;
                    this.PSBhandle.style.height = this.handleHeight + "px";

                    this.slider.handleLength = this.handleHeight;

                    this.visible = true;

                } .bind(this), 1);
            }
        }

        // När denna körs så expanderar skrollrarna, "åt båda håll" // Martin tar bort den från Andreas version
        //this.slider.setValue(this.currentValue);

        this.updateWheelDelta();
        try {
            this.updateScrollerFromView();
        } catch (e) {
        }
    },

    updateWheelDelta: function() {
        this.options.delta = 5 * (this.slider.handleLength / this.slider.trackLength);
    },


    updateView: function(value) {
        this.currentValue = value;
        this.content.scrollTop = Math.round(this.currentValue / this.maxValue * (this.content.scrollHeight - this.content.offsetHeight));
        this.content.scrollLeft = 0; // Denna behövs eftersom ScrollIntoView annars scrollar i sidled också...
    },
    updateScrollerFromView: function() {
        var newValue = (this.content.scrollTop * this.maxValue) / (this.content.scrollHeight - this.content.offsetHeight);
        this.currentValue = newValue;

        try {
            this.slider.setValue(newValue);
        } catch (e) { }
    }

}


Object.extend(Event, {
    wheel: function(event) {

        var delta = 0;
        if (!event) event = window.event;

        if (event.wheelDelta) {
            delta = event.wheelDelta / 120;
            /*
            if (Prototype.Browser.Opera) {
                delta = delta;
			}
			*/
        }
        else if (event.detail) {

            delta = -event.detail / 3;
        }
        return Math.round(delta); //Safari Round
    }
});