Skip to content

Instantly share code, notes, and snippets.

@TheSeamau5
Created September 2, 2015 01:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheSeamau5/5ac1c90f2f81e36665ca to your computer and use it in GitHub Desktop.
Save TheSeamau5/5ac1c90f2f81e36665ca to your computer and use it in GitHub Desktop.
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