mirror of
https://github.com/nunntom/elm-ui-select.git
synced 2024-11-22 21:19:26 +03:00
Prevent more unnecessary filtering
This commit is contained in:
parent
a75b080360
commit
559129d85e
@ -25,6 +25,7 @@ exampleProgramTest =
|
||||
[ Test.test "Filter for United Kingdom produces one result" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "United Kingdom"
|
||||
|> ProgramTest.ensureView
|
||||
(Query.find [ Selector.id (Select.toMenuElementId countrySelect) ]
|
||||
@ -38,12 +39,14 @@ exampleProgramTest =
|
||||
, Test.test "Click United Kingdom selects it" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "United"
|
||||
|> Select.Effect.simulateClickOption simulateInputConfig "country-select" "🇬🇧 United Kingdom of Great Britain and Northern Ireland"
|
||||
|> ProgramTest.expectViewHas [ Selector.text "You chose United Kingdom of Great Britain and Northern Ireland" ]
|
||||
, Test.test "Keyboard select United Kingdom" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "United"
|
||||
|> SimulateInput.arrowDown "country-select"
|
||||
|> SimulateInput.enter "country-select"
|
||||
@ -51,12 +54,12 @@ exampleProgramTest =
|
||||
, Test.test "Focusing on the input triggers the onFocus msg" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> ProgramTest.simulateDomEvent (Query.find [ Selector.id (Select.toInputElementId countrySelect) ]) Test.Html.Event.focus
|
||||
|> focusInput
|
||||
|> ProgramTest.expectModel (.inputIsFocused >> Expect.equal (Just True))
|
||||
, Test.test "Input losing focus triggers the onLoseFocus msg" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> ProgramTest.simulateDomEvent (Query.find [ Selector.id (Select.toInputElementId countrySelect) ]) Test.Html.Event.focus
|
||||
|> focusInput
|
||||
|> ProgramTest.simulateDomEvent (Query.find [ Selector.id (Select.toInputElementId countrySelect) ]) Test.Html.Event.blur
|
||||
|> ProgramTest.expectModel (.inputIsFocused >> Expect.equal (Just False))
|
||||
, Test.test "Filling in the input triggers the onInput msg" <|
|
||||
@ -67,26 +70,31 @@ exampleProgramTest =
|
||||
, Test.test "Typing 2 chars with withMinInputLength (Just 3) does not show any items" <|
|
||||
\() ->
|
||||
programTestWith (Select.withMinInputLength (Just 3))
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "un"
|
||||
|> ProgramTest.expectViewHasNot [ Selector.text "🇬🇧 United Kingdom of Great Britain and Northern Ireland" ]
|
||||
, Test.test "Typing 3 chars with withMinInputLength (Just 3) does shows items" <|
|
||||
\() ->
|
||||
programTestWith (Select.withMinInputLength (Just 3))
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "uni"
|
||||
|> ProgramTest.expectViewHas [ Selector.text "🇬🇧 United Kingdom of Great Britain and Northern Ireland" ]
|
||||
, Test.test "Typing less than minInputLength does not show no matches even if nothing matched" <|
|
||||
\() ->
|
||||
programTestWith (Select.withMinInputLength (Just 5))
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "zzzz"
|
||||
|> ProgramTest.expectViewHasNot [ Selector.text "No matches" ]
|
||||
, Test.test "Typing up to the minInputLength shows no matches if nothing matched" <|
|
||||
\() ->
|
||||
programTestWith (Select.withMinInputLength (Just 3))
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "zzzz"
|
||||
|> ProgramTest.expectViewHas [ Selector.text "No matches" ]
|
||||
, Test.test "Choosing an option and then focusing back on the input shows all the options again" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Choose a country" "United"
|
||||
|> Select.Effect.simulateClickOption simulateInputConfig "country-select" "🇬🇧 United Kingdom of Great Britain and Northern Ireland"
|
||||
|> ProgramTest.simulateDomEvent (Query.find [ Selector.id (Select.toInputElementId countrySelect) ]) Test.Html.Event.focus
|
||||
@ -155,3 +163,8 @@ simulateEffect effect =
|
||||
, sleep = SimulatedProcess.sleep
|
||||
}
|
||||
selectEffect
|
||||
|
||||
|
||||
focusInput : ProgramTest model msg effect -> ProgramTest model msg effect
|
||||
focusInput =
|
||||
ProgramTest.simulateDomEvent (Query.find [ Selector.id (Select.toInputElementId countrySelect) ]) Test.Html.Event.focus
|
||||
|
@ -1,10 +1,10 @@
|
||||
module RequestTest exposing (exampleProgramTest)
|
||||
|
||||
import EffectRequestExample as App
|
||||
import EffectRequestExample as App exposing (Cocktail)
|
||||
import Http
|
||||
import Json.Decode as Decode
|
||||
import ProgramTest exposing (ProgramTest, SimulatedEffect)
|
||||
import Select
|
||||
import Select exposing (Select)
|
||||
import Select.Effect
|
||||
import SimulateInput
|
||||
import SimulatedEffect.Cmd as SimulatedCmd
|
||||
@ -12,6 +12,7 @@ import SimulatedEffect.Http as SimulateHttp
|
||||
import SimulatedEffect.Process as SimulatedProcess
|
||||
import SimulatedEffect.Task as SimulatedTask
|
||||
import Test exposing (Test)
|
||||
import Test.Html.Event
|
||||
import Test.Html.Query as Query exposing (Single)
|
||||
import Test.Html.Selector as Selector exposing (Selector)
|
||||
|
||||
@ -22,6 +23,7 @@ exampleProgramTest =
|
||||
[ Test.test "Type in Chocolate, and choose second option with keyboard navigation" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Find a cocktail" "Chocolate"
|
||||
|> ProgramTest.advanceTime 500
|
||||
|> ProgramTest.simulateHttpOk "GET"
|
||||
@ -33,6 +35,7 @@ exampleProgramTest =
|
||||
, Test.test "Type in Chocolate, and choose \"Chocolate Drink\" with mouse click" <|
|
||||
\() ->
|
||||
programTest
|
||||
|> focusInput
|
||||
|> ProgramTest.fillIn "" "Find a cocktail" "Chocolate"
|
||||
|> ProgramTest.advanceTime 300
|
||||
|> ProgramTest.simulateHttpOk "GET"
|
||||
@ -97,6 +100,18 @@ simulateConfig =
|
||||
}
|
||||
|
||||
|
||||
drinkSelect : Select Cocktail
|
||||
drinkSelect =
|
||||
App.init ()
|
||||
|> Tuple.first
|
||||
|> .select
|
||||
|
||||
|
||||
focusInput : ProgramTest model msg effect -> ProgramTest model msg effect
|
||||
focusInput =
|
||||
ProgramTest.simulateDomEvent (Query.find [ Selector.id (Select.toInputElementId drinkSelect) ]) Test.Html.Event.focus
|
||||
|
||||
|
||||
cocktailsResponse : String
|
||||
cocktailsResponse =
|
||||
"""{
|
||||
|
@ -10,6 +10,7 @@ module Internal.Model exposing
|
||||
, isOpen
|
||||
, isRequestFailed
|
||||
, openMenu
|
||||
, requiresNewFilteredOptions
|
||||
, selectOption
|
||||
, setElements
|
||||
, setFilteredOptions
|
||||
@ -128,6 +129,10 @@ wasHighlightedByMouse (Model { highlightedByMouse }) =
|
||||
|
||||
toFilteredOptions : Maybe Int -> (a -> String) -> Maybe (Filter a) -> Model a -> List (Option a)
|
||||
toFilteredOptions minInputLength itemToString filter (Model model) =
|
||||
if not model.focused then
|
||||
[]
|
||||
|
||||
else
|
||||
case minInputLength of
|
||||
Just chars ->
|
||||
if String.length model.inputValue >= chars then
|
||||
@ -238,6 +243,11 @@ isRequestFailed (Model { requestState }) =
|
||||
requestState == Just Failed
|
||||
|
||||
|
||||
requiresNewFilteredOptions : Model a -> Bool
|
||||
requiresNewFilteredOptions (Model { filteredOptions }) =
|
||||
filteredOptions == Nothing
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
@ -8,6 +8,7 @@ type Msg a
|
||||
= InputChanged String (List (Option a))
|
||||
| OptionClicked (Option a)
|
||||
| InputFocused (Maybe Int)
|
||||
| GotNewFilteredOptions (List (Option a))
|
||||
| InputClicked (Maybe Int)
|
||||
| InputLostFocus
|
||||
{ clearInputValue : Bool
|
||||
|
@ -85,13 +85,19 @@ update_ { request, requestMinInputLength, debounceRequest, onFocus, onLoseFocus,
|
||||
, Effect.emitJust onLoseFocus
|
||||
)
|
||||
|
||||
GotNewFilteredOptions options ->
|
||||
( Model.setFilteredOptions options model
|
||||
, Effect.None
|
||||
)
|
||||
|
||||
MouseEnteredOption i ->
|
||||
( Model.highlightIndex (Just i) True model
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
KeyDown selectOnTab filteredOptions key ->
|
||||
handleKey selectOnTab tagger model key filteredOptions
|
||||
Model.setFilteredOptions filteredOptions model
|
||||
|> handleKey selectOnTab tagger key filteredOptions
|
||||
|
||||
GotContainerAndMenuElements maybeIdx result ->
|
||||
( model
|
||||
@ -176,8 +182,8 @@ onFocusMenu tagger maybeOptionIdx hasRequest model =
|
||||
)
|
||||
|
||||
|
||||
handleKey : Bool -> (Msg a -> msg) -> Model a -> String -> List (Option a) -> ( Model a, Effect effect msg )
|
||||
handleKey selectOnTab tagger model key filteredOptions =
|
||||
handleKey : Bool -> (Msg a -> msg) -> String -> List (Option a) -> Model a -> ( Model a, Effect effect msg )
|
||||
handleKey selectOnTab tagger key filteredOptions model =
|
||||
let
|
||||
selectHighlighted =
|
||||
case Model.toHighlighted model |> Maybe.andThen (\idx -> getAt idx filteredOptions) of
|
||||
|
@ -89,7 +89,8 @@ toElement model config =
|
||||
toElement_ : Placement -> List (Option a) -> Model a -> ViewConfigInternal a msg -> Element msg
|
||||
toElement_ placement filteredOptions model config =
|
||||
Element.el
|
||||
([ Element.htmlAttribute (Html.Attributes.id <| Model.toContainerElementId model)
|
||||
(List.concat
|
||||
[ [ Element.htmlAttribute (Html.Attributes.id <| Model.toContainerElementId model)
|
||||
, Element.width Element.fill
|
||||
, Element.below <|
|
||||
if
|
||||
@ -135,12 +136,19 @@ toElement_ placement filteredOptions model config =
|
||||
, optionElement = config.optionElement
|
||||
}
|
||||
]
|
||||
++ (if Model.isOpen model then
|
||||
, if Model.isOpen model then
|
||||
[ Element.htmlAttribute <| Html.Attributes.style "z-index" "21" ]
|
||||
|
||||
else
|
||||
[]
|
||||
)
|
||||
, if Model.isFocused model && Model.requiresNewFilteredOptions model then
|
||||
[ Element.htmlAttribute (Html.Events.on "focusin" (Decode.succeed (GotNewFilteredOptions filteredOptions |> config.onChange)))
|
||||
, Element.htmlAttribute (Html.Events.on "mousemove" (Decode.succeed (GotNewFilteredOptions filteredOptions |> config.onChange)))
|
||||
]
|
||||
|
||||
else
|
||||
[]
|
||||
]
|
||||
)
|
||||
(inputView filteredOptions model config)
|
||||
|
||||
@ -153,8 +161,9 @@ inputView filteredOptions model config =
|
||||
|> Maybe.andThen (Option.findIndex filteredOptions)
|
||||
in
|
||||
Input.text
|
||||
(config.inputAttribs
|
||||
++ [ Events.onFocus (InputFocused selectedIdx |> config.onChange)
|
||||
(List.concat
|
||||
[ config.inputAttribs
|
||||
, [ Events.onFocus (InputFocused selectedIdx |> config.onChange)
|
||||
, Events.onClick (InputClicked selectedIdx |> config.onChange)
|
||||
, Events.onLoseFocus
|
||||
(config.onChange
|
||||
@ -174,7 +183,8 @@ inputView filteredOptions model config =
|
||||
else
|
||||
Element.none
|
||||
]
|
||||
++ inputAccessibilityAttributes filteredOptions model
|
||||
, inputAccessibilityAttributes filteredOptions model
|
||||
]
|
||||
)
|
||||
{ onChange =
|
||||
\v ->
|
||||
|
Loading…
Reference in New Issue
Block a user