/**

 * jQuery Lightbox Plugin (balupton edition) - Lightboxes for jQuery

 * Copyright (C) 2008 Benjamin Arthur Lupton

 * http://jquery.com/plugins/project/jquerylightbox_bal

 *

 * This file is part of jQuery Lightbox (balupton edition).

 * 

 * jQuery Lightbox (balupton edition) is free software: you can redistribute it and/or modify

 * it under the terms of the GNU Affero General Public License as

 * published by the Free Software Foundation, either version 3 of the

 * License, or (at your option) any later version.

 * 

 * jQuery Lightbox (balupton edition) 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 Affero General Public License for more details.

 * 

 * You should have received a copy of the GNU Affero General Public License

 * along with jQuery Lightbox (balupton edition).  If not, see <http://www.gnu.org/licenses/>.

 *

 * @name jquery_lightbox: jquery.lightbox.js

 * @package jQuery Lightbox Plugin (balupton edition)

 * @version 1.3.7-final

 * @date April 25, 2009

 * @category jQuery plugin

 * @author Benjamin "balupton" Lupton {@link http://www.balupton.com}

 * @copyright (c) 2008 Benjamin Arthur Lupton {@link http://www.balupton.com}

 * @license GNU Affero General Public License - {@link http://www.gnu.org/licenses/agpl.html}

 * @example Visit {@link http://jquery.com/plugins/project/jquerylightbox_bal} for more information.

 */



// Start of our jQuery Plugin

(function($)

{   // Create our Plugin function, with $ as the argument (we pass the jQuery object over later)

    // More info: http://docs.jquery.com/Plugins/Authoring#Custom_Alias

    

    // Debug

    if ( typeof $.log === 'undefined' ) {

        if ( !$.browser.safari && typeof window.console !== 'undefined' && typeof window.console.log === 'function' )

        {   // Use window.console

            $.log = function(){

                var args = [];

                for(var i = 0; i < arguments.length; i++) {

                    args.push(arguments[i]);

                }

                window.console.log.apply(window.console, args);

            }

            $.console = {

                log:    $.log,

                debug:  window.console.debug    || $.log,

                warn:   window.console.warn     || $.log,

                error:  window.console.error    || $.log,

                trace:  window.console.trace    || $.log

            }

        }

        else

        {   // Don't use anything

            $.log = function ( ) { };

            $.console = {

                log:    $.log,

                debug:  $.log,

                warn:   $.log,

                error:  alert,

                trace:  $.log

            };

        }

    }

    

    // Pre-Req

    $.params_to_json = $.params_to_json || function ( params )

    {   // Turns a params string or url into an array of params

        // Adjust

        params = String(params);

        // Remove url if need be

        params = params.substring(params.indexOf('?')+1);

        // params = params.substring(params.indexOf('#')+1);

        // Change + to %20, the %20 is fixed up later with the decode

        params = params.replace(/\+/g, '%20');

        // Do we have JSON string

        if ( params.substring(0,1) === '{' && params.substring(params.length-1) === '}' )

        {   // We have a JSON string

            return eval(decodeURIComponent(params));

        }

        // We have a params string

        params = params.split(/\&|\&amp\;/);

        var json = {};

        // We have params

        for ( var i = 0, n = params.length; i < n; ++i )

        {

            // Adjust

            var param = params[i] || null;

            if ( param === null ) { continue; }

            param = param.split('=');

            if ( param === null ) { continue; }

            // ^ We now have "var=blah" into ["var","blah"]

            

            // Get

            var key = param[0] || null;

            if ( key === null ) { continue; }

            if ( typeof param[1] === 'undefined' ) { continue; }

            var value = param[1];

            // ^ We now have the parts

            

            // Fix

            key = decodeURIComponent(key);

            value = decodeURIComponent(value);

            try {

                // value can be converted

                value = eval(value);

            } catch ( e ) {

                // value is a normal string

            }

            

            // Set

            // console.log({'key':key,'value':value}, split);

            var keys = key.split('.');

            if ( keys.length === 1 )

            {   // Simple

                json[key] = value;

            }

            else

            {   // Advanced

                var path = '';

                for ( ii in keys )

                {   //

                    key = keys[ii];

                    path += '.'+key;

                    eval('json'+path+' = json'+path+' || {}');

                }

                eval('json'+path+' = value');

            }

            // ^ We now have the parts added to your JSON object

        }

        return json;

    };

    

    // Declare our class

    $.LightboxClass = function ( )

    {   // This is the handler for our constructor

        this.construct();

    };



    // Extend jQuery elements for Lightbox

    $.fn.lightbox = function ( options )

    {   // Init a el for Lightbox

        // Eg. $('#gallery a').lightbox();

        

        // If need be: Instantiate $.LightboxClass to $.Lightbox

        $.Lightbox = $.Lightbox || new $.LightboxClass();

        

        // Handle IE6 appropriatly

        if ( $.Lightbox.ie6 && !$.Lightbox.ie6_support )

        {   // We are IE6 and we want to ignore

            return this; // chain

        }

        

        // Establish options

        options = $.extend({start:false,events:true} /* default options */, options);

        

        // Get group

        var group = $(this);

        

        // Events?

        if ( options.events )

        {   // Add events

            $(group).unbind('click').click(function(){

                // Get obj

                var obj = $(this);

                // Get rel

                // var rel = $(obj).attr('rel');

                // Init group

                if ( !$.Lightbox.init($(obj)[0], group) )

                {   return false;   }

                // Display lightbox

                if ( !$.Lightbox.start() )

                {   return false;   }

                // Cancel href

                return false;

            });

            // Add style

            $(group).addClass('lightbox-enabled');

        }

        

        // Start?

        if ( options.start )

        {   // Start

            // Get obj

            var obj = $(this);

            // Get rel

            // var rel = $(obj).attr('rel');

            // Init group

            if ( !$.Lightbox.init($(obj)[0], group) )

            {   return this;    }

            // Display lightbox

            if ( !$.Lightbox.start() )

            {   return this;    }

        }

        

        // And chain

        return this;

    };

    

    // Define our class

    $.extend($.LightboxClass.prototype,

    {   // Our LightboxClass definition

        

        // -----------------

        // Everyting to do with images

        

        images: {

            

            // -----------------

            // Variables

            

            // Our array of images

            list:[], /* [ {

                src: 'url to image',

                link: 'a link to a page',

                title: 'title of the image',

                name: 'name of the image',

                description: 'description of the image'

            } ], */

            

            // The current active image

            image: false,

            

            // -----------------

            // Functions

            

            prev: function ( image )

            {   // Get previous image

                

                // Get previous from current?

                if ( typeof image === 'undefined' )

                {   image = this.active();

                    if ( !image ) { return image; }

                }

                

                // Is there a previous?

                if ( this.first(image) )

                {   return false;   }

                

                // Get the previous

                return this.get(image.index-1);

            },

            

            next: function ( image )

            {   // Get next image

                

                // Get next from current?

                if ( typeof image === 'undefined' )

                {   image = this.active();

                    if ( !image ) { return image; }

                }

                

                // Is there a next?

                if ( this.last(image) )

                {   return false;   }

                

                // Get the next

                return this.get(image.index+1);

            },

            

            first: function ( image )

            {   //

                // Get the first image?

                if ( typeof image === 'undefined' )

                {   return this.get(0); }

                

                // Are we the first?

                return image.index === 0;

            },

            

            last: function ( image )

            {   //

                // Get the last image?

                if ( typeof image === 'undefined' )

                {   return this.get(this.size()-1); }

                

                // Are we the last?

                return image.index === this.size()-1;

            },

        

            single: function ( )

            {   // Are we only one

                return this.size() === 1;

            },

            

            size: function ( )

            {   // How many images do we have

                return this.list.length;

            },

            

            empty: function ( )

            {   // Are we empty

                return this.size() === 0;

            },

            

            clear: function ( )

            {   // Clear image arrray

                this.list = [];

                this.image = false;

            },

        

            active: function ( image )

            {   // Set or get the active image

                // Use false to reset

                

                // Get the active image?

                if ( typeof image === 'undefined' )

                {   return this.image;  }

                

                // Set the ative image

                if ( image !== false )

                {   // Make sure image exists

                    image = this.get(image);

                    if ( !image )

                    {   // Error

                        return image;

                    }

                }

                

                // Set the active image

                this.image = image;

                return true;

            },

        

            add: function ( obj )

            {

                // Do we need to recurse?

                if ( obj[0] )

                {   // We have a lot of images

                    for ( var i = 0; i < obj.length; i++ )

                    {   this.add(obj[i]);   }

                    return true;

                }

                

                // Default image

                

                // Try and create a image

                var image = this.create(obj);

                if ( !image ) { return image; }

                

                // Set image index

                image.index = this.size();

                

                // Push image

                this.list.push(image);

                

                // Success

                return true;

            },

            

            create: function ( obj )

            {   // Create image

                

                // Define

                var image = { // default

                    src:    '',

                    title:  'Untitled',

                    description:    '',

                    name:   '',

                    index:  -1,

                    color:  null,

                    width:  null,

                    height: null,

                    image:  true

                };

                

                // Create

                if ( obj.image )

                {   // Already a image, so copy over values

                    image.src = obj.src || image.src;

                    image.title = obj.title || image.title;

                    image.description = obj.description || image.description;

                    image.name = obj.name || image.name;

                    image.color = obj.color || image.color;

                    image.width = obj.width || image.width;

                    image.height = obj.height || image.height;

                    image.index = obj.index || image.index;

                }

                else if ( obj.tagName )

                {   // We are an element

                    obj = $(obj);

                    if ( obj.attr('src') || obj.attr('href') )

                    {

                        image.src = obj.attr('src') || obj.attr('href');

                        image.title = obj.attr('title') || obj.attr('alt') || image.title;

                        image.name = obj.attr('name') || '';

                        image.color = obj.css('backgroundColor');

                        // Extract description from title

                        var s = image.title.indexOf(': ');

                        if ( s > 0 )

                        {   // Description exists

                            image.description = image.title.substring(s+2) || image.description;

                            image.title = image.title.substring(0,s) || image.title;

                        }

                    }

                    else

                    {   // Unsupported element

                        image = false;

                    }

                }

                else

                {   // Unknown

                    image = false;

                }

                

                if ( !image )

                {   // Error

                    $.console.error('We dont know what we have:', obj);

                    return false;

                }

                

                // Success

                return image;

            },

            

            get: function ( image )

            {   // Get the active, or specified image

                

                // Establish image

                if ( typeof image === 'undefined' || image === null )

                {   // Get the active image

                    return this.active();

                }

                else

                if ( typeof image === 'number' )

                {   // We have a index

                    

                    // Get image

                    image = this.list[image] || false;

                }

                else

                {   // Create

                    image = this.create(image);

                    if ( !image ) { return false; }

                    

                    // Find

                    var f = false;

                    for ( var i = 0; i < this.size(); i++ )

                    {

                        var c = this.list[i];

                        if ( c.src === image.src && c.title === image.title && c.description === image.description )

                        {   f = c;  }

                    }

                    

                    // Found?

                    image = f;

                }

                

                // Determine image

                if ( !image )

                {   // Image doesn't exist

                    $.console.error('The desired image does not exist: ', image, this.list);

                    return false;

                }

                

                // Return image

                return image;

            },

            

            debug: function ( )

            {

                return $.Lightbox.debug(arguments);

            }

            

        },

        

        // -----------------

        // Variables

        

        constructed:        false,

        compressed:         null,

        

        // -----------------

        // Options

        

        src:                null,       // the source location of our js file

        baseurl:            null,

        

        files: {

            compressed: {

                js: {

                    lightbox:   'js/jquery.lightbox.min.js',

                    colorBlend: 'js/jquery.color.min.js'

                },

                css: {

                    lightbox:   'css/jquery.lightbox.css'

                }

            },

            uncompressed: {

                js: {

                    lightbox:   'js/jquery.lightbox.js',

                    colorBlend: 'js/jquery.color.js'

                },

                css: {

                    lightbox:   'css/jquery.lightbox.css'

                }

            },

            images: {

                prev:       'images/prev.gif',

                next:       'images/next.gif',

                blank:      'images/blank.gif',

                loading:    'images/loading.gif'

            }

        },

        

        text: {

            // For translating

            image:      'Image',

            of:         'of',

            close:      'Close X',

            closeInfo:  'You can also click anywhere outside the image to close.',

            download:   'Download.',

            help: {

                close:      'Click to close',

                interact:   'Hover to interact'

            },

            about: {

                text:   '',

                title:  '',

                //link:   ''

            }

        },

        

        keys: {

            close:  'c',

            prev:   'p',

            next:   'n'

        },

        

        handlers: {

            // For custom actions

            show:   null

        },

        

        opacity:        0.9,

        padding:        null,       // if null - autodetect

        

        speed:          400,        // Duration of effect, milliseconds

        

        rel:            'lightbox', // What to look for in the rels

        

        auto_relify:    true,       // should we automaticly do the rels?

        

        auto_scroll:    'follow',   // should the lightbox scroll with the page? follow, disabled, ignore

        auto_resize:    true,       // true or false

        

        ie6:            null,       // are we ie6?

        ie6_support:    true,       // have ie6 support

        ie6_upgrade:    true,       // show ie6 upgrade message

        

        colorBlend:     null,       // null - auto-detect, true - force, false - no

        

        download_link:      true,   // Display the download link

        

        show_helper_text:   true,   // Display the helper text up the top right

        show_linkback:      true,   // true, false

        show_info:          'auto', // auto - automaticly handle, true - force

        show_extended_info: 'auto', // auto - automaticly handle, true - force  

        

        // names of the options that can be modified

        options:    ['show_helper_text', 'auto_scroll', 'auto_resize', 'download_link', 'show_info', 'show_extended_info', 'ie6_support', 'ie6_upgrade', 'colorBlend', 'baseurl', 'files', 'text', 'show_linkback', 'keys', 'opacity', 'padding', 'speed', 'rel', 'auto_relify'],

        

        // -----------------

        // Functions

        

        construct: function ( options )

        {   // Construct our Lightbox

            

            // -------------------

            // Prepare

            

            // Initial construct

            var initial = typeof this.constructed === 'undefined' || this.constructed === false;

            this.constructed = true;

            

            // Perform domReady

            var domReady = initial;

            

            // Prepare options

            options = options || {};

            

            // -------------------

            // Handle files

            

            // Prepend function to use later

            var prepend = function(item, value) {

                if ( typeof item === 'object' ) {

                    for (var i in item) {

                        item[i] = prepend(item[i], value);

                    }

                } else if ( typeof value === 'array' ) {

                    for (var i=0,n=item.length; i<n; ++i) {

                        item[i] = prepend(item[i], value);

                    }

                } else {

                    item = value+item;

                }

                return item;

            }

            

            // Add baseurl

            if ( initial && (typeof options.files === 'undefined') )

            {   // Load the files like default

                

                // Reset compressed

                this.compressed = null;

                

                // Get the src of the first script tag that includes our js file (with or without an appendix)

                var $script = $('script[src*='+this.files.compressed.js.lightbox+']:first');

                if ( $script.length !== 0 ) {

                    // Compressed

                    $.extend(true, this.files, this.files.compressed);

                    this.compressed = true;

                } else {

                    // Uncompressed

                    $script = $('script[src*='+this.files.uncompressed.js.lightbox+']:first');

                    if ( $script.length !== 0 ) {

                        // Uncompressed

                        $.extend(true, this.files, this.files.uncompressed);

                        this.compressed = false;

                    } else {

                        // Nothing

                    }

                }

                

                // Make sure we found ourselves

                if ( this.compressed === null )

                {   // We didn't

                    $.console.error('Lightbox was not able to find it\'s javascript script tag necessary for auto-inclusion.');

                    // We don't work with files anymore, so don't care for domReady

                    domReady = false;

                }

                else

                {   // We found ourself

                    

                    // Grab the script src

                    this.src = $script.attr('src');

                    

                    // The baseurl is the src up until the start of our js file

                    this.baseurl = this.src.substring(0, this.src.indexOf(this.files.js.lightbox));

                    

                    // Prepend baseurl to files

                    this.files = prepend(this.files, this.baseurl);

                    

                    // Now as we have source, we may have more params

                    options = $.extend(options, $.params_to_json(this.src));

                }

                

            }

            else

            if ( typeof options.files === 'object' )

            {   // We have custom files

                // Prepend baseurl to files

                options.files = prepend(options.files, this.baseurl);

            }

            else

            {   // Don't have any files, so no need to perform domReady

                domReady = false;

            }

            

            // -------------------

            // Apply options

            

            for ( var i in this.options )

            {   // Cycle through the options

                var name = this.options[i];

                if ( (typeof options[name] === 'object') && (typeof this[name] === 'object') )

                {   // We have a group like text or files

                    this[name] = $.extend(true, this[name], options[name]);

                }

                else if ( typeof options[name] !== 'undefined' )

                {   // We have that option, so apply it

                    this[name] = options[name];

                }

            }   delete i;

            

            // -------------------

            // Figure out what to do

            

            // Handle IE6

            if ( initial && navigator.userAgent.indexOf('MSIE 6') >= 0 )

            {   // Is IE6

                this.ie6 = true;

            }

            else

            {   // We are not IE6

                this.ie6 = false;

            }

            

            // -------------------

            // Handle our DOM

            

            if ( domReady || typeof options.download_link !== 'undefined' ||  typeof options.colorBlend !== 'undefined' || typeof options.files === 'object' || typeof options.text === 'object' || typeof options.show_linkback !== 'undefined' || typeof options.scroll_with !== 'undefined' )

            {   // We have reason to handle the dom

                $(function() {

                    // DOM is ready, so fire our DOM handler

                    $.Lightbox.domReady();

                });

            }

            

            // -------------------

            // Finish Up

            

            // All good

            return true;

        },

        

        domReady: function ( )

        {

            // -------------------

            // Include resources

            

            // Grab resources

            var bodyEl = document.getElementsByTagName($.browser.safari ? 'head' : 'body')[0];

            var stylesheets = this.files.css;

            var scripts = this.files.js;

            

            // Handle IE6 appropriatly

            if ( this.ie6 && this.ie6_upgrade )

            {   // Add the upgrade message

                scripts.ie6 = 'http://www.savethedevelopers.org/say.no.to.ie.6.js';

            }

            

            // colorBlend

            if ( this.colorBlend === true && typeof $.colorBlend === 'undefined' )

            {   // Force colorBlend

                this.colorBlend = true;

                // Leave file in place to be loaded

            }

            else

            {   // We either have colorBlend or we don't

                this.colorBlend = typeof $.colorBlend !== 'undefined';

                // Remove colorBlend file

                delete scripts.colorBlend;

            }

            

            // Include stylesheets

            for ( stylesheet in stylesheets )

            {

                var linkEl = document.createElement('link');

                linkEl.type = 'text/css';

                linkEl.rel = 'stylesheet';

                linkEl.media = 'screen';

                linkEl.href = stylesheets[stylesheet];

                linkEl.id = 'lightbox-stylesheet-'+stylesheet.replace(/[^a-zA-Z0-9]/g, '');

                $('#'+linkEl.id).remove();

                bodyEl.appendChild(linkEl);

            }

            

            // Include javascripts

            for ( script in scripts )

            {

                var scriptEl = document.createElement('script');

                scriptEl.type = 'text/javascript';

                scriptEl.src = scripts[script];

                scriptEl.id = 'lightbox-script-'+script.replace(/[^a-zA-Z0-9]/g, '');

                $('#'+scriptEl.id).remove();

                bodyEl.appendChild(scriptEl);

            }

            

            // Cleanup

            delete scripts;

            delete stylesheets;

            delete bodyEl;

            

            // -------------------

            // Append display

            

            // Append markup

            $('#lightbox,#lightbox-overlay').remove();

            $('body').append('<div id="lightbox-overlay"><div id="lightbox-overlay-text">'+(this.show_linkback?'<p><span id="lightbox-overlay-text-about"><a href="#" title="'+this.text.about.title+'">'+this.text.about.text+'</a></span></p><p>&nbsp;</p>':'')+(this.show_helper_text?'<p><span id="lightbox-overlay-text-close">'+this.text.help.close+'</span><br/>&nbsp;<span id="lightbox-overlay-text-interact">'+this.text.help.interact+'</span></p>':'')+'</div></div><div id="lightbox"><div id="lightbox-imageBox"><div id="lightbox-imageContainer"><img id="lightbox-image" /><div id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + this.files.images.loading + '" /></a></div></div></div><div id="lightbox-infoBox"><div id="lightbox-infoContainer"><div id="lightbox-infoHeader"><span id="lightbox-caption">'+(this.download_link ? '<a href="#" title="' + this.text.download + '" id="lightbox-caption-title"></a>' : '<span id="lightbox-caption-title"></span>')+'<span id="lightbox-caption-seperator"></span><span id="lightbox-caption-description"></span></span></div><div id="lightbox-infoFooter"><span id="lightbox-currentNumber"></span><span id="lightbox-close"><a href="#" id="lightbox-close-button" title="'+this.text.closeInfo+'">' + this.text.close + '</a></span></div><div id="lightbox-infoContainer-clear"></div></div></div></div>');

            

            // Update Boxes - for some crazy reason this has to be before the hide in safari and konqueror

            this.resizeBoxes();

            this.repositionBoxes();

            

            // Hide

            $('#lightbox,#lightbox-overlay,#lightbox-overlay-text-interact').hide();

            

            // -------------------

            // Browser specifics

            

            // Handle IE6

            if ( this.ie6 && this.ie6_support )

            {   // Support IE6

                // IE6 does not support fixed positioning so absolute it

                // ^ This is okay as we disable scrolling

                $('#lightbox-overlay').css({

                    position:   'absolute',

                    top:        '0px',

                    left:       '0px'

                });

            }

            

            // -------------------

            // Preload Images

            

            // Cycle and preload

            $.each(this.files.images, function()

            {   // Proload the image

                var preloader = new Image();

                preloader.onload = function() {

                    preloader.onload = null;

                    preloader = null;

                };  preloader.src = this;

            });

            

            // -------------------

            // Apply events

            

            // If the window resizes, act appropriatly

            $(window).unbind('resize').resize(function ()

            {   // The window has been resized

                $.Lightbox.resizeBoxes('resized');

            });

            

            // If the window scrolls, act appropriatly

            if ( this.scroll === 'follow' )

            {   // We want to

                $(window).scroll(function ()

                {   // The window has scrolled

                    $.Lightbox.repositionBoxes();

                });

            }

            

            // Prev

            $('#lightbox-nav-btnPrev').unbind().hover(function() { // over

                $(this).css({ 'background' : 'url(' + $.Lightbox.files.images.prev + ') left 45% no-repeat' });

            },function() { // out

                $(this).css({ 'background' : 'transparent url(' + $.Lightbox.files.images.blank + ') no-repeat' });

            }).click(function() {

                $.Lightbox.showImage($.Lightbox.images.prev());

                return false;

            });

                    

            // Next

            $('#lightbox-nav-btnNext').unbind().hover(function() { // over

                $(this).css({ 'background' : 'url(' + $.Lightbox.files.images.next + ') right 45% no-repeat' });

            },function() { // out

                $(this).css({ 'background' : 'transparent url(' + $.Lightbox.files.images.blank + ') no-repeat' });

            }).click(function() {

                $.Lightbox.showImage($.Lightbox.images.next());

                return false;

            });

            

            // Help

            if ( this.show_linkback )

            {   // Linkback exists so add handler

                $('#lightbox-overlay-text-about a').click(function(){window.open($.Lightbox.text.about.link); return false;});

            }

            $('#lightbox-overlay-text-close').unbind().hover(

                function(){

                    $('#lightbox-overlay-text-interact').fadeIn();

                },

                function(){

                    $('#lightbox-overlay-text-interact').fadeOut();

                }

            );

            

            // Image link

            $('#lightbox-caption-title').click(function(){window.open($(this).attr('href')); return false;});

            

            // Assign close clicks

            $('#lightbox-overlay, #lightbox, #lightbox-loading-link, #lightbox-btnClose').unbind().click(function() {

                $.Lightbox.finish();

                return false;   

            });

            

            // -------------------

            // Finish Up

            

            // Relify

            if ( this.auto_relify )

            {   // We want to relify, no the user

                this.relify();

            }

            

            // All good

            return true;

        },

        

        relify: function ( )

        {   // Create event

        

            //

            var groups = {};

            var groups_n = 0;

            var orig_rel = this.rel;

            // Create the groups

            $.each($('[rel*='+orig_rel+']'), function(index, obj){

                // Get the group

                var rel = $(obj).attr('rel');

                // Are we really a group

                if ( rel === orig_rel )

                {   // We aren't

                    rel = groups_n; // we are individual

                }

                // Does the group exist

                if ( typeof groups[rel] === 'undefined' )

                {   // Make the group

                    groups[rel] = [];

                    groups_n++;

                }

                // Append the image

                groups[rel].push(obj);

            });

            // Lightbox groups

            $.each(groups, function(index, group){

                $(group).lightbox();

            });

            // Done

            return true;

        },

        

        init: function ( image, images )

        {   // Init a batch of lightboxes

            

            // Establish images

            if ( typeof images === 'undefined' )

            {

                images = image;

                image = 0;

            }

            

            // Clear

            this.images.clear();

            

            // Add images

            if ( !this.images.add(images) )

            {   return false;   }

            

            // Do we need to bother

            if ( this.images.empty() )

            {   // No images

                $.console.warn('WARNING', 'Lightbox started, but no images: ', image, images);

                return false;

            }

            

            // Set active

            if ( !this.images.active(image) )

            {   return false;   }

            

            // Done

            return true;

        },

        

        start: function ( )

        {   // Display the lightbox

                

            // We are alive

            this.visible = true;

            

            // Adjust scrolling

            if ( this.scroll === 'disable' )

            {   // 

                $(document.body).css('overflow', 'hidden');

            }

            

            // Fix attention seekers

            $('embed, object, select').css('visibility', 'hidden');//.hide(); - don't use this, give it a go, find out why!

            

            // Resize the boxes appropriatly

            this.resizeBoxes('general');

            

            // Reposition the Boxes

            this.repositionBoxes({'speed':0});

            

            // Hide things

            $('#lightbox-infoFooter').hide(); // we hide this here because it makes the display smoother

            $('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-infoBox').hide();

                    

            // Display the boxes

            $('#lightbox-overlay').css('opacity',this.opacity).fadeIn(400, function(){

                // Show the lightbox

                $('#lightbox').fadeIn(300);

                

                // Display first image

                if ( !$.Lightbox.showImage($.Lightbox.images.active()) )

                {   $.Lightbox.finish();    return false;   }

            });

            

            // All done

            return true;

        },

        

        finish: function ( )

        {   // Get rid of lightbox

        

            // Hide lightbox

            $('#lightbox').hide();

            $('#lightbox-overlay').fadeOut(function() { $('#lightbox-overlay').hide(); });

            

            // Fix attention seekers

            $('embed, object, select').css({ 'visibility' : 'visible' });//.show();

            

            // Kill active image

            this.images.active(false);

            

            // Adjust scrolling

            if ( this.scroll === 'disable' )

            {   // 

                $(document.body).css('overflow', 'visible');

            }

            

            // We are dead

            this.visible = false;

            

        },

        

        resizeBoxes: function ( type )

        {   // Resize the boxes

            // Used on transition or window resize

            

            // Resize Overlay

            if ( type !== 'transition' )

            {   // We don't care for transition

                var $body = $(this.ie6 ? document.body : document);

                $('#lightbox-overlay').css({

                    width:      $body.width(),

                    height:     $body.height()

                });

                delete $body;

            }

            

            // Handle cases

            switch ( type )

            {

                case 'general': // general resize (start of lightbox)

                    return true;

                    break;

                case 'resized': // window was resized

                    if ( this.auto_resize === false )

                    {   // Stop

                        // Reposition

                        this.repositionBoxes({'nHeight':nHeight, 'speed':this.speed});

                        return true;

                    }

                case 'transition': // transition between images

                default: // unknown

                    break;

            }

            

            // Get image

            var image = this.images.active();

            if ( !image || !image.width || !this.visible )

            {   // No image or no visible lightbox, so we don't care

                //$.console.warn('A resize occured while no image or no lightbox...');

                return false;

            }

            

            // Resize image box

            // i:image, w:window, b:box, c:current, n:new, d:difference

            

            // Get image dimensions

            var iWidth  = image.width;

            var iHeight = image.height;

            

            // Get window dimensions

            var wWidth  = $(window).width();

            var wHeight = $(window).height();

            

            // Check if we are in size

            // Lightbox can take up 4/5 of size

            if ( this.auto_resize !== false )

            {   // We want to auto resize

                var maxWidth  = Math.floor(wWidth*(4/5));

                var maxHeight = Math.floor(wHeight*(4/5));

                var resizeRatio;

                while ( iWidth > maxWidth || iHeight > maxHeight )

                {   // We need to resize

                    if ( iWidth > maxWidth )

                    {   // Resize width, then height proportionally

                        resizeRatio = maxWidth/iWidth;

                        iWidth = maxWidth;

                        iHeight = Math.floor(iHeight*resizeRatio);

                    }

                    if ( iHeight > maxHeight )

                    {   // Resize height, then width proportionally

                        resizeRatio = maxHeight/iHeight;

                        iHeight = maxHeight;

                        iWidth = Math.floor(iWidth*resizeRatio);

                    }

                }

            }

            

            // Get current width and height

            var cWidth  = $('#lightbox-imageBox').width();

            var cHeight = $('#lightbox-imageBox').height();

    

            // Get the width and height of the selected image plus the padding

            // padding*2 for both sides (left+right || top+bottom)

            var nWidth  = (iWidth  + (this.padding * 2));

            var nHeight = (iHeight + (this.padding * 2));

            

            // Diferences

            var dWidth  = cWidth  - nWidth;

            var dHeight = cHeight - nHeight;

            

            // Set the overlay buttons height and the infobox width

            // Other dimensions specified by CSS

            $('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css('height', nHeight); 

            $('#lightbox-infoBox').css('width', nWidth);

            

            // Handle final action

            if ( type === 'transition' )

            {   // We are transition

                // Do we need to wait? (just a nice effect to counter the other

                if ( dWidth === 0 && dHeight === 0 )

                {   // We are the same size

                    this.pause(this.speed/3);

                    this.showImage(null, 3);

                }

                else

                {   // We are not the same size

                    // Animate

                    $('#lightbox-image').width(iWidth).height(iHeight);

                    $('#lightbox-imageBox').animate({width: nWidth, height: nHeight}, this.speed, function ( ) { $.Lightbox.showImage(null, 3); } );

                }

            }

            else

            {   // We are a resize

                // Animate Lightbox

                $('#lightbox-image').animate({width:iWidth, height:iHeight}, this.speed);

                $('#lightbox-imageBox').animate({width: nWidth, height: nHeight}, this.speed);

            }

            

            // Reposition

            this.repositionBoxes({'nHeight':nHeight, 'speed':this.speed});

            

            // Done

            return true;

        },

        

        repositioning:          false,  // are we currently repositioning

        reposition_failsafe:    false,  // failsafe

        repositionBoxes: function ( options )

        {

            // Prepare

            if ( this.repositioning )

            {   // Already here

                this.reposition_failsafe = true;

                return null;

            }

            this.repositioning = true;

            

            // Options

            options = $.extend({}, options);

            options.callback = options.callback || null;

            options.speed = options.speed || 'slow';

            

            // Get page scroll

            var pageScroll = this.getPageScroll();

            

            // Figure it out

            // alert($(window).height()+"\n"+$(document.body).height()+"\n"+$(document).height());

            // var nHeight = options.nHeight || parseInt($('#lightbox').height(),10) || $(document).height()/3;

            var nHeight = options.nHeight || parseInt($('#lightbox').height(),10);

            

            // Display lightbox in center

            // var nTop = pageScroll.yScroll + ($(document.body).height() /*frame height*/ - nHeight) / 2.5;

            var nTop = pageScroll.yScroll + ($(window).height() /*frame height*/ - nHeight) / 2.5;

            var nLeft = pageScroll.xScroll;

            

            // Animate

            var css = {

                left: nLeft,

                top: nTop

            };

            if (options.speed) {

                $('#lightbox').animate(css, 'slow', function(){

                    if ( $.Lightbox.reposition_failsafe )

                    {   // Fire again

                        $.Lightbox.repositioning = $.Lightbox.reposition_failsafe = false;

                        $.Lightbox.repositionBoxes(options);

                    }

                    else

                    {   // Done

                        $.Lightbox.repositioning = false;

                        if ( options.callback )

                        {   // Call the user callback

                            options.callback();

                        }

                    }

                });

            }

            else

            {

                $('#lightbox').css(css);

                if ( this.reposition_failsafe )

                {   // Fire again

                    this.repositioning = this.reposition_failsafe = false;

                    this.repositionBoxes(options);

                }

                else

                {   // Done

                    this.repositioning = false;

                }

            }

            

            // Done

            return true;

        },

        

        visible: false,

        showImage: function ( image, step )

        {

            // Establish image

            image = this.images.get(image);

            if ( !image ) { return image; }

            

            // Default step

            step = step || 1;

            

            // Split up below for jsLint compliance

            var skipped_step_1 = step > 1 && this.images.active().src !== image.src;

            var skipped_step_2 = step > 2 && $('#lightbox-image').attr('src') !== image.src;

            if ( skipped_step_1 || skipped_step_2 )

            {   // Force step 1

                $.console.info('We wanted to skip a few steps: ', image, step, skipped_step_1, skipped_step_2);

                step = 1;

            }

            

            // What do we need to do

            switch ( step )

            {

                // ---------------------------------

                // We need to preload

                case 1:

                

                    // Disable keyboard nav

                    this.KeyboardNav_Disable();

                    

                    // Show the loading image

                    $('#lightbox-loading').show();

                    

                    // Hide things

                    $('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-infoBox').hide();

                    

                    // Remove show info events

                    $('#lightbox-imageBox').unbind();

                    // ^ Why? Because otherwise when the image is changing, the info pops out, not good!

                    

                    // Make the image the active image

                    if ( !this.images.active(image) ) { return false; }

                    

                    // Check if we need to preload

                    if ( image.width && image.height )

                    {   // We don't

                        // Continue to next step

                        this.showImage(null, 2);

                    }

                    else

                    {   // We do

                        // Create preloader

                        var preloader = new Image();

                        // Set callback

                        preloader.onload = function()

                        {   // We have preloaded the image

                            // Update image with our new info

                            image.width  = preloader.width;

                            image.height = preloader.height;

                            // Continue to next step

                            $.Lightbox.showImage(null, 2);

                            // Kill preloader

                            preloader.onload = null;

                            preloader = null;

                        };

                        // Start preload

                        preloader.src = image.src;

                    }

                    

                    // Done

                    break;

                

                

                // ---------------------------------

                // Resize the container

                case 2:

                    

                    // Apply image changes

                    $('#lightbox-image').attr('src', image.src);

                    

                    // Set container border (Moved here for Konqueror fix - Credits to Blueyed)

                    if ( typeof this.padding === 'undefined' || this.padding === null || isNaN(this.padding) )

                    {   // Autodetect

                        this.padding = parseInt($('#lightbox-imageContainer').css('padding-left'), 10) || parseInt($('#lightbox-imageContainer').css('padding'), 10) || 0;

                    }

                    

                    // Use colorBlend?

                    if ( this.colorBlend )

                    {   // We have colorBlend

                        // Background

                        $('#lightbox-overlay').animate({'backgroundColor':image.color}, this.speed*2);

                        // Border

                        $('#lightbox-imageBox').css('borderColor', image.color);

                    }

                    

                    // Resize boxes

                    this.resizeBoxes('transition');

                    // ^ contains callback to next step

                    

                    // Done

                    break;

                

                

                // ---------------------------------

                // Display the image

                case 3:

                    

                    // Hide loading

                    $('#lightbox-loading').hide();

                    

                    // Animate image

                    $('#lightbox-image').fadeIn(this.speed*1.5, function() {$.Lightbox.showImage(null, 4); });

                    

                    // Start the proloading of other images

                    this.preloadNeighbours();

                    

                    // Fire custom handler show

                    if ( this.handlers.show !== null )

                    {   // Fire it

                        this.handlers.show(image);

                    }

                    

                    // Done

                    break;

                

                

                // ---------------------------------

                // Set image info / Set navigation

                case 4:

                    

                    // ---------------------------------

                    // Set image info

                    

                    // Hide and set image info

                    var $title = $('#lightbox-caption-title').html(image.title || 'Untitled');

                    if ( this.download_link )

                    {   $title.attr('href', this.download_link ? image.src : '');   }

                    delete $title;

                    $('#lightbox-caption-seperator').html(image.description ? ': ' : '');

                    $('#lightbox-caption-description').html(image.description || '&nbsp;');

                    

                    // If we have a set, display image position

                    if ( this.images.size() > 1 )

                    {   // Display

                        $('#lightbox-currentNumber').html(this.text.image + '&nbsp;' + ( image.index + 1 ) + '&nbsp;' + this.text.of + '&nbsp;' + this.images.size());

                    } else

                    {   // Empty

                        $('#lightbox-currentNumber').html('&nbsp;');

                    }

                    

                    // ---------------------------------

                    // Info events

                    

                    // Apply event

                    $('#lightbox-imageBox').unbind('mouseover').mouseover(function(){

                        $('#lightbox-infoBox:not(:visible)').stop().slideDown('fast');

                    });

                    

                    // Apply event

                    $('#lightbox-infoBox').unbind('mouseover').mouseover(function(){

                        $('#lightbox-infoFooter:not(:visible)').stop().slideDown('fast');

                    });

                    

                    // Forced show?

                    if ( this.show_extended_info === true )

                    {   // Force show

                        $('#lightbox-imageBox').trigger('mouseover');

                        $('#lightbox-infoBox').trigger('mouseover');

                    }

                    else if ( this.show_info === true )

                    {   // Force show

                        $('#lightbox-imageBox').trigger('mouseover');

                    }

                    

                    // ---------------------------------

                    // Set navigation

        

                    // Instead to define this configuration in CSS file, we define here. And it's need to IE. Just.

                    $('#lightbox-nav-btnPrev, #lightbox-nav-btnNext').css({ 'background' : 'transparent url(' + this.files.images.blank + ') no-repeat' });

                    

                    // If not first, show previous button

                    if ( !this.images.first(image) ) {

                        // Not first, show button

                        $('#lightbox-nav-btnPrev').show();

                    }

                    

                    // If not last, show next button

                    if ( !this.images.last(image) ) {

                        // Not first, show button

                        $('#lightbox-nav-btnNext').show();

                    }

                    

                    // Make navigation active / show it

                    $('#lightbox-nav').show();

                    

                    // Enable keyboard navigation

                    this.KeyboardNav_Enable();

                    

                    // Done

                    break;

                    

                    

                // ---------------------------------

                // Error handling

                default:

                    $.console.error('Don\'t know what to do: ', image, step);

                    return this.showImage(image, 1);

                    // break;

                

            }

            

            // All done

            return true;

        },

        

        preloadNeighbours: function ( )

        {   // Preload all neighbour images

            

            // Do we need to do this?

            if ( this.images.single() || this.images.empty() )

            {   return true;    }

            

            // Get active image

            var image = this.images.active();

            if ( !image ) { return image; }

            

            // Load previous

            var prev = this.images.prev(image);

            var objNext;

            if ( prev ) {

                objNext = new Image();

                objNext.src = prev.src;

            }

            

            // Load next

            var next = this.images.next(image);

            if ( next ) {

                objNext = new Image();

                objNext.src = next.src;

            }

        },

        

        // --------------------------------------------------

        // Things we don't really care about

        

        KeyboardNav_Enable: function ( ) {

            $(document).keydown(function(objEvent) {

                $.Lightbox.KeyboardNav_Action(objEvent);

            });

        },

        

        KeyboardNav_Disable: function ( ) {

            $(document).unbind('keydown');

        },

        

        KeyboardNav_Action: function ( objEvent ) {

            // Prepare

            objEvent = objEvent || window.event;

            

            // Get the keycode

            var keycode = objEvent.keyCode;

            var escapeKey = objEvent.DOM_VK_ESCAPE /* moz */ || 27;

            

            // Get key

            var key = String.fromCharCode(keycode).toLowerCase();

            

            // Close?

            if ( key === this.keys.close || keycode === escapeKey )

            {   return $.Lightbox.finish();     }

            

            // Prev?

            if ( key === this.keys.prev || keycode === 37 )

            {   // We want previous

                return $.Lightbox.showImage($.Lightbox.images.prev());

            }

            

            // Next?

            if ( key === this.keys.next || keycode === 39 )

            {   // We want next

                return $.Lightbox.showImage($.Lightbox.images.next());

            }

            

            // Unknown

            return true;

        },

        

        getPageScroll: function ( ) {

            var xScroll, yScroll;

            if (self.pageYOffset)

            {   // Some browser

                yScroll = self.pageYOffset;

                xScroll = self.pageXOffset;

            } else if (document.documentElement && document.documentElement.scrollTop)

            {   // Explorer 6 Strict

                yScroll = document.documentElement.scrollTop;

                xScroll = document.documentElement.scrollLeft;

            } else if (document.body)

            {   // All other browsers

                yScroll = document.body.scrollTop;

                xScroll = document.body.scrollLeft; 

            }

            var arrayPageScroll = {'xScroll':xScroll,'yScroll':yScroll};

            return arrayPageScroll;

        },

        

        pause: function ( ms ) {

            var date = new Date();

            var curDate = null;

            do { curDate = new Date(); }

            while ( curDate - date < ms);

        }

    

    }); // We have finished extending/defining our LightboxClass





    // --------------------------------------------------

    // Finish up

    

    // Instantiate

    if ( typeof $.Lightbox === 'undefined' )

    {   // 

        $.Lightbox = new $.LightboxClass();

    }



// Finished definition



})(jQuery); // We are done with our plugin, so lets call it with jQuery as the argument


