{-# LANGUAGE OverloadedStrings, TypeFamilies, GeneralizedNewtypeDeriving #-} -- | Events relating to the @postMessage@ API for passing messages between -- windows. module Haste.Events.MessageEvents ( MessageEvent (..) , MessageData (..), Recipient (..), Window , getContentWindow, window, fromAny ) where import Control.Monad.IO.Class import Haste.JSString (JSString) import Haste.Prim.Foreign import Haste.Events.Core import Haste.DOM.Core (Elem (..)) -- | A DOM window. newtype Window = Window JSAny deriving (ToAny, FromAny, Eq) class Recipient a where -- | Post a message to the given window. Messages are serialized using the -- structured clone algorithm, meaning that you can post pretty much any -- type of data, except functions, references and the like. postMessage :: (ToAny msg, MonadIO m) => a -> msg -> m () instance Recipient Window where postMessage wnd msg = liftIO $ postMessage' wnd (toAny msg) instance EventSource Window where eventSource (Window e) = e -- | The window in which the program is executing. window :: Window window = constant "window" -- | Event data for keyboard events. data MessageData = MessageData { messageData :: !JSAny , messageOrigin :: !JSString , messageSource :: !Window } data MessageEvent = Message instance Event MessageEvent where type EventData MessageEvent = MessageData eventName Message = "message" eventData _ e = MessageData <$> get e "data" <*> get e "origin" <*> get e "source" postMessage' :: Window -> JSAny -> IO () postMessage' = ffi "(function(w,m){w.postMessage(m,'*');})" -- | Get the window object for an iframe. Must be called after the iframe is -- attached to the DOM. getContentWindow :: MonadIO m => Elem -> m (Maybe Window) getContentWindow e = liftIO $ getContentWindow' e getContentWindow' :: Elem -> IO (Maybe Window) getContentWindow' = ffi "(function(e){return e.contentWindow;})"