//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.

/*
---

script: More.js

description: MooTools More

license: MIT-style license

authors:
- Guillermo Rauch
- Thomas Aylott
- Scott Kyle

requires:
- core:1.2.4/MooTools

provides: [MooTools.More]

...
*/

MooTools.More = {
        'version': '1.2.4.4',
        'build': '6f6057dc645fdb7547689183b2311063bd653ddf'
};

/*
---

script: Fx.Scroll.js

description: Effect to smoothly scroll any element, including the window.

license: MIT-style license

authors:
- Valerio Proietti

requires:
- core:1.2.4/Fx
- core:1.2.4/Element.Event
- core:1.2.4/Element.Dimensions
- /MooTools.More

provides: [Fx.Scroll]

...
*/

Fx.Scroll = new Class({

        Extends: Fx,

        options: {
                offset: {x: 0, y: 0},
                wheelStops: true
        },

        initialize: function(element, options){
                this.element = this.subject = document.id(element);
                this.parent(options);
                var cancel = this.cancel.bind(this, false);

                if ($type(this.element) != 'element') this.element = document.id(this.element.getDocument().body);

                var stopper = this.element;

                if (this.options.wheelStops){
                        this.addEvent('start', function(){
                                stopper.addEvent('mousewheel', cancel);
                        }, true);
                        this.addEvent('complete', function(){
                                stopper.removeEvent('mousewheel', cancel);
                        }, true);
                }
        },

        set: function(){
                var now = Array.flatten(arguments);
                if (Browser.Engine.gecko) now = [Math.round(now[0]), Math.round(now[1])];
                this.element.scrollTo(now[0], now[1]);
        },

        compute: function(from, to, delta){
                return [0, 1].map(function(i){
                        return Fx.compute(from[i], to[i], delta);
                });
        },

        start: function(x, y){
                if (!this.check(x, y)) return this;
                var scrollSize = this.element.getScrollSize(),
                        scroll = this.element.getScroll(),
                        values = {x: x, y: y};
                for (var z in values){
                        var max = scrollSize[z];
                        if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z] : max;
                        else values[z] = scroll[z];
                        values[z] += this.options.offset[z];
                }
                return this.parent([scroll.x, scroll.y], [values.x, values.y]);
        },

        toTop: function(){
                return this.start(false, 0);
        },

        toLeft: function(){
                return this.start(0, false);
        },

        toRight: function(){
                return this.start('right', false);
        },

        toBottom: function(){
                return this.start(false, 'bottom');
        },

        toElement: function(el){
                var position = document.id(el).getPosition(this.element);
                return this.start(position.x, position.y);
        },

        scrollIntoView: function(el, axes, offset){
                axes = axes ? $splat(axes) : ['x','y'];
                var to = {};
                el = document.id(el);
                var pos = el.getPosition(this.element);
                var size = el.getSize();
                var scroll = this.element.getScroll();
                var containerSize = this.element.getSize();
                var edge = {
                        x: pos.x + size.x,
                        y: pos.y + size.y
                };
                ['x','y'].each(function(axis) {
                        if (axes.contains(axis)) {
                                if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis];
                                if (pos[axis] < scroll[axis]) to[axis] = pos[axis];
                        }
                        if (to[axis] == null) to[axis] = scroll[axis];
                        if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
                }, this);
                if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
                return this;
        },

        scrollToCenter: function(el, axes, offset){
                axes = axes ? $splat(axes) : ['x', 'y'];
                el = $(el);
                var to = {},
                        pos = el.getPosition(this.element),
                        size = el.getSize(),
                        scroll = this.element.getScroll(),
                        containerSize = this.element.getSize(),
                        edge = {
                                x: pos.x + size.x,
                                y: pos.y + size.y
                        };

                ['x','y'].each(function(axis){
                        if(axes.contains(axis)){
                                to[axis] = pos[axis] - (containerSize[axis] - size[axis])/2;
                        }
                        if(to[axis] == null) to[axis] = scroll[axis];
                        if(offset && offset[axis]) to[axis] = to[axis] + offset[axis];
                }, this);
                if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
                return this;
        }

});


/*
---

script: Fx.Slide.js

description: Effect to slide an element in and out of view.

license: MIT-style license

authors:
- Valerio Proietti

requires:
- core:1.2.4/Fx Element.Style
- /MooTools.More

provides: [Fx.Slide]

...
*/

Fx.Slide = new Class({

        Extends: Fx,

        options: {
                mode: 'vertical',
                wrapper: false,
                hideOverflow: true
        },

        initialize: function(element, options){
                this.addEvent('complete', function(){
                        this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0);
                        if (this.open) this.wrapper.setStyle('height', '');
                        if (this.open && Browser.Engine.webkit419) this.element.dispose().inject(this.wrapper);
                }, true);
                this.element = this.subject = document.id(element);
                this.parent(options);
                var wrapper = this.element.retrieve('wrapper');
                var styles = this.element.getStyles('margin', 'position', 'overflow');
                //if (this.options.hideOverflow) styles = $extend(styles, {overflow: 'hidden' });
                if (this.options.hideOverflow) styles = $extend(styles, {overflow: 'hidden',position: "relative" });

                if (this.options.wrapper) wrapper = document.id(this.options.wrapper).setStyles(styles);
                this.wrapper = wrapper || new Element('div', {
                        styles: styles
                }).wraps(this.element);
                this.element.store('wrapper', this.wrapper).setStyle('margin', 0);
                this.now = [];
                this.open = true;
        },

        vertical: function(){
                this.margin = 'margin-top';
                this.layout = 'height';
                this.offset = this.element.offsetHeight;
        },

        horizontal: function(){
                this.margin = 'margin-left';
                this.layout = 'width';
                this.offset = this.element.offsetWidth;
        },

        set: function(now){
                this.element.setStyle(this.margin, now[0]);
                this.wrapper.setStyle(this.layout, now[1]);
                return this;
        },

        compute: function(from, to, delta){
                return [0, 1].map(function(i){
                        return Fx.compute(from[i], to[i], delta);
                });
        },

        start: function(how, mode){
                if (!this.check(how, mode)) return this;
                this[mode || this.options.mode]();
                var margin = this.element.getStyle(this.margin).toInt();
                var layout = this.wrapper.getStyle(this.layout).toInt();
                var caseIn = [[margin, layout], [0, this.offset]];
                var caseOut = [[margin, layout], [-this.offset, 0]];
                var start;
                switch (how){
                        case 'in': start = caseIn; break;
                        case 'out': start = caseOut; break;
                        case 'toggle': start = (layout == 0) ? caseIn : caseOut;
                }
                return this.parent(start[0], start[1]);
        },

        slideIn: function(mode){
                return this.start('in', mode);
        },

        slideOut: function(mode){
                return this.start('out', mode);
        },

        hide: function(mode){
                this[mode || this.options.mode]();
                this.open = false;
                return this.set([-this.offset, 0]);
        },

        show: function(mode){
                this[mode || this.options.mode]();
                this.open = true;
                return this.set([0, this.offset]);
        },

        toggle: function(mode){
                return this.start('toggle', mode);
        }

});

Element.Properties.slide = {

        set: function(options){
                var slide = this.retrieve('slide');
                if (slide) slide.cancel();
                return this.eliminate('slide').store('slide:options', $extend({link: 'cancel'}, options));
        },

        get: function(options){
                if (options || !this.retrieve('slide')){
                        if (options || !this.retrieve('slide:options')) this.set('slide', options);
                        this.store('slide', new Fx.Slide(this, this.retrieve('slide:options')));
                }
                return this.retrieve('slide');
        }

};

Element.implement({

        slide: function(how, mode){
                how = how || 'toggle';
                var slide = this.get('slide'), toggle;
                switch (how){
                        case 'hide': slide.hide(mode); break;
                        case 'show': slide.show(mode); break;
                        case 'toggle':
                                var flag = this.retrieve('slide:flag', slide.open);
                                slide[flag ? 'slideOut' : 'slideIn'](mode);
                                this.store('slide:flag', !flag);
                                toggle = true;
                        break;
                        default: slide.start(how, mode);
                }
                if (!toggle) this.eliminate('slide:flag');
                return this;
        }

});


/*
---

script: Fx.SmoothScroll.js

description: Class for creating a smooth scrolling effect to all internal links on the page.

license: MIT-style license

authors:
- Valerio Proietti

requires:
- core:1.2.4/Selectors
- /Fx.Scroll

provides: [Fx.SmoothScroll]

...
*/

var SmoothScroll = Fx.SmoothScroll = new Class({

        Extends: Fx.Scroll,

        initialize: function(options, context){
                context = context || document;
                this.doc = context.getDocument();
                var win = context.getWindow();
                this.parent(this.doc, options);
                this.links = $$(this.options.links || this.doc.links);
                var location = win.location.href.match(/^[^#]*/)[0] + '#';
                this.links.each(function(link){
                        if (link.href.indexOf(location) != 0) {return;}
                        var anchor = link.href.substr(location.length);
                        if (anchor) this.useLink(link, anchor);
                }, this);
                if (!Browser.Engine.webkit419) {
                        this.addEvent('complete', function(){
                                win.location.hash = this.anchor;
                        }, true);
                }
        },

        useLink: function(link, anchor){
                var el;
                link.addEvent('click', function(event){
                        if (el !== false && !el) el = document.id(anchor) || this.doc.getElement('a[name=' + anchor + ']');
                        if (el) {
                                event.preventDefault();
                                this.anchor = anchor;
                                this.toElement(el).chain(function(){
                                        this.fireEvent('scrolledTo', [link, el]);
                                }.bind(this));
                                link.blur();
                        }
                }.bind(this));
        }
});
