summaryrefslogtreecommitdiffstats
path: root/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/functional-prog-examples/elm/Todo.elm
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/functional-prog-examples/elm/Todo.elm390
1 files changed, 390 insertions, 0 deletions
diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/functional-prog-examples/elm/Todo.elm b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/functional-prog-examples/elm/Todo.elm
new file mode 100644
index 0000000000..bf1d39db31
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/functional-prog-examples/elm/Todo.elm
@@ -0,0 +1,390 @@
+port module Todo exposing (..)
+
+{-| TodoMVC implemented in Elm, using plain HTML and CSS for rendering.
+
+This application is broken up into four distinct parts:
+
+ 1. Model - a full description of the application as data
+ 2. Update - a way to update the model based on user actions
+ 3. View - a way to visualize our model with HTML
+
+This program is not particularly large, so definitely see the following
+document for notes on structuring more complex GUIs with Elm:
+http://guide.elm-lang.org/architecture/
+-}
+
+import Dom
+import Task
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import Html.Lazy exposing (lazy, lazy2)
+import Html.App
+import Navigation exposing (Parser)
+import String
+import String.Extra
+import Todo.Task
+
+
+-- MODEL
+-- The full application state of our todo app.
+
+
+type alias Model =
+ { tasks : List Todo.Task.Model
+ , field : String
+ , uid : Int
+ , visibility : String
+ }
+
+
+type alias Flags =
+ Maybe Model
+
+
+emptyModel : Model
+emptyModel =
+ { tasks = []
+ , visibility = "All"
+ , field = ""
+ , uid = 0
+ }
+
+
+
+-- UPDATE
+-- A description of the kinds of actions that can be performed on the model of
+-- our application. See the following post for more info on this pattern and
+-- some alternatives: http://guide.elm-lang.org/architecture/
+
+
+type Msg
+ = NoOp
+ | UpdateField String
+ | Add
+ | UpdateTask ( Int, Todo.Task.Msg )
+ | DeleteComplete
+ | CheckAll Bool
+ | ChangeVisibility String
+
+
+
+-- How we update our Model on any given Message
+
+
+update : Msg -> Model -> ( Model, Cmd Msg )
+update msg model =
+ case Debug.log "MESSAGE: " msg of
+ NoOp ->
+ ( model, Cmd.none )
+
+ UpdateField str ->
+ let
+ newModel =
+ { model | field = str }
+ in
+ ( newModel, save model )
+
+ Add ->
+ let
+ description =
+ String.trim model.field
+
+ newModel =
+ if String.isEmpty description then
+ model
+ else
+ { model
+ | uid = model.uid + 1
+ , field = ""
+ , tasks = model.tasks ++ [ Todo.Task.init description model.uid ]
+ }
+ in
+ ( newModel, save newModel )
+
+ UpdateTask ( id, taskMsg ) ->
+ let
+ updateTask t =
+ if t.id == id then
+ Todo.Task.update taskMsg t
+ else
+ Just t
+
+ newModel =
+ { model | tasks = List.filterMap updateTask model.tasks }
+ in
+ case taskMsg of
+ Todo.Task.Focus elementId ->
+ newModel ! [ save newModel, focusTask elementId ]
+
+ _ ->
+ ( newModel, save newModel )
+
+ DeleteComplete ->
+ let
+ newModel =
+ { model
+ | tasks = List.filter (not << .completed) model.tasks
+ }
+ in
+ ( newModel, save newModel )
+
+ CheckAll bool ->
+ let
+ updateTask t =
+ { t | completed = bool }
+
+ newModel =
+ { model | tasks = List.map updateTask model.tasks }
+ in
+ ( newModel, save newModel )
+
+ ChangeVisibility visibility ->
+ let
+ newModel =
+ { model | visibility = visibility }
+ in
+ ( newModel, save model )
+
+
+focusTask : String -> Cmd Msg
+focusTask elementId =
+ Task.perform (\_ -> NoOp) (\_ -> NoOp) (Dom.focus elementId)
+
+
+
+-- VIEW
+
+
+view : Model -> Html Msg
+view model =
+ div
+ [ class "todomvc-wrapper"
+ , style [ ( "visibility", "hidden" ) ]
+ ]
+ [ section
+ [ class "todoapp" ]
+ [ lazy taskEntry model.field
+ , lazy2 taskList model.visibility model.tasks
+ , lazy2 controls model.visibility model.tasks
+ ]
+ , infoFooter
+ ]
+
+
+taskEntry : String -> Html Msg
+taskEntry task =
+ header
+ [ class "header" ]
+ [ h1 [] [ text "todos" ]
+ , input
+ [ class "new-todo"
+ , placeholder "What needs to be done?"
+ , autofocus True
+ , value task
+ , name "newTodo"
+ , onInput UpdateField
+ , Todo.Task.onFinish Add NoOp
+ ]
+ []
+ ]
+
+
+taskList : String -> List Todo.Task.Model -> Html Msg
+taskList visibility tasks =
+ let
+ isVisible todo =
+ case visibility of
+ "Completed" ->
+ todo.completed
+
+ "Active" ->
+ not todo.completed
+
+ -- "All"
+ _ ->
+ True
+
+ allCompleted =
+ List.all .completed tasks
+
+ cssVisibility =
+ if List.isEmpty tasks then
+ "hidden"
+ else
+ "visible"
+ in
+ section
+ [ class "main"
+ , style [ ( "visibility", cssVisibility ) ]
+ ]
+ [ input
+ [ class "toggle-all"
+ , type' "checkbox"
+ , name "toggle"
+ , checked allCompleted
+ , onClick (CheckAll (not allCompleted))
+ ]
+ []
+ , label
+ [ for "toggle-all" ]
+ [ text "Mark all as complete" ]
+ , ul
+ [ class "todo-list" ]
+ (List.map
+ (\task ->
+ let
+ id =
+ task.id
+
+ taskView =
+ Todo.Task.view task
+ in
+ Html.App.map (\msg -> UpdateTask ( id, msg )) taskView
+ )
+ (List.filter isVisible tasks)
+ )
+ ]
+
+
+controls : String -> List Todo.Task.Model -> Html Msg
+controls visibility tasks =
+ let
+ tasksCompleted =
+ List.length (List.filter .completed tasks)
+
+ tasksLeft =
+ List.length tasks - tasksCompleted
+
+ item_ =
+ if tasksLeft == 1 then
+ " item"
+ else
+ " items"
+ in
+ footer
+ [ class "footer"
+ , hidden (List.isEmpty tasks)
+ ]
+ [ span
+ [ class "todo-count" ]
+ [ strong [] [ text (toString tasksLeft) ]
+ , text (item_ ++ " left")
+ ]
+ , ul
+ [ class "filters" ]
+ [ visibilitySwap "#/" "All" visibility
+ , text " "
+ , visibilitySwap "#/active" "Active" visibility
+ , text " "
+ , visibilitySwap "#/completed" "Completed" visibility
+ ]
+ , button
+ [ class "clear-completed"
+ , hidden (tasksCompleted == 0)
+ , onClick DeleteComplete
+ ]
+ [ text ("Clear completed (" ++ toString tasksCompleted ++ ")") ]
+ ]
+
+
+visibilitySwap : String -> String -> String -> Html Msg
+visibilitySwap uri visibility actualVisibility =
+ let
+ className =
+ if visibility == actualVisibility then
+ "selected"
+ else
+ ""
+ in
+ li
+ [ onClick (ChangeVisibility visibility) ]
+ [ a [ class className, href uri ] [ text visibility ] ]
+
+
+infoFooter : Html msg
+infoFooter =
+ footer
+ [ class "info" ]
+ [ p [] [ text "Double-click to edit a todo" ]
+ , p []
+ [ text "Written by "
+ , a [ href "https://github.com/evancz" ] [ text "Evan Czaplicki" ]
+ ]
+ , p []
+ [ text "Part of "
+ , a [ href "http://todomvc.com" ] [ text "TodoMVC" ]
+ ]
+ ]
+
+
+
+-- wire the entire application together
+
+
+main : Program Flags
+main =
+ Navigation.programWithFlags urlParser
+ { urlUpdate = urlUpdate
+ , view = view
+ , init = init
+ , update = update
+ , subscriptions = subscriptions
+ }
+
+
+
+-- URL PARSERS - check out evancz/url-parser for fancier URL parsing
+
+
+toUrl : String -> String
+toUrl visibility =
+ "#/" ++ String.toLower visibility
+
+
+fromUrl : String -> Maybe String
+fromUrl hash =
+ let
+ cleanHash =
+ String.dropLeft 2 hash
+ in
+ if (List.member cleanHash [ "all", "active", "completed" ]) == True then
+ Just cleanHash
+ else
+ Nothing
+
+
+urlParser : Parser (Maybe String)
+urlParser =
+ Navigation.makeParser (fromUrl << .hash)
+
+
+{-| The URL is turned into a Maybe value. If the URL is valid, we just update
+our model with the new visibility settings. If it is not a valid URL,
+we set the visibility filter to show all tasks.
+-}
+urlUpdate : Maybe String -> Model -> ( Model, Cmd Msg )
+urlUpdate result model =
+ case result of
+ Just visibility ->
+ update (ChangeVisibility (String.Extra.toSentenceCase visibility)) model
+
+ Nothing ->
+ update (ChangeVisibility "All") model
+
+
+init : Flags -> Maybe String -> ( Model, Cmd Msg )
+init flags url =
+ urlUpdate url (Maybe.withDefault emptyModel flags)
+
+
+
+-- interactions with localStorage
+
+
+port save : Model -> Cmd msg
+
+
+subscriptions : Model -> Sub Msg
+subscriptions model =
+ Sub.none