Created
January 22, 2017 20:34
-
-
Save jturner/5ea8abf45d4093760bc6d555fcfaf7c6 to your computer and use it in GitHub Desktop.
Elm example app
This file contains 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 characters
module PhotoGroove exposing (..) | |
import Html exposing (..) | |
import Html.Events exposing (onClick) | |
import Array exposing (Array) | |
import Random | |
import Http | |
import Html.Attributes exposing (id, checked, class, classList, src, name, type_, title) | |
import Json.Decode exposing (string, int, list, Decoder) | |
import Json.Decode.Pipeline exposing (decode, required, optional) | |
urlPrefix : String | |
urlPrefix = | |
"http://elm-in-action.com/" | |
type ThumbnailSize | |
= Small | |
| Medium | |
| Large | |
view : Model -> Html Msg | |
view model = | |
div [ class "content" ] | |
[ h1 [] [ text "Photo Groove" ] | |
, button | |
[ onClick SurpriseMe ] | |
[ text "Surprise Me!" ] | |
, h3 [] [ text "Thumbnail Size:" ] | |
, div [ id "choose-size" ] | |
(List.map (viewSizeChooser model.chosenSize) [ Small, Medium, Large ]) | |
, div [ id "thumbnails", class (sizeToString model.chosenSize) ] | |
(List.map (viewThumbnail model.selectedUrl) model.photos) | |
, viewLarge model.selectedUrl | |
] | |
viewOrError : Model -> Html Msg | |
viewOrError model = | |
case model.loadingError of | |
Nothing -> | |
view model | |
Just errorMessage -> | |
div [ class "error-message" ] | |
[ h1 [] [ text "Photo Groove" ] | |
, p [] [ text errorMessage ] | |
] | |
viewLarge : Maybe String -> Html Msg | |
viewLarge maybeUrl = | |
case maybeUrl of | |
Nothing -> | |
text "" | |
Just url -> | |
img [ class "large", src (urlPrefix ++ "large/" ++ url) ] [] | |
viewThumbnail : Maybe String -> Photo -> Html Msg | |
viewThumbnail selectedUrl thumbnail = | |
img | |
[ src (urlPrefix ++ thumbnail.url) | |
, title (thumbnail.title ++ " [" ++ toString thumbnail.size ++ " KB]") | |
, classList [ ( "selected", selectedUrl == Just thumbnail.url ) ] | |
, onClick (SelectByUrl thumbnail.url) | |
] | |
[] | |
viewSizeChooser : ThumbnailSize -> ThumbnailSize -> Html Msg | |
viewSizeChooser chosenSize size = | |
label [] | |
[ input | |
[ type_ "radio" | |
, name "size" | |
, onClick (SetSize size) | |
, checked (chosenSize == size) | |
] | |
[] | |
, text (sizeToString size) | |
] | |
sizeToString : ThumbnailSize -> String | |
sizeToString size = | |
case size of | |
Small -> | |
"small" | |
Medium -> | |
"med" | |
Large -> | |
"large" | |
photoDecoder : Decoder Photo | |
photoDecoder = | |
decode Photo | |
|> required "url" string | |
|> required "size" int | |
|> optional "title" string "(untitled)" | |
type alias Photo = | |
{ url : String | |
, size : Int | |
, title : String | |
} | |
type alias Model = | |
{ photos : List Photo | |
, selectedUrl : Maybe String | |
, loadingError : Maybe String | |
, chosenSize : ThumbnailSize | |
} | |
initialModel : Model | |
initialModel = | |
{ photos = [] | |
, selectedUrl = Nothing | |
, loadingError = Nothing | |
, chosenSize = Medium | |
} | |
initialCmd : Cmd Msg | |
initialCmd = | |
list photoDecoder | |
|> Http.get "http://elm-in-action.com/photos/list.json" | |
|> Http.send LoadPhotos | |
type Msg | |
= SelectByUrl String | |
| SelectByIndex Int | |
| SurpriseMe | |
| SetSize ThumbnailSize | |
| LoadPhotos (Result Http.Error (List Photo)) | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
SelectByIndex index -> | |
let | |
newSelectedUrl : Maybe String | |
newSelectedUrl = | |
model.photos | |
|> Array.fromList | |
|> Array.get index | |
|> Maybe.map .url | |
in | |
( { model | selectedUrl = newSelectedUrl }, Cmd.none ) | |
SelectByUrl url -> | |
( { model | selectedUrl = Just url }, Cmd.none ) | |
SurpriseMe -> | |
let | |
randomPhotoPicker : Random.Generator Int | |
randomPhotoPicker = | |
Random.int 0 (List.length model.photos - 1) | |
in | |
( model, Random.generate SelectByIndex randomPhotoPicker ) | |
SetSize size -> | |
( { model | chosenSize = size }, Cmd.none ) | |
LoadPhotos (Ok photos) -> | |
( { model | |
| photos = photos | |
, selectedUrl = Maybe.map .url (List.head photos) | |
} | |
, Cmd.none | |
) | |
LoadPhotos (Err _) -> | |
( { model | |
| loadingError = Just "Error! (Try turning it off and on again?)" | |
} | |
, Cmd.none | |
) | |
main : Program Never Model Msg | |
main = | |
Html.program | |
{ init = ( initialModel, initialCmd ) | |
, view = viewOrError | |
, update = update | |
, subscriptions = (\_ -> Sub.none) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment