Closed fonsp closed 5 months ago
Open Julia and type:
julia> import Pkg
julia> Pkg.activate(temp=true)
julia> Pkg.add(url="https://github.com/fonsp/Pluto.jl", rev="AbstractPlutoDingetjes.Display.with_js_link")
julia> using Pluto
How will this help to better support JSServe?
@Pangoraw this API could easily be used with a WASM backend, right? E.g. when you export to HTML, each js link could be compiled to WASM, and the WASM blob is inserted?
Hey @SimonDanisch!
I think the main work for better JSServe support is using the existing AbstractPlutoDingetjes.Display.published_to_js
API for the initial state object (e.g. the initial plot data with WebGLMakie), and the JavaScript this
and invalidation
API for a persistent display that can update instead of just re-render (see the Web notebooks on https://featured.plutojl.org/).
I don't think this PR will help with https://github.com/fonsp/Pluto.jl/issues/2706, but we can use it to make JSServe use Pluto's existing websocket connection instead of a new one. But right now this PR is one-directional (only JS can initiate), not bidirectional.
but we can use it to make JSServe use Pluto's existing websocket connection instead of a new one.
How will JSServe use the websocket connection if it's not bi-directional?
Yeah exactly, it's not usable for this yet.
@Pangoraw this API could easily be used with a WASM backend, right? E.g. when you export to HTML, each js link could be compiled to WASM, and the WASM blob is inserted?
Yes! Though, it will probably need to provide the signature to know which method to compile:
const sqrt_from_julia = $(AbstractPlutoDingetjes.Display.with_js_link(sqrt, (Float32,)))
So, it's not really superseding those PRs, right? Is there a plan to actually implement those features still?
I think the main work for better JSServe support is using the existing AbstractPlutoDingetjes.Display.published_to_js API
Are there any docs that explain well, what I will need to do?
@SimonDanisch Can we continue this another time? We'll work on better docs π
Implementing the explorable mandelbrot set is so much easier with this PR!
https://github.com/fonsp/Pluto.jl/assets/12846528/009a01c1-8ad5-49c5-b7e1-98ff68ac8c5e
This code simply recomputes the mandelbrot set with a fixed number of points per dimension (500 over x and 500 over y) over the current range of the axes of the plot. So it is recomputed upon zoom or upon panning.
The notebook code hidden below should use the version of AbstractPlutoDingetjes from this branch, but it will be overwritten to the latest registered version when adding or removing packages (I believe)
@disberd thanks for the encouragement! I updated the TODO list, we should be able to merge it soon :)
Any progress with this pull request? I was actually developing a package to visualize the analogues of the Mandelbrot and Julia sets for other families of functions and having an UI integrated with Pluto would be ideal! I'm using GLMakie currently, but I like how responsive @disberd plots were in the video.
Also, what do I need to do to run that notebook? I tried installing both Pluto and AbstractPlutoDingetjes using the branches from this PR, but the plots don't update after the initial plot. The sqrt example also doesn't work (I get an Uncaught (in promise) TypeError: pluto_actions.request_js_link_response(...) is not iterable
in the browser console, but no errors in Julia).
I confirm that with the current status of this branch I am not able to reproduce any of the examples currently shown here as I also get a JS error about some object not being iterable.
This simple cell code
@htl("""
<script>
let asd = $(AbstractPlutoDingetjes.Display.with_js_link(x -> x+1))
const lol = await(asd(1))
</script>
""")
produces this error on JS:
@fonsp is there anything we can do to help finalize this PR? I find new cool use cases for this functionality basically every week so it would be very cool to have it available :D
Hey all! Sorry, this feature is taking a lot of work to go from a prototype to a release. Once we release, we ideally don't need to change the API again, so I am trying to cover as many use cases as possible from the start.
Difficult things are:
@htl
and keep the examples simple :) You can make a PR or just comment on the existing PR with the contents of the docstring.notebook.execute_token
?invalidation
callback on the Julia side. We need to have a good working example, and write tests for that example.I recently made the with_js_link
callback run synchronous with execution instead of as a background task. This fixed all edge cases, but now it's no longer possible to make a bidirectional callback out of it (which you need for JSServe).
I'm considering releasing this first API first, maybe as with_js_link_sync
, and try to support an async link (maybe with #2780) in the future.
Hmmm never mind I think #2780 is good enough to work, and it's much cooler to have an async API :)
Bidirectional link with multiple clients in https://github.com/fonsp/disorganised-mess/blob/main/APD%20with_js_link%20bidirectional%203.jl using #2780
@disberd and @vambrosi there you go! It's merged but not yet released. Can you test your apps with the latest version to make sure everything works? Also check out the new docs on https://github.com/JuliaPluto/AbstractPlutoDingetjes.jl/pull/13
Amazing @fonsp, I am gonna start trying out many things to see if it breaks :D.
The mandelbrot notebook works with Pluto#main and AbstractPlutoDingetjes@v1.3
πππ
Super cool!!
Thanks @fonsp, it looks great!
https://github.com/fonsp/Pluto.jl/assets/42151837/90fbdd18-6751-470e-8779-082532c7a309
I just get this flickering though, not sure if this is because of Plotly (you can see it in the video). It also happens with @disberd updated notebook.
@vambrosi, on my laptop I do not see the same flickering as you (at least on my notebook). There is some kind of misalignment only seldomly when zooming in (twice in this video below despite zooming more than twice):
https://github.com/fonsp/Pluto.jl/assets/12846528/b2b1bb5a-ee98-40a1-b46f-06cf97c0995d
Would be nice if you could debug this before I make the release! To me it looks like a plotly issue
Any update?
Just one thing, I figured out that it happens on Firefox, but not on Safari or Chrome. So I am guessing is a Plotly issue.
In case it is still relevant @fonsp, the flickering seems to be an old Plotly issue: https://github.com/plotly/plotly.js/issues/4377 (still checking to see if it is the exact same problem).
@vambrosi This notebook is super cool! Would you be interested in submitting it to https://github.com/JuliaPluto/featured ? Make a PR and we can discuss more there!
NOTE: documentation at https://plutojl.org/en/docs/abstractplutodingetjes/#with_js_link
New JavaScript API to request calculations and data from Julia dynamically. This is useful for:
@bind
interaction@bind
input widget that lets you type Julia code with a submit button, but it validates your input while you type.Matching AbstractPlutoDingetjes PR: https://github.com/JuliaPluto/AbstractPlutoDingetjes.jl/pull/13
Supersedes #991 and #2392
API
The easiest way to use this API is with HypertextLiteral. The use is very similar to
APD.Display.published_to_js
: the new functionAbstractPlutoDingetjes.Display.with_js_link
returns a "piece of JavaScript code" that you interpolate directly into a<script>
tag.In JavaScript, the "piece of JavaScript code" returns a function. You can call this function with an argument (which will be passed to your Julia function), and it returns a Promise that resolves to the answer from your Julia function.
Serialization and inner workings
The request and response use Pluto's internal communication protocol (with MsgPack and WebSocket), so the performance is optimal. The same serialization is used as
published_to_js
, so in particular,Vector{Float64}
orVector{UInt8}
are really fast.Since this API is designed for one-off requests, this communication does not go through Pluto's state management (the request and response are not stored in the state). If multiple clients are connected in parallel, then the messages are not shared between clients.
When not to use it
This API is only meant to support use cases that can not be covered with
@bind
andDisplay.published_to_js
. If possible, the use of these APIs is preferred overwith_js_link
because they will work with the Static HTML export and PlutoSliderServer.Example
Code
```julia @htl("""Input:
Output:
TODO
@async
on the web server.~ Right now it runs sequentially with other code execution. But then lots of calls can clog up the queue... And queued messages can be invalid once they get executed.published_to_js(::Function)
... EDIT: that would be cute but thenis_supported_by_display
can't check for it soooooo no :(pure::Bool
kwarg to declare that your callback is pure? Or maybe that should be assumed by default? (Yes because multiple clients can connect to the same notebook) How do you declare the possible values etc?