jQuery Simple Spy no longer works with jQuery 1.5

2019-05-26 22:31发布

问题:

I'm trying to use Remy Sharp's Simple Spy (http://jqueryfordesigners.com/simple-jquery-spy-effect) with jQuery 1.5. It works fine with 1.4, but in 1.5 it does not load any additional comments after the first one disappears.

Can anyone see what needs to be updated in the code so it will work with 1.5?

$(function () {
$('ul.spy').simpleSpy();
});

(function ($) {

$.fn.simpleSpy = function (limit, interval) {

limit = limit || 4;
interval = interval || 4000;

return this.each(function () {
    // 1. setup
        // capture a cache of all the list items
        // chomp the list down to limit li elements
    var $list = $(this),
        items = [], // uninitialised
        currentItem = limit,
        total = 0, // initialise later on
        height = $list.find('> li:first').height();

    // capture the cache
    $list.find('> li').each(function () {
        items.push('<li>' + $(this).html() + '</li>');
    });

    total = items.length;

    $list.wrap('<div class="spyWrapper" />').parent().css({ height : height * limit });

    $list.find('> li').filter(':gt(' + (limit - 1) + ')').remove();

    // 2. effect        
    function spy() {
        // insert a new item with opacity and height of zero
        var $insert = $(items[currentItem]).css({
            height : 0,
            opacity : 0,
            display : 'none'
        }).prependTo($list);

        // fade the LAST item out
        $list.find('> li:last').animate({ opacity : 0}, 1000, function () {
            // increase the height of the NEW first item
            $insert.animate({ height : height }, 1000).animate({ opacity : 1 }, 1000);

            // AND at the same time - decrease the height of the LAST item
            // $(this).animate({ height : 0 }, 1000, function () {
                // finally fade the first item in (and we can remove the last)
                $(this).remove();
            // });
        });

        currentItem++;
        if (currentItem >= total) {
            currentItem = 0;
        }

        setTimeout(spy, interval)
    }

    spy();
});
};

})(jQuery);

I've posted a copy of it on JSBin where you can see what happens:

http://jsbin.com/olutu3

Here's a working version with an older version of jQuery:

http://jqueryfordesigners.com/demo/simple-spy.html

回答1:

OK so in the spy() function, at the very top, try doing this:

var $insert = $(items[currentItem]).css({
    height : 0,
    opacity : 0
}).prependTo($list);

I have this mocked up here:

http://jsfiddle.net/treeface/xaJ9F/ (jsbin was annoying me)

The difference here is that you aren't declaring that it should be "display:none". There must have been a change in the implicit assumptions jQuery makes when changing the animated opacity of an object, because the plugin creator seemed to not have to change the display value after he animated the opacity to 1 and the height to whatever px. This isn't exactly the most robust plugin, though...it doesn't give you an option for setting the height, it just assumes that the first one is the height all of them will be.

Anyway...try that and see if it works. If it doesn't (or causes cross-browser issues) try reinserting the display:none and calling $insert.show() somewhere thereafter.



回答2:

As @treeface said, the problem is the setting of "display: none" on the $insert element. Except, I don't think the plugin should have ever worked as it did. I believe this exploited some sort of bug that was fixed in 1.5.0. Another "fix" for the original code would be:

...
var $insert = $(items[currentItem]).css({
  height : 0,
  opacity : 0,
  display: 'none'
}).prependTo($list);

$list.find('> li:last').toggle().animate({ opacity : 0}, 1000, function () {
...

Notice the addition of the .toggle() call. In order for the newly inserted element to affect the content flow it must have a visible display.