Warning: This package is still very early in development. Feedback, issues and PRs are most welcome.
This is simple package that allows Julia to interact with JavaScript in a browser and is heavily inspired by Blink.jl.
JavaScriptBridge is not registered and it requires another unregistered package: StringInterpolation. To install, you'll need to run the following commands:
julia> Pkg.clone("https://github.com/EricForgy/StringInterpolation.jl.git")
julia> Pkg.clone("https://github.com/EricForgy/JavaScriptBridge.jl.git")
After installation, running the following from the Julia REPL
julia> using JavaScriptBridge
Listening on 0.0.0.0:8000...
will start an HttpServer. Open your browser to http://localhost:8000/julia and you should see a blank page with "JavaScriptBridge" in the browser tab.
With the browser open, run the following:
julia> include(Pkg.dir("JavaScriptBridge","examples","plotly.jl"))
If the stars are aligned, you should see several sample charts appear in the browser window. If not, you can try running the above command again. If that still doesn't work, please let me know and I'll try to help.
Julia code can be called from JavaScript using callback
s stored in a Dict
. For example, in Julia, you can define:
callback["sayhello"] = () -> println("Hello")
and call this from JavaScript (console or scripts) via:
Julia.message("sayhello")
You can also define callbacks with arguments, e.g. in Julia, define:
callback["say"] = args -> println(args)
and call this from JavaScript via:
Julia.message("say","Hello")
Multiple arguments are also supported, e.g. in Julia, define:
callback["rand"] = args -> println(rand(args...))
and call this from JavaScript via:
Julia.message("rand",[2,3,4])
An important callback is notify
. This callback allows Julia to listen for JavaScript events via Condition
s. An example is provided in api.jl
:
function addlibrary(url)
name = basename(url)
condition[name] = Condition()
js"""
var script = document.createElement("script");
script.src = "$(url)";
script.onload = Julia.message("notify","$(name)");
document.head.appendChild(script);
"""
wait(condition[name])
delete!(condition,name)
end
JavaScriptBridge keeps a dictionary of Condition
s. The method, addlibrary
, takes a url and adds a Condition
indexed by the basename of the url to the dictionary. The JS library is added to the page in the browser and, when loading is completed, sends a message back to Julia using the notify
callback. Julia will wait for this notification and finally delete it from the dictionary. This provides a simple blocking mechanism so that subsequent Julia code will not execute until the library is ready for use.
The non-standard string literal js
supports interpolation, but at the moment, the Julia expression needs to be enclosed in parentheses, e.g. instead of
julia> msg = "Hello World"
julia> js"""
console.log("$msg")
"""
you will need to enclose msg
in parentheses as illustrated below:
julia> msg = "Hello World"
julia> js"""
console.log("$(msg)")
"""
JavaScriptBridge creates an active link between Julia and your browser via WebSockets so you can update your charts from Julia without reloading the page. To see this, try rerunning the above example several times:
julia> include(Pkg.dir("JavaScriptBridge","examples","plotly.jl"))
julia> include(Pkg.dir("JavaScriptBridge","examples","plotly.jl"))
julia> include(Pkg.dir("JavaScriptBridge","examples","plotly.jl"))
julia> include(Pkg.dir("JavaScriptBridge","examples","plotly.jl"))
Each time you run from the REPL, the charts are updated without having to reload.
A fun artefact of using WebSockets is that you can "broadcast" your charts to several browsers and they will all get updated interactively. Here is a silly video demonstrating three browsers (including an iphone) with charts being interactively controlled from the Julia REPL.