Last active
August 29, 2015 14:24
-
-
Save TheSeamau5/9cd1c9f58d954a517503 to your computer and use it in GitHub Desktop.
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 characters
import Html exposing (Html) | |
import Html.Attributes | |
import Html.Events | |
import Signal exposing (Address) | |
import List | |
import Window | |
----------------- | |
-- HELPER CODE -- | |
infixl 2 => | |
(=>) = (,) | |
type alias Vector = | |
{ x : Float | |
, y : Float | |
} | |
----------------- | |
type alias State child = | |
{ children : List child | |
, cellHeight : Float | |
, numCols : Int | |
, gridWidth : Float | |
} | |
type Action action | |
= Child Int action | |
| Resize Float | |
type alias Context = | |
{ index : Int | |
, total : Int | |
, row : Int | |
, column : Int | |
, size : Vector | |
} | |
cellSize : State child -> Vector | |
cellSize {cellHeight, numCols, gridWidth} = | |
{ x = gridWidth / (toFloat numCols) | |
, y = cellHeight | |
} | |
gridSize : State child -> Vector | |
gridSize {children, cellHeight, gridWidth, numCols} = | |
let | |
numChildren = List.length children | |
numRows = | |
if numCols == 0 then 0 else numChildren // numCols | |
gridHeight = | |
toFloat numRows * cellHeight | |
in | |
{ x = gridWidth , y = gridHeight } | |
resize : Float -> State child -> State child | |
resize size state = | |
let | |
numChildren = List.length state.children | |
numRows = | |
if state.numCols == 0 then 0 else numChildren // state.numCols + 1 | |
oldGridHeight = | |
toFloat numRows * state.cellHeight | |
ratio = | |
size / state.gridWidth | |
newCellHeight = | |
ratio * state.cellHeight | |
in | |
{ state | cellHeight <- newCellHeight | |
, gridWidth <- size | |
} | |
update : (Context -> Maybe action -> child -> child) -> Maybe (Action action) -> State child -> State child | |
update updateChild maybeAction state = | |
case maybeAction of | |
Nothing -> | |
state | |
Just action -> | |
case action of | |
Child n childAction -> | |
let | |
updateN index child = | |
if n == index | |
then | |
let | |
numChildren = | |
List.length state.children | |
context = | |
{ index = n | |
, size = cellSize state | |
, total = numChildren | |
, column = index % state.numCols | |
, row = index // state.numCols | |
} | |
in | |
updateChild context (Just childAction) child | |
else | |
child | |
in | |
{ state | children <- List.indexedMap updateN state.children } | |
Resize width -> | |
let | |
gridDims = | |
gridSize state | |
ratio = | |
width / gridDims.x | |
height = | |
ratio * gridDims.y | |
updateN index child = | |
let | |
numChildren = | |
List.length state.children | |
context = | |
{ index = index | |
, size = | |
{ x = width | |
, y = height | |
} | |
, total = numChildren | |
, column = index % state.numCols | |
, row = index // state.numCols | |
} | |
in | |
updateChild context Nothing child | |
in | |
resize width { state | children <- List.indexedMap updateN state.children } | |
view : (Context -> Address action -> child -> Html) -> Address (Action action) -> State child -> Html | |
view viewChild address state = | |
let | |
gridDims = | |
gridSize state | |
cellDims = | |
cellSize state | |
containerStyles = | |
[ "position" => "absolute" | |
, "top" => "0px" | |
, "left" => "0px" | |
, "width" => toString gridDims.x ++ "px" | |
, "height" => toString gridDims.y ++ "px" | |
] | |
viewN index child = | |
let | |
left = | |
cellDims.x * toFloat (index % state.numCols) | |
top = | |
cellDims.y * toFloat (index // state.numCols) | |
childContainer = | |
[ "position" => "absolute" | |
, "left" => toString left ++ "px" | |
, "top" => toString top ++ "px" | |
, "width" => toString cellDims.x ++ "px" | |
, "height" => toString cellDims.y ++ "px" | |
-- , "border" => "1px solid black" | |
] | |
childAddress = | |
Signal.forwardTo address (Child index) | |
numChildren = | |
List.length state.children | |
context = | |
{ index = index | |
, size = cellDims | |
, total = numChildren | |
, column = index % state.numCols | |
, row = index // state.numCols | |
} | |
in | |
Html.div | |
[ Html.Attributes.style childContainer ] | |
[ viewChild context childAddress child ] | |
in | |
Html.div | |
[ Html.Attributes.style containerStyles ] | |
( List.indexedMap viewN state.children ) | |
------------------------------------------------------------ | |
-- Counter Component | |
type alias Count = Int | |
type CountAction | |
= Increment | |
| Decrement | |
updateCount : Context -> Maybe CountAction -> Count -> Count | |
updateCount _ maybeAction count = | |
case maybeAction of | |
Nothing -> | |
count | |
Just action -> | |
case action of | |
Increment -> | |
count + 1 | |
Decrement -> | |
count - 1 | |
viewCount : Context -> Address CountAction -> Count -> Html | |
viewCount context address count = | |
let | |
isOdd = | |
if context.row % 2 == 0 | |
then | |
if context.column % 2 == 0 | |
then | |
True | |
else | |
False | |
else | |
if context.column % 2 == 0 | |
then | |
False | |
else | |
True | |
fontSize = | |
(min context.size.x context.size.y) / 3 | |
(color, backgroundColor) = | |
if isOdd | |
then | |
("white", "black") | |
else | |
("black", "white") | |
containerStyle = | |
[ "position" => "absolute" | |
, "top" => "0px" | |
, "left" => "0px" | |
, "width" => toString context.size.x ++ "px" | |
, "height" => toString context.size.y ++ "px" | |
, "background-color" => backgroundColor | |
, "color" => color | |
] | |
decrementButtonStyle = | |
[ "position" => "absolute" | |
, "top" => toString (2 * context.size.y / 3) ++ "px" | |
, "left" => "0px" | |
, "width" => toString context.size.x ++ "px" | |
, "height" => toString (context.size.y / 3) ++ "px" | |
, "background-color" => backgroundColor | |
, "color" => color | |
, "text-align" => "center" | |
, "cursor" => "pointer" | |
, "-webkit-user-select" => "none" | |
, "font-size" => toString fontSize ++ "px" | |
] | |
incrementButtonStyle = | |
[ "position" => "absolute" | |
, "top" => "0px" | |
, "left" => "0px" | |
, "width" => toString context.size.x ++ "px" | |
, "height" => toString (context.size.y / 3) ++ "px" | |
, "background-color" => backgroundColor | |
, "color" => color | |
, "text-align" => "center" | |
, "cursor" => "pointer" | |
, "-webkit-user-select" => "none" | |
, "font-size" => toString fontSize ++ "px" | |
] | |
counterTextStyle = | |
[ "position" => "absolute" | |
, "top" => toString (context.size.y / 3) ++ "px" | |
, "left" => "0px" | |
, "width" => toString context.size.x ++ "px" | |
, "height" => toString (context.size.y / 3) ++ "px" | |
, "text-align" => "center" | |
, "font-size" => toString fontSize ++ "px" | |
] | |
in | |
Html.div | |
[ Html.Attributes.style containerStyle ] | |
[ Html.div | |
[ Html.Events.onClick address Decrement | |
, Html.Attributes.style decrementButtonStyle | |
] | |
[ Html.text "-" ] | |
, Html.div | |
[ Html.Events.onClick address Increment | |
, Html.Attributes.style incrementButtonStyle | |
] | |
[ Html.text "+" ] | |
, Html.span | |
[ Html.Attributes.style counterTextStyle ] | |
[ Html.text (toString count) ] | |
] | |
initialCount = 0 | |
------------------------------------------- | |
-- update : (Context -> Maybe action -> child -> child) -> Maybe (Action action) -> State child -> State child | |
-- view : (Context -> Address action -> child -> Html) -> Address (Action action) -> State child -> Html | |
initial : State Count | |
initial = | |
{ gridWidth = 400 | |
, cellHeight = 50 | |
, numCols = 8 | |
, children = List.repeat 64 initialCount | |
} | |
actionMailbox = Signal.mailbox Nothing | |
address = | |
Signal.forwardTo actionMailbox.address Just | |
resizes = | |
let | |
resize (x,_) = | |
x | |
|> toFloat | |
|> Resize | |
|> Just | |
in | |
Signal.map resize Window.dimensions | |
signal = | |
Signal.merge | |
(actionMailbox.signal) | |
(resizes) | |
main = | |
Signal.map (view viewCount address) | |
(Signal.foldp (update updateCount) initial signal) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment