/**
 * Shadowbox is released under version 3.0 of the Creative Commons Attribution-
 * Noncommercial-Share Alike license. This means that it is absolutely free
 * for personal, noncommercial use provided that you 1) make attribution to the
 * author and 2) release any derivative work under the same or a similar
 * license.
 *
 * If you wish to use Shadowbox for commercial purposes, licensing information
 * can be found at http://mjijackson.com/shadowbox/.
 *
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright   2007-2008 Michael J. I. Jackson
 * @license     http://creativecommons.org/licenses/by-nc-sa/3.0/
 * @version     SVN: $Id: shadowbox.js 108 2008-07-11 04:19:01Z mjijackson $
 */
var Shadowbox = {};

Shadowbox.lib = function(){    
    var styleCache = {};
    var camelRe = /(-[a-z])/gi;
    var camelFn = function(m, a){
        return a.charAt(1).toUpperCase();
    };
    var toCamel = function(style){
        var camel;
        if(!(camel = styleCache[style])){
            camel = styleCache[style] = style.replace(camelRe, camelFn);
        }
        return camel;
    };

    var view = document.defaultView;
    var alphaRe = /alpha\([^\)]*\)/gi;
    var setOpacity = function(el, opacity){
        var s = el.style;
        if(window.ActiveXObject){ 
            s.zoom = 1; 
            s.filter = (s.filter || '').replace(alphaRe, '') +
                (opacity == 1 ? '' : ' alpha(opacity=' + (opacity * 100) + ')');
        }else{
            s.opacity = opacity;
        }
    };

    return {
        adapter: 'standalone',
        getStyle: function(){
            return view && view.getComputedStyle
                ? function(el, style){
                    var v, cs, camel;
                    if(style == 'float') style = 'cssFloat';
                    if(v = el.style[style]) return v;
                    if(cs = view.getComputedStyle(el, '')){
                        return cs[toCamel(style)];
                    }
                    return null;
                }
                : function(el, style){
                    var v, cs, camel;
                    if(style == 'opacity'){
                        if(typeof el.style.filter == 'string'){
                            var m = el.style.filter.match(/alpha\(opacity=(.+)\)/i);
                            if(m){
                                var fv = parseFloat(m[1]);
                                if(!isNaN(fv)) return (fv ? fv / 100 : 0);
                            }
                        }
                        return 1;
                    }else if(style == 'float'){
                        style = 'styleFloat';
                    }
                    var camel = toCamel(style);
                    if(v = el.style[camel]) return v;
                    if(cs = el.currentStyle) return cs[camel];
                    return null;
                };
        }(),
        setStyle: function(el, style, value){
            if(typeof style == 'string'){
                var camel = toCamel(style);
                if(camel == 'opacity'){
                    setOpacity(el, value);
                }else{
                    el.style[camel] = value;
                }
            }else{
                for(var s in style){
                    this.setStyle(el, s, style[s]);
                }
            }
        },
        get: function(el){
            return typeof el == 'string' ? document.getElementById(el) : el;
        },
        remove: function(el){
            el.parentNode.removeChild(el);
        },
        getTarget: function(e){
            var t = e.target ? e.target : e.srcElement;
            return t.nodeType == 3 ? t.parentNode : t;
        },
        getPageXY: function(e){
            var x = e.pageX || (e.clientX +
                (document.documentElement.scrollLeft || document.body.scrollLeft));
            var y = e.pageY || (e.clientY +
                (document.documentElement.scrollTop || document.body.scrollTop));
            return [x, y];
        },
        preventDefault: function(e){
            if(e.preventDefault){
                e.preventDefault();
            }else{
                e.returnValue = false;
            }
        },
        keyCode: function(e){
            return e.which ? e.which : e.keyCode;
        },
        addEvent: function(el, name, handler){
            if(el.addEventListener){
                el.addEventListener(name, handler, false);
            }else if(el.attachEvent){
                el.attachEvent('on' + name, handler);
            }
        },
        removeEvent: function(el, name, handler){
            if(el.removeEventListener){
                el.removeEventListener(name, handler, false);
            }else if(el.detachEvent){
                el.detachEvent('on' + name, handler);
            }
        },
        append: function(el, html){
            if(el.insertAdjacentHTML){
                el.insertAdjacentHTML('BeforeEnd', html);
            }else if(el.lastChild){
                var range = el.ownerDocument.createRange();
                range.setStartAfter(el.lastChild);
                var frag = range.createContextualFragment(html);
                el.appendChild(frag);
            }else{
                el.innerHTML = html;
            }
        }

    };

}();
 
if(typeof Shadowbox == 'undefined'){
    throw 'Unable to load Shadowbox, no base library adapter found';
}

/**
 * @class       Shadowbox
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @singleton
 */
(function(){

    var version = '2.0';

    var options = {
        animate:            true,
        animateFade:        true,
        animSequence:       'wh',
        flvPlayer:          'flvplayer.swf',
        modal:              false,
        overlayColor:       '#000',
        overlayOpacity:     0.8,
        flashBgColor:       '#000000',
        autoplayMovies:     true,
        showMovieControls:  true,
        slideshowDelay:     0,
        resizeDuration:     0.55,
        fadeDuration:       0.35,
        displayNav:         true,
        continuous:         false,
        displayCounter:     true,
        counterType:        'default',
        counterLimit:       10,
        viewportPadding:    20,
        handleOversize:     'resize',
        handleException:    null,
        handleUnsupported:  'link',
        initialHeight:      160,
        initialWidth:       320,
        enableKeys:         true,
        onOpen:             null,
        onFinish:           null,
        onChange:           null,
        onClose:            null,
        skipSetup:          false,
        errors:         {
            fla:        {
                name:   'Flash',
                url:    'http://www.adobe.com/products/flashplayer/'
            },

            qt:         {
                name:   'QuickTime',
                url:    'http://www.apple.com/quicktime/download/'
            },

            wmp:        {
                name:   'Windows Media Player',
                url:    'http://www.microsoft.com/windows/windowsmedia/'
            },

            f4m:        {
                name:   'Flip4Mac',
                url:    'http://www.flip4mac.com/wmv_download.htm'
            }

        },
        ext:     {
            img:        ['png', 'jpg', 'jpeg', 'gif', 'bmp'],
            swf:        ['swf'],
            flv:        ['flv'],
            qt:         ['dv', 'mov', 'moov', 'movie', 'mp4'],
            wmp:        ['asf', 'wm', 'wmv'],
            qtwmp:      ['avi', 'mpg', 'mpeg'],
            iframe:     ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'pl', 'php',
                        'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml',
                        'txt', 'vbs']
        }

    };
    var SB = Shadowbox;
    var SL = SB.lib;
    var default_options;
    var RE = {
        domain:         /:\/\/(.*?)[:\/]/, 
        inline:         /#(.+)$/, 
        rel:            /^(light|shadow)box/i, 
        gallery:        /^(light|shadow)box\[(.*?)\]/i, 
        unsupported:    /^unsupported-(\w+)/, 
        param:          /\s*([a-z_]*?)\s*=\s*(.+)\s*/, 
        empty:          /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i 
    };
    var cache = [];
    var gallery;
    var current;
    var content;
    var content_id = 'shadowbox_content';
    var dims;
    var initialized = false;
    var activated = false;
    var slide_timer;
    var slide_start;
    var slide_delay = 0;
    var ua = navigator.userAgent.toLowerCase();
    var client = {
        isStrict:   document.compatMode == 'CSS1Compat',
        isOpera:    ua.indexOf('opera') > -1,
        isIE:       ua.indexOf('msie') > -1,
        isIE7:      ua.indexOf('msie 7') > -1,
        isSafari:   /webkit|khtml/.test(ua),
        isWindows:  ua.indexOf('windows') != -1 || ua.indexOf('win32') != -1,
        isMac:      ua.indexOf('macintosh') != -1 || ua.indexOf('mac os x') != -1,
        isLinux:    ua.indexOf('linux') != -1
    };
    client.isBorderBox = client.isIE && !client.isStrict;
    client.isSafari3 = client.isSafari && !!(document.evaluate);
    client.isGecko = ua.indexOf('gecko') != -1 && !client.isSafari;


    var ltIE7 = client.isIE && !client.isIE7;


    var plugins;


    if(navigator.plugins && navigator.plugins.length){
        var detectPlugin = function(plugin_name){
            var detected = false;
            for (var i = 0, len = navigator.plugins.length; i < len; ++i){
                if(navigator.plugins[i].name.indexOf(plugin_name) > -1){
                    detected = true;
                    break;
                }
            }
            return detected;
        };
        var f4m = detectPlugin('Flip4Mac');
        plugins = {
            fla:    detectPlugin('Shockwave Flash'),
            qt:     detectPlugin('QuickTime'),
            wmp:    !f4m && detectPlugin('Windows Media'), 
            f4m:    f4m
        };
    }else{
        var detectPlugin = function(plugin_name){
            var detected = false;
            try{
                var axo = new ActiveXObject(plugin_name);
                if(axo) detected = true;
            }catch(e){}
            return detected;
        };
        plugins = {
            fla:    detectPlugin('ShockwaveFlash.ShockwaveFlash'),
            qt:     detectPlugin('QuickTime.QuickTime'),
            wmp:    detectPlugin('wmplayer.ocx'),
            f4m:    false
        };
    }



    var apply = function(o, e){
        for(var p in e) o[p] = e[p];
        return o;
    };


    var isLink = function(el){
        return el && typeof el.tagName == 'string' && (el.tagName.toUpperCase() == 'A' || el.tagName.toUpperCase() == 'AREA');
    };


    SL.getViewportHeight = function(){
        var h = window.innerHeight; 
        var mode = document.compatMode;
        if((mode || client.isIE) && !client.isOpera){
            h = client.isStrict ? document.documentElement.clientHeight : document.body.clientHeight;
        }
        return h;
    };

    SL.getViewportWidth = function(){
        var w = window.innerWidth; 
        var mode = document.compatMode;
        if(mode || client.isIE){
            w = client.isStrict ? document.documentElement.clientWidth : document.body.clientWidth;
        }
        return w;
    };

    SL.createHTML = function(obj){
        var html = '<' + obj.tag;
        for(var attr in obj){
            if(attr == 'tag' || attr == 'html' || attr == 'children') continue;
            if(attr == 'cls'){
                html += ' class="' + obj['cls'] + '"';
            }else{
                html += ' ' + attr + '="' + obj[attr] + '"';
            }
        }
        if(RE.empty.test(obj.tag)){
            html += '/>';
        }else{
            html += '>';
            var cn = obj.children;
            if(cn){
                for(var i = 0, len = cn.length; i < len; ++i){
                    html += this.createHTML(cn[i]);
                }
            }
            if(obj.html) html += obj.html;
            html += '</' + obj.tag + '>';
        }
        return html;
    };

    var ease = function(x){
        return 1 + Math.pow(x - 1, 3);
    };

    var animate = function(el, p, to, d, cb){
        var from = parseFloat(SL.getStyle(el, p));
        if(isNaN(from)) from = 0;

        if(from == to){
            if(typeof cb == 'function') cb();
            return;
        }

        var delta = to - from;
        var op = p == 'opacity';
        var unit = op ? '' : 'px';
        var fn = function(ease){
            SL.setStyle(el, p, from + ease * delta + unit);
        };


        if(!options.animate && !op || op && !options.animateFade){
            fn(1);
            if(typeof cb == 'function') cb();
            return;
        }

        d *= 1000;
        var begin = new Date().getTime();
        var end = begin + d;

        var timer = setInterval(function(){
            var time = new Date().getTime();
            if(time >= end){
                clearInterval(timer);
                fn(1);
                if(typeof cb == 'function') cb();
            }else{
                fn(ease((time - begin) / d));
            }
        }, 10);
    };

    var clearOpacity = function(el){
        var s = el.style;
        if(client.isIE){
            if(typeof s.filter == 'string' && (/alpha/i).test(s.filter)){
                s.filter = s.filter.replace(/[\w\.]*alpha\(.*?\);?/i, '');
            }
        }else{
            s.opacity = '';
            s['-moz-opacity'] = '';
            s['-khtml-opacity'] = '';
        }
    };

    var getComputedHeight = function(el){
        var h = Math.max(el.offsetHeight, el.clientHeight);
        if(!h){
            h = parseInt(SL.getStyle(el, 'height'), 10) || 0;
            if(!client.isBorderBox){
                h += parseInt(SL.getStyle(el, 'padding-top'), 10)
                    + parseInt(SL.getStyle(el, 'padding-bottom'), 10)
                    + parseInt(SL.getStyle(el, 'border-top-width'), 10)
                    + parseInt(SL.getStyle(el, 'border-bottom-width'), 10);
            }
        }
        return h;
    };

    var getPlayer = function(url){
        var m = url.match(RE.domain);
        var d = m && document.domain == m[1];
        if(url.indexOf('#') > -1 && d) return 'inline';
        var q = url.indexOf('?');
        if(q > -1) url = url.substring(0, q);
        if(RE.img.test(url)) return 'img';
        if(RE.swf.test(url)) return plugins.fla ? 'swf' : 'unsupported-swf';
        if(RE.flv.test(url)) return plugins.fla ? 'flv' : 'unsupported-flv';
        if(RE.qt.test(url)) return plugins.qt ? 'qt' : 'unsupported-qt';
        if(RE.wmp.test(url)){
            if(plugins.wmp) return 'wmp';
            if(plugins.f4m) return 'qt';
            if(client.isMac) return plugins.qt ? 'unsupported-f4m' : 'unsupported-qtf4m';
            return 'unsupported-wmp';
        }else if(RE.qtwmp.test(url)){
            if(plugins.qt) return 'qt';
            if(plugins.wmp) return 'wmp';
            return client.isMac ? 'unsupported-qt' : 'unsupported-qtwmp';
        }else if(!d || RE.iframe.test(url)){
            return 'iframe';
        }
        return 'unsupported';
    };

    var handleClick = function(ev){
        var link;
        if(isLink(this)){
            link = this;
        }else{
            link = SL.getTarget(ev);
            while(!isLink(link) && link.parentNode){
                link = link.parentNode;
            }
        }

        if(link){
            SB.open(link);
            if(gallery.length) SL.preventDefault(ev);
        }
    };

    var toggleNav = function(id, on){
        var el = SL.get('shadowbox_nav_' + id);
        if(el) el.style.display = on ? '' : 'none';
    };

    var buildBars = function(cb){
        var obj = gallery[current];
        var title_i = SL.get('shadowbox_title_inner');

        title_i.innerHTML = obj.title || '';

        var nav = SL.get('shadowbox_nav');
        if(nav){
            var c, n, pl, pa, p;

            if(options.displayNav){
                c = true;
                var len = gallery.length;
                if(len > 1){
                    if(options.continuous){
                        n = p = true; 
                    }else{
                        n = (len - 1) > current; 
                        p = current > 0; 
                    }
                }
                
                if(options.slideshowDelay > 0 && hasNext()){
                    pa = slide_timer != 'paused';
                    pl = !pa;
                }
            }else{
                c = n = pl = pa = p = false;
            }

            toggleNav('close', c);
            toggleNav('next', n);
            toggleNav('play', pl);
            toggleNav('pause', pa);
            toggleNav('previous', p);
        }

        
        var counter = SL.get('shadowbox_counter');
        if(counter){
            var co = '';

            
            if(options.displayCounter && gallery.length > 1){
                if(options.counterType == 'skip'){
                    
                    var i = 0, len = gallery.length, end = len;
                    var limit = parseInt(options.counterLimit);
                    if(limit < len){ 
                        var h = Math.round(limit / 2);
                        i = current - h;
                        if(i < 0) i += len;
                        end = current + (limit - h);
                        if(end > len) end -= len;
                    }
                    while(i != end){
                        if(i == len) i = 0;
                        co += '<a onclick="Shadowbox.change(' + i + ');"';
                        if(i == current) co += ' class="shadowbox_counter_current"';
                        co += '>' + (++i) + '</a>';
                    }
                }else{ 
                    co = (current + 1) + ' ' + SB.LANG.of + ' ' + len;
                }
            }

            counter.innerHTML = co;
        }

        cb();
    };

    var hideBars = function(anim, cb){
        var obj = gallery[current];
        var title = SL.get('shadowbox_title');
        var info = SL.get('shadowbox_info');
        var title_i = SL.get('shadowbox_title_inner');
        var info_i = SL.get('shadowbox_info_inner');

        
        var fn = function(){
            buildBars(cb);
        };

        var title_h = getComputedHeight(title);
        var info_h = getComputedHeight(info) * -1;
        if(anim){
            
            animate(title_i, 'margin-top', title_h, 0.35);
            animate(info_i, 'margin-top', info_h, 0.35, fn);
        }else{
            SL.setStyle(title_i, 'margin-top', title_h + 'px');
            SL.setStyle(info_i, 'margin-top', info_h + 'px');
            fn();
        }
    };

    var showBars = function(cb){
        var title_i = SL.get('shadowbox_title_inner');
        var info_i = SL.get('shadowbox_info_inner');
        var t = title_i.innerHTML != ''; 

        if(t) animate(title_i, 'margin-top', 0, 0.35);
        animate(info_i, 'margin-top', 0, 0.35, cb);
    };

    var loadContent = function(){
        var obj = gallery[current];
        if(!obj) return; 

        var changing = false;
        if(content){
            content.remove(); 
            changing = true; 
        }

        
        var p = obj.player == 'inline' ? 'html' : obj.player;

        
        if(typeof SB[p] != 'function'){
            SB.raise('Unknown player ' + obj.player);
        }
        content = new SB[p](content_id, obj); 

        listenKeys(false); 
        toggleLoading(true);

        hideBars(changing, function(){ 
            if(!content) return;

            
            if(!changing){
                 SL.get('shadowbox').style.display = '';
            }

            var fn = function(){
                resizeContent(function(){
                    if(!content) return;


                    showBars(function(){
                        if(!content) return;

                        
                        SL.get('shadowbox_body_inner').innerHTML = SL.createHTML(content.markup(dims));

                        toggleLoading(false, function(){
                            if(!content) return;

                            if(typeof content.onLoad == 'function'){
                                content.onLoad(); 
                            }
                            if(options.onFinish && typeof options.onFinish == 'function'){
                                options.onFinish(gallery[current]); 
                            }
                            if(slide_timer != 'paused'){
                                SB.play(); 
                            }
                            listenKeys(true); 
                        });
                    });
                });
            };

            if(typeof content.ready != 'undefined'){ 
                var id = setInterval(function(){ 
                    if(content){
                        if(content.ready){
                            clearInterval(id); 
                            id = null;
                            fn();
                        }
                    }else{ 
                        clearInterval(id);
                        id = null;
                    }
                }, 100);
            }else{
                fn();
            }
        });

        
        if(gallery.length > 1){
            var next = gallery[current + 1] || gallery[0];
            if(next.player == 'img'){
                var a = new Image();
                a.src = next.content;
            }
            var prev = gallery[current - 1] || gallery[gallery.length - 1];
            if(prev.player == 'img'){
                var b = new Image();
                b.src = prev.content;
            }
        }
    };

    var setDimensions = function(height, width, resizable){
        resizable = resizable || false;

        var sb = SL.get('shadowbox_body');
        var h = height = parseInt(height);
        var w = width = parseInt(width);
        var view_h = SL.getViewportHeight();
        var view_w = SL.getViewportWidth();

        
        var border_w = parseInt(SL.getStyle(sb, 'border-left-width'), 10)
            + parseInt(SL.getStyle(sb, 'border-right-width'), 10);
        var extra_w = border_w + 2 * options.viewportPadding;
        if(w + extra_w >= view_w){
            w = view_w - extra_w;
        }

        
        var border_h = parseInt(SL.getStyle(sb, 'border-top-width'), 10)
            + parseInt(SL.getStyle(sb, 'border-bottom-width'), 10);
        var bar_h = getComputedHeight(SL.get('shadowbox_title'))
            + getComputedHeight(SL.get('shadowbox_info'));
        var extra_h = border_h + 2 * options.viewportPadding + bar_h;
        if(h + extra_h >= view_h){
            h = view_h - extra_h;
        }

        
        var drag = false;
        var resize_h = height;
        var resize_w = width;
        var handle = options.handleOversize;
        if(resizable && (handle == 'resize' || handle == 'drag')){
            var change_h = (height - h) / height;
            var change_w = (width - w) / width;
            if(handle == 'resize'){
                if(change_h > change_w){
                    w = Math.round((width / height) * h);
                }else if(change_w > change_h){
                    h = Math.round((height / width) * w);
                }
                
                resize_w = w;
                resize_h = h;
            }else{
                
                var link = gallery[current];
                if(link) drag = link.player == 'img' && (change_h > 0 || change_w > 0);
            }
        }

        
        dims = {
            height:     h + border_h + bar_h,
            width:      w + border_w,
            inner_h:    h,
            inner_w:    w,
            top:        (view_h - (h + extra_h)) / 2 + options.viewportPadding,
            resize_h:   resize_h,
            resize_w:   resize_w,
            drag:       drag
        };
    };

    var resizeContent = function(cb){
        if(!content) return; 

        
        setDimensions(content.height, content.width, content.resizable);

        if(cb){
            switch(options.animSequence){
                case 'hw':
                    adjustHeight(dims.inner_h, dims.top, true, function(){
                        adjustWidth(dims.width, true, cb);
                    });
                    break;
                case 'wh':
                    adjustWidth(dims.width, true, function(){
                        adjustHeight(dims.inner_h, dims.top, true, cb);
                    });
                    break;
                case 'sync':
                default:
                    adjustWidth(dims.width, true);
                    adjustHeight(dims.inner_h, dims.top, true, cb);
            }
        }else{ 
            adjustWidth(dims.width, false);
            adjustHeight(dims.inner_h, dims.top, false);
            var c = SL.get(content_id);
            if(c){
                
                if(content.resizable && options.handleOversize == 'resize'){
                    c.height = dims.resize_h;
                    c.width = dims.resize_w;
                }
                
                if(gallery[current].player == 'img' && options.handleOversize == 'drag'){
                    var top = parseInt(SL.getStyle(c, 'top'));
                    if(top + content.height < dims.inner_h){
                        SL.setStyle(c, 'top', dims.inner_h - content.height + 'px');
                    }
                    var left = parseInt(SL.getStyle(c, 'left'));
                    if(left + content.width < dims.inner_w){
                        SL.setStyle(c, 'left', dims.inner_w - content.width + 'px');
                    }
                }
            }
        }
    };

    var adjustHeight = function(height, top, anim, cb){
        height = parseInt(height);

        
        var sb = SL.get('shadowbox_body');
        if(anim){
            animate(sb, 'height', height, options.resizeDuration);
        }else{
            SL.setStyle(sb, 'height', height + 'px');
        }

        
        var s = SL.get('shadowbox');
        if(anim){
            animate(s, 'top', top, options.resizeDuration, cb);
        }else{
            SL.setStyle(s, 'top', top + 'px');
            if(typeof cb == 'function') cb();
        }
    };

    var adjustWidth = function(width, anim, cb){
        width = parseInt(width);

        
        var s = SL.get('shadowbox');
        if(anim){
            animate(s, 'width', width, options.resizeDuration, cb);
        }else{
            SL.setStyle(s, 'width', width + 'px');
            if(typeof cb == 'function') cb();
        }
    };

    var listenKeys = function(on){
        if(!options.enableKeys) return;
        SL[(on ? 'add' : 'remove') + 'Event'](document, 'keydown', handleKey);
    };

    var handleKey = function(e){
        var code = SL.keyCode(e);

        
        SL.preventDefault(e);

        if(code == 81 || code == 88 || code == 27){ 
            SB.close();
        }else if(code == 37){ 
            SB.previous();
        }else if(code == 39){ 
            SB.next();
        }else if(code == 32){ 
            SB[(typeof slide_timer == 'number' ? 'pause' : 'play')]();
        }
    };

    var toggleLoading = function(on, cb){
        var loading = SL.get('shadowbox_loading');
        if(on){
            loading.style.display = '';
            if(typeof cb == 'function') cb();
        }else{
            var p = gallery[current].player;
            var anim = (p == 'img' || p == 'html'); 
            var fn = function(){
                loading.style.display = 'none';
                clearOpacity(loading);
                if(typeof cb == 'function') cb();
            };
            if(anim){
                animate(loading, 'opacity', 0, options.fadeDuration, fn);
            }else{
                fn();
            }
        }
    };

    var fixTop = function(){
        SL.get('shadowbox_container').style.top = document.documentElement.scrollTop + 'px';
    };

    var fixHeight = function(){
        SL.get('shadowbox_overlay').style.height = SL.getViewportHeight() + 'px';
    };

    var hasNext = function(){
        return gallery.length > 1 && (current != gallery.length - 1 || options.continuous);
    };

    var toggleVisible = function(cb){
        var els, v = (cb) ? 'hidden' : 'visible';
        var hide = ['select', 'object', 'embed']; 
        for(var i = 0; i < hide.length; ++i){
            els = document.getElementsByTagName(hide[i]);
            for(var j = 0, len = els.length; j < len; ++j){
                els[j].style.visibility = v;
            }
        }

        
        var so = SL.get('shadowbox_overlay');
        var sc = SL.get('shadowbox_container');
        var sb = SL.get('shadowbox');
        if(cb){
            
            SL.setStyle(so, {
                backgroundColor: options.overlayColor,
                opacity: 0
            });
            if(!options.modal) SL.addEvent(so, 'click', SB.close);
            if(ltIE7){
                
                fixTop();
                fixHeight();
                SL.addEvent(window, 'scroll', fixTop);
            }

            
            sb.style.display = 'none'; 
            sc.style.visibility = 'visible';
            animate(so, 'opacity', parseFloat(options.overlayOpacity), options.fadeDuration, cb);
        }else{
            SL.removeEvent(so, 'click', SB.close);
            if(ltIE7) SL.removeEvent(window, 'scroll', fixTop);

            
            sb.style.display = 'none';
            animate(so, 'opacity', 0, options.fadeDuration, function(){
                sc.style.visibility = 'hidden';
                sb.style.display = '';
                clearOpacity(so);
            });
        }
    };

    Shadowbox.init = function(opts){
        
        if(initialized) return;

        
        if(typeof SB.LANG == 'undefined'){
            SB.raise('No Shadowbox language loaded');
            return;
        }
        
        if(typeof SB.SKIN == 'undefined'){
            SB.raise('No Shadowbox skin loaded');
            return;
        }

        
        apply(options, opts || {});

        
        var markup = SB.SKIN.markup.replace(/\{(\w+)\}/g, function(m, p){
            return SB.LANG[p];
        });
        var bd = document.body || document.documentElement;
        SL.append(bd, markup);

        
        if(ltIE7){
            
            SL.setStyle(SL.get('shadowbox_container'), 'position', 'absolute');
            
            SL.get('shadowbox_body').style.zoom = 1;
            
            var png = SB.SKIN.png_fix;
            if(png && png.constructor == Array){
                for(var i = 0; i < png.length; ++i){
                    var el = SL.get(png[i]);
                    if(el){
                        var match = SL.getStyle(el, 'background-image').match(/url\("(.*\.png)"\)/);
                        if(match){
                            SL.setStyle(el, {
                                backgroundImage: 'none',
                                filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,src=' + match[1] + ',sizingMethod=scale);'
                            });
                        }
                    }
                }
            }
        }

        
        for(var e in options.ext){
            RE[e] = new RegExp('\.(' + options.ext[e].join('|') + ')\s*$', 'i');
        }

        
        var id;
        SL.addEvent(window, 'resize', function(){
            
            if(id){
                clearTimeout(id);
                id = null;
            }
            id = setTimeout(function(){
                if(ltIE7) fixHeight();
                resizeContent();
            }, 50);
        });

        if(!options.skipSetup) SB.setup();
        initialized = true;
    };

    Shadowbox.loadSkin = function(skin, dir){
        if(!(/\/$/.test(dir))) dir += '/';
        skin = dir + skin + '/';

        
        document.write('<link rel="stylesheet" type="text/css" href="' + skin + 'skin.css">');
        document.write('<scr' + 'ipt type="text/javascript" src="' + skin + 'skin.js"><\/script>');
    };

    Shadowbox.loadLanguage = function(lang, dir){
        if(!(/\/$/.test(dir))) dir += '/';

        
        document.write('<scr' + 'ipt type="text/javascript" src="' + dir + 'shadowbox-' + lang + '.js"><\/script>');
    };

    Shadowbox.loadPlayer = function(players, dir){
        if(typeof players == 'string') players = [players];
        if(!(/\/$/.test(dir))) dir += '/';

        for(var i = 0, len = players.length; i < len; ++i){
            
            document.write('<scr' + 'ipt type="text/javascript" src="' + dir + 'shadowbox-' + players[i] + '.js"><\/script>');
        }
    };
    Shadowbox.setup = function(links, opts){
        
        if(!links){
            var links = [];
            var a = document.getElementsByTagName('a'), rel;
            for(var i = 0, len = a.length; i < len; ++i){
                rel = a[i].getAttribute('rel');
                if(rel && RE.rel.test(rel)) links[links.length] = a[i];
            }
        }else if(!links.length){
            links = [links]; 
        }

        var link;
        for(var i = 0, len = links.length; i < len; ++i){
            link = links[i];
            if(typeof link.shadowboxCacheKey == 'undefined'){
                
                
                link.shadowboxCacheKey = cache.length;
                SL.addEvent(link, 'click', handleClick); 
            }
            cache[link.shadowboxCacheKey] = this.buildCacheObj(link, opts);
        }
    };

    Shadowbox.buildCacheObj = function(link, opts){
        var href = link.href; 
        var o = {
            el:         link,
            title:      link.getAttribute('title'),
            player:     getPlayer(href),
            options:    apply({}, opts || {}), 
            content:    href
        };

        
        var opt, l_opts = ['player', 'title', 'height', 'width', 'gallery'];
        for(var i = 0, len = l_opts.length; i < len; ++i){
            opt = l_opts[i];
            if(typeof o.options[opt] != 'undefined'){
                o[opt] = o.options[opt];
                delete o.options[opt];
            }
        }

        
        var rel = link.getAttribute('rel');
        if(rel){
            
            var match = rel.match(RE.gallery);
            if(match) o.gallery = escape(match[2]);

            
            var params = rel.split(';');
            for(var i = 0, len = params.length; i < len; ++i){
                match = params[i].match(RE.param);
                if(match){
                    if(match[1] == 'options'){
                        eval('apply(o.options, ' + match[2] + ')');
                    }else{
                        o[match[1]] = match[2];
                    }
                }
            }
        }

        return o;
    };

    Shadowbox.applyOptions = function(opts){
        if(opts){
            
            default_options = apply({}, options); 
            options = apply(options, opts); 
        }
    };

    Shadowbox.revertOptions = function(){
        if(default_options){
            options = default_options; 
            default_options = null; 
        }
    };

    Shadowbox.open = function(obj, opts){
        
        this.revertOptions();

        
        if(isLink(obj)){
            if(typeof obj.shadowboxCacheKey == 'undefined' || typeof cache[obj.shadowboxCacheKey] == 'undefined'){
                
                
                obj = this.buildCacheObj(obj, opts);
            }else{
                
                obj = cache[obj.shadowboxCacheKey];
            }
        }

        
        if(obj.constructor == Array){
            gallery = obj;
            current = 0;
        }else{
            
            var copy = apply({}, obj);

            
            if(!obj.gallery){ 
                gallery = [copy];
                current = 0;
            }else{
                current = null; 
                gallery = []; 
                var ci;
                for(var i = 0, len = cache.length; i < len; ++i){
                    ci = cache[i];
                    if(ci.gallery){
                        if(ci.content == obj.content
                            && ci.gallery == obj.gallery
                            && ci.title == obj.title){ 
                                current = gallery.length; 
                        }
                        if(ci.gallery == obj.gallery){
                            gallery.push(apply({}, ci));
                        }
                    }
                }
                
                if(current == null){
                    gallery.unshift(copy);
                    current = 0;
                }
            }
        }

        obj = gallery[current];

        
        if(obj.options || opts){
            
            this.applyOptions(apply(apply({}, obj.options || {}), opts || {}));
        }

        
        var match, r;
        for(var i = 0, len = gallery.length; i < len; ++i){
            r = false; 
            if(gallery[i].player == 'unsupported'){ 
                r = true;
            }else if(match = RE.unsupported.exec(gallery[i].player)){ 
                if(options.handleUnsupported == 'link'){
                    gallery[i].player = 'html';
                    
                    var s, a, oe = options.errors;
                    switch(match[1]){
                        case 'qtwmp':
                            s = 'either';
                            a = [oe.qt.url, oe.qt.name, oe.wmp.url, oe.wmp.name];
                        break;
                        case 'qtf4m':
                            s = 'shared';
                            a = [oe.qt.url, oe.qt.name, oe.f4m.url, oe.f4m.name];
                        break;
                        default:
                            s = 'single';
                            if(match[1] == 'swf' || match[1] == 'flv') match[1] = 'fla';
                            a = [oe[match[1]].url, oe[match[1]].name];
                    }
                    var msg = SB.LANG.errors[s].replace(/\{(\d+)\}/g, function(m, i){
                        return a[i];
                    });
                    gallery[i].content = '<div class="shadowbox_message">' + msg + '</div>';
                }else{
                    r = true;
                }
            }else if(gallery[i].player == 'inline'){ 
                
                var match = RE.inline.exec(gallery[i].content);
                if(match){
                    var el;
                    if(el = SL.get(match[1])){
                        gallery[i].content = el.innerHTML;
                    }else{
                        SB.raise('Cannot find element with id ' + match[1]);
                    }
                }else{
                    SB.raise('Cannot find element id for inline content');
                }
            }
            if(r){
                gallery.splice(i, 1); 
                if(i < current){
                    --current;
                }else if(i == current){
                    
                    current = i > 0 ? current - 1 : i;
                }
                --i; 
                len = gallery.length; 
            }
        }

        
        if(gallery.length){
            
            if(options.onOpen && typeof options.onOpen == 'function'){
                options.onOpen(obj);
            }

            if(!activated){
				
                SL.setStyle(SL.get('shadowbox_container'),{display:'block'}); 
                
                setDimensions(options.initialHeight, options.initialWidth);
                adjustHeight(dims.inner_h, dims.top, false);
                adjustWidth(dims.width, false);
                toggleVisible(loadContent);
            } else {
                loadContent();
            }

            activated = true;
        }
    };

    Shadowbox.change = function(num){
        if(!gallery) return; 
        if(!gallery[num]){ 
            if(!options.continuous){
                return;
            }else{
                num = num < 0 ? (gallery.length - 1) : 0; 
            }
        }

        if(typeof slide_timer == 'number'){
            clearTimeout(slide_timer);
            slide_timer = null;
            slide_delay = slide_start = 0; 
        }
        current = num; 

        if(options.onChange && typeof options.onChange == 'function'){
            options.onChange(gallery[current]); 
        }

        loadContent();
    };

    Shadowbox.next = function(){
        this.change(current + 1);
    };

    Shadowbox.previous = function(){
        this.change(current - 1);
    };

    Shadowbox.play = function(){
        if(!hasNext()) return;
        if(!slide_delay) slide_delay = options.slideshowDelay * 1000;
        if(slide_delay){
            slide_start = new Date().getTime();
            slide_timer = setTimeout(function(){
                slide_delay = slide_start = 0; 
                SB.next();
            }, slide_delay);

            
            toggleNav('play', false);
            toggleNav('pause', true);
        }
    };

    Shadowbox.pause = function(){
        if(typeof slide_timer == 'number'){
            var time = new Date().getTime();
            slide_delay = Math.max(0, slide_delay - (time - slide_start));

            
            if(slide_delay){
                clearTimeout(slide_timer);
                slide_timer = 'paused';
            }

            
            toggleNav('pause', false);
            toggleNav('play', true);
        }
    };

    Shadowbox.close = function(){
        if(!activated) return; 

        
        listenKeys(false);
        
        toggleVisible(false);
		
        SL.setStyle(SL.get('shadowbox_container'),{display:'none'}); 
        
        if(content){
            content.remove();
            content = null;
        }

        
        if(typeof slide_timer == 'number') clearTimeout(slide_timer);
        slide_timer = null;
        slide_delay = 0;

        
        if(options.onClose && typeof options.onClose == 'function'){
            options.onClose(gallery[current]);
        }

        activated = false;
    };

    Shadowbox.clearCache = function(){
        for(var i = 0, len = cache.length; i < len; ++i){
            if(cache[i].el){
                SL.removeEvent(cache[i].el, 'click', handleClick);
                delete cache[i].el.shadowboxCacheKey; 
            }
        }
        cache = [];
    };

    Shadowbox.getPlugins = function(){
        return plugins;
    };

    Shadowbox.getOptions = function(){
        return options;
    };

    Shadowbox.getCurrent = function(){
        return gallery[current];
    };

    Shadowbox.getVersion = function(){
        return version;
    };

    Shadowbox.getClient = function(){
        return client;
    };

    Shadowbox.getContent = function(){
        return content;
    };

    Shadowbox.getDimensions = function(){
        return dims;
    };

    Shadowbox.raise = function(e){
        if(typeof options.handleException == 'function'){
            options.handleException(e);
        }else{
            throw e;
        }
    };

})();