Matthieu Pizenberg
2017-05-06 09:00:11 UTC
Hi all,
I'm currently rewriting my multitouch package (mpizenberg/elm-touch-events
<http://package.elm-lang.org/packages/mpizenberg/elm-touch-events/latest>)
to provide a much simpler API
<https://github.com/mpizenberg/elm-touch-events/issues/1>. While doing so,
I am also trying to clean the code. And one thing that is very hacky is the
way I'm decoding the touches for multitouch. Basically, the JS object value
to decode <https://developer.mozilla.org/en-US/docs/Web/API/TouchList> is
of the form:
{ length: Int, item: (function), "0": Touch, "1": Touch, ..., "n-1": Touch }
where n is the number of fingers touching the surface (so it's also the
value of the int `length` attribute).
Figuring out this form of the TouchList object was already a challenge
since getting it as an `Encode.Value` just create a runtime error. The key
function that made this available is the combination of `Json.Decode.maybe
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#maybe>`
function with `Json.Decode.dict
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#dict>
`.
maybe
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#maybe>
: Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
a -> Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
(Maybe
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Maybe#Maybe> a)
dict
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#dict>
: Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
a -> Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
(Dict <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Dict#Dict>
String a)
figureStructureDecoder : Decoder (Dict String Bool)
figureStructureDecoder =
Decode.dict (Decode.succeed True)
type alias Touch = ... -- some type for decoding a JS Touch object
touchDecoder : Decoder Touch
tryDecodeTouches : Decoder (Dict String (Maybe Touch))
tryDecodeTouches =
Decode.maybe touchDecoder
|> Decode.dict
Using the `figureStructureDecoder` decoder enabled me to figure out Touch
JS object structure. Then, using the `tryDecodeTouches` with different
variations of `touchDecoder` I managed to get a an elm record of the form:
{ "length": Nothing, "item": Nothing, "0": Just Touch, ..., "n-1": Just
Touch }
In the end, retrieving all the touches is just a matter of filtering out
the `Nothing`.
Now this is obviously not very clean. I've been trying to use
*`Decode.andThen`* by first decoding the `length` attribute (to get `n`)
and then trying to decode all the "0", ... "n-1" attributes by creating a
list of dedicated decoders (each using the approriate `Decode.field`
function). The problem is now I get a *`List (Decoder Touch)`* and no way
to make that a *`Decoder (List Touch)`*.
I've tried to use the *`Json.Extra.sequence`* function:
sequence : List (Decoder a) -> Decoder (List a)
But I couldn't figure out how to make it work. Actually it's because of
this mention: "Note that this function expects the list of decoders to have
the same length as the list of values in the JSON". Well, ... first I don't
have a list of values but one value and a list of decoders for different
objects inside that value. And by looking at the code, I realized that it
also relies on the use of *`Decode.value`*, which in this case would create
a runtime exception anyway as I explained earlier.
So in the end, I can't figure out a cleaner way to decode a multitouch
event. *Any ideas or tips?*
I'm currently rewriting my multitouch package (mpizenberg/elm-touch-events
<http://package.elm-lang.org/packages/mpizenberg/elm-touch-events/latest>)
to provide a much simpler API
<https://github.com/mpizenberg/elm-touch-events/issues/1>. While doing so,
I am also trying to clean the code. And one thing that is very hacky is the
way I'm decoding the touches for multitouch. Basically, the JS object value
to decode <https://developer.mozilla.org/en-US/docs/Web/API/TouchList> is
of the form:
{ length: Int, item: (function), "0": Touch, "1": Touch, ..., "n-1": Touch }
where n is the number of fingers touching the surface (so it's also the
value of the int `length` attribute).
Figuring out this form of the TouchList object was already a challenge
since getting it as an `Encode.Value` just create a runtime error. The key
function that made this available is the combination of `Json.Decode.maybe
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#maybe>`
function with `Json.Decode.dict
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#dict>
`.
maybe
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#maybe>
: Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
a -> Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
(Maybe
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Maybe#Maybe> a)
dict
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#dict>
: Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
a -> Decoder
<http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode#Decoder>
(Dict <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Dict#Dict>
String a)
figureStructureDecoder : Decoder (Dict String Bool)
figureStructureDecoder =
Decode.dict (Decode.succeed True)
type alias Touch = ... -- some type for decoding a JS Touch object
touchDecoder : Decoder Touch
tryDecodeTouches : Decoder (Dict String (Maybe Touch))
tryDecodeTouches =
Decode.maybe touchDecoder
|> Decode.dict
Using the `figureStructureDecoder` decoder enabled me to figure out Touch
JS object structure. Then, using the `tryDecodeTouches` with different
variations of `touchDecoder` I managed to get a an elm record of the form:
{ "length": Nothing, "item": Nothing, "0": Just Touch, ..., "n-1": Just
Touch }
In the end, retrieving all the touches is just a matter of filtering out
the `Nothing`.
Now this is obviously not very clean. I've been trying to use
*`Decode.andThen`* by first decoding the `length` attribute (to get `n`)
and then trying to decode all the "0", ... "n-1" attributes by creating a
list of dedicated decoders (each using the approriate `Decode.field`
function). The problem is now I get a *`List (Decoder Touch)`* and no way
to make that a *`Decoder (List Touch)`*.
I've tried to use the *`Json.Extra.sequence`* function:
sequence : List (Decoder a) -> Decoder (List a)
But I couldn't figure out how to make it work. Actually it's because of
this mention: "Note that this function expects the list of decoders to have
the same length as the list of values in the JSON". Well, ... first I don't
have a list of values but one value and a list of decoders for different
objects inside that value. And by looking at the code, I realized that it
also relies on the use of *`Decode.value`*, which in this case would create
a runtime exception anyway as I explained earlier.
So in the end, I can't figure out a cleaner way to decode a multitouch
event. *Any ideas or tips?*
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.