Skip to content

Instantly share code, notes, and snippets.

@jturner
Created January 22, 2017 20:34
Show Gist options
  • Save jturner/5ea8abf45d4093760bc6d555fcfaf7c6 to your computer and use it in GitHub Desktop.
Save jturner/5ea8abf45d4093760bc6d555fcfaf7c6 to your computer and use it in GitHub Desktop.
Elm example app
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