aurelia / ui-virtualization

A plugin that provides a virtualized repeater and other virtualization services.
MIT License
90 stars 45 forks source link

Can't scroll in Safari (Demo Site) #23

Closed AStoker closed 8 years ago

AStoker commented 9 years ago

Opened up the Demo site to ensure it would work for our needs in Safari, but I cannot scroll the list.
I am unable to use the scroll indicator to drag (looks like a custom one), and there are no errors in the console either.

martingust commented 9 years ago

@AStoker In Safari 9 on OS X El Capitan I'm not able to scroll with the touchpad. Mouse wheel and key up/down is working. Is this what you are experiencing as well?

That is right, the scroll indicator is a custom one. Since the list is virtual, and the scroll height does not represent the list height, a native scrollbar can't be used. However we have plans for making the scroll indicator draggable. This plugin is going to change a lot and is still in early development. So I would not recommend using it in production yet.

AStoker commented 9 years ago

I'm on the same setup. However I'm using the mouse (the magic mouse that is). Is it not possible to make the the scrollable list nested inside of a div, and have the outside div have the native scroll bar? For example, something real basic:

.scroll-container {
   overflow: scroll;
}
<div class="scroll-container">
   <ul class="scrolling-list">
      <li class="scroll-top-buffer"></li>
      <li virtual-repeat.for="item of items">
        <template replaceable part="item-template"></template>
      </li>
      <li class="scroll-bottom-buffer"></li>
   </ul>
</div>

You could then as you scroll through the list of items, determine the height of the element you're popping off and add that height to the <li class="scroll-top-buffer"></li>. Likewise for the scroll buffer on the bottom.

That might be a completely different implementation than what you're creating though. However, a benefit of this design would also allow you to have list elements of different size (https://github.com/aurelia/ui-virtualization/issues/24), since you're not computing the buffer size until it's been created in the DOM, and then popped off.

The only downside of that, I guess, would be that you might not know the exact height of the entire list at creation time, and so your scroll bar wouldn't be correct in it's size.
However, that might not be a problem, as if we start dealing with paging results, we might not know exactly how many elements are left on the list (if we start dealing with 1000's of elements, we might not want to ask the server for all of them at once). So in that case, it would be following suit with Google images, Pinterest, Facebook... Scrolling and adjusting the scroll bar as you find more elements.

Sorry, super long response.

martingust commented 9 years ago

That is acctually one of the approches I started out with. Except was only using the scroll-bottom-buffer, but I was running in to some problems that I wish I could remember exactly what that was. Maybe I just didn't give it enough time. I think it's worth investigating again. Another drawback could be the browsers maximum height that will limit really long lists. Probably a pretty rare case though. Perhaps it could support both and have different scrolling strategies pluggable.

cc @stoffeastrom do you have any input on this?

stoffeastrom commented 9 years ago

@martingust As discussed. I think the best way is to have a virtual-scrollbar api to handle very large lists. The native scrollbar becomes unstable and as you said there is an max height on a DOMElement which is different in basically all browsers. So it's all about what kind of requirements you have. What platforms you must support and which input methods you want to support. What I mean with that is for example on a windows hybrid device you can switch input methods e.g first you use a mouse and then you touch the screen and you could potentially want a totally different virtual-scrollbar since on touch you want to interact with it easily. So to sum up, I think there needs to be multiple different apis working together.

_Data_ - It needs to know how many rows you have etz _Virtual scrollbar_ - Represent the whole data, scrolling api and potential different ui:s _Virtual list_ - You may want to have different rendering strategies

Ofc, the devil is in the details but they would need to be hashed out..

martingust commented 9 years ago

After giving this some more thought I also think keeping virtual-scrollbar is the way going forward, that will give the plugin maximum flexibility and performance. It would be unfortunate to not support very long lists. And the gain of native scrollbar wouldn't be much if the plugin would expose a scrollbar api (like @stoffeastrom mentions), providing different implementations per platform and for users to plug in their own.

AStoker commented 9 years ago

Sorry, was away for thanksgiving, so I couldn't contribute to the discussion. In regards to max height, if you go with the nested approach I mentioned, then you don't have max height issues. Our company has created a tree control which uses the method I mentioned, and we're dealing with the thousands of elements (edge cases of much more), and it handles perfectly. So performance wouldn't suffer in any way I'm aware of. @stoffeastrom, how does the native scrollbar become unstable? In my experiences, the native scrollbar has outperformed the virtual one multiple times, and has the best support for mobile. Again, that's just my experiences, so I'm not saying that's everybody's experience. I've had very poor experiences with virtual scrollbars on mobile devices.
So I guess a question would be, what does the virtual scrollbar actually buy you in flexibility and performance? I'll give you that a virtual scrollbar allows the user to style it themselves, but that's about it, that I can think of.

martingust commented 9 years ago

@AStoker If I understand the nested approach you mentioned you add height to the buffer as you scroll through the list and at some point in a very long list the buffer element will be too tall for the browser to handle and the scrolling would break down. Or did I misunderstand your approach?

Here is an example with react virtual list if I change item height from 100 to 200 I won't be able to scroll all the way through the list in Chrome. In IE 11 it breaks already at 8000 items with 200 item height. This would not happen with a purely virtual list.

With performance I was also thinking about the ability to take advantage of hardware acceleration with CSS 3D transforms when the plugin simulates scrolling. Perhaps that is possible with native scroll as well with -webkit-overflow-scrolling: touch I guess, not sure about none webkit browsers? Or how is scrolling and adding/removing items handled in the nested approach?

With flexibility as you said the ability to plugin different scrollbars. But also the ability to handle different scroll behaviors like momentum scroll, snap to grid functionality etc.

I see pros and cons with both approaches, and as @stoffeastrom mentioned it all depends on the requirements. Perhaps if right things are separated the plugin could support both approaches. Thoughts?

AStoker commented 9 years ago

Thanks for that example @martingust, that definitely changes my opinion in this case. You could still take this approach, but modify it a bit so that your scroll element's height reaches a max height, and you actually use Javascript to manage the heights instead of relying on the elements themselves. This approach would have to kick in at a height where the scroll bar reaches it's smallest size (a percentage of the window height). To add and remove elements, you would have a scroll event listener that would trigger a decision on whether or not to add/remove an element. It would all be pretty straight forward javascript. Momentum scroll, snap to grid, those are all things that can happen with native scroll bars by the way. You can really do a lot with the scroll events in javascript. I'd love to make a fork of this project and try and make a native approach, but I think you might be right with going on with this approach. I'm not sure if the plugin could support both approaches, because it seems like the changes would be architecturally different. I would push, however, that the default scroll bar should look as much like the native scrollbar as possible on whatever device it's on. Nothing, can mess up a design like scrollbar that looks like it belonged back in 2000 :P (not saying this one does, just giving an example).

martingust commented 9 years ago

@AStoker It would be awesome if you wanted do a native scroll implementation. And then we can see what parts can be re-used or replaced. I'm making some big refactorings right now, please feel free to hit me up on Gitter so we can align.

AStoker commented 9 years ago

Sounds good. I'll try to get to it in the next few weeks (hopefully your big refactors will be implemented by then). Got some big deadlines coming up at work, and the need for a virtual list is on a less prioritized project. Also, in relation to the initial bug report, I guess I'll try scrolling again after the next big release.

vegarringdal commented 8 years ago

Hi Does it really matter if some browsers will only be able to show 8000 rows if performance is a lot better? Little chance any users will scroll and look at each row, they will start to filter it down before any scrolling starts. First 1000 and last 1000 needs to be correct. Thats the only one they might look at :)

I played around with this while trying to learn more html/javascript: https://github.com/vegarringdal/mobileGrid (scrolling works, dont complain if code is weird)

One thing I notice/you can see it in the react demo also, is that when list is big and you scroll really quickly to bottom IE and maybe other browsers will have a performance issue(laggy scrolling), so really should not do anything at that moment, better to wait for user to stop scrolling.

martingust commented 8 years ago

@vegarringdal In most cases not. But there are definitely use cases where the requirements are to display 8000 rows or more. It would be great to be able to support these use cases and without a performance degradation, I think we can.

We are experimenting with @AStoker:s approach in this branch: https://github.com/aurelia/ui-virtualization/tree/native-scrolling

If it turns out good it will get merged/implemented in master.

martingust commented 8 years ago

Fixed in https://github.com/aurelia/ui-virtualization/commit/dc486a9ee43d7f7e4893f688d8be2b56b5910b4c