/* jzoomit.js * v1.0
Copyright (c) 2010, Victor Soroka, http://www.jzoomit.com
Liscensed under the MIT License (http://www.jzoomit.com/MIT-LICENSE.txt)
*/

if ( typeof jzoomit == 'undefined' )
jzoomit = new function() {
    var
    numSteps = 15,
    delay = 15,

    dd = null,
    src = null,
    el = {},

    iTicker = 0,
    iLoading = null,
    iAnimate = null,

    Show = function()
    {
        el.big.style.left = parseInt(dd.ix+=dd.dx)+'px';
        el.big.style.top = parseInt(dd.iy+=dd.dy)+'px';
        el.big.style.width = parseInt(dd.iw+=dd.dw)+'px';
        el.big.style.height = parseInt(dd.ih+=dd.dh)+'px';
        if ( --dd.step ) return;
        // Finished
        el.big.src = src;
        clearInterval(iAnimate);
        iAnimate = null;
        el.overlay.className = 'jzoomitOverlay';
        return;
    },

    Hide = function()
    {
        if ( el.big.src != el.thumb.src ) el.big.src = el.thumb.src;
        el.big.style.left = parseInt(dd.ix-=dd.dx)+'px';
        el.big.style.top = parseInt(dd.iy-=dd.dy)+'px';
        el.big.style.width = parseInt(dd.iw-=dd.dw)+'px';
        el.big.style.height = parseInt(dd.ih-=dd.dh)+'px';
        if ( --dd.step ) return;
        // Finished
        clearInterval(iAnimate);
        iAnimate = null;
        if ( el.big )
        {
            if ( el.big.offsetParent ) document.body.removeChild(el.big);
            delete el.big;
        }
        if ( el.overlay ) { document.body.removeChild(el.overlay); delete el.overlay; }
        el.thumb = null;
        return;
    },

    Close = function()
    {
        DetachEvent(el.big, 'click', Close);
        DetachEvent(el.overlay, 'click', Close);
        if ( iLoading ) { clearTimeout(iLoading); iLoading = null; }
        if ( iAnimate ) { clearTimeout(iAnimate); iAnimate = null; }
        if ( el.loading ) { document.body.removeChild(el.loading); delete el.loading; }
        el.overlay.className = '';

        if ( el.big.complete )
        {
            dd.step = dd.step > 0 ? numSteps-dd.step : numSteps;
            iAnimate = setInterval(Hide, delay);
        }
        else
        {
            if ( el.big )
            {
                if ( el.big.offsetParent ) document.body.removeChild(el.big);
                delete el.big;
            }
            if ( el.overlay ) { document.body.removeChild(el.overlay); delete el.overlay; }
        }
    },

    OnKey = function(e)
    {
        if ( e.keyCode != 27 ) return e;
        DetachEvent(document, 'keypress', OnKey);
        Close();
    }

    Loading = function()
    {
        if ( !el.big.complete )
        {
            if ( iTicker++ > 600 )
            {
                // Image has not been loaded, cancelling zoom
                clearInterval(iLoading);
                iLoading = null;
                document.body.removeChild(el.loading);
                delete el.loading;
            }
            else if ( !el.loading )
            {
                // Add LOADING hover
                el.loading = document.createElement('div');
                document.body.appendChild(el.loading);
                var l = el.loading, t = el.thumb, pos = GetXY(t);
                l.className = 'jzoomitLoading';
                l.innerHTML = 'Loading...';
                l.style.position = 'absolute';
                l.style.zIndex = '1000';
                l.style.left = parseInt(pos.x + (t.clientWidth - l.clientWidth)/2)+'px';
                l.style.top = parseInt(pos.y + (t.clientHeight - l.clientHeight)/2)+'px';
            }
            return;
        }
        // Image loaded
        clearInterval(iLoading);
        if ( el.loading )
        {
            document.body.removeChild(el.loading);
            delete el.loading;
        }

        var sw = document.documentElement ? document.documentElement.clientWidth : window.innerWidth,
            sh = document.documentElement ? document.documentElement.clientHeight : window.innerHeight,
            bw = el.big.width,
            bh = el.big.height,
            ox = GetScrollLeft(),
            oy = GetScrollTop();

        document.body.appendChild(el.big);
        el.big.style.position = 'absolute';
        el.big.style.zIndex = '1001';
        el.big.style.left = el.big.style.top = '-10000px';

        var bcw = el.big.clientWidth,
            bch = el.big.clientHeight,
            pos = GetXY(el.thumb);

        dd = {
            step: numSteps,
            bw: bw,
            bh: bh,
            bcw: bcw,
            bch: bch
        };

        if ( bcw > sw-20 )
        {
            bw = bw-bcw+sw-20;
            bh = bh*bw/dd.bw;
            bcw -= dd.bw-bw;
            bch -= dd.bh-bh;
        }
        if ( bch > sh-20 )
        {
            bh = bh-bch+sh-20;
            bw = bw*bh/dd.bh;
            bcw -= dd.bw-bw;
            bch -= dd.bh-bh;
        }

        // Initial values
        dd.ix = pos.x-(bcw-bw)/2;
        dd.iy = pos.y-(bch-bh)/2;
        dd.iw = el.thumb.width;
        dd.ih = el.thumb.height;

        // Final values
        dd.fx = dd.ix+dd.iw/2-bcw/2;
        dd.fy = dd.iy+dd.ih/2-bch/2;
        dd.fw = bw;
        dd.fh = bh;

        if ( dd.fx+bcw > sw-10+ox ) dd.fx = sw-10+ox-bcw;
        if ( dd.fy+bch > sh-10+oy ) dd.fy = sh-10+oy-bch;
        if ( dd.fx < ox+10 ) dd.fx = ox+10;
        if ( dd.fy < oy+10 ) dd.fy = oy+10;

        // Steps
        dd.dx = (dd.fx-dd.ix)/numSteps;
        dd.dy = (dd.fy-dd.iy)/numSteps;
        dd.dw = (dd.fw-dd.iw)/numSteps;
        dd.dh = (dd.fh-dd.ih)/numSteps;

        // Set initial position
        el.big.style.left = dd.ix+'px';
        el.big.style.top = dd.iy+'px';
        el.big.style.width = dd.iw+'px';
        el.big.style.height = dd.ih+'px';

        el.big.src = el.thumb.src;
        AttachEvent(el.big, 'click', Close);

        // Animate it
        iAnimate = setInterval(Show, delay);
    },

    // Misc functions

    GetScrollTop = function()
    {
        return self.pageYOffset || (document.documentElement && document.documentElement.scrollTop) || (document.body && document.body.scrollTop);
    },

    GetScrollLeft = function()
    {
        return self.pageXOffset || (document.documentElement && document.documentElement.scrollLeft) || (document.body && document.body.scrollLeft);
    },

    GetXY = function(p)
    {
        var s = {x: 0, y: 0};
        if ( p.getBoundingClientRect )
        {
            // Internet Explorer sheme
            var oBox = p.getBoundingClientRect();
            s.y = parseInt(oBox.top) + GetScrollTop();
            s.x = parseInt(oBox.left) + GetScrollLeft();
        }
        else
        {
            while (p.offsetParent)
            {
                s.x += p.offsetLeft;
                s.y += p.offsetTop;
                p = p.offsetParent;
            }
        }
        return s;
    },

    GetDocSize = function()
    {
        var db = document.body, dde = document.documentElement;
        return {
            width: Math.max(db.scrollWidth, dde.scrollWidth, db.offsetWidth, dde.offsetWidth, db.clientWidth, dde.clientWidth),
            height: Math.max(db.scrollHeight, dde.scrollHeight, db.offsetHeight, dde.offsetHeight, db.clientHeight, dde.clientHeight)
        };
    },

    AttachEvent = function(element, event, callback)
    {
        if ( element.addEventListener )
            element.addEventListener(event, callback, false);
        else
            element.attachEvent('on'+event, callback);
    },

    DetachEvent = function(element, event, callback)
    {
        if ( element.removeEventListener )
            element.removeEventListener(event, callback, false);
        else
            element.detachEvent('on'+event, callback);
    }

    // Public methods
    return {
        Open: function(o)
        {
            // Check if some image is already open
            if ( el.thumb != null ) return false;
            // Check for correct html
            if ( typeof o != 'object' || typeof o.tagName == 'undefined' || o.tagName != 'A' ) return false;
            if ( o.firstChild == null || o.childNodes.length > 1 || o.firstChild.tagName != 'IMG' || !o.firstChild.complete ) return false;

            el.thumb = o.firstChild;
            src = o.href;

            AttachEvent(document, 'keypress', OnKey);

            // Create OVERLAY
            el.overlay = document.createElement('div');
            document.body.appendChild(el.overlay);
            var ds = GetDocSize(), s = el.overlay.style;
            s.position = 'absolute';
            s.zIndex = '1000';
            s.top = s.left= '0px';
            s.width = ds.width+'px';
            s.height = ds.height+'px';
            AttachEvent(el.overlay, 'click', Close);

            // Create BIG image container
            el.big = document.createElement('img');
            el.big.className = 'jzoomitBig';
            iTicker = 0;
            iLoading = setInterval(Loading, 100);
            el.big.src = src;

            return false;
        }
    }
}

