Skip to content

Instantly share code, notes, and snippets.

@eriklott
Last active November 19, 2019 18:56
Show Gist options
  • Save eriklott/bb78ae787d94e0157befc480fbd6b06e to your computer and use it in GitHub Desktop.
Save eriklott/bb78ae787d94e0157befc480fbd6b06e to your computer and use it in GitHub Desktop.
module Touch exposing (..)
{-| A useful set of utilities for decoding browser touch events
# Types
@docs Position
# Decoders
@docs position, target, identifier, touches, touch, targetTouches, targetTouch,
changedTouches, changedTouch, touchList
-}
import Json.Decode as Json
import Dict
{-| position represents an on-screen position
-}
type alias Position =
{ x : Int
, y : Int
}
{-| The decoder used to extract a `Position` from a JavaScript touch event.
-}
position : Json.Decoder Position
position =
Json.map2 Position
(Json.field "pageX" Json.int)
(Json.field "pageY" Json.int)
{-| get the target of the touch event
-}
target : Json.Decoder a -> Json.Decoder a
target =
Json.field "target"
{-| get the touch identifier
-}
identifier : Json.Decoder Int
identifier =
Json.field "identifier" Json.int
{-| A list of Touches for every point of contact currently touching the surface.
-}
touches : Json.Decoder a -> Json.Decoder (List a)
touches =
Json.field "touches" << touchList
{-| Get point of contact currently touching the surface by its identifier
-}
touch : Int -> Json.Decoder a -> Json.Decoder (Maybe a)
touch ident decoder =
touches (Json.map2 (,) identifier decoder)
|> Json.map Dict.fromList
|> Json.map (Dict.get ident)
{-| A list of Touches for every point of contact that is touching the surface
and started on the element that is the target of the current event
-}
targetTouches : Json.Decoder a -> Json.Decoder (List a)
targetTouches =
Json.field "touches" << touchList
{-| Get point of contact that is touching the surface and started on the
element that is the target of the current event by its identifier.
-}
targetTouch : Int -> Json.Decoder a -> Json.Decoder (Maybe a)
targetTouch ident decoder =
targetTouches (Json.map2 (,) identifier decoder)
|> Json.map Dict.fromList
|> Json.map (Dict.get ident)
{-| A list of Touches for every point of contact which contributed to the event.
-}
changedTouches : Json.Decoder a -> Json.Decoder (List a)
changedTouches =
Json.field "changedTouches" << touchList
{-| Get point of contact which contributed to the event by its identifier.
-}
changedTouch : Int -> Json.Decoder a -> Json.Decoder (Maybe a)
changedTouch ident decoder =
changedTouches (Json.map2 (,) identifier decoder)
|> Json.map Dict.fromList
|> Json.map (Dict.get ident)
{-| A list of Touches.
-}
touchList : Json.Decoder a -> Json.Decoder (List a)
touchList decoder =
let
toTouchKeysLoop num count accum =
if count < num then
toTouchKeysLoop num (count + 1) (accum ++ [ toString count ])
else
accum
toTouchKeys num =
toTouchKeysLoop num 0 []
decodeTouchValues =
List.map (\key -> Json.field key decoder)
>> List.foldr (Json.map2 (\a accum -> a :: accum)) (Json.succeed [])
in
Json.field "length" Json.int
|> Json.map toTouchKeys
|> Json.andThen decodeTouchValues
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment