Skip to content

Instantly share code, notes, and snippets.

@botandrose
Forked from NickAger/elm-slider.elm
Last active April 3, 2016 17:42
Show Gist options
  • Save botandrose/55210a78e604ee5436e7309d58aaf430 to your computer and use it in GitHub Desktop.
Save botandrose/55210a78e604ee5436e7309d58aaf430 to your computer and use it in GitHub Desktop.
Understand how components work in Elm - An Elm version of https://jqueryui.com/slider/
module Slider where
import Html exposing (..)
import Html.Attributes exposing (class, style)
import Mouse
import Signal
-- MODEL
type alias Position =
{ x : Int
, y : Int
}
toPosition : (Int, Int) -> Position
toPosition = uncurry Position
zeroPosition : Position
zeroPosition =
Position 0 0
type alias Model =
{ properties: { topLeft : Position, height : Int}
, percentValue : Int
}
initialModel : Model
-- topLeft should be retrieved from jquery#offset
initialModel =
{ properties = { topLeft = { x = 10, y = 10 }, height = 200 }
, percentValue = 50
}
-- CSS
trackCSS : List (String, String)
trackCSS =
[ ("width", "12px")
, ("background", "#eeeeee")
, ("border-radius", "4px")
, ("border", "1px solid #dddddd")
, ("position", "relative")
, ("margin-left", "10px")
, ("margin-top", "10px")
]
thumbCSS : List (String, String)
thumbCSS =
[ ("border", "1px solid #cccccc")
, ("background", "#f6f6f6")
, ("left", "-4px")
, ("margin-left", "0")
, ("margin-bottom", "-4px")
, ("position", "absolute")
, ("z-index", "2")
, ("width", "18px")
, ("height", "18px")
, ("border-radius", "4px")
]
-- VIEW
view : Model -> Html
view model =
div []
[ renderSlider model
, renderModel model
]
renderSlider : Model -> Html
renderSlider model =
div [ style (("height", toString model.properties.height ++ "px") :: trackCSS) ]
[ div [ style (("bottom", toString model.percentValue ++ "%") :: thumbCSS )]
[]
]
renderModel : Model -> Html
renderModel model =
div []
[ hr [] []
, text <| toString model
]
-- UPDATE
update : Position -> Model -> Model
update downPosition model =
if mouseDownWithinSlider downPosition model
then { model | percentValue = barPercent downPosition model }
else model
mouseDownWithinSlider : Position -> Model -> Bool
mouseDownWithinSlider downPosition model =
let
mx = downPosition.x
x = model.properties.topLeft.x
my = downPosition.y
y = model.properties.topLeft.y
height = model.properties.height
isWithin = \a b c -> c > a && c < b
in
(isWithin (x - 15) (x + 25) mx) && (isWithin y (y + height) my)
barPercent : Position -> Model -> Int
barPercent downPosition model =
let
posY = toFloat downPosition.y
y = toFloat model.properties.topLeft.y
height = toFloat model.properties.height
barPercent = round <| 100 - ((posY - y) / (height / 100))
in
clamp 0 100 barPercent
-- SIGNALS
mouseDownPositionSignal : Signal Position
mouseDownPositionSignal =
let
maybeMouseDownPosition (isDown, mousePosition) =
if isDown
then Just <| toPosition mousePosition
else Nothing
in
Signal.map2 (,) Mouse.isDown Mouse.position
|> Signal.filterMap maybeMouseDownPosition zeroPosition
modelSignal : Signal Model
modelSignal =
Signal.foldp update initialModel mouseDownPositionSignal
--
main : Signal Html
main =
Signal.map view modelSignal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment