We add a padded div to our container for the buddy
list to give scrolling the illusion that we've
rendered every list item, while still letting
the browser do the heavy lifting instead of trying
to fake it out too much.
This new div allows us to split out two concerns:
semantic list of items - remains in #user_presences
widget real estate - controlled by new #buddy_list_wrapper
We will use this for progressive rendering. We want to add
padding to the buddy list without messing with the integrity
of the actual HTML '<ul>' list. (One ugly alternative would
have been to add a dummy list item, which be a pitfall for
any code traversing the list.)
Basically, all the code relating to click handlers and similar
things was left alone. We only change js/css related to
scrolling, resizing, and overflow.
This version of progressive scrolling lazily
renders buddy list items, but it doesn't
provide the browser with any notion of upcoming
list items, so as you scroll down and the size
of the rendered list grows, the scrollbar shows
you being too close to the bottom.
This maintains 100% coverage on buddy_list.js.
We were passing this in before, but having it as
a data member reinforces the idea that we'll want
this to be a first-class concept in the list, since
we depend on ordering for various things.
We now keep track of keys in buddy_list.js, so that
when we insert/remove items, we no longer need to
traverse all the DOM. Instead, we just find out
which position in the list we need to insert the
key in (where "key" is "user_id") and then find
the relevant DOM node directly and insert the new
HTML before that node. (And of course we still
account for the "append" case.)
There's a little more bookkeeping to make this
happen, but it should help reduce some code in
upcoming commits and pave the way toward
progressive rendering optimizations.
This commit should produce a minor speedup
for activity-related events that go through
buddy_list.insert_or_move(), since we are
not traversing the DOM to find insertion points
any more.
This commit prepares the frontend code to be consumed by webpack.
It is a hack: In theory, modules should be declaring and importing the
modules they depend on and the globals they expose directly.
However, that requires significant per-module work, which we don't
really want to block moving our toolchain to webpack on.
So we expose the modules by setting window.varName = varName; as
needed in the js files.
This is preparation for enabling an eslint indentation configuration.
90% of these changes are just fixes for indentation errors that have
snuck into the codebase over the years; the others are more
significant reformatting to make eslint happy (that are not otherwise
actually improvements).
The one area that we do not attempt to work on here is the
"switch/case" indentation.
This introduces a generic class called list_cursor to handle the
main details of navigating the buddy list and wires it into
activity.js. It replaces some fairly complicated code that
was coupled to stream_list and used lots of jQuery.
The new code interacts with the buddy_list API instead of jQuery
directly. It also persists the key across redraws, so we don't
lose our place when a focus ping happens or we type more characters.
Note that we no longer cycle to the top when we hit the bottom, or
vice versa. Cycling can be kind of an anti-feature when you want to
just lay on the arrow keys until they hit the end.
The changes to stream_list.js here do not affect the left sidebar;
they only remove code that was used for the right sidebar.
In this cleanup I make it so that all jQuery selector references
are toward the top of the module, and we do all finds relative
to the container ('#user_presences').
This will make it easier to make a better list abstraction for
the buddy list, for things like progressive rendering.
This change makes a common code path for these two operations:
* clicking on a user
* hitting enter when a user is highlighted
The newer codepath, for the enter key, had some differences that
were just confusing. For example, there's no need to open the
compose box, since that's already handled by the narrowing code.
For possibly dubious reasons, I let each handler still call
popovers.hide_all() on its own, since it makes the code a bit
more consistent with existing code patterns.