Skip to content

Instantly share code, notes, and snippets.

@ccapndave
Created February 3, 2016 15:27
Show Gist options
  • Save ccapndave/a7b032e8d7a21e289a45 to your computer and use it in GitHub Desktop.
Save ccapndave/a7b032e8d7a21e289a45 to your computer and use it in GitHub Desktop.
module Form.Form (selectField, selectCountryField, dateOfBirthField) where
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import List.Extra exposing (zip)
import Date exposing (Date)
import Date.Core exposing (monthList)
import Date.Utils exposing (dateFromFields)
import Json.Decode as JD
import Task exposing (Task)
type alias SelectFieldOpts valueType actionType =
{ label : String
, value : valueType
, action : actionType }
selectField : Signal.Address actionType -> valueType -> List (SelectFieldOpts valueType actionType) -> Html
selectField address currentValue opts =
let
-- Build a list of a numerical key matched with the settings for each option
ids = List.map toString [0..(List.length opts)]
idAndOpts = zip ids opts
-- Given an id, this returns the action for that id
getActionForId id =
let
selectFieldOpts = case (List.filter (\(listId, _) -> listId == id) idAndOpts |> List.head) of
Just opt -> opt |> snd
Nothing -> Debug.crash "Somehow an option without a matching id was selected (this should be impossible!)"
in
selectFieldOpts.action
isSelected opt =
currentValue == opt.value
valueDecoder : JD.Decoder String
valueDecoder =
JD.at ["target", "value"] JD.string
makeOption (id, opt) =
option [ value id
, selected (isSelected opt)
] [ text opt.label ]
in
select [ on "change" valueDecoder (\id -> Signal.message address (getActionForId id)) ] (List.map makeOption idAndOpts)
selectCountryField : Signal.Address a -> String -> (String -> a) -> Html
selectCountryField address currentCountry action =
let
countries = ["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas" ,"Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia & Herzegovina","Botswana","Brazil","British Virgin Islands" ,"Brunei","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Cape Verde","Cayman Islands","Chad","Chile","China","Colombia","Congo","Cook Islands","Costa Rica" ,"Cote D Ivoire","Croatia","Cruise Ship","Cuba","Cyprus","Czech Republic","Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea" ,"Estonia","Ethiopia","Falkland Islands","Faroe Islands","Fiji","Finland","France","French Polynesia","French West Indies","Gabon","Gambia","Georgia","Germany","Ghana" ,"Gibraltar","Greece","Greenland","Grenada","Guam","Guatemala","Guernsey","Guinea","Guinea Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India" ,"Indonesia","Iran","Iraq","Ireland","Isle of Man","Israel","Italy","Jamaica","Japan","Jersey","Jordan","Kazakhstan","Kenya","Kuwait","Kyrgyz Republic","Laos","Latvia" ,"Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macau","Macedonia","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Mauritania" ,"Mauritius","Mexico","Moldova","Monaco","Mongolia","Montenegro","Montserrat","Morocco","Mozambique","Namibia","Nepal","Netherlands","Netherlands Antilles","New Caledonia" ,"New Zealand","Nicaragua","Niger","Nigeria","Norway","Oman","Pakistan","Palestine","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal" ,"Puerto Rico","Qatar","Reunion","Romania","Russia","Rwanda","Saint Pierre & Miquelon","Samoa","San Marino","Satellite","Saudi Arabia","Senegal","Serbia","Seychelles" ,"Sierra Leone","Singapore","Slovakia","Slovenia","South Africa","South Korea","Spain","Sri Lanka","St Kitts & Nevis","St Lucia","St Vincent","St. Lucia","Sudan" ,"Suriname","Swaziland","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor L'Este","Togo","Tonga","Trinidad & Tobago","Tunisia" ,"Turkey","Turkmenistan","Turks & Caicos","Uganda","Ukraine","United Arab Emirates","United Kingdom","Uruguay","Uzbekistan","Venezuela","Vietnam","Virgin Islands (US)" ,"Yemen","Zambia","Zimbabwe"]
opts = List.map (\country -> { label = country, value = country, action = action country }) countries
in
selectField address currentCountry opts
type DateOfBirthAction = Noop | ChangeDay Int | ChangeMonth Date.Month | ChangeYear Int
dateOfBirthField : Signal.Address a -> Date -> (Date -> a) -> Html
dateOfBirthField address currentDate action =
let
mailbox : Signal.Mailbox DateOfBirthAction
mailbox = Signal.mailbox Noop
-- So now I need to somehow turn the Signal from this mailbox into a date and send it out on address as action.
-- I think maybe I can use forwardTo. Maybe I need map too? Actually I think this is a case for foldp. But how?
-- Maybe the problem is that this foldp is disconnected from any other foldp, and it should integrate address/action
-- or something. I kind of need something like 'on', but that is native
--date : Signal Date
date =
let
dateUpdate : DateOfBirthAction -> Date -> Date
dateUpdate action date = case action of
ChangeDay day -> dateFromFields day (Date.month date) (Date.year date) 0 0 0 0
ChangeMonth month -> dateFromFields (Date.day date) month (Date.year date) 0 0 0 0
ChangeYear year -> dateFromFields (Date.day date) (Date.month date) year 0 0 0 0
otherwise -> date
sendDate : Date -> Signal.Message
sendDate date =
Signal.message address (action date)
date : Signal Date
date = Signal.foldp (dateUpdate >> sendDate) currentDate mailbox.signal
in
-- the thing I want to send to 'address' is 'action latestSignalInDate'
1
dateSelect = selectField
mailbox.address
(Date.day currentDate)
(List.map (\day -> { label = toString day, value = day, action = ChangeDay day }) [1..31])
monthSelect = selectField
mailbox.address
(Date.month currentDate)
(List.map (\month -> { label = toString month, value = month, action = ChangeMonth month }) monthList)
yearSelect = selectField
mailbox.address
(Date.day currentDate)
(List.map (\year -> { label = toString year, value = year, action = ChangeYear year }) [1935..2015]) -- TODO: up to the current year?
in
div []
[ dateSelect
, monthSelect
, yearSelect ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment