{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
module Graphics.UI.Threepenny.Core (
Config(..), defaultConfig, startGUI,
loadFile, loadDirectory,
UI, runUI, MonadUI(..), askWindow, liftIOLater,
module Control.Monad.IO.Class,
module Control.Monad.Fix,
Window, title,
Element, getWindow, mkElement, mkElementNamespace, delete,
string,
getHead, getBody,
(#+), children, text, html, attr, style, value,
getElementsByTagName, getElementById, getElementsByClassName,
grid, row, column,
EventData, domEvent, unsafeFromJSON, disconnect, on, onEvent, onChanges,
module Reactive.Threepenny,
(#), (#.),
Attr, WriteAttr, ReadAttr, ReadWriteAttr(..),
set, sink, get, mkReadWriteAttr, mkWriteAttr, mkReadAttr,
bimapAttr, fromObjectProperty,
Widget(..), element, widget,
debug, timestamp,
ToJS, FFI,
JSFunction, ffi, runFunction, callFunction,
CallBufferMode(..), setCallBufferMode, flushCallBuffer,
ffiExport,
toJSObject, liftJSWindow,
fromJQueryProp,
) where
import Control.Monad (forM_, forM, void)
import Control.Monad.Fix
import Control.Monad.IO.Class
import qualified Control.Monad.Catch as E
import qualified Data.Aeson as JSON
import qualified Foreign.JavaScript as JS
import qualified Graphics.UI.Threepenny.Internal as Core
import qualified Reactive.Threepenny as Reactive
import Foreign.JavaScript (Config(..), defaultConfig)
import Graphics.UI.Threepenny.Internal
import Reactive.Threepenny hiding (onChange)
title :: WriteAttr Window String
title :: WriteAttr Window String
title = forall i x. (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr forall a b. (a -> b) -> a -> b
$ \String
s Window
_ ->
JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"document.title = %1;" String
s
(#+) :: UI Element -> [UI Element] -> UI Element
#+ :: UI Element -> [UI Element] -> UI Element
(#+) UI Element
mx [UI Element]
mys = do
Element
x <- UI Element
mx
[Element]
ys <- forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [UI Element]
mys
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Element -> Element -> UI ()
Core.appendChild Element
x) [Element]
ys
forall (m :: * -> *) a. Monad m => a -> m a
return Element
x
children :: WriteAttr Element [Element]
children :: WriteAttr Element [Element]
children = forall i x. (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr forall {t :: * -> *}. Foldable t => t Element -> Element -> UI ()
set
where
set :: t Element -> Element -> UI ()
set t Element
xs Element
x = do
Element -> UI ()
Core.clearChildren Element
x
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Element -> Element -> UI ()
Core.appendChild Element
x) t Element
xs
html :: WriteAttr Element String
html :: WriteAttr Element String
html = forall i x. (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr forall a b. (a -> b) -> a -> b
$ \String
s Element
el ->
JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"$(%1).html(%2)" Element
el String
s
attr :: String -> WriteAttr Element String
attr :: String -> WriteAttr Element String
attr String
name = forall i x. (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr forall a b. (a -> b) -> a -> b
$ \String
s Element
el ->
JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"$(%1).attr(%2,%3)" Element
el String
name String
s
style :: WriteAttr Element [(String,String)]
style :: WriteAttr Element [(String, String)]
style = forall i x. (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr forall a b. (a -> b) -> a -> b
$ \[(String, String)]
xs Element
el -> forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(String, String)]
xs forall a b. (a -> b) -> a -> b
$ \(String
name,String
val) ->
JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"%1.style[%2] = %3" Element
el String
name String
val
value :: Attr Element String
value :: Attr Element String
value = forall x o i.
(x -> UI o) -> (i -> x -> UI ()) -> ReadWriteAttr x i o
mkReadWriteAttr forall {t} {a}. (ToJS t, FromJS a) => t -> UI a
get forall {t} {t}. (ToJS t, ToJS t) => t -> t -> UI ()
set
where
get :: t -> UI a
get t
el = forall a. JSFunction a -> UI a
callFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"$(%1).val()" t
el
set :: t -> t -> UI ()
set t
v t
el = JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"$(%1).val(%2)" t
el t
v
text :: WriteAttr Element String
text :: WriteAttr Element String
text = forall i x. (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr forall a b. (a -> b) -> a -> b
$ \String
s Element
el ->
JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"$(%1).text(%2)" Element
el String
s
string :: String -> UI Element
string :: String -> UI Element
string String
s = String -> UI Element
mkElement String
"span" forall a b. a -> (a -> b) -> b
# forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
set WriteAttr Element String
text String
s
getHead :: Window -> UI Element
getHead :: Window -> UI Element
getHead Window
_ = JSObject -> UI Element
fromJSObject forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. JSFunction a -> UI a
callFunction (forall a. FFI a => String -> a
ffi String
"document.head")
getBody :: Window -> UI Element
getBody :: Window -> UI Element
getBody Window
_ = JSObject -> UI Element
fromJSObject forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. JSFunction a -> UI a
callFunction (forall a. FFI a => String -> a
ffi String
"document.body")
getElementsByTagName
:: Window
-> String
-> UI [Element]
getElementsByTagName :: Window -> String -> UI [Element]
getElementsByTagName Window
_ String
tag =
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM JSObject -> UI Element
fromJSObject forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. JSFunction a -> UI a
callFunction (forall a. FFI a => String -> a
ffi String
"document.getElementsByTagName(%1)" String
tag)
getElementById
:: Window
-> String
-> UI (Maybe Element)
getElementById :: Window -> String -> UI (Maybe Element)
getElementById Window
_ String
id =
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
(e -> m a) -> m a -> m a
E.handle (\(JavaScriptException
e :: JS.JavaScriptException) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing) forall a b. (a -> b) -> a -> b
$
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. JSObject -> UI Element
fromJSObject forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. JSFunction a -> UI a
callFunction (forall a. FFI a => String -> a
ffi String
"document.getElementById(%1)" String
id)
getElementsByClassName
:: Window
-> String
-> UI [Element]
getElementsByClassName :: Window -> String -> UI [Element]
getElementsByClassName Window
window String
s =
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM JSObject -> UI Element
fromJSObject forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. JSFunction a -> UI a
callFunction (forall a. FFI a => String -> a
ffi String
"document.getElementsByClassName(%1)" String
s)
row :: [UI Element] -> UI Element
row :: [UI Element] -> UI Element
row [UI Element]
xs = [[UI Element]] -> UI Element
grid [[UI Element]
xs]
column :: [UI Element] -> UI Element
column :: [UI Element] -> UI Element
column = [[UI Element]] -> UI Element
grid forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall a. a -> [a] -> [a]
:[])
grid :: [[UI Element]] -> UI Element
grid :: [[UI Element]] -> UI Element
grid [[UI Element]]
mrows = do
[[Element]]
rows0 <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence) [[UI Element]]
mrows
[Element]
rows <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [[Element]]
rows0 forall a b. (a -> b) -> a -> b
$ \[Element]
row0 -> do
[Element]
row <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Element]
row0 forall a b. (a -> b) -> a -> b
$ \Element
entry ->
forall {a}. Widget a => String -> [a] -> UI Element
wrap String
"table-cell" [Element
entry]
forall {a}. Widget a => String -> [a] -> UI Element
wrap String
"table-row" [Element]
row
forall {a}. Widget a => String -> [a] -> UI Element
wrap String
"table" [Element]
rows
where
wrap :: String -> [a] -> UI Element
wrap String
c [a]
xs = String -> UI Element
mkElement String
"div" forall a b. a -> (a -> b) -> b
# forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
set (String -> WriteAttr Element String
attr String
"class") String
c UI Element -> [UI Element] -> UI Element
#+ forall a b. (a -> b) -> [a] -> [b]
map forall (m :: * -> *) w. (MonadIO m, Widget w) => w -> m Element
element [a]
xs
on :: (element -> Event a) -> element -> (a -> UI void) -> UI ()
on :: forall element a void.
(element -> Event a) -> element -> (a -> UI void) -> UI ()
on element -> Event a
f element
x = forall (f :: * -> *) a. Functor f => f a -> f ()
void forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a void. Event a -> (a -> UI void) -> UI (UI ())
onEvent (element -> Event a
f element
x)
onEvent :: Event a -> (a -> UI void) -> UI (UI ())
onEvent :: forall a void. Event a -> (a -> UI void) -> UI (UI ())
onEvent Event a
e a -> UI void
h = do
Window
window <- UI Window
askWindow
let flush :: UI ()
flush = forall a. (Window -> IO a) -> UI a
liftJSWindow forall a b. (a -> b) -> a -> b
$ \Window
w -> do
CallBufferMode
mode <- Window -> IO CallBufferMode
JS.getCallBufferMode Window
w
case CallBufferMode
mode of
CallBufferMode
FlushOften -> Window -> IO ()
JS.flushCallBuffer Window
w
CallBufferMode
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
IO ()
unregister <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. Event a -> Handler a -> IO (IO ())
register Event a
e (forall (f :: * -> *) a. Functor f => f a -> f ()
void forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Window -> UI a -> IO a
runUI Window
window forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> UI ()
flush) forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> UI void
h)
forall (m :: * -> *) a. Monad m => a -> m a
return (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
unregister)
onChanges :: Behavior a -> (a -> UI void) -> UI ()
onChanges :: forall a void. Behavior a -> (a -> UI void) -> UI ()
onChanges Behavior a
b a -> UI void
f = do
Window
window <- UI Window
askWindow
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. Behavior a -> Handler a -> IO ()
Reactive.onChange Behavior a
b (forall (f :: * -> *) a. Functor f => f a -> f ()
void forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Window -> UI a -> IO a
runUI Window
window forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> UI void
f)
infixl 8 #
infixl 8 #+
infixl 8 #.
(#) :: a -> (a -> b) -> b
# :: forall a b. a -> (a -> b) -> b
(#) = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> b) -> a -> b
($)
(#.) :: UI Element -> String -> UI Element
#. :: UI Element -> String -> UI Element
(#.) UI Element
mx String
s = UI Element
mx forall a b. a -> (a -> b) -> b
# forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
set (String -> WriteAttr Element String
attr String
"class") String
s
type Attr x a = ReadWriteAttr x a a
type ReadAttr x o = ReadWriteAttr x () o
type WriteAttr x i = ReadWriteAttr x i ()
data ReadWriteAttr x i o = ReadWriteAttr
{ forall x i o. ReadWriteAttr x i o -> x -> UI o
get' :: x -> UI o
, forall x i o. ReadWriteAttr x i o -> i -> x -> UI ()
set' :: i -> x -> UI ()
}
instance Functor (ReadWriteAttr x i) where
fmap :: forall a b. (a -> b) -> ReadWriteAttr x i a -> ReadWriteAttr x i b
fmap a -> b
f = forall i' i o o' x.
(i' -> i)
-> (o -> o') -> ReadWriteAttr x i o -> ReadWriteAttr x i' o'
bimapAttr forall a. a -> a
id a -> b
f
bimapAttr :: (i' -> i) -> (o -> o')
-> ReadWriteAttr x i o -> ReadWriteAttr x i' o'
bimapAttr :: forall i' i o o' x.
(i' -> i)
-> (o -> o') -> ReadWriteAttr x i o -> ReadWriteAttr x i' o'
bimapAttr i' -> i
from o -> o'
to ReadWriteAttr x i o
attr = ReadWriteAttr x i o
attr
{ get' :: x -> UI o'
get' = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap o -> o'
to forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x i o. ReadWriteAttr x i o -> x -> UI o
get' ReadWriteAttr x i o
attr
, set' :: i' -> x -> UI ()
set' = \i'
i' -> forall x i o. ReadWriteAttr x i o -> i -> x -> UI ()
set' ReadWriteAttr x i o
attr (i' -> i
from i'
i')
}
set :: ReadWriteAttr x i o -> i -> UI x -> UI x
set :: forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
set ReadWriteAttr x i o
attr i
i UI x
mx = do { x
x <- UI x
mx; forall x i o. ReadWriteAttr x i o -> i -> x -> UI ()
set' ReadWriteAttr x i o
attr i
i x
x; forall (m :: * -> *) a. Monad m => a -> m a
return x
x; }
sink :: ReadWriteAttr x i o -> Behavior i -> UI x -> UI x
sink :: forall x i o. ReadWriteAttr x i o -> Behavior i -> UI x -> UI x
sink ReadWriteAttr x i o
attr Behavior i
bi UI x
mx = do
x
x <- UI x
mx
Window
window <- UI Window
askWindow
IO () -> UI ()
liftIOLater forall a b. (a -> b) -> a -> b
$ do
i
i <- forall (m :: * -> *) a. MonadIO m => Behavior a -> m a
currentValue Behavior i
bi
forall a. Window -> UI a -> IO a
runUI Window
window forall a b. (a -> b) -> a -> b
$ forall x i o. ReadWriteAttr x i o -> i -> x -> UI ()
set' ReadWriteAttr x i o
attr i
i x
x
forall a. Behavior a -> Handler a -> IO ()
Reactive.onChange Behavior i
bi forall a b. (a -> b) -> a -> b
$ \i
i -> forall a. Window -> UI a -> IO a
runUI Window
window forall a b. (a -> b) -> a -> b
$ forall x i o. ReadWriteAttr x i o -> i -> x -> UI ()
set' ReadWriteAttr x i o
attr i
i x
x
forall (m :: * -> *) a. Monad m => a -> m a
return x
x
get :: ReadWriteAttr x i o -> x -> UI o
get :: forall x i o. ReadWriteAttr x i o -> x -> UI o
get ReadWriteAttr x i o
attr = forall x i o. ReadWriteAttr x i o -> x -> UI o
get' ReadWriteAttr x i o
attr
mkReadWriteAttr
:: (x -> UI o)
-> (i -> x -> UI ())
-> ReadWriteAttr x i o
mkReadWriteAttr :: forall x o i.
(x -> UI o) -> (i -> x -> UI ()) -> ReadWriteAttr x i o
mkReadWriteAttr x -> UI o
get i -> x -> UI ()
set = ReadWriteAttr { get' :: x -> UI o
get' = x -> UI o
get, set' :: i -> x -> UI ()
set' = i -> x -> UI ()
set }
mkReadAttr :: (x -> UI o) -> ReadAttr x o
mkReadAttr :: forall x o. (x -> UI o) -> ReadAttr x o
mkReadAttr x -> UI o
get = forall x o i.
(x -> UI o) -> (i -> x -> UI ()) -> ReadWriteAttr x i o
mkReadWriteAttr x -> UI o
get (\()
_ x
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ())
mkWriteAttr :: (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr :: forall i x. (i -> x -> UI ()) -> WriteAttr x i
mkWriteAttr i -> x -> UI ()
set = forall x o i.
(x -> UI o) -> (i -> x -> UI ()) -> ReadWriteAttr x i o
mkReadWriteAttr (\x
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()) i -> x -> UI ()
set
fromJQueryProp :: String -> (JSON.Value -> a) -> (a -> JSON.Value) -> Attr Element a
fromJQueryProp :: forall a. String -> (Value -> a) -> (a -> Value) -> Attr Element a
fromJQueryProp String
name Value -> a
from a -> Value
to = forall x o i.
(x -> UI o) -> (i -> x -> UI ()) -> ReadWriteAttr x i o
mkReadWriteAttr forall {t}. ToJS t => t -> UI a
get forall {t}. ToJS t => a -> t -> UI ()
set
where
set :: a -> t -> UI ()
set a
v t
el = JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"$(%1).prop(%2,%3)" t
el String
name (a -> Value
to a
v)
get :: t -> UI a
get t
el = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Value -> a
from forall a b. (a -> b) -> a -> b
$ forall a. JSFunction a -> UI a
callFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi String
"$(%1).prop(%2)" t
el String
name
fromObjectProperty :: (FromJS a, ToJS a) => String -> Attr Element a
fromObjectProperty :: forall a. (FromJS a, ToJS a) => String -> Attr Element a
fromObjectProperty String
name = forall x o i.
(x -> UI o) -> (i -> x -> UI ()) -> ReadWriteAttr x i o
mkReadWriteAttr forall {t} {a}. (ToJS t, FromJS a) => t -> UI a
get forall {t} {t}. (ToJS t, ToJS t) => t -> t -> UI ()
set
where
set :: t -> t -> UI ()
set t
v t
el = JSFunction () -> UI ()
runFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi (String
"%1." forall a. [a] -> [a] -> [a]
++ String
name forall a. [a] -> [a] -> [a]
++ String
" = %2") t
el t
v
get :: t -> UI a
get t
el = forall a. JSFunction a -> UI a
callFunction forall a b. (a -> b) -> a -> b
$ forall a. FFI a => String -> a
ffi (String
"%1." forall a. [a] -> [a] -> [a]
++ String
name) t
el
class Widget w where
getElement :: w -> Element
instance Widget Element where
getElement :: Element -> Element
getElement = forall a. a -> a
id
element :: MonadIO m => Widget w => w -> m Element
element :: forall (m :: * -> *) w. (MonadIO m, Widget w) => w -> m Element
element = forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. Widget w => w -> Element
getElement
widget :: Widget w => w -> UI w
widget :: forall w. Widget w => w -> UI w
widget = forall (m :: * -> *) a. Monad m => a -> m a
return