summaryrefslogtreecommitdiff
path: root/elm/Lib/Html.elm
blob: fd5ebf5dc1faa8d0ec02fee2e6d1e3837f65f295 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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-<br> (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 -> String -> (String -> m) -> List (Attribute m) -> List (String, String) -> Html m
inputSelect nam sel onch attrs lst =
  let opt (id, name) = option [ value id, selected (id == sel) ] [ text name ]
  in select (
    [ tabindex 10
    , onInput onch
    ]
    ++ attrs
    ++ (if nam == "" then [] else [ id nam, name nam ])
  ) <| List.map 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
    ]
    ++ 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 ])
  ) []


-- 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
--   "input::String" -> Label that refers to the named input
--
-- (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
      td [ class "label" ]
      [ case String.split "::" lbl of
          [name, txt] -> label [ for name ] [ text txt ]
          txt         -> text <| String.concat txt
      ]
  , td (class "field" :: if lbl == "none" then [ colspan 2 ] else []) cont
  ]