Infinite scrolling and other things requiring element layout knowledge

228 views
Skip to first unread message

James Wilson

unread,
Sep 1, 2015, 7:08:08 PM9/1/15
to Elm Discuss
Hello!

I'm pretty new to Elm, having only used it for a weekend thus far writing a small app to see how it fares, but its pretty exciting and I can see it growing on me.

One thing I've had to do in an Angular app I work on is create an infinite scrolling list, so that we can sanely handle many thousands of items. My angular implementation allows flexbox to render outer elements for each item on the list of a known size, while hiding anything inside them to save adding additional elements to the DOM among other things.

A further optimisation to this would be to use absolute positioning, calculate positions based on container size, and only render the elements currently on screen, ignoring the rest entirely.

I cannot offhand see any way to get at underlying element information (width, height, position, scroll offset etc) that would be necessary to pull this sort of thing off in Elm. My feeling is that youd have to tag elements with some unique class, say, and use ports and some JS to provide this custom data back to Elm each time, say, the scroll or window dimensions change, so that the infinite list knows what to show/hide etc.

Being new to Elm I fear I may be missing something however. Is there a way to do this in-house without JS?

Thanks 😊
James

Max Goldstein

unread,
Sep 1, 2015, 8:11:28 PM9/1/15
to Elm Discuss
If you're using Graphics.Element, there's widthOf. If you're using elm-html, I don't think you can get back the current HTML on the page; you have to regenerate it from your model and let diffing handle it. I think you're best bet would be to store everything in your model, presumably an Elm record, and have the view downstream of that. Just to sketch it out, and assuming constant and uniform element height,

elementHeight = 40

type alias Model = { items : List Item, yOffset : Int}

render (w,h) model =
  let items = model.items |> List.drop (yOffset // elementHeight) |> List.take (h // elementHeight)
  in ...

Hope that helps.

James Wilson

unread,
Sep 2, 2015, 3:35:48 AM9/2/15
to Elm Discuss
Thanks for your reply!

Unfortunately the list I had in mind fills a space of unknown size (let's say there are columns either side that can be expanded or collapsed to provide options and things for instance). More generally I have had a number of reasons to need to perform measurements on elements in the DOM to either lay things out properly or react somehow to that layout.

I took a look at Graphics.Element. I must admit I've been confused at why there are two ways of doing HTML bits, elm-html (which I gather is the virtual DOM wrapper) and Graphics.* (which until I looked at the source code just now I had assumed would be about canvas stuff). I would assume elm-html is the way to go for a medium to large single page app, and Graphics.Element better suited for drawing things but not sure when I'd ever favour the latter.

My feeling is that being able to access these raw DOM node props is important. I might be inclined to add elementSize, elementPosition, elementOffset etc functions to use alongside things like onClick and whatnot, that return perhaps a Maybe value, and so prior to actual layout Nothing.

I imagine the (about to change I gather) Native interface is required for this kind of thing. I'd want to think about when to sample these props as well, for instance I'd want to say "get me a new elementPosition when they scroll there or click here", in the same sort of way you can use Signal.sampleOn in that area.

Anyway, just some random pondering there in case someone wants to shout at me and say there is a better approach 😊

Peter Damoc

unread,
Sep 2, 2015, 7:14:12 AM9/2/15
to Elm Discuss
On Wed, Sep 2, 2015 at 10:35 AM, James Wilson <jam...@gmail.com> wrote:
I took a look at Graphics.Element. I must admit I've been confused at why there are two ways of doing HTML bits, elm-html (which I gather is the virtual DOM wrapper) and Graphics.* (which until I looked at the source code just now I had assumed would be about canvas stuff).

My interpretation of this is that Elm started ambitiously trying to replace html+css+js with something better: elm code. The Graphics.* package is a legacy of that ambition. In the mean time, practicality won and the visual part of Elm got downgraded to Html+CSS. I view this as the equivalent of a C programmer returning to writing in assembly. :)

Who knows, maybe that ambitious struggle will return or (and I view this as more probable) someone else will try to solve that another way (I've seen other people searching for the holy grail of Elm GUI programming). 





--
There is NO FATE, we are the creators.
blog: http://damoc.ro/
Reply all
Reply to author
Forward
0 new messages