statgen / locuszoom

A Javascript/d3 embeddable plugin for interactively visualizing statistical genetic data from customizable sources.
https://statgen.github.io/locuszoom/
MIT License
154 stars 29 forks source link

Refactor Curtains and Add Loader #71

Closed Frencil closed 8 years ago

Frencil commented 8 years ago

What

This branch is designed to address the general problem that implementers of LocusZoom.js apps have where they want to indicate to users that LocusZoom is "working" or otherwise doing something.

Refactored Curtain

The curtain, an overlay for both plots and panels, has been refactored. Previously this was an SVG object with styles that couldn't be easily modified. Text shown on the curtain (ideal for error messages when an API endpoint throws an error) was a one-line SVG element, making it difficult to show lengthy error messages in full.

This has now been refactored as an HTML element overlay. Curtains can still be called for the plot or for individual panels on a plot and have the following changes:

This branch also introduces the concept of the loader. The loader is a little HTML overlay similar in appearance to the panel description element. It is used similarly to how the curtain is used and is present for usage on the entire plot or on individual panels.

To see the loader in action check out this branch and pull up demo.html, then navigate to any region using the top hits links or the region input. The loader will appear while new data is being fetched and will disappear when the data is rendered using an event hook.

The loader takes a custom text string when shown but will display "Loading..." if not provided any string. It also shows a minimal loading bar in the style of nanobar. Loaders have a setPercentCompleted() method to exert direct control over the progress of the loading bar if needed. Loaders also provide an animate() method that will use a pure CSS animation to make the loading bar "cycle" if it isn't known how long the progress will take or no checkpointing events are available.

Chainable Returns

The curtain and loader, along with other HTML overlay objects like controls and panel boundaries, now have consistent returns to make methods chainable. For example, in demo.html the implementation to show the loader when applying a new range to the state looks like this:

plot.loader.show("Loading region...").animate();

The first method displays the loader with a string specific to what it's doing and the second chained method starts it animating, since we're not setting up checkpoints and updating the loading bar that way.

To do

This branch is development complete but it exposes methods on plots and instances that really need to be in the documentation. When it's ready to merge I plan to build out documentation for all such HTML overlay objects and the methods to use them.

Frencil commented 8 years ago

One other thing I forgot to mention: the loader cancel button. It's there in the code but commented out. If uncommented in its current state it just hides the loader. I really wanted to make a functional cancel button but as I started digging I learned how complicated it can be to cancel promises in flight. If anyone has thoughts on how best to approach the plumbing of canceling arbitrarily many promises stacked in an array and wrapped with an all() promise let's talk, because I think a functional cancel button on the loader could be really useful in some cases.

MrFlick commented 8 years ago

So we were playing with the loader by throttling the data transfer speeds in Chrome on the demo page. It seems that the loading indicator does not come up during the first data load. There is still also the problem of when jumping around regions, showing out-of-sync data between panels. (The p-values shown don't match up to the genes show) and there's not really an indication which part is current and which is out-of-date. I'm not sure if this means that we need a loader per panel? Or maybe we don't update the drawing until we have all the data for all layers? Or we remove points from the plot when we change regions? Or maybe yet another option?

Frencil commented 8 years ago

Interesting... the loader actually is set up to work on a per-panel basis in addition to per-plot just as the curtains are. It will be simple to get the demo using per-panel loaders. I'll also take a look at throttling to see if I can produce any confusing behavior.

Frencil commented 8 years ago

Okay, see the latest demo.html. I migrated the loader to show on panels instead of the entire plot (may not be worth having for the entire plot?) and added a new event for "data_requested" that instance and plot will emit right before making requests. This seems to work as expected with heavy throttling, but let me know if you still something that looks off.