module Lib.Html exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Json.Decode as JD
import List
import Lib.Api as Api
-- onClick with stopPropagation & preventDefault
onClickN : m -> Attribute m
onClickN action = custom "click" (JD.succeed { message = action, stopPropagation = True, preventDefault = True})
-- Multi-
(ugly but oh, so, convenient)
br_ : Int -> Html m
br_ n = if n == 1 then br [] [] else span [] <| List.repeat n <| br [] []
-- Submit button with loading indicator and error message display
submitButton : String -> Api.State -> Bool -> Bool -> Html m
submitButton val state valid load = div []
[ input [ type_ "submit", class "submit", tabindex 10, value val, disabled (state == Api.Loading || not valid || load) ] []
, case state of
Api.Error r -> p [] [ b [class "standout" ] [ text <| Api.showResponse r ] ]
_ -> if valid
then text ""
else p [] [ b [class "standout" ] [ text "The form contains errors, please fix these before submitting. " ] ]
, if state == Api.Loading || load
then div [ class "spinner" ] []
else text ""
]
inputSelect : String -> a -> (a -> m) -> List (Attribute m) -> List (a, String) -> Html m
inputSelect nam sel onch attrs lst =
let
opt n (id, name) = option [ value (String.fromInt n), selected (id == sel) ] [ text name ]
call first n =
case List.drop (Maybe.withDefault 0 <| String.toInt n) lst |> List.head of
Just (id, name) -> onch id
Nothing -> onch first
ev =
case List.head lst of
Just first -> [ onInput <| call <| Tuple.first first ]
Nothing -> []
in select (
[ tabindex 10 ]
++ ev
++ attrs
++ (if nam == "" then [] else [ id nam, name nam ])
) <| List.indexedMap opt lst
inputText : String -> String -> (String -> m) -> List (Attribute m) -> Html m
inputText nam val onch attrs = input (
[ type_ "text"
, class "text"
, tabindex 10
, value val
, onInput onch
]
++ attrs
++ (if nam == "" then [] else [ id nam, name nam ])
) []
inputPassword : String -> String -> (String -> m) -> List (Attribute m) -> Html m
inputPassword nam val onch attrs = input (
[ type_ "password"
, class "text"
, tabindex 10
, value val
, onInput onch
]
++ attrs
++ (if nam == "" then [] else [ id nam, name nam ])
) []
inputTextArea : String -> String -> (String -> m) -> List (Attribute m) -> Html m
inputTextArea nam val onch attrs = textarea (
[ tabindex 10
, onInput onch
, rows 4
, cols 50
]
++ attrs
++ (if nam == "" then [] else [ id nam, name nam ])
) [ text val ]
inputCheck : String -> Bool -> (Bool -> m) -> Html m
inputCheck nam val onch = input (
[ type_ "checkbox"
, tabindex 10
, onCheck onch
, checked val
]
++ (if nam == "" then [] else [ id nam, name nam ])
) []
inputRadio : String -> Bool -> (Bool -> m) -> Html m
inputRadio nam val onch = input (
[ type_ "radio"
, tabindex 10
, onCheck onch
, checked val
]
++ (if nam == "" then [] else [ name nam ])
) []
-- Same as an inputText, but formats/parses an integer as Q###
inputWikidata : String -> Maybe Int -> (Maybe Int -> m) -> Html m
inputWikidata nam val onch =
inputText nam
(case val of
Nothing -> ""
Just v -> "Q" ++ String.fromInt v)
(\v -> onch <| if v == "" then Nothing else String.toInt <| if String.startsWith "Q" v then String.dropLeft 1 v else v)
[ pattern "^Q?[1-9][0-9]{0,8}$" ]
-- Generate a form field (table row) with a label. The `label` string can be:
--
-- "none" -> To generate a full-width field (colspan=2)
-- "" -> Empty label
-- "Some string" -> Text label
-- "Some string#eng" -> Text label with (English please!) message
-- "input::String" -> Label that refers to the named input (also supports #eng)
--
-- (Yeah, stringly typed arguments; I wish Elm had typeclasses)
formField : String -> List (Html m) -> Html m
formField lbl cont =
tr [ class "newfield" ]
[ if lbl == "none"
then text ""
else
let
(nlbl, eng) = if String.endsWith "#eng" lbl then (String.dropRight 4 lbl, True) else (lbl, False)
genlbl str = text str :: if eng then [ br [] [], b [ class "standout" ] [ text "English please!" ] ] else []
in
td [ class "label" ] <|
case String.split "::" nlbl of
[name, txt] -> [ label [ for name ] (genlbl txt) ]
txt -> genlbl (String.concat txt)
, td (class "field" :: if lbl == "none" then [ colspan 2 ] else []) cont
]