Created
September 2, 2015 01:08
-
-
Save TheSeamau5/5ac1c90f2f81e36665ca 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, Attribute, ul, li, div) | |
import Html.Attributes | |
import Html.Events exposing (on) | |
import Json.Decode exposing (Decoder, (:=), at, float) | |
import List | |
import Signal exposing (Address, message) | |
import Array exposing (Array) | |
---------------------------------------------------------- | |
-- ROUGH SKETCH FOR INFINITE SCROLL LIST IMPLEMENTATION -- | |
---------------------------------------------------------- | |
------------- | |
-- The state of the list | |
type alias State rowState | |
= { rows : Array rowState | |
, offset : Float | |
, bufferSize : Int | |
, size : Vector | |
, rowHeight : Float | |
} | |
-- The options for the initializer | |
type alias Options rowOptions | |
= { rowOptions : List rowOptions | |
, size : Vector | |
, rowHeight : Float | |
} | |
-- The context for the rows | |
type alias RowContext | |
= { index : Int | |
, size : Vector | |
} | |
-- The actions possible on the list | |
type Action rowAction rowState | |
= RowAction Int rowAction | |
| Scroll Float | |
| Resize Vector | |
| InsertRow rowState | |
| NoOp | |
-- The effects possible on the list | |
type Effect rowEffect | |
= RequestNewRows Int | |
| RowEffects Int (List rowEffect) | |
------------- | |
-------------------------------------------------- | |
-- INIT FUNCTION: | |
-- Initialize an infinite scroll list given | |
-- a means to initialize the individual rows | |
-------------------------------------------------- | |
init : (RowContext -> Init rowOptions rowState rowEffect) | |
-> Init (Options rowOptions) (State rowState) (Effect rowEffect) | |
init initRowFromContext options = | |
let | |
-- rowSize : Vector | |
rowSize = | |
{ x = options.size.x | |
, y = options.rowHeight | |
} | |
-- promoteEffect : Int | |
-- -> (rowState, List rowEffect) | |
-- -> (rowState, Effect rowEffect) | |
promoteEffect index (state, effects) = | |
(state, RowEffects index effects) | |
-- initRowFromIndex : Int -> Init rowOptions rowState rowEffect | |
initRow index = | |
initRowFromContext | |
{ index = index | |
, size = rowSize | |
} | |
>> promoteEffect index | |
-- rows : (Array rowState, List rowEffect) | |
(rows, effects) = | |
options.rowOptions | |
|> List.indexedMap initRow | |
|> List.unzip | |
|> (\(rs, fx) -> (Array.fromList rs, fx)) | |
offset = | |
0 | |
bufferSize = | |
10 | |
in | |
( { rows = rows | |
, offset = offset | |
, bufferSize = bufferSize | |
, size = options.size | |
, rowHeight = options.rowHeight | |
} | |
, effects | |
) | |
-------------------------------------------------- | |
-- UPDATE FUNCTION: | |
-- Update an infinite scroll list given | |
-- a means to update the individual rows | |
-------------------------------------------------- | |
update : (RowContext -> Update rowAction rowState rowEffect) | |
-> Update (Action rowAction rowState) (State rowState) (Effect rowEffect) | |
update updateRowFromContext action state = | |
case action of | |
RowAction index rowAction -> | |
case Array.get index state.rows of | |
Nothing -> | |
(state, []) | |
Just x -> | |
let | |
rowContext = | |
{ index = index | |
, size = { x = state.size.x | |
, y = state.rowHeight | |
} | |
} | |
(row, rowEffects) = | |
updateRowFromContext rowContext rowAction x | |
effects = | |
RowEffects index rowEffects | |
in | |
( { state | rows <- Array.set index row state.rows }, [effects] ) | |
Scroll offset -> | |
( { state | offset <- offset }, [] ) | |
Resize size -> | |
( { state | size <- size }, [] ) | |
InsertRow rowState -> | |
( { state | rows <- Array.push rowState state.rows }, [] ) | |
NoOp -> | |
(state, []) | |
-------------------------------------------------- | |
-- VIEW FUNCTION: | |
-- View an infinite scroll list given | |
-- a means to view the individual rows | |
-------------------------------------------------- | |
view : View rowAction rowState | |
-> View (Action rowAction rowState) (State rowState) | |
view viewRow address state = | |
let | |
viewN index row = | |
let | |
rowAddress = | |
Signal.forwardTo address (RowAction index) | |
in | |
li | |
[] | |
[ viewRow rowAddress row ] | |
in | |
ul | |
[] | |
( Array.indexedMap viewN state.rows |> Array.toList ) | |
----------------------------- | |
-- THE ELM ARCHITECTURE TYPES | |
----------------------------- | |
type alias Init options state effect | |
= options -> (state, List effect) | |
type alias Update action state effect | |
= action -> state -> (state, List effect) | |
type alias View action state | |
= Address action -> state -> Html | |
-------------- | |
-- HELPER CODE | |
-------------- | |
infixl 2 => | |
(=>) = (,) | |
type alias Vector | |
= { x : Float | |
, y : Float | |
} | |
updateN : Int -> (a -> a) -> Array a -> Array a | |
updateN n f array = | |
case Array.get n array of | |
Nothing -> | |
array | |
Just x -> | |
Array.set n (f x) array | |
scrollTop : Decoder Float | |
scrollTop = | |
at ["target", "scrollTop" ] float | |
onScroll : Address a -> (Float -> a) -> Attribute | |
onScroll address constructor = | |
on "scroll" scrollTop (constructor >> message address) | |
-------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment