Created
July 4, 2017 13:28
-
-
Save anonymous/6e1df73bd0cc16443d87c58647eead17 to your computer and use it in GitHub Desktop.
Revisions
-
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,194 @@ module Main exposing (..) import Html exposing (Html, Attribute, div, ul, label, span, li, a, input, text) import Html.Attributes exposing (..) import Html.Events exposing (on, onInput, onClick, keyCode) import Tuple exposing (first, second) import Json.Decode as Json main = Html.beginnerProgram { model = model , view = view , update = update } -- MODEL type alias Task = { id : Int , description : String , isComplete : Bool } type alias Model = { uid : Int , description : String , tasks : List Task , visibilityFilter : String } model : Model model = Model 3 "" initStartTasks "all" initStartTasks : List Task initStartTasks = List.map mapTask startingTasks startingTasks : List ( Int, String ) startingTasks = [ ( 0, "Buy milk" ) , ( 1, "Read paper" ) , ( 2, "Post letter" ) ] mapTask : ( Int, String ) -> Task mapTask obj = taskInit (first obj) (second obj) taskInit : Int -> String -> Task taskInit id description = { id = id , description = description , isComplete = False } -- UPDATE type Msg = DescriptionChange String | Add | ApplyFilter String | ToggleStatus Int Bool update : Msg -> Model -> Model update msg model = case msg of DescriptionChange newContent -> { model | description = newContent } Add -> { model | uid = model.uid + 1 , description = "" , tasks = if String.isEmpty model.description then model.tasks else model.tasks ++ [ taskInit model.uid model.description ] } ApplyFilter filter -> { model | visibilityFilter = filter } ToggleStatus id isCompleted -> let updateEntry t = if t.id == id then { t | isComplete = isCompleted } else t in { model | tasks = List.map updateEntry model.tasks } -- VIEW view : Model -> Html Msg view model = div [ id "root" ] [ viewInputBox model , div [] [ viewTasks model ] , div [] [ viewFilters model.visibilityFilter ] ] viewInputBox : Model -> Html Msg viewInputBox model = div [ class "has-float-label" ] [ input [ type_ "text", placeholder " ", value model.description, onInput DescriptionChange, onEnter Add ] [] , label [] [ text "What do you need to do?" ] ] viewTasks : Model -> Html Msg viewTasks model = let liItems = List.map viewTaskItem (List.filter (taskFilter model.visibilityFilter) model.tasks) in ul [ id "task-list" ] ([] ++ liItems) taskFilter filter = filterTasks filter filterTasks : String -> Task -> Bool filterTasks filter task = case filter of "active" -> not task.isComplete "complete" -> task.isComplete _ -> True viewTaskItem : Task -> Html Msg viewTaskItem task = li [ class "list-item", id ("task-" ++ toString task.id) ] [ label [ class "list-item__checkbox tickbox" ] [ input [ type_ "checkbox", checked task.isComplete, onClick (ToggleStatus task.id (not task.isComplete)) ] [] , span [] [ text task.description ] ] ] viewFilters : String -> Html Msg viewFilters filter = div [ class "filters" ] [ visibilityFilter "all" filter , text " " , visibilityFilter "active" filter , text " " , visibilityFilter "complete" filter ] visibilityFilter: String -> String -> Html Msg visibilityFilter filter activeFilter = a [ href ("#/" ++ filter), classList [("selected", filter == activeFilter)], onClick (ApplyFilter filter) ] [ text (capitalise filter) ] capitalise: String -> String capitalise str = (String.toUpper (String.left 1 str)) ++ String.slice 1 (String.length str) str onEnter : Msg -> Attribute Msg onEnter msg = let isEnter code = if code == 13 then Json.succeed msg else Json.fail "not ENTER" in on "keydown" (Json.andThen isEnter keyCode) This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,15 @@ { "version": "1.0.0", "summary": "Attempt to write own version of todo list (WiP)\n", "repository": "https://github.com/user/project.git", "license": "BSD3", "source-directories": [ "." ], "exposed-modules": [], "dependencies": { "elm-lang/core": "5.1.1 <= v < 5.1.1", "elm-lang/html": "2.0.0 <= v < 2.0.0" }, "elm-version": "0.18.0 <= v < 0.19.0" } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,168 @@ <html> <head> <style> body { background: #fff; font-size: 16px; font-family: Consolas, "monospace"; } </style> <style id="has-float-label"> .has-float-label { display: -webkit-box; display: -ms-flexbox; display: flex; position: relative; } .has-float-label label, .has-float-label > span { position: absolute; left: 5px; top: 1px; cursor: text; font-size: .75em; opacity: 1; -webkit-transition: all .2s; transition: all .2s; } .has-float-label select { -webkit-appearance: none; -moz-appearance: none; appearance: none; } .has-float-label input, .has-float-label select { font-size: inherit; padding: 0 .5em; padding-top: 1em; margin-bottom: 2px; border: 0; border-radius: 0; border-bottom: 2px solid rgba(0, 0, 0, 0.1); } .has-float-label input::-webkit-input-placeholder, .has-float-label select::-webkit-input-placeholder { opacity: 1; -webkit-transition: all .2s; transition: all .2s; } .has-float-label input:placeholder-shown:not(:focus)::-webkit-input-placeholder, .has-float-label select:placeholder-shown:not(:focus)::-webkit-input-placeholder { opacity: 0; } .has-float-label input:placeholder-shown:not(:focus) + *:not(.input-has-content), .has-float-label select:placeholder-shown:not(:focus) + *:not(.input-has-content) { font-size: 1.3em; opacity: .5; pointer-events: none; top: .25em; left: .5em; } .has-float-label input:focus, .has-float-label select:focus { outline: none; border-color: rgba(0, 0, 0, 0.5); } .has-float-label.input-list-container input { padding-bottom: 0.3em; } .has-float-label.input-list-container input:placeholder-shown:not(:focus) + *:not(.input-has-content) { font-size: 1.3em; opacity: .5; pointer-events: none; top: 1em; } .has-float-label.select-container::after { content: "\2335"; position: absolute; top: 50%; right: 5px; -webkit-transform: translateY(-50%); transform: translateY(-50%); font-weight: bold; pointer-events: none; } </style> <style> .tickbox { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; -webkit-box-align: center; -ms-flex-align: center; align-items: center; padding: 2px; cursor: pointer; } .tickbox input[type="checkbox"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; -webkit-transition: all 0.3s; transition: all 0.3s; position: relative; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; width: 20px; height: 20px; margin: 0 5px; } .tickbox input:before, .tickbox input:checked:before { color: #000; -webkit-transition: all 0.3s; transition: all 0.3s; cursor: pointer; z-index: 1; } .tickbox input:before { content: "\2610"; font-size: 2em; } .tickbox input:disabled:before { content: "\274c"; font-size: 1em; color: #444; } .tickbox input:checked:before { content: "\2611"; color: #0f0; } </style> <style> ul { list-style-type: none; padding: 5px; margin: 5px 0; } </style> <style> input[type="text"] { width: 300px; max-width: 100%; } input[type="checkbox"]:checked + span { text-decoration: line-through; } .filters > .selected { color: #ccc; } </style> </head> <body> <script> var app = Elm.Main.fullscreen() </script> </body> </html>