dhilt / vscroll-native

Virtual scroll module for native javascript applications
https://dhilt.github.io/vscroll-native/
MIT License
10 stars 2 forks source link

Idea: ScrollerFactory() that allows alternate template type and renderer #2

Open darcyparker opened 3 years ago

darcyparker commented 3 years ago

I like this vscroll-native example. But I would like to use something different than innerHTML in createItemElement.

createItemElement is a fine default, but there would be some advantages if something like uhtml or lithtml were an option. (I prefer uhtml, but I am sure lithtml and others could be popular too.)

What if there was ScrollerFactory that is provided the desired renderer and returns a Scroller class with the applicable Template type for the renderer chosen?

Is this something you'd consider? If so, I am happy to see if this idea works and create a pull request. (I may have some flaws in my current thinking/idea, but my hope is that its mostly feasible and that I can work out problems if I pursue it.) I just want to proceed if the idea is not valued.

Alternatively I could use vscroll-native as an example and create my own implementation that uses my preferred renderer. But it feels like there is opportunity for reuse if there were a ScrollerFactory that provided the desired renderer.

dhilt commented 3 years ago

@darcyparker DOM-related operations is one of the weak points through the vscroll infrastructure. I tried to make the implementation as simple/rough as possible, relying on browser year-to-year growing performance rather than lib performance. The idea of pluggable DOM-engine is very good. Moreover, I already extracted the most part of the DOM-related logic into a separate class inside the core: vscroll/src/classes/domRoutines.ts. And I planned to make it replaceable: a consumer (vscroll-native) should be able to override this class via config of the Workflow super-entity. Currently such approach is done for the Adapter reactive props, which are configurable at the Datasource factory level: core DS factory -> consumer specific DS. The Workflow should receive domRoutines configuration.

1) Routines is not finished yet, for example items rendering is not under its control, and this relates to what you want to change: hiding items in vscroll-native is served by render process in vscroll. Both operations can be moved to Routines and Routines could be replaced by consumer. The argument of createItemElement is an instance of Item class which has Routines instance on it. As you see, we can't separate these two operations and replace one of it (core relies on hiding!), but we can try to gather them in a single place and provide a consumer-core overriding mechanism to replace them both. This is one point of the createItemElement problem.

2) Another one is that you want to give an option to change a consumer DOM-related logic, which is not connected with the core. This is VERY good idea, but before discussing the details, let's think about scoping. The logic we are going to deal with is the most low-level across the project, and my guess the consumer layer is the best place that matches it, so it should not leak into the end app. Let me put here the vscroll introduction image:

So your suggestion could be treated as a factory of native consumers. Setting up such a factory would require good qualifications from the end app devs. My idea is not to give in the hands of the end app devs such fundamental pieces as rendering implementation, even if it's optional. Maybe it will be better to

darcyparker commented 3 years ago

My idea is not to give in the hands of the end app devs such fundamental pieces as rendering implementation, even if it's optional. Maybe it will be better to

I agree.

With regards to the 4 options:

The popular choices for a renderer are likely uhtml, lit-html et al... and there could be more.

darcyparker commented 3 years ago

I am going to chew on your other comments... but also interested in helping.

dhilt commented 3 years ago

@darcyparker My other comments were about the createItemElement method can't be replaced entirely due to render-hiding-showing logic that is scattered over the core and consumer; additional efforts are needed to put it in a single configurable DOM Routines class (which is not configurable for now, and more efforts are needed to make it configurable).

But if you don't want to change these particular operations (btw they are required by the core doc), we may start the Factory developing. From the one hand, I'd be glad to see something like core Datasource factory (a parametrized function returning extended class); from the other hand, we may move toward ts abstract class or native mixins. I think, since the project is quite small, it should be not a problem to update the infrastructure. The more important is to implement a new renderer...

Once we have two different renderers (1 default and 1 new), we'll be able to generalize the Scroller entity, taking into account their specificity. The entry (and the only important) point is the Workflow run callback implementation, which is wrapped with the wf-storage:

https://github.com/dhilt/vscroll-native/blob/d422f6806182e5a174f9a3160a137701b88526ed/src/vscroll-native.ts#L43

So the updateViewport must satisfy the requirements listed in the doc. The updateViewport method calls createItemElement in the end. That's how the default Scroller class is written. Another implementation of the Scroller class might not contain createItemElement at all, it just should provide correct updateViewport method.

Adding you to the repository collaborators for not to waste time. We may continue the discussion by the code.

darcyparker commented 3 years ago

@dhilt - Thanks for adding me as a repository collaborator.

I understand what you mean about the render hiding logic being scattered over core and consumer. I have some thoughts but they aren't fully formed.

I can get started with the factory development... (likely Monday).

With regards to the Datasource factory, I am open to an abstract ts class or native mixins too. But you're right, that if a factory is created, and later like another approach its probably not too hard to update. As a side question, would you be open to adding something like (index: number) => AsyncIterable<T> | (index: number) => Iterable<T> to DatasourceGet? (Notice a count is not necessary because the consumer can iterate as much as needed.)

dhilt commented 3 years ago

@darcyparker Great!

If you are speaking about a new signature for the Datasource.get method, then why not. There are only two places where this emerges:

Also, there is a spec in ngx-ui-scroll project handling the Datasource and Fetch process running: datasource.spec.ts. I'd recommend to run it in parallel with vscroll developing, this part of the doc tells how to do it. I'd be happy to remove the Datasource spec from ngx-ui-scroll and create a new one in vscroll; it should a) explicitly check all signatures with all possible (especially wrong) arguments, b) emulate Fetch process run and check all possible immediate and delayed results.

darcyparker commented 3 years ago

@dhilt - FYI. I started this today and made some progress, but it is still a WIP.

dhilt commented 3 years ago

@darcyparker Here's the tip on core-consumer development:

You may push your wip-branch to the original repo, open draft PR, then it may be easier to discuss