
Airbnb Releases Infinity.js: A Javascript Library for Smoother Scrolling - reissbaker
http://airbnb.github.com/infinity/
======
threepointone
OT - I can't help but mentally shorten code snippets with underscore/whatever.
For example, I see this -

for(var index = 0, length = listItems.length; index < length; index++) {
listItems[index].remove(); }

and I think to myself -

_(listItems).invoke('remove')

~~~
thinkingisfun
that's funny, I'm the other way around.. whenever I see syntactic sugar
implemented via javascript, I unroll it in my head and consider it overhead,
compared to sending a bunch of more bytes down the wire which hardly matter
after gzip.

~~~
thedz
TIL javascript functions are syntactic sugar.

~~~
thinkingisfun
And TIL stands for what, exactly? Sure you would not simply equate "syntactic
sugar" with "syntactic sugar implemented in javascript".. so what are "TIL
javascrip functions"? I tried searching, but no luck, woth none of the
permutations. There are too many acronyms for TIL to just blindly guess.

My point basically was that

 __(listItems).invoke('remove')_

is actually short for

* [content of <http://underscorejs.org/underscore-min.js>] _(listItems).invoke('remove')*

and even if you removed all non-called parts from underscore, that's still a
lot more complex than

 _for(var index = 0, length = listItems.length; index < length; index++) {
listItems[index].remove(); }_

it's just hidden, out of sight and out of mind.

~~~
Terretta
TIL stands for Today I Learned.

They were attempting to use a meme acronym sarcastically -- an example of
content-free commenting that works well for karma elsewhere but hopefully
doesn't gain a foothold here.

On topic, I agree with your amplification of your point.

~~~
brianfryer
If you use memes on HN, you're going to have a bad time.

(They tend to be downvoted to oblivion, 'round these parts.)

------
whirlycott1
I tested infinite scrolling on a large site about a year ago and the results
were decidedly negative in almost every significant respect according to our
A/B testing. Does anybody actually have evidence that infinite scrolling is a
good thing?

~~~
marknutter
HN likes to pretend that infinite scrolling has no utility, but it's simply
not true. For sites where you want to quickly scan a lot of content, infinite
scrolling is vastly superior to static pagination. For sites where you will
typically consume every item in the list carefully and want to refer back to
specific points in the list, pagination is vastly superior to infinite
scrolling. They both have their benefits.

~~~
rplnt
It's a good feature but it is often done so horribly it becomes not liked.
Rule number one: If you use infinite scrolling instead of pages, don't remove
pages. Especially on pages where content is somehow ordered (shops, lists,
..).

~~~
marknutter
I agree it should be done well, but I don't agree you _always_ need pages. For
instance, when I use google images, I'm usually just looking for a few
specific images in a sea of pictures and I don't care too much about keeping
my place in that list. I care a lot more about being able to quickly scan
through a very large grid of images, though, which infinite scrolling allows
me to do.

~~~
s_henry_paulson
The one caveat here is, if you're going to use infinite scrolling. Don't have
links on the bottom of the page!

Sites like Facebook do this, and I have no idea why.

Want to "Create a page". Well there's a link at the bottom. But if you scroll
to the bottom of the page, it's going to load more content and push the link
down.

I just tried it, and the page reloaded 15 times before I gave up... never did
get to the link.

~~~
isnotchicago
On the right sidebar, under "Facebook (c) 2012" should be duplicates of all of
the links at the bottom of the page. For the "Create a page" link, you have to
click "More".

This is clearly unintuitive, but at least it exists.

------
ars
Loading their demo linked from the word "on" froze my browser for about 20
seconds. Scrolling the page afterward was horrible, very jerky and laggy.

I have noscript installed, but all scripts on that page were allowed.

~~~
gilini
Same here, but I wouldn't expect much from a jQuery plugin that implements
"infinite scroll". Like I need stuff to start loading by itself whenever I
reach the bottom of the page.

Also, looking at their code, the first thing I laid eyes on was this
statement:

    
    
      var infinity = window.infinity = {};
    

Which, in this context, would be the exact same as

    
    
      var infinity = {};

~~~
brown9-2
I believe they are doing that to override any functions/objects already bound
to _window.infinity_ from other plugins/scripts. Look at the
_infinity.noConflict()_ function at the bottom of the source, which seems to
be inspired by the _jQuery.noConflict()_.

~~~
gilini
It doesn't matter. Both snippets do the exact same thing, except the first has
two attributions, the second just one.

------
bicknergseng
Note to all developers planning on implementing infinite scrolling:

Don't have a footer. Example of this error: LinkedIn. Try to get to their ToS
or Help Center from the logged in home page. Good luck.

~~~
fuzzythinker
It can, it just needs to be position as fixed.

~~~
bicknergseng
I stand corrected. I personally like what Facebook now does (they used to have
the same problem). They put the same information in a tile at the bottom of
their right pane, which is fixed.

------
yason
I tried both off and on demos, and all I got was a huge page loading slowly
with scrolling causing flickering and stuttering. This is on Linux/Chrome.
Maybe people shouldn't try to create large, image heavy pages in the first
place, not to mention make them infinitely long.

~~~
notatoad
Yeah, Mac/FireFox here and the same experience. both the on and off demos gave
me a spinning beach ball for a minute while what seemed like the entirety of
the content loaded. I thought that's what infinite scrolling was supposed to
prevent?

------
weixiyen
UITableView was made for mobile devices not for infinite scrolling per se, but
simply for large lists (such as address books) due to the memory limitations
of iOS devices.

Those memory limitations are simply nonexistent for the web for almost all but
the smallest number of cases (ie, infinite lists).

But lets pretend that this infinite scrolling is even a real problem (honestly
it's probably not the best UI for large infinite lists of things on the web).

The current implementation clearly needs some work. It's trying to over-
optimize for memory to the point of choking the scrolling.

This, however, can be fixed fairly trivially.

Allow the user to scroll anywhere (even past loaded content). If you can't
eagerload elements to compensate for it, then lazyload after the user gets to
that point. This gives users the illusion that the scrolling is truly smooth
and responsive. The important thing is never allow scrolling to stop unless
it's truly at a dead end and there is absolutely no more elements to load.

The above is how UITableView functions. Infinity.js is UITableView for loading
elements, but does not function anything like UITableView from a user
interaction standpoint.

------
pokoleo
...I don't think I understand the utility of this. Scrolling is already pretty
smooth. (unless I'm wrong)

~~~
reissbaker
Author here. The utility is just to improve scroll smoothness (aka repaint
times) of very-expensive-to-render pages, like infinite feeds with nice CSS
effects. If you check out the demos linked to on the page, the demo with
Infinity turned off should be noticeably choppier than the demo with it on,
even once it's completely loaded and the browser's stopped reflowing. Probably
depends on your machine/OS/browser combination -- but it'll keep loading more
pugs as you scroll down, and eventually the version with Infinity off will
grind just about anything to a halt.

~~~
snprbob86
By repaint times, do you mean re-layout times? ie. time required for
CSS/HTML/JS to determine _where to paint to_?

The demo is not any smoother on my 27" Apple display driven by a late 2010
model MacBook air. However, even low res hardware accelerated video renders
choppy at large window sizes (although perf gets better when VLC or QuickTime
is true fullscreen; presumably the compositor is off)

Faster JavaScript is unlikely to be effective at enhancing buffer flip times,
which (for me) dominate repaint times.

~~~
reissbaker
Both repaints and relayouts are improved, actually. The faster repaints are
what improves scrolling performance (repaints are triggered every time you
scroll, but relayouts are not) -- but because there are fewer elements in the
DOM tree, relayouts are cheaper as well.

We experimented with using display:none instead of removing the elements; it
increased scrolling performance just as much as actual element removal, but
the relayouts when new content was appended got to be prohibitively expensive
once a certain amount of content was loaded (literally pausing the browser for
a noticeable amount of time), because the browser still had to traverse a
giant tree of HTML entities during the relayout. So even if the buffer flip
times are still too slow for you to get completely smooth scrolling in complex
demos like this -- and that makes sense, given your large-screen setup --
you'll hopefully still benefit some from the faster, non-browser-freezing
relayouts.

~~~
Terretta
_Both repaints and relayouts are improved, actually._

When _actually_ is defined as _for some on certain machines_ , judging from
the number of directly contradictory observations in this thread.

The word "actually" ought to be reserved for concrete facts with zero counter
examples.

The word "hopefully" in your closing sentence seems more apt.

That said, very much appreciate the sharing of the hypothesis and
implementation. It's great to see ideas from other areas (video game terrain
feature pop in) leveraged to improve end users' browsing experience.

------
losvedir
Hm, it doesn't degrade very well without javascript on (pagination would be a
neat fallback). I know it's not generally worthwhile to cater to such a
limited user population, but what about search engines? Should this only be
used for content you don't need indexed, or you have indexed a different way?

Or, since I think Google uses javascript in its crawlers, I wonder how it
handles it. Presumably it would just keep scrolling until the content ran out
or it gave up. But does it ever come back later? I know with pagination it
could pick up on the links it left off on, but couldn't really do that here,
right?

edit: I guess this is really a question of infinite scrolling more than this
particular implementation. Kudos to Dropbox for releasing a well-done version
of the technique.

------
tantalor
If this only works on jQuery objects, why not implement this as jQuery plugin?

    
    
      jQuery.fn.infinity = function (options) {...};
      $(el).infinity(options);
    

And so on.

~~~
lucian1900
I think it might work with other methods of selecting DOM elements. At least
that's what the API suggests.

~~~
tantalor
Maybe I'm not reading it right, but it says it depends on jQuery and accepts
selectors or jQuery objects, not DOM elements.

------
devgutt
OP: Maybe you should change the links [on]/[off] to [demo on]/ [demo off].

------
jazzychad
Thank you for using sane js code style.

------
SeckinJohn
If you try to move really fast with Infinity on, the screen turns completely
white for a split second: <http://airbnb.github.com/infinity/demo-on.html>

~~~
reissbaker
True fact. That's just due to scrolling fast enough to get outside the buffer
before the throttled scroll event fires -- if you want, you can turn the
scroll throttle down to make sure that doesn't happen, at the expense of doing
slightly more computation while scrolling. For Wish Lists, we optimize for
people browsing through the feeds, which is generally not super fast. :)

~~~
hueyp
Its much faster for me as well.

In order to calculate the size of each ListItem you add it to the dom briefly
when its appended to the ListView. This seems to be a fast operation since you
do it hundreds of times yet the page is loading quickly. Is there a trick
there that is avoiding having to calculate a ton of layout, or is that just
not a big concern compared to other work the browser is doing?

Thanks!

~~~
reissbaker
Just one trick, although I use it in both the on and off demos to keep
everything fair: I'm adding elements in smaller batches of 70 rows per tick of
execution (arbitrary number), and then using a setTimeout to wait a few
milliseconds before adding more. The demo loads a tooon of elements upfront --
much more than an ordinary site would -- and Firefox would sometimes complain
if I loaded 400 rows of pugs at a single time. Chrome, of course, had no
complaints, and IE was surprisingly fine as well.

~~~
hueyp
And from the comment above:

"...but because there are fewer elements in the DOM tree, relayouts are
cheaper as well"

If I understand, this also applies? When I add the 400th (or whatever)
ListItem it does trigger a layout when its added to the dom (to calculate its
dimensions) but its much faster due to only having the currently viewable
ListItems contained in the ListView?

Thanks again!

------
crag
We (at our company) don't use pagination anywhere now. But we do have
extensive search abilities. We have found, very few of our users just scroll.
They use the search. But the "infinite" scrolling is there if they want it.

------
humbyvaldes
Cool! So basically it's a lazy load

------
gamzer
Android 4.1.1 with or without Infinity: "The page has become unresponsive.
Wait or kill?"

------
shocks
Both demos are the same for me. Chrome, Windows 7 64bit.

------
frontendbeauty
Awesome! This is going to help so much.

------
lowglow
I think Lue Links was doing this for several years. I'm glad to finally have a
library for it.

------
dotborg
why it's based on jQuery?

~~~
shmageggy
Because re-inventing the wheel is _soooo_ 20th century.

~~~
dotborg2
what if I don't use jQuery in my project?

~~~
threepointone
Just for you, I went through their source, and these are all the jquery
specific calls -

.height() .width() .offset() .remove() .append() .prepend() .prependTo()
.find() .parent() .on() .off() .scrollTop() .outerHeight() .length

It seems to me like all of these would be covered by zepto. Or qwery. Or you
could make your own adapter with Prototype. Or Mootools. Or Ext. Or YUI. Heck,
you could probably whip up your own little library based on sizzle, or even
just querySelectorAll. Then just fork infinity to use your lib, and you're
good to go.

I hope you're not confused any more!

[I'm not affiliated with airbnb, just thought I'd help you out]

~~~
dotborg2
ok, sounds like a lot of boilerplate code to write, because "Its _only_
dependency is on jQuery."

~~~
threepointone
<script src="zepto.js"></script> <script> var jQuery = Zepto; </script>
<script src="infinity.js"></script>

There.

------
89a
off version actually worked better for me

