Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite scroll: multiply handlers on refresh (F5) #80

Closed
ova2 opened this issue Aug 6, 2012 · 19 comments
Closed

Infinite scroll: multiply handlers on refresh (F5) #80

ova2 opened this issue Aug 6, 2012 · 19 comments

Comments

@ova2
Copy link

ova2 commented Aug 6, 2012

Hi,

I have found an issue with Infinite Scrolling http://imakewebthings.com/jquery-waypoints/infinite-scroll/ Your example works fine. BUT if you refresh the page (e.g. via F5), the waypoint handler gets registered again and again without to be destroyed. I only have one waypoint on my page and register the handler by this way

var $loading = $("<div class='loading'><p>Loading more items...</p></div>");

$('#footer').waypoint('destroy').waypoint(function(event, direction) {
    if (direction == "down") {
        $('#footer').waypoint('remove');
        $('body').append($loading);

        console.log("Load...");

        $('#container').append("... some long content ...");

        $loading.detach();
        $('#footer')waypoint({offset: '100%'});
    }
}, {offset: '100%'});

Scrolling is ok - I see "Load..." only once in the console. But as I said, I see multiply "Load ..." messages after every page refresh. They are getting more and more with each page refresh and the browser ends up with an JS error "too much recursions". I tried to call "destroy" instead of "remove", but the handler is destroyed then. I tried 10+ various things but without success.

Please help! Thanks a lot in advance!

@imakewebthings
Copy link
Owner

@ova2 So you say this is only happening on your page but not my example, correct? Can you share that page with me or provide a reduced test case on something like JSFiddle?

@ova2
Copy link
Author

ova2 commented Aug 7, 2012

I just adapted your page to my needs. This is almost the same. You can use your HTML structure. I think it should also happen for your example. Just put console.log("....") between $('body').append($loading) and $loading.detach(). Call the page and push F5. Then scroll to the bottom (to fire waypoint event) and push F5 again. Scroll to the buttom and push F5 again...

@ova2
Copy link
Author

ova2 commented Aug 7, 2012

Look the output in Firebug console of course.

@ova2
Copy link
Author

ova2 commented Aug 7, 2012

I meant

$(document).ready(function() {
    var $loading = $("<div class='loading'><p>Loading more items&hellip;</p></div>"),
    $footer = $('footer'),
    opts = {
        offset: '100%'
    };

    $footer.waypoint(function(event, direction) {
        $footer.waypoint('remove');
        $('body').append($loading);
        $.get($('.more a').attr('href'), function(data) {
                       // LOGGER
                       console.log("Loading...");

            var $data = $(data);
            $('#container').append($data.find('.article'));
            $loading.detach();
            $('.more').replaceWith($data.find('.more'));
            $footer.waypoint(opts);
        });
    }, opts);
});

@ova2
Copy link
Author

ova2 commented Aug 8, 2012

Sorry for annoying. Could you reproduce this now?

@ova2
Copy link
Author

ova2 commented Aug 8, 2012

I've debugged your code. It looks like an endless recursion. Calls sequence:

registered waypoint handler --> $footer.waypoint(opts) (see code above) --> plugins init() --> wps --> way.element.trigger(eventName, dir) (see plugins triggerWaypoint()) --> registered waypoint handler.

I'm getting crazy...

@imakewebthings
Copy link
Owner

Is this Firefox only?

@ova2
Copy link
Author

ova2 commented Aug 8, 2012

Yes. Not tested in IE, but Chrome is ok. It seems to be only Firefox.

Great plugin by the way. I'm implementing just now a new JSF (JavaServer Faces) component "Waypoint" in PrimeFaces Extensions http://code.google.com/p/primefaces-extensions/ and found this issue for the first use case "Infinite Scrolling".

Thanks in advance for any tips.

@ova2
Copy link
Author

ova2 commented Aug 8, 2012

Tested in IE8. Works fine too. Only Firefox. By some reason, $footer.waypoint(opts) in handler calls init() and init() calls refresh() which triggers waypoint handler again. When I scroll now and my handler is invoked, say 10 times, then it will be invoked exactly 10 times more on page refresh (F5).

@imakewebthings
Copy link
Owner

This would all be much easier if I could see YOUR page. I can reproduce something similar but benign in Firefox with my example. Firefox will keep trying to scroll to the original position and will keep triggering waypoints until it gets there (which I think is actually desirable). But it correctly destroys the waypoint handlers when calling 'remove' and only triggers until it gets to the old position, so you are left with exactly the same page as before you refreshed. (Compared to in Chrome, where you will only get one trigger and then Chrome gives up trying to scroll to the original point while the AJAX GET is out doing its thing.)

@ova2
Copy link
Author

ova2 commented Aug 8, 2012

Yes, exactly. On a new loaded page I scroll quite down --> waypoint handler gets invoked once. Then I do a page refresh --> Firefox stays on the same scroll position and the waypoint gets invoked twice. If the waypoint handler would got invoked during scrolling e.g. 4 times, after a page refresh it would be invoked 4 times too. Etc.

Should I provide my page? It's the same as in your example with Infinite Scrolling.

@imakewebthings
Copy link
Owner

@ova2 How is that infinite recursion? I think this might be something special to Firefox and how it handles its scrolling on load. I happen to think this behavior can be nice, but if it's something that throws a wrench in your design you might be able to get around it. You could use the onlyOnScroll option to prevent refreshes from new waypoint additions ever triggering waypoints. You might also try figuring out some way to trick FF into not scrolling down the page the way it does naturally.

In either case, I'm not sure this is a Waypoints bug. Maybe a FF bug at best. From everything I see in the stack Waypoints is behaving as expected:

  1. Handler registered, triggering init.
  2. init calls refresh after the waypoint is added to the appropriate Context.
  3. refresh looks to see if the waypoint should have already been triggered in the down direction based on the current scroll position. In this case yes, it should, so it triggers the handler.
  4. The handler immediately removes itself.
  5. A GET request is fired off.
  6. When the response comes back, the handler reregisters itself.
  7. Repeat until the waypoint shouldn't be triggered in step 3 because it hasn't been reached yet.

Like I said, in every other browser, after page load it will try to scroll down to the offset that, at first, is much larger than the window height, but stops at the bottom of the initial window. Firefox will keep issuing scroll events until it gets there. If you replace your console.log text with $(window).scrollTop() you'll see that. I don't know if there is spec on how browsers should behave in this case, but it's interesting that FF does what it does.

@ova2
Copy link
Author

ova2 commented Aug 8, 2012

No, onlyOnScroll="true" doesn't help!

It seems to be worked if I call "destroy" instead of "remove" and register the waypoint with the same handler again (after AJAX update). Maybe you should call first .unbind() before .bind() events, because it's only one difference. I don't know. Thanks anyway.

@ova2
Copy link
Author

ova2 commented Aug 9, 2012

It has nothing to do with "onlyOnScroll" (this option doesn't have eny effect). As I said, go to the http://imakewebthings.com/jquery-waypoints/infinite-scroll/ please, open Firebug, scroll down, say 3 times. You will see 3 requests. Push F5 now. You will see 3 requests on page load instead of max. one. Scoll down next 3 times. You will see next 3 requests. Push now F5 again. You will see 6 requests on page load! If you repeat this trick many times, you will end up in "too much recursion". The browser gets freezed. It's easy to reproduce and I'm pretty sure there is a workaround to fix this in Waypoints.

@imakewebthings
Copy link
Owner

It has nothing to do with "onlyOnScroll" (this option doesn't have eny effect).

I was only suggesting a possible workaround.

As I said, go to the http://imakewebthings.com/jquery-waypoints/infinite-scroll/ please, open Firebug, scroll down, say 3 times. You will see 3 requests. Push F5 now. You will see 3 requests on page load instead of max. one. Scoll down next 3 times. You will see next 3 requests. Push now F5 again. You will see 6 requests on page load!

Yes, I've done that as noted above and can completely see what you're talking about. I then detailed in great length how this behavior is a feature of Firefox and how it handles scrolling to the user's previous location on reload. Firefox is generating legitimate scroll events that trigger legitimate waypoint handlers. I can't think of a way to distinguish these scroll events from any other scroll event. If you have specific suggestions, I'm open to them.

We might all be better served by a bug report on the FF bugzilla. If I can find some sliver of time to talk with somebody more knowledgable than me on how browsers should behave in this situation or if the spec even defines it, I will. In the meantime you'll need to find a way to work around this browser quirk in how you implement infinite scroll with Waypoints.

@ova2
Copy link
Author

ova2 commented Aug 9, 2012

Ok, thanks! Looking forward to hear from you again.

@ova2
Copy link
Author

ova2 commented Aug 9, 2012

I've spent almost one day, but found a working workaround. After reading some articles I've figured out that a reset of scoll position helps (.scrollLeft(0), .scrollTop(0)). The idea is to buffer current scroll postions, reset scroll positions and restore them to the original then when the AJAX update is finished. The waypoint handler is fired once with this code snippet (cross-browser):

$(document).ready(function() {
    var $loading = $("<div class='loading'><p>Loading more items...</p></div>");
    var $window = $(window);
    var $footer = $('footer');
    var opts = {offset: '100%'};

    $footer.waypoint(function(event, direction) {
        // buffer current scroll coordinates
        var winleft = $window.scrollLeft();
        var wintop = $window.scrollTop();

        // reset current scroll coordinates
        $window.scrollLeft(0);
        $window.scrollTop(0);

        $footer.waypoint('remove');
        $('body').append($loading);

        $.get($('.more a').attr('href'), function(data) {
            var $data = $(data);
            $('#container').append($data.find('.article'));
            $loading.detach();

            // restore current scroll coordinates
            $window.scrollLeft(winleft);
            $window.scrollTop(wintop);

            $('.more').replaceWith($data.find('.more'));
            $footer.waypoint(opts);
        });
    }, opts);
});

A reset of scrollTop should be enough actually. I only should check now if the browser is FF and include this code.

@imakewebthings
Copy link
Owner

If this works to alleviate your problem, and I totally believe it does because browsers do insane things sometimes, then I'd almost certainly call this a bug in FF. From just reading the code this should, as I suspect it does in other sane browsers, have no effect. Well, a flicker as the page scrolls up until the GET arrives. But nothing that should effect the waypoint trigger. Good to know.

@ova2
Copy link
Author

ova2 commented Aug 9, 2012

In the fact, I don't have flickers in FF. Scrollbar stays without any moving. Even if GET takes 1 min. and more :-) No flicker at all. I only can see small flicker in IE, but this code should not be executed for IE (it's easy with some browser check).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants