Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling Haskell from JavaScript #182

Closed
bradrn opened this issue May 4, 2017 · 4 comments
Closed

Calling Haskell from JavaScript #182

bradrn opened this issue May 4, 2017 · 4 comments

Comments

@bradrn
Copy link
Contributor

bradrn commented May 4, 2017

When using exportHandler to export a Haskell function to JavaScript, how do you call the exported function from the JavaScript side?

@HeinrichApfelmus
Copy link
Owner

You can use it like an ordinary JavaScript function, e.g.

handler <- ffiExport something
runFunction $ ffi "%1('hello')" handler

I should probably write this down somewhere in the documentation.

@bradrn
Copy link
Contributor Author

bradrn commented May 7, 2017

I think you misinterpreted my question --- I should probably have been clearer. This is what I meant to ask:

Can you call a Haskell function from a JavaScript script e.g. something like this:

--Main.hs
...
    handler <- ffiExport something
...
// Script.hs
...
runHaskellFunction()
...

@HeinrichApfelmus
Copy link
Owner

Perhaps confusingly, the ffiExport function does not add a new name to the JavaScript namespace. Instead, it turns a Haskell function into something that can be used on the JavaScript side.

The ffi function is the only way to transport this function to the JavaScript side. You can always do

handler <- ffiExport something
runFunction $ ffi "window.myFunction = %1" handler

to make a new identifier myFunction available in the global JavaScript namespace.

@bradrn
Copy link
Contributor Author

bradrn commented May 8, 2017

Thank you!


You can use it like an ordinary JavaScript function, e.g.

handler <- ffiExport something
runFunction $ ffi "%1('hello')" handler

I should probably write this down somewhere in the documentation.

It might also be a good idea to record the method you gave for 'exporting' a Haskell function in the documentation.


P.S.: In case you want to know what I needed this for, I'm using it to create a menu using Electron (see #111 and https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/doc/electron.md). My code:

-- Main.hs

module Main where

import qualified Graphics.UI.Threepenny       as UI
import           Graphics.UI.Threepenny.Core

...

setup :: Window -> UI ()
setup window = do
    fname <- UI.input
    saveBtn <- UI.button # set text "Save file"
    box <- UI.textarea # set UI.id_ "text"
    ...
    let fun = void $ runUI window $ element box # set text "Hello from Haskell!"
    handler <- ffiExport fun
    runFunction $ ffi "window.sayHello = %1" handler
    ...
// electron.js
...

  function createWindow() {
    // Create the browser window.
    win = new BrowserWindow({
      width: 800,
      height: 600,
      webPreferences: { nodeIntegration: false },
    });

    ...

  app.on('ready', () => {
    ...
    setMainMenu()
  });

  ...

  // based on http://stackoverflow.com/a/37798089
  function setMainMenu() {
    const template = [
      {
        label: 'Hello',
        submenu: [
         {
           ...
           label: 'Hello from Haskell',
           accelerator: 'CmdOrCtrl+H',
             click() {
                 win.webContents.executeJavaScript('window.sayHello()')
             }
         }]
      }
    ];
    Menu.setApplicationMenu(Menu.buildFromTemplate(template));
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants