Inspect JSON for schema

I’ve been learning Elm for less than a week, so lots of ways I could be off track here, hope this isn’t an awfully stupid question. When browsing around brought me to a nice paper about FRP, I found in it a little one-liner program that displays mouse coordinates on a mouse move event. Of course that program doesn’t have a thing in it that works in 0.19, but I assume the capability is not gone, so I thought I’d try to get it working.

Now I have a program with
subscriptions model = Browser.Events.onMouseMove Json.Decode.____

But how do I know what to ask for in that JSON blob? Maybe what I’m looking for isn’t even in there, but … what is in there? The schema, maybe that would be the word.

I’m guessing, from limited experience with JSON, that this is a data structure marshaled into a string. Is there any way, within the standard elm distribution, to just return that string?

Hi @Donn, browser events expecting a JSON decoder are under the hood hooks to html events, so here the mousemouve event, which follows the MouseEvent interface. This means this listener will receive as argument a JavaScript value with all the mouse events properties (clientX/Y, pageX/Y, etc.). But this is a JS value so to retrieve it in Elm land, we need to pass it into a decoder. I suggest starting with the guide on the section explaining JSON decoders if it’s the first time you hear about it.

So, let’s say you are interested in the clientX/Y coordinates of the mouse event. You could use the following decoder:

clientPosDecoder : Decoder (Int, Int)
clientPosDecoder =
    Json.Decode.map2 (\x y -> (x, y))
        (Json.Decode.field "clientX" Json.Decode.int)
        (Json.Decode.field "clientY" Json.Decode.int)

Then you need to transform that into a message type, so for example:

type Msg = MouseMoving (Int, Int)

subscriptions model =
    Browser.Events.onMouseMove
        (Json.Decode.map MouseMoving clientPosDecoder)
3 Likes

Thanks! I had in fact guessed there might be “x” and “y” fields, which as it turns out are also provided as aliases, so I did have something working -

type Msg = Coord Int Int

subscriptions model = Browser.Events.onMouseMove
    (Json.Decode.map2
        Coord
        (Json.Decode.field "x" Json.Decode.int)
        (Json.Decode.field "y" Json.Decode.int))

… and with the helpful pointer to the MouseEvent schema, we’re good for anything else we might want to know about that. Another response led me to look at Json.Encode.encode as a way to look at the marshaled values, which I tried as

     (Json.Decode.map (Json.Encode.encode 4) Json.Decode.value)

but curiously all I actually get out of that is { "isTrusted": true }.

Working with events is a bit annoying if you want to explore the JS values underneath because event objects contain recursive values. Since Json.Encode.encode is based on the JSON.stringify() JavaScript function, it has the same limitations for this use case.

One way to inspect those values, is to use the JS function console.log inside a port. See this Ellie for example (you need to open you console in dev tools to see the logs): https://ellie-app.com/cQn8k3z3NQRa1

Thanks! Lots more there. I see “isTrusted” reported as the first element in the abridged log display.