/*
 * MooTools based zoom tool
 * Copyright (C) Nick Wellnhofer, 2009
 * wellnhofer@aevum.de
 */

var AEZoom = new Class({
    Implements: [ Options ],
    options: {
        initialPos: { x: 0.5, y: 0.2 }
    },
    initialize: function(handle, scroller, options) {
        this.handle   = $(handle);
        this.scroller = $(scroller);
        this.setOptions(options);
        
        // get maximum scroll coordinates
        
        var zoomedSize   = this.scroller.getScrollSize();
        var scrollerSize = this.sizeWithoutBorder(this.scroller);
        var scrollXMax = zoomedSize.x - scrollerSize.x;
        var scrollYMax = zoomedSize.y - scrollerSize.y;
        
        // get limit of draggable handle
        
        this.dragLimit = this.options.dragLimit;
        
        if(!this.dragLimit) {
            // MooTools bug, we have to use $() for IE here
            var offsetParent = $(this.handle.getOffsetParent());
            var normalSize = this.sizeWithoutBorder(offsetParent);
            var handleSize = this.handle.getSize();
            
            this.dragLimit = {
                x: [ 0, normalSize.x - handleSize.x ],
                y: [ 0, normalSize.y - handleSize.y ]
            };
        }
        
        var limitWidth  = this.dragLimit.x[1] - this.dragLimit.x[0];
        var limitHeight = this.dragLimit.y[1] - this.dragLimit.y[0];
        
        // compute zoom factor
        
        this.factor = {
            x: scrollXMax / limitWidth,
            y: scrollYMax / limitHeight
        };
        
        // set initial position
        
        var initialPos = this.options.initialPos;
        this.moveHandle(
            initialPos.x * limitWidth,
            initialPos.y * limitHeight
        );
        this.moveScroller(
            initialPos.x * scrollXMax,
            initialPos.y * scrollYMax
        );
        
        // create draggables
        
        new Drag(this.handle, {
            limit: this.dragLimit,
            preventDefault: true,
            onDrag: this.dragHandle.bind(this)
        });
        
        new Drag(this.scroller, {
            style: false,
            invert: true,
            modifiers: {
                x: 'scrollLeft',
                y: 'scrollTop'
            },
            preventDefault: true,
            onDrag: this.dragScroller.bind(this)
        });
    },
    sizeWithoutBorder: function(el) {
        var size = el.getSize();
        
        size.x -= el.getStyle('border-right-width').toInt() +
                  el.getStyle('border-left-width').toInt();
        size.y -= el.getStyle('border-top-width').toInt() +
                  el.getStyle('border-bottom-width').toInt();
        
        return size;
    },
    moveHandle: function(x, y) {
        this.handle.setStyles({
            left: (this.dragLimit.x[0] + Math.round(x)) + 'px',
            top:  (this.dragLimit.y[0] + Math.round(y)) + 'px'
        });
    },
    moveScroller: function(x, y) {
        this.scroller.scrollTo(
            Math.round(x),
            Math.round(y)
        );
    },
    dragHandle: function(el, event) {
        var x = el.getStyle('left').toInt();
        var y = el.getStyle('top').toInt();
        this.moveScroller(
            (x - this.dragLimit.x[0]) * this.factor.x,
            (y - this.dragLimit.y[0]) * this.factor.y
        );
    },
    dragScroller: function(el, event) {
        this.moveHandle(
            this.scroller.scrollLeft / this.factor.x,
            this.scroller.scrollTop  / this.factor.y
        );
    }
});

window.addEvent('domready', function() {
    var zoom = $('zoom');
    new AEZoom(zoom.getElement('.handle'), zoom.getElement('.scroller'));
});

