From ea559050160e045c61cc6a0ebee66990515ac2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Debois?= Date: Wed, 30 Mar 2016 21:19:06 +0200 Subject: [PATCH] Filter scroll events. --- examples/Demo.elm | 5 +---- examples/Demo/Grid.elm | 35 ++++++++++++++++++++++++++++++ src/Material/Layout.elm | 47 ++++++++++++++++++++++++++++------------- 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/examples/Demo.elm b/examples/Demo.elm index fd33b64..b6e8d1d 100644 --- a/examples/Demo.elm +++ b/examples/Demo.elm @@ -13,7 +13,6 @@ import Material.Layout as Layout exposing (defaultLayoutModel) import Material exposing (lift, lift') import Material.Style as Style -import Material.Icon as Icon import Material import Demo.Buttons @@ -25,8 +24,6 @@ import Demo.Badges -- MODEL -x = 0 + "foo" - layoutModel : Layout.Model layoutModel = @@ -196,7 +193,7 @@ init = (model, Effects.none) inputs : List (Signal.Signal Action) inputs = - [ Layout.setupSizeChangeSignal LayoutAction + [ Layout.setupSignals LayoutAction ] diff --git a/examples/Demo/Grid.elm b/examples/Demo/Grid.elm index 3a92e8e..320f14c 100644 --- a/examples/Demo/Grid.elm +++ b/examples/Demo/Grid.elm @@ -3,6 +3,8 @@ module Demo.Grid where import Material.Grid exposing (..) import Material.Style exposing (Style, css) +import Markdown + import Html exposing (..) -- Cell styling @@ -50,3 +52,36 @@ view = ] +intro : Html +intro = """ +From the +[Material Design Lite documentation](http://www.getmdl.io/components/#layout-section/grid): + +> The Material Design Lite (MDL) grid component is a simplified method for laying +> out content for multiple screen sizes. It reduces the usual coding burden +> required to correctly display blocks of content in a variety of display +> conditions. +> +> The MDL grid is defined and enclosed by a container element. A grid has 12 +> columns in the desktop screen size, 8 in the tablet size, and 4 in the phone +> size, each size having predefined margins and gutters. Cells are laid out +> sequentially in a row, in the order they are defined, with some exceptions: +> +> - If a cell doesn't fit in the row in one of the screen sizes, it flows +> into the following line. +> - If a cell has a specified column size equal to or larger than the number +> of columns for the current screen size, it takes up the entirety of its +> row. + +#### See also + + - [Demo source code](https://github.com/debois/elm-mdl/blob/master/examples/Demo/Grid.elm) + - [elm-mdl package documentation](http://package.elm-lang.org/packages/debois/elm-mdl/latest/Material-Grid) + - [Material Design Specification](https://www.google.com/design/spec/layout/responsive-ui.html#responsive-ui-grid) + - [Material Design Lite documentation](http://www.getmdl.io/components/#layout-section/grid) + +#### Demo + +""" |> Markdown.toHtml + + diff --git a/src/Material/Layout.elm b/src/Material/Layout.elm index 1eb31dd..bf046e9 100644 --- a/src/Material/Layout.elm +++ b/src/Material/Layout.elm @@ -1,5 +1,5 @@ module Material.Layout - ( setupSizeChangeSignal + ( setupSignals , Mode(..), Model, defaultLayoutModel, initState , Action(SwitchTab, ToggleDrawer), update , row, spacer, title, navigation, link @@ -39,7 +39,7 @@ module Material.Layout @docs row, spacer, title, navigation, link # Setup -@docs setupSizeChangeSignal +@docs setupSignals -} @@ -63,21 +63,38 @@ import DOM -- SETUP -{-| Setup signal for registering changes in display size. Use with StartApp -like so, supposing you have a `LayoutAction` encapsulating actions of the +scrollMailbox : Signal.Mailbox Float +scrollMailbox = Signal.mailbox 0.0 + + +{-| Setup various signals layout needs (viewport size changes, scrolling). Use +with StartApp like so, supposing you have a `LayoutAction` encapsulating +actions of the layout: inputs : List (Signal.Signal Action) inputs = - [ Layout.setupSizeChangeSignal LayoutAction + [ Layout.setupSignals LayoutAction ] -} -setupSizeChangeSignal : (Action -> a) -> Signal a -setupSizeChangeSignal f = - Window.width - |> Signal.map ((>) 1024) - |> Signal.dropRepeats - |> Signal.map (SmallScreen >> f) +setupSignals : (Action -> a) -> Signal a +setupSignals f = + {- NB! mergeMany propagates only the first provided signal if more than one + signal changes value at the same time. We are processing two signals: (1) + viewport size changes and (2) scrolling of main contents. It /appears/ + that these cannot happen at the same time, so the following should be + safe. + -} + Signal.mergeMany + [ Window.width + |> Signal.map ((>) 1024) + |> Signal.dropRepeats + |> Signal.map (SmallScreen >> f) + , scrollMailbox.signal + |> Signal.map ((<) 0.0) + |> Signal.dropRepeats + |> Signal.map (ScrollContents >> f) + ] -- MODEL @@ -172,7 +189,7 @@ type Action -- Private | SmallScreen Bool -- True means small screen | ScrollTab Float - | ScrollContents Float + | ScrollContents Bool -- True means strictly positive scrollTop | Ripple Int Ripple.Action | Click | TransitionEnd @@ -214,12 +231,12 @@ update action model = (model, Effects.none) -- TODO - ScrollContents scrollTop -> + ScrollContents isScrolled -> let headerVisible = state.isSmallScreen || model.fixedHeader state' = { state - | isCompact = scrollTop > 0 + | isCompact = isScrolled , isAnimating = headerVisible } in @@ -505,7 +522,7 @@ view addr model { drawer, header, tabs, main } = ( class "mdl-layout__content" :: ( if isWaterfall model.mode then - [ on "scroll" (DOM.target DOM.scrollTop) (ScrollContents >> Signal.message addr) ] + [ on "scroll" (DOM.target DOM.scrollTop) (Signal.message scrollMailbox.address) ] else [] )