Gestione eventi tastiera in Elm
Elm è un linguaggio di tipo funzionale con uno dominio di utilizzo ben preciso: è pensato per creare interfacce grafiche per il web. La compilazione di un programma in Elm produce direttamente tutto il codice javascript che il browser deve interpretare.
Curioso di provare questo linguaggio, perché interessato ad imparare le basi della programmazione funzionale, ho deciso di utilizzarlo in un piccolo progetto di studio ts-converter.
Sviluppando questo progetto ho dovuto capire come gestire con Elm gli eventi che arrivano
dalla tastiera.
L’esempio presenta la gestione dell’evento enter
.
L’idea di questo articolo è fornire alcune note per poter gestire questa attività nella propria applicazione.
Due sono gli scenari possibili
Scenario 1: Catturare tutti gli eventi dell’applicazione
Vediamo come catturare qualunque tasto premuto all’interno dell’applicazione
Per questo scenario abbiamo bisogno delle subscription
Prima di tutto si deve registrare una subscription
Una subscription
è un’operazione che ci permette di ricevere un evento esterno
Creandone una si comunica al runtime di Elm che vogliamo compiere un’azione al manifestarsi
dell’evento. In particolare il runtime produce un messaggio di update
quando viene ascoltato
l’evento di interesse.
subscriptions _ =
onKeyPress keyDecoder
Viene creata una sottoscrizione all’evento onKeyPress
, quando
questo intervento viene intercettato viene invocata la funzione keyDecoder
keyDecoder : Decode.Decoder Msg
keyDecoder =
Decode.map toKey (Decode.field "key" Decode.string)
Decode.field "key" Decode.string
permette di trasformare elementi
JSON in valori validi per Elm. In particolare l’evento catturato viene rappresentato
come un oggetto serializzato in JSON e nel cui campo key viene inserito il
valore del tasto che è stato premuto
Il valore di tale tasto viene passato alla funzione toKey
.
toKey : String -> Msg
toKey keyValue =
case String.uncons keyValue of
Just ( char, "" ) ->
CharacterKey char
_ ->
ControlKey keyValue
String.uncons
considera la Stringa come una array di caratteri e ne divide la
testa dal resto dell’array. A seconda se il carattere di testa è un valore alfanumerico
o meno produce il relativo messaggio di update
CharacterKey k ->
( model
, Cmd.none
)
ControlKey k ->
( { model | result = formatter }
, Cmd.none
)
Nella funzione di update
verranno gestiti i due casi.
Scenario 2: Catturare un evento legato a un campo di input
Elm non supporta al momento (0.19) nativamente onEnter, ma offre la funzione
on
che permette di creare un custom event listener
onEnter: Msg -> Attribute Msg
onEnter msg =
let
isEnter code =
if code == 13 then
Decode.succeed msg
else
Decode.fail "not ENTER"
in
on "keydown" (Decode.andThen isEnter keyCode)
Con on "keydown" (Decode.andThen isEnter keyCode)
creiamo un listener
in ascolto sull’evento keydown
e al suo manifestarsi eseguiamo (Decode.andThen isEnter keyCode)
dove keyCode
è la funzione che ritorna il valore intero del tasto premuto,
isEnter
controlla se e' stato premuto il tasto che ci interessa enter
(valore 13)
producendo rispettivamente un messaggio per la funzione di update
o un fallimento
La funzione onEnter
viene usata nel campo input che ci interessa monitorare.
input [ size 20, value (tsToString model.ts), onInput SetTs, onEnter Convert, autofocus True] []