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

⚡️ AbstractPlutoDingetjes.Display.with_js_link to request calculations and data from Julia dynamically #2726

Merged
merged 24 commits into from
Feb 28, 2024

Conversation

fonsp
Copy link
Owner

@fonsp fonsp commented Nov 21, 2023

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:

  • Lazy loading more data in a display
    • An infinite zooming mandelbrot display
    • A table with millions of rows, that loads data on demand
  • Letting Julia calculate something on-demand, without requiring a @bind interaction
    • A @bind input widget that lets you type Julia code with a submit button, but it validates your input while you type.
    • An interaction where you select two points on a map, and Julia calculates the shortest path between them, and they are displayed on the same map.
    • Play chess against an AI written in Julia.

Matching AbstractPlutoDingetjes PR: JuliaPluto/AbstractPlutoDingetjes.jl#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 function AbstractPlutoDingetjes.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.

@htl("""
<script>
const sqrt_from_julia = $(AbstractPlutoDingetjes.Display.with_js_link(sqrt))

// I can now call sqrt_from_julia like a JavaScript function. It returns a Promise:
const result = await sqrt_from_julia(9.0)
console.log(result)

</script>
""")

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} or Vector{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 and Display.published_to_js. If possible, the use of these APIs is preferred over with_js_link because they will work with the Static HTML export and PlutoSliderServer.

Example

image
Code
@htl("""
<div>
	<p>Input:<br>
	<input>&nbsp;<input type="submit"></p>
	
	<p>Output:<br>
	<textarea cols=40 rows=5></textarea>
<script>
	let sqrt_with_julia = $(AbstractPlutoDingetjes.Display.with_js_link(sqrt))

	let wrapper = currentScript.closest("div")

	let input = wrapper.querySelector("input")
	let submit = wrapper.querySelector("input[type='submit']")
	let output = wrapper.querySelector("textarea")

	submit.addEventListener("click", async () => {
		let result = await sqrt_with_julia(Number(input.value))
		output.innerText = result
	})
</script>

</div>
""")

TODO

  • Exception handling inside the callback
  • Logging inside the callback
  • Stdout inside the callback?
  • Running the callback async or in a thread? Right now the callback runs @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.
  • What should happen when the notebook is running while using the callback? What if the cell itself is running?
  • What happens when the callback takes long?
  • Make sure that everything is cleaned up properly
  • Tests
  • Docs
  • Future-proof to allow a bi-directional API in the future. EDIT: with the invalidation callback it can be done! Need to make a MWE and maybe test it
  • Could be published_to_js(::Function)... EDIT: that would be cute but then is_supported_by_display can't check for it soooooo no :(
  • Add an invallidation callback (I already have this on my computer but still need to push)
  • What about PlutoSliderServer? Maybe also a 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?
  • Disabled cells should have js links disabled?

Copy link
Contributor

Try this Pull Request!

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

@fonsp fonsp added enhancement New feature or request backend Concerning the julia server and runtime HTTP/WS The connection between backend and frontend display & PlutoRunner & AbstractPlutoDingetjes.jl other packages Integration with other Julia packages labels Nov 21, 2023
@SimonDanisch
Copy link

How will this help to better support JSServe?

@fonsp
Copy link
Owner Author

fonsp commented Nov 21, 2023

@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?

@fonsp
Copy link
Owner Author

fonsp commented Nov 21, 2023

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 #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.

@SimonDanisch
Copy link

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?

@fonsp
Copy link
Owner Author

fonsp commented Nov 21, 2023

Yeah exactly, it's not usable for this yet.

@fonsp
Copy link
Owner Author

fonsp commented Nov 21, 2023

Schermopname.2023-11-21.om.14.38.07.mov

@Pangoraw
Copy link
Collaborator

@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,)))

@SimonDanisch
Copy link

So, it's not really superseding those PRs, right? Is there a plan to actually implement those features still?

@SimonDanisch
Copy link

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?

@fonsp
Copy link
Owner Author

fonsp commented Nov 21, 2023

@SimonDanisch Can we continue this another time? We'll work on better docs 💛

@disberd
Copy link
Contributor

disberd commented Nov 22, 2023

Implementing the explorable mandelbrot set is so much easier with this PR!

9fe778b7-34f2-421a-bd92-7b49247093f4.mp4

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)

Notebook Code
### A Pluto.jl notebook ###
# v0.19.32

using Markdown
using InteractiveUtils

# ╔═╡ d6a4d6f0-8920-11ee-1360-dbb4ff626eb6
begin
	using PlutoPlotly
	using HypertextLiteral
	using AbstractPlutoDingetjes
end

# ╔═╡ b4655ee1-dfe3-47a4-8b19-48c9fb2b6349
# This code is taken from a Mandelbrot notebook shared in https://discourse.julialang.org/t/mandelbrot-with-plots-jl/52410
begin
to_range(raw_range, n) = range(minimum(raw_range), maximum(raw_range); length=n)
function mandel(z:: Complex) 
    c = z 
    maxiter = 128
    for n = 1:maxiter 
        if abs2(z) > 4 
            return n-1 
        end 
        z = z^2 + c 
    end 
    return maxiter 
end
function mandel_slice!(grid, ix, x, yrange)
	@inbounds for (iy, y) in enumerate(yrange)
		grid[iy, ix] = mandel(Complex(x,y))
	end
end
function mandel_grid(xrange, yrange)
	grid = Matrix{UInt8}(undef, length(xrange), length(yrange))
	futures = Vector{Task}(undef, length(xrange))
	@inbounds for (ix, x) in enumerate(xrange)
		futures[ix] = Threads.@spawn mandel_slice!(grid, ix, x, yrange)
	end
	wait.(futures)
	grid
end
end

# ╔═╡ 059bbb92-5a68-46d7-a210-69fc1ce91aff
let # This code generates the plot with re-computation upon zooming
	n = 500
	x = to_range([-1, 1], n)
	y = to_range([-1, 1], n)
	z = mandel_grid(x,y)
	data = heatmap(;x,y,z)
	p = plot(data, Layout(xaxis_range = [-1, 1], yaxis = attr(;
		range = [-1,1],
		scaleanchor = "x",
		scaleratio = 1,
	)))
	add_plotly_listener!(p, "plotly_relayout", htl_js("async (e) => {
		let xrange = PLOT._fullLayout.xaxis.range
		let yrange = PLOT._fullLayout.yaxis.range
		if (PLOT.updated_data == undefined) {return}
		console.log(PLOT.updated_data)
		let update = await PLOT.updated_data({x: xrange, y: yrange})
		Plotly.restyle(PLOT, update)
	}"))
	f(d) = let
		x = range(d["x"]..., n) |> collect
		y = range(d["y"]..., n) |> collect
		z = mandel_grid(x,y) |> PlutoPlotly._preprocess
		out = (;
			x = [x],
			y = [y],
			z = [z],
		)
		out
	end
	@htl("""
	$p
	<script>
		const plt = currentScript.closest('pluto-cell').querySelector('.js-plotly-plot')
		plt.updated_data = $(AbstractPlutoDingetjes.Display.with_js_link(f))
	</script>
	""")
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
AbstractPlutoDingetjes = "6e696c72-6542-2067-7265-42206c756150"
HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
PlutoPlotly = "8e989ff0-3d88-8e9f-f020-2b208a939ff0"

[compat]
AbstractPlutoDingetjes = "~1.2.0"
HypertextLiteral = "~0.9.5"
PlutoPlotly = "~0.4.3"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

julia_version = "1.10.0-beta3"
manifest_format = "2.0"
project_hash = "cc56535668b6e8901cb9ab7a99dbc6e210e21f3b"

[[deps.AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "308ee5441d5a481d4ce0152d04f3ef411b05c2b4"
repo-rev = "Display.with_js_link"
repo-url = "https://github.com/JuliaPluto/AbstractPlutoDingetjes.jl.git"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.2.0"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.1"

[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[deps.BaseDirs]]
git-tree-sha1 = "1c9b6f39f40dba0ef22244a175e2d4e42c8f6ee7"
uuid = "18cc8868-cbac-4acf-b575-c8ff214dc66f"
version = "1.2.0"

[[deps.ColorSchemes]]
deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"]
git-tree-sha1 = "67c1f244b991cad9b0aa4b7540fb758c2488b129"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.24.0"

[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.4"

[[deps.ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"]
git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.10.0"

    [deps.ColorVectorSpace.extensions]
    SpecialFunctionsExt = "SpecialFunctions"

    [deps.ColorVectorSpace.weakdeps]
    SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"

[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "fc08e5930ee9a4e03f84bfb5211cb54e7769758a"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.10"

[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.0.5+1"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[deps.DelimitedFiles]]
deps = ["Mmap"]
git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae"
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
version = "1.9.1"

[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.3"

[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
version = "1.6.0"

[[deps.FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"

[[deps.FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[deps.HypertextLiteral]]
deps = ["Tricks"]
git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.5"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.4"

[[deps.LaTeXStrings]]
git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.1"

[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
version = "0.6.4"

[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
version = "8.0.1+1"

[[deps.LibGit2]]
deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[deps.LibGit2_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"]
uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5"
version = "1.6.4+0"

[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
version = "1.11.0+1"

[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[deps.LinearAlgebra]]
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
version = "2.28.2+1"

[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2023.1.10"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
version = "1.2.0"

[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
version = "0.3.23+2"

[[deps.OrderedCollections]]
git-tree-sha1 = "2e73fe17cac3c62ad1aebe70d44c963c3cfdc3e3"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.2"

[[deps.Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.3"

[[deps.Parsers]]
deps = ["Dates", "PrecompileTools", "UUIDs"]
git-tree-sha1 = "a935806434c9d4c506ba941871b327b96d41f2bf"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.8.0"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.10.0"

[[deps.PlotlyBase]]
deps = ["ColorSchemes", "Dates", "DelimitedFiles", "DocStringExtensions", "JSON", "LaTeXStrings", "Logging", "Parameters", "Pkg", "REPL", "Requires", "Statistics", "UUIDs"]
git-tree-sha1 = "56baf69781fc5e61607c3e46227ab17f7040ffa2"
uuid = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
version = "0.8.19"

[[deps.PlutoPlotly]]
deps = ["AbstractPlutoDingetjes", "BaseDirs", "Colors", "Dates", "Downloads", "HypertextLiteral", "InteractiveUtils", "LaTeXStrings", "Markdown", "Pkg", "PlotlyBase", "Reexport", "TOML"]
git-tree-sha1 = "0b8880a45f96d8404ae1cf6e4d715e3a79369441"
uuid = "8e989ff0-3d88-8e9f-f020-2b208a939ff0"
version = "0.4.3"

    [deps.PlutoPlotly.extensions]
    PlotlyKaleidoExt = "PlotlyKaleido"
    UnitfulExt = "Unitful"

    [deps.PlutoPlotly.weakdeps]
    PlotlyKaleido = "f2990250-8cf9-495f-b13a-cce12b45703c"
    Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[[deps.PrecompileTools]]
deps = ["Preferences"]
git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f"
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
version = "1.2.0"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.4.1"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Random]]
deps = ["SHA"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"

[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"

[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[deps.SparseArrays]]
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
version = "1.10.0"

[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
version = "1.10.0"

[[deps.SuiteSparse_jll]]
deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
version = "7.2.0+1"

[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
version = "1.0.3"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
version = "1.10.0"

[[deps.TensorCore]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6"
uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50"
version = "0.1.1"

[[deps.Tricks]]
git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f"
uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"
version = "0.1.8"

[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[deps.UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
version = "1.2.13+1"

[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
version = "5.8.0+1"

[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
version = "1.52.0+1"

[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
version = "17.4.0+2"
"""

# ╔═╡ Cell order:
# ╠═d6a4d6f0-8920-11ee-1360-dbb4ff626eb6
# ╠═b4655ee1-dfe3-47a4-8b19-48c9fb2b6349
# ╠═059bbb92-5a68-46d7-a210-69fc1ce91aff
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

@fonsp
Copy link
Owner Author

fonsp commented Dec 2, 2023

@disberd thanks for the encouragement! I updated the TODO list, we should be able to merge it soon :)

@fonsp fonsp mentioned this pull request Jan 5, 2024
@vambrosi
Copy link

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).

@disberd
Copy link
Contributor

disberd commented Feb 19, 2024

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:
image

@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

@fonsp
Copy link
Owner Author

fonsp commented Feb 19, 2024

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:

  • Writing tests (in this PR) (see last point)
  • Writing docs (in Display.with_js_link to request calculations and data from Julia dynamically JuliaPluto/AbstractPlutoDingetjes.jl#13 ). If you have some time then your contribution would be welcome! Try to match the style of other APD docs, use @htl and keep the examples simple :) You can make a PR or just comment on the existing PR with the contents of the docstring.
  • Async/threaded behaviour: should with_js_link calculations be executed async (this mostly works, except when using functions defined in other cells), or sync, using notebook.execute_token?
  • We want to future-proof the ability to write a bidirectional link with this API. Currently, it looks like this is possible if we add an invalidation callback on the Julia side. We need to have a good working example, and write tests for that example.

@fonsp
Copy link
Owner Author

fonsp commented Feb 26, 2024

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.

@fonsp
Copy link
Owner Author

fonsp commented Feb 26, 2024

Hmmm never mind I think #2780 is good enough to work, and it's much cooler to have an async API :)

@fonsp
Copy link
Owner Author

fonsp commented Feb 26, 2024

Bidirectional link with multiple clients in https://github.com/fonsp/disorganised-mess/blob/main/APD%20with_js_link%20bidirectional%203.jl using #2780

@fonsp fonsp marked this pull request as ready for review February 28, 2024 16:07
@fonsp fonsp changed the title AbstractPlutoDingetjes.Display.with_js_link to request calculations and data from Julia dynamically ⚡️ AbstractPlutoDingetjes.Display.with_js_link to request calculations and data from Julia dynamically Feb 28, 2024
@fonsp fonsp merged commit 017a084 into main Feb 28, 2024
12 of 16 checks passed
@fonsp fonsp deleted the AbstractPlutoDingetjes.Display.with_js_link branch February 28, 2024 16:35
@fonsp
Copy link
Owner Author

fonsp commented Feb 28, 2024

@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 JuliaPluto/AbstractPlutoDingetjes.jl#13

@disberd
Copy link
Contributor

disberd commented Feb 28, 2024

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

🎉🎉🎉

Updated Mandelbrot notebook
### A Pluto.jl notebook ###
# v0.19.40

using Markdown
using InteractiveUtils

# ╔═╡ 28a24682-9a36-48d0-88c2-88841854df46
begin
	using PlutoPlotly
	using HypertextLiteral
	using AbstractPlutoDingetjes
end

# ╔═╡ 572b1939-b61a-4d81-8000-10cac4048c8d
# This code is taken from a Mandelbrot notebook shared in https://discourse.julialang.org/t/mandelbrot-with-plots-jl/52410
begin
to_range(raw_range, n) = range(minimum(raw_range), maximum(raw_range); length=n)
function mandel(z:: Complex) 
    c = z 
    maxiter = 128
    for n = 1:maxiter 
        if abs2(z) > 4 
            return n-1 
        end 
        z = z^2 + c 
    end 
    return maxiter 
end
function mandel_slice!(grid, ix, x, yrange)
	@inbounds for (iy, y) in enumerate(yrange)
		grid[iy, ix] = mandel(Complex(x,y))
	end
end
function mandel_grid(xrange, yrange)
	grid = Matrix{UInt8}(undef, length(xrange), length(yrange))
	futures = Vector{Task}(undef, length(xrange))
	@inbounds for (ix, x) in enumerate(xrange)
		futures[ix] = Threads.@spawn mandel_slice!(grid, ix, x, yrange)
	end
	wait.(futures)
	grid
end
end

# ╔═╡ da487aae-0670-4199-a8d4-ebea52ab2896
let # This code generates the plot with re-computation upon zooming
	n = 500
	x = to_range([-1, 1], n)
	y = to_range([-1, 1], n)
	z = mandel_grid(x,y)
	data = heatmap(;x,y,z)
	p = plot(data, Layout(xaxis_range = [-1, 1], yaxis = attr(;
		range = [-1,1],
		scaleanchor = "x",
		scaleratio = 1,
	)))
	add_plotly_listener!(p, "plotly_relayout", htl_js("async (e) => {
		let xrange = PLOT._fullLayout.xaxis.range
		let yrange = PLOT._fullLayout.yaxis.range
		if (PLOT.updated_data == undefined) {return}
		let update = await PLOT.updated_data({x: xrange, y: yrange})
		Plotly.restyle(PLOT, update)
	}"))
	f(d) = let
		x = range(d["x"]..., n) |> collect
		y = range(d["y"]..., n) |> collect
		z = mandel_grid(x,y) |> PlutoPlotly._preprocess
		out = (;
			x = [x],
			y = [y],
			z = [z],
		)
		out
	end
	@htl("""
	$p
	<script>
		const plt = currentScript.closest('pluto-cell').querySelector('.js-plotly-plot')
		plt.updated_data = $(AbstractPlutoDingetjes.Display.with_js_link(f))
	</script>
	""")
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
AbstractPlutoDingetjes = "6e696c72-6542-2067-7265-42206c756150"
HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
PlutoPlotly = "8e989ff0-3d88-8e9f-f020-2b208a939ff0"

[compat]
AbstractPlutoDingetjes = "~1.3.0"
HypertextLiteral = "~0.9.5"
PlutoPlotly = "~0.4.5"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

julia_version = "1.10.1"
manifest_format = "2.0"
project_hash = "d816ed2045a595d53cb3c87792dc8e3c6d5b003e"

[[deps.AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "0f748c81756f2e5e6854298f11ad8b2dfae6911a"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.3.0"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.1"

[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[deps.BaseDirs]]
git-tree-sha1 = "3e93fcd95fe8db4704e98dbda14453a0bfc6f6c3"
uuid = "18cc8868-cbac-4acf-b575-c8ff214dc66f"
version = "1.2.3"

[[deps.ColorSchemes]]
deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"]
git-tree-sha1 = "67c1f244b991cad9b0aa4b7540fb758c2488b129"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.24.0"

[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.4"

[[deps.ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"]
git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.10.0"

    [deps.ColorVectorSpace.extensions]
    SpecialFunctionsExt = "SpecialFunctions"

    [deps.ColorVectorSpace.weakdeps]
    SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"

[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "fc08e5930ee9a4e03f84bfb5211cb54e7769758a"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.10"

[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.1.0+0"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[deps.DelimitedFiles]]
deps = ["Mmap"]
git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae"
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
version = "1.9.1"

[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.3"

[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
version = "1.6.0"

[[deps.FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"

[[deps.FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[deps.HypertextLiteral]]
deps = ["Tricks"]
git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.5"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.4"

[[deps.LaTeXStrings]]
git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.1"

[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
version = "0.6.4"

[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
version = "8.4.0+0"

[[deps.LibGit2]]
deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[deps.LibGit2_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"]
uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5"
version = "1.6.4+0"

[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
version = "1.11.0+1"

[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[deps.LinearAlgebra]]
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
version = "2.28.2+1"

[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2023.1.10"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
version = "1.2.0"

[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
version = "0.3.23+4"

[[deps.OrderedCollections]]
git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.3"

[[deps.Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.3"

[[deps.Parsers]]
deps = ["Dates", "PrecompileTools", "UUIDs"]
git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.8.1"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.10.0"

[[deps.PlotlyBase]]
deps = ["ColorSchemes", "Dates", "DelimitedFiles", "DocStringExtensions", "JSON", "LaTeXStrings", "Logging", "Parameters", "Pkg", "REPL", "Requires", "Statistics", "UUIDs"]
git-tree-sha1 = "56baf69781fc5e61607c3e46227ab17f7040ffa2"
uuid = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
version = "0.8.19"

[[deps.PlutoPlotly]]
deps = ["AbstractPlutoDingetjes", "BaseDirs", "Colors", "Dates", "Downloads", "HypertextLiteral", "InteractiveUtils", "LaTeXStrings", "Markdown", "Pkg", "PlotlyBase", "Reexport", "TOML"]
git-tree-sha1 = "fbf637823ec24c5669b1a66f3771c2306f60857c"
uuid = "8e989ff0-3d88-8e9f-f020-2b208a939ff0"
version = "0.4.5"

    [deps.PlutoPlotly.extensions]
    PlotlyKaleidoExt = "PlotlyKaleido"
    UnitfulExt = "Unitful"

    [deps.PlutoPlotly.weakdeps]
    PlotlyKaleido = "f2990250-8cf9-495f-b13a-cce12b45703c"
    Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[[deps.PrecompileTools]]
deps = ["Preferences"]
git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f"
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
version = "1.2.0"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.4.1"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Random]]
deps = ["SHA"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"

[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"

[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[deps.SparseArrays]]
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
version = "1.10.0"

[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
version = "1.10.0"

[[deps.SuiteSparse_jll]]
deps = ["Artifacts", "Libdl", "libblastrampoline_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
version = "7.2.1+1"

[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
version = "1.0.3"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
version = "1.10.0"

[[deps.TensorCore]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6"
uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50"
version = "0.1.1"

[[deps.Tricks]]
git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f"
uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"
version = "0.1.8"

[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[deps.UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
version = "1.2.13+1"

[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
version = "5.8.0+1"

[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
version = "1.52.0+1"

[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
version = "17.4.0+2"
"""

# ╔═╡ Cell order:
# ╠═28a24682-9a36-48d0-88c2-88841854df46
# ╠═572b1939-b61a-4d81-8000-10cac4048c8d
# ╠═da487aae-0670-4199-a8d4-ebea52ab2896
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

@fonsp
Copy link
Owner Author

fonsp commented Feb 28, 2024

Super cool!!

@vambrosi
Copy link

Thanks @fonsp, it looks great!

mandel.mp4

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.

@disberd
Copy link
Contributor

disberd commented Mar 1, 2024

@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):

5cf71adb-f943-4007-ae33-c95a5d8d4d69.mp4

@fonsp
Copy link
Owner Author

fonsp commented Mar 4, 2024

Would be nice if you could debug this before I make the release! To me it looks like a plotly issue

@fonsp
Copy link
Owner Author

fonsp commented Mar 7, 2024

Any update?

@vambrosi
Copy link

vambrosi commented Mar 7, 2024

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.

@vambrosi
Copy link

vambrosi commented Mar 21, 2024

In case it is still relevant @fonsp, the flickering seems to be an old Plotly issue: plotly/plotly.js#4377 (still checking to see if it is the exact same problem).

@fonsp
Copy link
Owner Author

fonsp commented Apr 22, 2024

@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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Concerning the julia server and runtime display & PlutoRunner & AbstractPlutoDingetjes.jl enhancement New feature or request HTTP/WS The connection between backend and frontend other packages Integration with other Julia packages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants