(function ($) {
    $.fn.crossfadeLinks = function (startOptions, endOptions) {
    var defaults = {
            'start' : {
                'type' : 'mouseenter',
                'delay' : 250,
                'callback' : null,
                'condition' : function () { return true; }
            },
            
            'end' : {
                'type' : 'mouseleave',
                'delay' : 1500,
                'callback' : null,
                'condition' : function () { return true; }
            }
        };
        
        if (typeof options == 'number') {
            options = {
                'start' : { 'delay' : options },
                'end' : { 'delay' : options }
            };
        }
        
        var settings = {};
        settings.start = $.extend({}, defaults.start, startOptions);
        settings.end = $.extend({}, defaults.end, endOptions);

        // return this;
        return this.each(function (i) { 
        	if ($(this).attr('id') != "selected")
        	{
            var $$ = $(this);
            var pos = $(this).css("background-position");
            pos = pos.split(" ")[0];
            
            var targetImage = $('<a id="'+$$.attr('id')+'" href="'+$$.attr('href')+'" style="margin-bottom: -32px;"></a>').css('backgroundPosition', ''+pos+' -32px');
            var hiddenImage = $$.wrap('<span style="position: relative;"></span>').parent().prepend(targetImage);

            // CSS tweaks to position the starting image correctly
            if ($.browser.mozilla) {
                $$.css({
                    'position' : 'absolute', 
                    'left' : 0,
                    'background' : '',
                    'top' : this.offsetTop
                });
            } else if ($.browser.opera && $.browser.version < 9.5) {
                // opera < 9.5 has a render bug - so this is required to get around it
                // we can't apply the 'top' : 0 separately because Mozilla strips
                // the style set originally somehow...
                $$.css({
                    'position' : 'absolute', 
                    'left' : 0,
                    'background' : '',
                    'top' : "0"
                });
            } else {
                $$.css({
                    'position' : 'absolute', 
                    'left' : 0,
                    'background' : ''
                });
            }
            
            if (settings.start.type) {
                $$.bind(settings.start.type, function () {
                    if (settings.start.condition.call(this)) {
                        $(this).stop().animate({
                            opacity: 0
                        }, settings.start.delay);
                    }
                    if (settings.start.callback) return settings.start.callback.call(this);
                });
            }
            
            if (settings.end.type) {
                $$.bind(settings.end.type, function () {
                    if (settings.end.condition.call(this) && !$$.prev('a').hasClass('selected')) {
                        $(this).stop().animate({
                            opacity: 1
                        }, settings.end.delay);
                    }
                    if (settings.end.callback) return settings.end.callback.call(this);
                });
            }
            }
        });
    };
    
    $.fn.crossfade = function (startOptions, endOptions) {
        var defaults = {
            'start' : {
                'type' : 'mouseenter',
                'delay' : 250,
                'callback' : null,
                'condition' : function () { return true; }
            },
            
            'end' : {
                'type' : 'mouseleave',
                'delay' : 1500,
                'callback' : null,
                'condition' : function () { return true; }
            }
        };
        
        if (typeof options == 'number') {
            options = {
                'start' : { 'delay' : options },
                'end' : { 'delay' : options }
            };
        }
        
        var settings = {};
        settings.start = $.extend({}, defaults.start, startOptions);
        settings.end = $.extend({}, defaults.end, endOptions);

        // return this;
        return this.each(function (i) { 
        	if ($(this).attr('id') != "selected")
        	{
            var $$ = $(this);
            var targetImage = $$.attr('src').replace(/^url|[\)\(]/g, '').replace(/.jpg/g, '_hover.jpg');
            var hiddenImage = $$.wrap('<span style="position: relative;"></span>').parent().prepend('<img style="border: 0" />').find(':first-child').attr('src', targetImage);

            // CSS tweaks to position the starting image correctly
            if ($.browser.mozilla) {
                $$.css({
                    'position' : 'absolute', 
                    'left' : 0,
                    'background' : '',
                    'top' : this.offsetTop
                });
            } else if ($.browser.opera && $.browser.version < 9.5) {
                // opera < 9.5 has a render bug - so this is required to get around it
                // we can't apply the 'top' : 0 separately because Mozilla strips
                // the style set originally somehow...
                $$.css({
                    'position' : 'absolute', 
                    'left' : 0,
                    'background' : '',
                    'top' : "0"
                });
            } else {
                $$.css({
                    'position' : 'absolute', 
                    'left' : 0,
                    'background' : ''
                });
            }
            
            if (settings.start.type) {
                $$.bind(settings.start.type, function () {
                    if (settings.start.condition.call(this)) {
                        $(this).stop().animate({
                            opacity: 0
                        }, settings.start.delay);
                    }
                    if (settings.start.callback) return settings.start.callback.call(this);
                });
            }
            
            if (settings.end.type) {
                $$.bind(settings.end.type, function () {
                    if (settings.end.condition.call(this)) {
                        $(this).stop().animate({
                            opacity: 1
                        }, settings.end.delay);
                    }
                    if (settings.end.callback) return settings.end.callback.call(this);
                });
            }
            }
        });
    };
    
})(jQuery);