Resizable element events

Hello,

I’m working in Elm on kind of a game, and what I need to achieve is this:

  • user can create new HTML elements (e.g. divs) on the page
  • user can drag & drop the elements
  • user can resize the elements
  • user can save the page state to the server and load it back (so the whole HTML page will be loaded from the server and restored)

I have problem with the resizing. I can use the CSS ‘resize: both’ style, but I can’t read the element’s new size, and so I couldn’t save it then to and restore from the server. For dragging there are HTML events (and also there are Elm libraries), but for resizing there are no events, and so I can’t use same approach.

Is there any way/idea/workaround to keep tracking changing element’s size when user freely resizes it?

Another possible option I think of is to read all the DOM, iterate through every element, read its properties (like size, position, etc.), and save it so then it all could be restored. Is there any way to do this in Elm? Let’s say, all the actions happen inside a ‘container’ DIV that is created in the Elm application, and all elements user creates are created as children of the container - is there any way in Elm to iterate all the child elements of the container DIV?

Thanks

Elm ports and Resize Observers might be what you need, but they are not supported very well currently:
https://caniuse.com/#feat=resizeobserver

1 Like

Yes, I’ve learnt about resize observers, but they’re not supported so well so I could use this, unfortunately.

There is a polyfill https://github.com/juggle/resize-observer

Rather than using ports I would wrap the observer in a custom element and have it fire events, port wiring is cumbersome compared to regular events IMO.

1 Like

You could do this with just Elm, no ports. I made a table with resizeable columns this way.

Place a div on each edge of the elements, with onMouseDown (MouseDown itemId <Edge>)

type Edge = Top | Bottom | Left | Right

subscriptions = Browser.Events.onMouseMove <| 
  Decode.map2 MouseMove 
    (Decode.field "pageX" Decode.int)
    (Decode.field "pageY" Decode.int)

update msg model
  case msg of
    MouseDown id edge ->
     ({model | dragging = Just (id, edge)}, Cmd.none)

    MouseMove x y ->
     case model.dragging of
       Just (id, edge) ->
         -- do some math and update the dragged item's height/width/position etc.

       Nothing ->
         (model, Cmd.none)

Sorry for the brief example, hope it makes sense :slightly_smiling_face:

Btw, the css resize property is not supported by IE or Edge, but doing it this way works.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.