(function($) {
    $.fn.fadeNav = function(opt) {
        var container = $(this),  // container holds the images
        
            defaults = {
                caption: null, 
                navigation: null,           // element to hold the navigation controls
                speed: 600,                 // speed of the cross-fade between images
                easing: 'swing',            // animation easing for cross-fade
                src_attr: 'href',
                slideshow: false,           // slideshow mode
                slideshow_timeout: 8000     // time between slides in slideshow mode
            },
            o = $.extend({}, defaults, opt),
            
            cur = 0;        // references the index of the visible image
        
        
        // Set up required styles
        var images = container.find('img').css({opacity: 0}).parent().css({
            position: 'absolute', top: 0, left: 0
        }).end();
        
        container.each(function() {
            var ps = $(this).css('position');
            if (ps != 'absolute' && ps != 'relative') {
                $(this).css('position', 'relative');
            }
        });

        var img_sources = $.map(images, function(img) {
            var p = $(img).parent();
            var src = p.attr(o.src_attr);
            return src || $(img).attr('src');
        });

        // Set up navigation controls
        var nav = o.navigation || $('<div class="image-nav"></div>').appendTo(container),
            nav_container = $('<div class="nav-controls"></div>').appendTo(nav),
            title = $('<h2></h2>').hide().appendTo(nav),
            prev = $('<a class="image-prev prev">&lt;</a>').appendTo(nav_container),
            count = $('<span class="count">1 of 8</span').appendTo(nav_container),
            next = $('<a class="image-next next">&gt;</a>').appendTo(nav_container),
            caption = o.caption || $('<div class="image-caption"></div>').hide().appendTo(nav);

        if (images.length < 2) nav_container.hide();
    
        // Image getter
        var index = function(n) {
            return (n + images.length ) % images.length
        }
        
        // Image loading
        var preload = function(n) {
            n = index(n);
            var img = images.eq(n).attr('src', img_sources[n]);
        }
        
        // Switching images
        var show = function(n, speed) {
            var last = cur; cur = index(n);
            var img = images.eq(cur);
            speed = speed == null ? o.speed : speed;

            if (!img.attr('src')) preload(cur);
                        
            // Show the new current image.
            var title_text = img.attr('title');
            if (title_text) title.text(title_text).show();
            else title.hide();
            var caption_text = img.attr('alt');
            if (caption_text) caption.empty().html(caption_text).show();
            else caption.empty().hide()
            images.eq(last).stop().animate({
                opacity: 0
            }, speed, o.easing, function() {
                $(this).parent().hide();
            });

            count.text((cur+1) + ' of ' + images.length);
            images.eq(cur).stop().parent().show().end().animate({
                opacity: 1
            }, speed, o.easing, function() {
                setTimeout(function() { container.find('a.play').css('opacity', '') }, 100);
                // Preload images on either side of current.
                for (i=cur; i < cur + 2; i++ ) {
                    preload(i);
                }
                i = cur - 1;
                for (i = cur-1; i > cur-2; i--) {
                    preload(i);
                }
            });
        }

        
        // Load event positions images and shows the first image.
        preload(cur);
        $(window).load(function() {
            show(cur);
        });

        // Navigation Events
        prev.click(function() { show(cur-1); return false; });
        next.click(function() { show(cur+1); return false; });
        if (images.length > 1) {
            images.parent().click(function() { 
                show(cur+1); return false; 
            });
        } else {
            images.parent().css({
                cursor: 'default'
            }).click(function() {return false; });
        }
        
        
        // If in slideshow mode, start the show...
        if (o.slideshow && images.length > 1) {
            var t = setInterval(function() {
                show(cur+1);
            }, o.slideshow_timeout);
        }

        return this;
    }
})(jQuery);

