haskelldomghcjsghcjs-dom

GHCJS-DOM event guidance


I'm trying to understand how to create a GUI with GHCJS-DOM. I've been looking at the hello world example https://github.com/ghcjs/ghcjs-dom-hello, which is trivial. Adding new nodes is straightforward. What I can't do, and cannot work out from the library documentation (only signatures) is to add some events. For example add a new node to the body on a mouse click.

I wish to avoid using JS libraries like JQuery, because I want by GUI to be portable between GHC (webkit) and GHCJS.

Ultimately I'd like to be able to express a mouse event as a FRP Event, but I'll settle for one step at a time.

If anyone has any guidance I'd be most grateful. I've used haskell for a few years now, but this is my first venture into DOM.


Solution

  • You can get information about the DOM from a number of places including mozilla. Here is an example that adds an event handler for click events on the document body...

    module Main (
        main
    ) where
    
    import Control.Applicative ((<$>))
    import Control.Monad.Trans (liftIO)
    import GHCJS.DOM
           (enableInspector, webViewGetDomDocument, runWebGUI)
    import GHCJS.DOM.Document (documentGetBody, documentCreateElement)
    import GHCJS.DOM.HTMLElement (htmlElementSetInnerHTML, htmlElementSetInnerText)
    import GHCJS.DOM.Element (elementOnclick)
    import GHCJS.DOM.HTMLParagraphElement
           (castToHTMLParagraphElement)
    import GHCJS.DOM.Node (nodeAppendChild)
    import GHCJS.DOM.EventM (mouseClientXY)
    
    main = runWebGUI $ \ webView -> do
        enableInspector webView
        Just doc <- webViewGetDomDocument webView
        Just body <- documentGetBody doc
        htmlElementSetInnerHTML body "<h1>Hello World</h1>"
        elementOnclick body $ do
            (x, y) <- mouseClientXY
            liftIO $ do
                Just newParagraph <- fmap castToHTMLParagraphElement <$> documentCreateElement doc "p"
                htmlElementSetInnerText newParagraph $ "Click " ++ show (x, y)
                nodeAppendChild body (Just newParagraph)
                return ()
        return ()