Advertisement
Guest User

Untitled

a guest
Jul 29th, 2016
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.83 KB | None | 0 0
  1. import Html exposing (Html, Attribute, div, text, input, button)
  2. import Html.App as Html
  3. import Html.Attributes exposing (..)
  4. import Html.Events exposing (onInput, onClick)
  5. import String
  6. import Regex exposing (regex, contains)
  7. import Process
  8. import Task
  9. import Time
  10. import Debug
  11. import Dict
  12.  
  13. main =
  14. Html.program { init = (model, Cmd.none), view = view, update = update, subscriptions = subscriptions }
  15.  
  16. subscriptions : Model -> Sub Msg
  17. subscriptions model =
  18. Sub.none
  19.  
  20. type Msg
  21. = Name String
  22. | Password String
  23. | PasswordAgain String
  24. | Debounce Time.Time Msg
  25. | DebounceAssign Time.Time Msg Time.Time
  26. | DebounceFinish Time.Time Msg Time.Time
  27.  
  28. type alias Elapsed b =
  29. { since : Time.Time
  30. , data : b
  31. }
  32.  
  33. type alias Model =
  34. { name : String
  35. , password : String
  36. , passwordAgain : String
  37. , showMessages : Bool
  38. , debounceModel : Dict.Dict String (Elapsed Msg)
  39. }
  40.  
  41. model : Model
  42. model =
  43. Model "" "" "" False Dict.empty
  44.  
  45. update : Msg -> Model -> (Model, Cmd Msg)
  46. update msg model =
  47. case msg of
  48. Name name ->
  49. ({ model | name = name }, Cmd.none)
  50. Password password ->
  51. ({ model | password = password, showMessages = True }, Cmd.none)
  52. PasswordAgain password ->
  53. ({ model | passwordAgain = password, showMessages = True }, Cmd.none)
  54. Debounce delay msg ->
  55. let
  56. ( msgSplit, assignTask ) =
  57. ( String.split " " (toString msg)
  58. , Task.perform
  59. Debug.crash (\t -> DebounceAssign delay msg t) Time.now
  60. )
  61. in
  62. ( model
  63. , case msgSplit of
  64. msgName::_ ->
  65. case (Dict.get msgName model.debounceModel) of
  66. Just elapsed -> assignTask
  67. Nothing -> Cmd.batch
  68. [ assignTask
  69. , Task.perform
  70. Debug.crash
  71. (\t -> DebounceFinish delay msg t)
  72. (Process.sleep delay `Task.andThen` \_ -> Time.now)
  73. ]
  74. [] -> Cmd.none
  75. )
  76. DebounceAssign delay msg current ->
  77. case (String.split " " (toString msg)) of
  78. msgName::_ ->
  79. ({ model | debounceModel
  80. = Dict.insert msgName (Elapsed current msg) model.debounceModel
  81. }
  82. , Cmd.none)
  83. [] ->
  84. (model, Cmd.none)
  85. DebounceFinish delay msg current ->
  86. case (String.split " " (toString msg)) of
  87. msgName::_ ->
  88. case (Dict.get msgName model.debounceModel) of
  89. Just elapsed ->
  90. if elapsed.since + delay > current then
  91. (model, Task.perform Debug.crash (\t -> DebounceFinish delay msg t)
  92. (Process.sleep (elapsed.since + delay - current)
  93. `Task.andThen` \_ -> Time.now))
  94. else
  95. ({ model | debounceModel = Dict.remove msgName model.debounceModel}
  96. , Task.perform Debug.crash (\_ -> elapsed.data) Time.now
  97. )
  98. Nothing -> (model, Cmd.none)
  99. [] -> (model, Cmd.none)
  100.  
  101. debounceTime : Time.Time
  102. debounceTime = 1000 * Time.millisecond
  103.  
  104. view : Model -> Html Msg
  105. view model =
  106. div []
  107. [ input [ placeholder "Same", onInput Name ] []
  108. , input [ type' "password", placeholder "Password", onInput (Password >> Debounce debounceTime) ] []
  109. , input [ type' "password", placeholder "Re-enter Password", onInput PasswordAgain ] []
  110. , viewValidation model
  111. ]
  112.  
  113. viewValidation : Model -> Html msg
  114. viewValidation model =
  115. let
  116. (color, messages) =
  117. if model.showMessages && List.length (validator model) > 0 then
  118. ("red", (validator model))
  119. else if model.showMessages then
  120. ("green", ["OK"])
  121. else
  122. ("green", [])
  123. in
  124. div [ style [("color", color)] ]
  125. (List.map (\m -> div [] [text m]) messages)
  126.  
  127. type alias Validation =
  128. { predicate : Model -> Bool
  129. , message : String
  130. }
  131.  
  132. validationBuilder : Validation -> Model -> Maybe String
  133. validationBuilder val model =
  134. if val.predicate model then Nothing else Just val.message
  135.  
  136. validations : List (Model -> Maybe String)
  137. validations =
  138. List.map validationBuilder
  139. [ { predicate = (\m -> (String.length m.password) >= 8)
  140. , message = "Password must be > 8 characters"
  141. }
  142. , { predicate = (\m -> contains (regex "[0-9]+") m.password)
  143. , message = "Password must contain at least 1 number"
  144. }
  145. , { predicate = (\m -> contains (regex "[a-z]+") m.password)
  146. , message = "Password must contain at least 1 lowercase character"
  147. }
  148. , { predicate = (\m -> contains (regex "[A-Z]+") m.password)
  149. , message = "Password must contain at least 1 uppercase character"
  150. }
  151. , { predicate = (\m -> m.password == m.passwordAgain)
  152. , message = "Passwords must match"
  153. }
  154. ]
  155.  
  156. validator : Model -> List String
  157. validator model =
  158. List.filterMap (\fn -> fn model) validations
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement