Search code examples
domtypeerrorelm

Elm How to make custom event decoder to get mouse x/y position at mouse-wheel-move


I am trying to get the x and y coordinates of the mouse during a mouse-wheel-move event in the Elm 0.19 programming language. I attempt it with this package. See under "Advanced Usage": https://package.elm-lang.org/packages/mpizenberg/elm-pointer-events/3.1.0/Html-Events-Extra-Wheel

The package itself did not describe a clear example so I looked for an example in a similar package. See the example under "advanced usage" in this page: https://package.elm-lang.org/packages/mpizenberg/elm-pointer-events/3.1.0/Html-Events-Extra-Mouse

This example is very similar to what I need, but I can also not get this to work. Get exactly the same problem.

Here is my code adapted from the example to fit with mouse wheel:

module WheelDecoder exposing(..)

import Html exposing (div, text)
import Html.Events.Extra.Wheel as Wheel
import Json.Decode as Decode


type alias WheelEventWithOffsetXY =
  { wheelEvent : Wheel.Event
  , offsetXY : {x: Float, y: Float}
  }

decodeWeelWithOffsetXY : Decode.Decoder WheelEventWithOffsetXY
decodeWeelWithOffsetXY =
  Decode.map2 WheelEventWithOffsetXY
    Wheel.eventDecoder
    offsetXYDecoder

offsetXYDecoder : Decode.Decoder {x: Float, y: Float}
offsetXYDecoder =
  Decode.map2 (\a b -> {x=a,y=b})
    (Decode.field "offsetY" Decode.float)
    (Decode.field "offsetY" Decode.float)

type Msg
  = WheelOffsetXY {x: Float, y: Float}

view = 
  div
    [ (onWheelOffsetXY (\wheelEvent -> WheelOffsetXY (wheelEvent.offsetXY))) ]
    [ (text "mousewheel here") ]


onWheelOffsetXY : (WheelEventWithOffsetXY -> msg) -> Html.Attribute msg
onWheelOffsetXY tag =
  let
    options = { stopPropagation = True, preventDefault = True }
    func = Decode.map tag decodeWeelWithOffsetXY
    attribute = Wheel.onWithOptions options func
  in
    attribute

When I try to compile with "elm make" I get the following error:

-- TYPE MISMATCH -------------------------------------- src/Map/WheelDecoder.elm

The 2nd argument to `onWithOptions` is not what I expect:

39|     attribute = Wheel.onWithOptions options func
                                                ^^^^
This `func` value is a:

    Decode.Decoder msg

But `onWithOptions` needs the 2nd argument to be:

    Wheel.Event -> msg

Hint: I always figure out the argument types from left to right. If an argument
is acceptable, I assume it is “correct” and move on. So the problem may actually
be in one of the previous arguments!

This error message makes sense as I can see there is a type mismatch, but I have no clue about how to solve it.


Solution

  • It seems like Wheel.eventDecoder was meant to work with Html.Events.on or Html.Events.onWithOptions rather than Wheel.onWithOptions. These were removed in 0.19 in favor of Html.Events.custom, however, which is slightly different. Replacing onWheelOffsetXY with this seems to work:

    onWheelOffsetXY : (WheelEventWithOffsetXY -> msg) -> Html.Attribute msg
    onWheelOffsetXY tag =
      let
        options message =
            { message = message
            , stopPropagation = True
            , preventDefault = True
            }
        decoder =
            decodeWeelWithOffsetXY
            |> Decode.map tag 
            |> Decode.map options
      in
      Html.Events.custom "wheel" decoder
    

    PS: There's a typo in decodeWeelWithOffsetXY, btw. I've left the typo in place.

    PPS: Also, you're looking at outdated documentation. Here's the documentation for the latest version.