Skip to content

Commit

Permalink
Double Slider refactor (#16)
Browse files Browse the repository at this point in the history
* Choose the min/max of the current value and the highest/lowest value +- a step.

* Use the overlapThreshold.

* fallback view as the main view

* Flip view and fallbackView

* elm bump
  • Loading branch information
ccmdo authored May 9, 2019
1 parent f9b1d38 commit 8f64cb4
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 219 deletions.
2 changes: 1 addition & 1 deletion elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "carwow/elm-slider",
"summary": "Elm slider implementation",
"license": "BSD-3-Clause",
"version": "7.0.2",
"version": "8.0.0",
"exposed-modules": [
"DoubleSlider",
"SingleSlider"
Expand Down
229 changes: 11 additions & 218 deletions src/DoubleSlider.elm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ module DoubleSlider exposing
-}

import Browser
import Browser.Events
import DOM exposing (boundingClientRect)
import Html exposing (Html, div, input)
import Html.Attributes exposing (..)
Expand All @@ -40,12 +39,6 @@ type alias Model =
, step : Int
, lowValue : Float
, highValue : Float
, dragging : Bool
, draggedValueType : SliderValueType
, rangeStartValue : Float
, thumbStartingPosition : Float
, dragStartPosition : Float
, thumbParentWidth : Float
, overlapThreshold : Float
, minFormatter : Float -> String
, maxFormatter : Float -> String
Expand All @@ -63,9 +56,6 @@ type SliderValueType
-}
type Msg
= TrackClicked SliderValueType String
| DragStart SliderValueType Int Float Float
| DragAt Int
| DragEnd
| RangeChanged SliderValueType String Bool


Expand All @@ -79,12 +69,6 @@ defaultModel =
, lowValue = 0
, highValue = 100
, overlapThreshold = 1
, dragging = False
, draggedValueType = None
, rangeStartValue = 0
, thumbStartingPosition = 0
, thumbParentWidth = 0
, dragStartPosition = 0
, minFormatter = String.fromFloat
, maxFormatter = String.fromFloat
, currentRangeFormatter = defaultCurrentRangeFormatter
Expand Down Expand Up @@ -145,101 +129,6 @@ update message model =
in
( newModel, Cmd.none, True )

DragStart valueType positionX offsetLeft offsetWidth ->
let
newModel =
{ model
| dragging = True
, draggedValueType = valueType
, rangeStartValue =
case valueType of
LowValue ->
model.lowValue - model.min

HighValue ->
model.highValue - model.min

None ->
0
, thumbStartingPosition = offsetLeft + 16
, thumbParentWidth = offsetWidth
, dragStartPosition = toFloat positionX
}
in
( newModel, Cmd.none, False )

DragAt positionX ->
let
rangeStart =
case model.draggedValueType of
HighValue ->
model.rangeStartValue

LowValue ->
model.max - model.rangeStartValue - model.min

None ->
0

offset =
case model.draggedValueType of
HighValue ->
model.thumbStartingPosition

LowValue ->
model.thumbParentWidth - model.thumbStartingPosition

None ->
0

ratio =
rangeStart / offset

delta =
toFloat positionX - model.dragStartPosition

newValue =
case model.draggedValueType of
HighValue ->
model.min + snapValue ((offset + delta) * ratio) model.step

LowValue ->
model.min + snapValue ((model.thumbParentWidth - offset + delta) * ratio) model.step

None ->
0

newModel =
if model.draggedValueType == LowValue && newValue + (toFloat model.step * model.overlapThreshold) > model.highValue then
model

else if model.draggedValueType == HighValue && newValue - (toFloat model.step * model.overlapThreshold) < model.lowValue then
model

else if newValue >= model.min && newValue <= model.max then
case model.draggedValueType of
LowValue ->
{ model | lowValue = newValue }

HighValue ->
{ model | highValue = newValue }

None ->
model

else
model
in
( newModel, Cmd.none, False )

DragEnd ->
( { model
| dragging = False
}
, Cmd.none
, True
)


snapValue : Float -> Int -> Float
snapValue value step =
Expand Down Expand Up @@ -320,16 +209,6 @@ onInsideRangeClick model =
Json.Decode.map2 TrackClicked valueTypeDecoder valueDecoder


onThumbMouseDown : SliderValueType -> Json.Decode.Decoder Msg
onThumbMouseDown valueType =
Json.Decode.map4
DragStart
(Json.Decode.succeed valueType)
pageXDecoder
(Json.Decode.at [ "target", "offsetLeft" ] Json.Decode.float)
(Json.Decode.at [ "target", "offsetParent", "offsetWidth" ] Json.Decode.float)


onRangeChange : SliderValueType -> Bool -> Json.Decode.Decoder Msg
onRangeChange valueType shouldFetchModels =
Json.Decode.map3
Expand All @@ -339,10 +218,10 @@ onRangeChange valueType shouldFetchModels =
(Json.Decode.succeed shouldFetchModels)


{-| Displays the slider using two inputs
{-| Displays the slider
-}
fallbackView : Model -> Html Msg
fallbackView model =
view : Model -> Html Msg
view model =
let
lowValue =
round model.lowValue
Expand Down Expand Up @@ -408,6 +287,13 @@ fallbackView model =
]


{-| DEPRECATED: Displays the slider
-}
fallbackView : Model -> Html Msg
fallbackView model =
view model


{-| Renders the current values using the formatter
-}
formatCurrentRange : Model -> String
Expand All @@ -419,101 +305,8 @@ formatCurrentRange model =
model.currentRangeFormatter model.lowValue model.highValue model.min model.max


{-| Displays the slider
-}
view : Model -> Html Msg
view model =
let
lowValue =
round model.lowValue

highValue =
round model.highValue

progressRatio =
100 / (model.max - model.min)

lowThumbStartingPosition =
String.fromFloat ((model.lowValue - model.min) * progressRatio) ++ "%"

highThumbStartingPosition =
String.fromFloat ((model.highValue - model.min) * progressRatio) ++ "%"

progressLow =
String.fromFloat ((model.lowValue - model.min) * progressRatio) ++ "%"

progressHigh =
String.fromFloat ((model.max - model.highValue) * progressRatio) ++ "%"

mouseDownEvent t =
onThumbMouseDown t
|> Json.Decode.map (\msg -> { message = msg, stopPropagation = True, preventDefault = True })
|> Html.Events.custom "mousedown"
in
div []
[ div
[ Html.Attributes.class "input-range-container" ]
[ div
[ Html.Attributes.class "slider-thumb slider-thumb--first"
, Html.Attributes.style "left" lowThumbStartingPosition
, Html.Attributes.style "float" "left"
, mouseDownEvent LowValue
]
[]
, div
[ Html.Attributes.class "slider-thumb slider-thumb--second"
, Html.Attributes.style "left" highThumbStartingPosition
, Html.Attributes.style "float" "left"
, mouseDownEvent HighValue
]
[]
, div
[ Html.Attributes.class "input-range__track"
, Html.Events.on "click" (onOutsideRangeClick model)
]
[]
, div
[ Html.Attributes.class "input-range__progress"
, Html.Attributes.style "left" progressLow
, Html.Attributes.style "right" progressHigh
, Html.Events.on "click" (onInsideRangeClick model)
]
[]
]
, div
[ Html.Attributes.class "input-range-labels-container" ]
[ div [ Html.Attributes.class "input-range-label" ] [ Html.text (model.minFormatter model.min) ]
, div
[ Html.Attributes.class "input-range-label input-range-label--current-value" ]
[ Html.text (formatCurrentRange model) ]
, div [ Html.Attributes.class "input-range-label" ] [ Html.text (model.maxFormatter model.max) ]
]
]


{-| Returns the subscriptions necessary to run
-}
subscriptions : Model -> Sub Msg
subscriptions model =
if model.dragging then
let
moveDecoder : Json.Decode.Decoder Msg
moveDecoder =
Json.Decode.map DragAt pageXDecoder

upDecoder : Json.Decode.Decoder Msg
upDecoder =
Json.Decode.succeed DragEnd
in
Sub.batch
[ Browser.Events.onMouseMove moveDecoder
, Browser.Events.onMouseUp upDecoder
]

else
Sub.none


pageXDecoder : Json.Decode.Decoder Int
pageXDecoder =
Json.Decode.field "pageX" Json.Decode.int
Sub.none

0 comments on commit 8f64cb4

Please sign in to comment.