module Reflex.Dom.Widget.Resize where
import Reflex
import Reflex.Dom.Class
import Reflex.Dom.Widget.Basic
import Control.Monad
import Control.Monad.IO.Class
import Data.Monoid
import GHCJS.DOM.Element hiding (reset)
import GHCJS.DOM.EventM (on)
resizeDetector :: MonadWidget t m => m a -> m (Event t (), a)
resizeDetector = resizeDetectorWithStyle ""
resizeDetectorWithStyle :: MonadWidget t m
=> String
-> m a
-> m (Event t (), a)
resizeDetectorWithStyle styleString w = do
let childStyle = "position: absolute; left: 0; top: 0;"
containerAttrs = "style" =: "position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
(parent, (expand, expandChild, shrink, w')) <- elAttr' "div" ("style" =: ("position: relative;" <> styleString)) $ do
w' <- w
elAttr "div" containerAttrs $ do
(expand, (expandChild, _)) <- elAttr' "div" containerAttrs $ elAttr' "div" ("style" =: childStyle) $ return ()
(shrink, _) <- elAttr' "div" containerAttrs $ elAttr "div" ("style" =: (childStyle <> "width: 200%; height: 200%;")) $ return ()
return (expand, expandChild, shrink, w')
let reset = do
let e = _el_element expand
s = _el_element shrink
eow <- getOffsetWidth e
eoh <- getOffsetHeight e
let ecw = eow + 10
ech = eoh + 10
setAttribute (_el_element expandChild) "style" (childStyle <> "width: " <> show ecw <> "px;" <> "height: " <> show ech <> "px;")
esw <- getScrollWidth e
setScrollLeft e esw
esh <- getScrollHeight e
setScrollTop e esh
ssw <- getScrollWidth s
setScrollLeft s ssw
ssh <- getScrollHeight s
setScrollTop s ssh
lastWidth <- getOffsetWidth (_el_element parent)
lastHeight <- getOffsetHeight (_el_element parent)
return (Just lastWidth, Just lastHeight)
resetIfChanged ds = do
pow <- getOffsetWidth (_el_element parent)
poh <- getOffsetHeight (_el_element parent)
if ds == (Just pow, Just poh)
then return Nothing
else liftM Just reset
pb <- getPostBuild
expandScroll <- wrapDomEvent (_el_element expand) (`on` scroll) $ return ()
shrinkScroll <- wrapDomEvent (_el_element shrink) (`on` scroll) $ return ()
size0 <- performEvent $ fmap (const $ liftIO reset) pb
rec resize <- performEventAsync $ fmap (\d cb -> liftIO $ cb =<< resetIfChanged d) $ tag (current dimensions) $ leftmost [expandScroll, shrinkScroll]
dimensions <- holdDyn (Nothing, Nothing) $ leftmost [ size0, fmapMaybe id resize ]
return (fmap (const ()) $ fmapMaybe id resize, w')