module Html.Events exposing
( onClick, onDoubleClick
, onMouseDown, onMouseUp
, onMouseEnter, onMouseLeave
, onMouseOver, onMouseOut
, onInput, onCheck, onSubmit
, onBlur, onFocus
, on, onWithOptions, Options, defaultOptions
, targetValue, targetChecked, keyCode
)
{-|
It is often helpful to create an [Union Type][] so you can have many different kinds
of events as seen in the [TodoMVC][] example.
[Union Type]: http://elm-lang.org/learn/Union-Types.elm
[TodoMVC]: https://github.com/evancz/elm-todomvc/blob/master/Todo.elm
# Mouse Helpers
@docs onClick, onDoubleClick,
onMouseDown, onMouseUp,
onMouseEnter, onMouseLeave,
onMouseOver, onMouseOut
# Form Helpers
@docs onInput, onCheck, onSubmit
# Focus Helpers
@docs onBlur, onFocus
# Custom Event Handlers
@docs on, onWithOptions, Options, defaultOptions
# Custom Decoders
@docs targetValue, targetChecked, keyCode
-}
import Html exposing (Attribute)
import Json.Decode as Json
import VirtualDom
-- MOUSE EVENTS
{-|-}
onClick : msg -> Attribute msg
onClick msg =
on "click" (Json.succeed msg)
{-|-}
onDoubleClick : msg -> Attribute msg
onDoubleClick msg =
on "dblclick" (Json.succeed msg)
{-|-}
onMouseDown : msg -> Attribute msg
onMouseDown msg =
on "mousedown" (Json.succeed msg)
{-|-}
onMouseUp : msg -> Attribute msg
onMouseUp msg =
on "mouseup" (Json.succeed msg)
{-|-}
onMouseEnter : msg -> Attribute msg
onMouseEnter msg =
on "mouseenter" (Json.succeed msg)
{-|-}
onMouseLeave : msg -> Attribute msg
onMouseLeave msg =
on "mouseleave" (Json.succeed msg)
{-|-}
onMouseOver : msg -> Attribute msg
onMouseOver msg =
on "mouseover" (Json.succeed msg)
{-|-}
onMouseOut : msg -> Attribute msg
onMouseOut msg =
on "mouseout" (Json.succeed msg)
-- FORM EVENTS
{-| Capture [input](https://developer.mozilla.org/en-US/docs/Web/Events/input)
events for things like text fields or text areas.
It grabs the **string** value at `event.target.value`, so it will not work if
you need some other type of information. For example, if you want to track
inputs on a range slider, make a custom handler with [`on`](#on).
For more details on how `onInput` works, check out [targetValue](#targetValue).
-}
onInput : (String -> msg) -> Attribute msg
onInput tagger =
on "input" (Json.map tagger targetValue)
{-| Capture [change](https://developer.mozilla.org/en-US/docs/Web/Events/change)
events on checkboxes. It will grab the boolean value from `event.target.checked`
on any input event.
Check out [targetChecked](#targetChecked) for more details on how this works.
-}
onCheck : (Bool -> msg) -> Attribute msg
onCheck tagger =
on "change" (Json.map tagger targetChecked)
{-| Capture a [submit](https://developer.mozilla.org/en-US/docs/Web/Events/submit)
event with [`preventDefault`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
in order to prevent the form from changing the page’s location. If you need
different behavior, use `onWithOptions` to create a customized version of
`onSubmit`.
-}
onSubmit : msg -> Attribute msg
onSubmit msg =
onWithOptions "submit" onSubmitOptions (Json.succeed msg)
onSubmitOptions : Options
onSubmitOptions =
{ defaultOptions | preventDefault = True }
-- FOCUS EVENTS
{-|-}
onBlur : msg -> Attribute msg
onBlur msg =
on "blur" (Json.succeed msg)
{-|-}
onFocus : msg -> Attribute msg
onFocus msg =
on "focus" (Json.succeed msg)
-- CUSTOM EVENTS
{-| Create a custom event listener. Normally this will not be necessary, but
you have the power! Here is how `onClick` is defined for example:
import Json.Decode as Json
onClick : msg -> Attribute msg
onClick message =
on "click" (Json.succeed message)
The first argument is the event name in the same format as with JavaScript's
[`addEventListener`][aEL] function.
The second argument is a JSON decoder. Read more about these [here][decoder].
When an event occurs, the decoder tries to turn the event object into an Elm
value. If successful, the value is routed to your `update` function. In the
case of `onClick` we always just succeed with the given `message`.
If this is confusing, work through the [Elm Architecture Tutorial][tutorial].
It really does help!
[aEL]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
[decoder]: http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Decode
[tutorial]: https://github.com/evancz/elm-architecture-tutorial/
-}
on : String -> Json.Decoder msg -> Attribute msg
on =
VirtualDom.on
{-| Same as `on` but you can set a few options.
-}
onWithOptions : String -> Options -> Json.Decoder msg -> Attribute msg
onWithOptions =
VirtualDom.onWithOptions
{-| Options for an event listener. If `stopPropagation` is true, it means the
event stops traveling through the DOM so it will not trigger any other event
listeners. If `preventDefault` is true, any built-in browser behavior related
to the event is prevented. For example, this is used with touch events when you
want to treat them as gestures of your own, not as scrolls.
-}
type alias Options =
{ stopPropagation : Bool
, preventDefault : Bool
}
{-| Everything is `False` by default.
defaultOptions =
{ stopPropagation = False
, preventDefault = False
}
-}
defaultOptions : Options
defaultOptions =
VirtualDom.defaultOptions
-- COMMON DECODERS
{-| A `Json.Decoder` for grabbing `event.target.value`. We use this to define
`onInput` as follows:
import Json.Decode as Json
onInput : (String -> msg) -> Attribute msg
onInput tagger =
on "input" (Json.map tagger targetValue)
You probably will never need this, but hopefully it gives some insights into
how to make custom event handlers.
-}
targetValue : Json.Decoder String
targetValue =
Json.at ["target", "value"] Json.string
{-| A `Json.Decoder` for grabbing `event.target.checked`. We use this to define
`onCheck` as follows:
import Json.Decode as Json
onCheck : (Bool -> msg) -> Attribute msg
onCheck tagger =
on "input" (Json.map tagger targetChecked)
-}
targetChecked : Json.Decoder Bool
targetChecked =
Json.at ["target", "checked"] Json.bool
{-| A `Json.Decoder` for grabbing `event.keyCode`. This helps you define
keyboard listeners like this:
import Json.Decode as Json
onKeyUp : (Int -> msg) -> Attribute msg
onKeyUp tagger =
on "keyup" (Json.map tagger keyCode)
**Note:** It looks like the spec is moving away from `event.keyCode` and
towards `event.key`. Once this is supported in more browsers, we may add
helpers here for `onKeyUp`, `onKeyDown`, `onKeyPress`, etc.
-}
keyCode : Json.Decoder Int
keyCode =
Json.field "keyCode" Json.int