✨ Highlights
- 🔧 More Control Over
Manipulate
- 📊 Expanded Plotly API
Full access to Plotly's update methods:
- Allows precise control over visual elements (e.g. opacity, color).
- Enables dynamic updates using event handlers like sliders.
- 🎞️ Improved GUI for
Animate
- 🌐 Improved Dynamic HTML Export (Live Demo)
Full demo available here: LiveHTML Demo. Exporting widgets with
Manipulate
/Animate
to HTML is now much more practical and feature-rich. - We disabled automatic updates
More control over Manipulate
You can specify when to update the expression after or during user's action
Manipulate[Column[{ Style[StringTemplate["`` m/s"][x], Blue], Table["🚗", {i, Floor[x/25]}]//Row }], {x,10,100}, (*BB[*)(ContinuousAction->True)(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRAeB5AILqnMSXXKr0hjgskHleakFnMBGU6JydnpRfmleSlpzDDlQe5Ozvk5+UVFDGDwwR6dwcAAAAHdFiw="*)(*]BB*)] // Quiet
(*GB[*){{(*VB[*)(EventObject[<|"Id" -> "859d0076-5a64-4177-9850-24cc06474b21", "Initial" -> {55.}, "View" -> "576e67c2-30db-4f71-a964-61c65ce843a9"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKm5qbpZqZJxvpGhukJOmapJkb6iZampnomhkmm5kmp1qYGCdaAgB9HhVR"*)(*]VB*)}(*||*),(*||*){(*VB[*)(FrontEndRef["90083ee4-1dd3-445d-bbcd-b93516befe83"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKWxoYWBinpproGqakGOuamJim6CYlJQMJS2NTQ7Ok1LRUC2MAhNYWBA=="*)(*]VB*)}}(*]GB*)
Expanded API for Plotly
We fully exposed the available methods to update your Plotly
graphs
p = Plotly[<|"type"->"line", "y"->{1,2,3,4,5,6}|>] EventHandler[InputRange[0,1,0.1,1.0], (PlotlyRestyle[p, <|"opacity"->#, "marker.color"->"red"|>])&]
(*VB[*)(FrontEndRef["2ccca95f-4a5f-4859-84b0-abdef4e9f593"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKGyUnJydamqbpmiSCCAtTS10LkyQD3cSklNQ0k1TLNFNLYwCR8xZG"*)(*]VB*)
(*VB[*)(EventObject[<|"Id" -> "29af7c92-67e5-4dfc-8167-1fd9a95adc3c", "Initial" -> 1., "View" -> "9fbf4db9-7a1f-40af-bc5f-c8d9f7ad0234"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKW6YlpZmkJFnqmicapumaGCSm6SYlm6bpJlukWKaZJ6YYGBmbAACcGBaa"*)(*]VB*)
GUI for Animate
We upgraded Animate
Animate[Series[Cos[x], {x,0,n}], {n,2, 10, 1}, AnimationRate->3]
(*VB[*)(FrontEndRef["d8266190-9a0e-4e5b-aa21-0aecf09081e2"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKp1gYmZkZWhroWiYapOqapJom6SYmGhnqGiSmJqcZWBpYGKYaAQCAJRWT"*)(*]VB*)
Dynamic HTML Export
Check it out!
Here is a full demo
IDW interpolation with categorical partitioning
Motivation
When you are trying to export a widget with continuously changing input data (it can be a canvas with a pointer or an input range with fine steps), it becomes cumbersome and inefficient to manually sample all possible positions of them.
Imagine a Gaussian distribution controlled by a mouse. How can this be exported to HTML? For each mouse position, you have to recalculate the Gaussian. This is done by the WL kernel and not the JavaScript frontend.
udata = {{-1,0}, {1,0}}; Graphics[{ Cyan, Line[udata // Offload], Red, PointSize[0.05], EventHandler[Point[{0,0.5}], { "drag" -> ((udata = generate[#, 0.1])&) }] }, PlotRange->{{-1,1}, {0,1}}, ImagePadding->None, Axes->{True, False}, ImageSize->Small] ClearAll[generate]; generate[{x_, y_}, k_] := Table[{t, y Exp[- (*FB[*)(((*SpB[*)Power[(x - t)(*|*),(*|*)2](*]SpB*))(*,*)/(*,*)(2 k))(*]FB*)]}, {t,-1,1, 0.03}]
(*VB[*)(Graphics[{RGBColor[0, 1, 1], Line[Offload[udata]], RGBColor[1, 0, 0], PointSize[0.05], EventListener[Point[{0, 0.5}], {"drag" -> "87be2e86-95dd-4e22-9134-cb9a41ec6daa"}]}, PlotRange -> {{-1, 1}, {0, 1}}, ImagePadding -> None, Axes -> {True, False}, ImageSize -> Small])(*,*)(*"1:eJxtUFtOwzAQdIEKKsEhkPjNR0MozVcFCApSBVXCBTbxOlhybWQnCHETuAG34ibghyyawH6MZh8zGu1xpQo2IoSYPQu3SlA2dt2BhaWG5ydemzBx+xU3LduN+2J5eaWE0txywkcRfu1WXGLo9i08MCYUUOPcOgot/OPkTUiEoJ1YWCsu25K/of54d/W5YDtud2Th+gVl65KhRB0k4ygJVzG6N9XE19diO6fZuiw6gaUjVENTnlgyP68wxfksyc8oTTJM0ySfnmZJXeWQTbGeUYC+PoQWqi1ANthPMcj0bSv87W/Wwdw7H1pyt4EG10Apl43f3CuJgztHLl7R9G09edQd+h/dgDBD3ST6u3f7q3IDQvwAMSp2ew=="*)(*]VB*)
Try to drag a red dot if you are reading it from the wljs
blog page
Solution
Quite often, we do not need all possible points to be sampled, but only the randomly scattered probe points, which are practical to obtain. The rest can be interpolated using a general Inverse Distance Weighting (IDW) in continuous feature space. Non-numerical data such as checkboxes and select boxes can be treated as categorical types.
What about the output? It can be:
- Number
- Array (List)
- Tensor
- String
- Other expressions
The first three can easily be interpolated, while for strings and other expressions, we can pick the closest one from an N-dimensional space.
More about a string type
However, we went deeper. Look at this example.
Manipulate[Style[StringTemplate["`` m/s"][x], Blue], {x,10,100}, ContinuousAction->True] // Quiet
(*GB[*){{(*VB[*)(EventObject[<|"Id" -> "1a55b5d2-6aef-4761-9d22-12bb46ecea26", "Initial" -> {55.}, "View" -> "cb8b1804-0e26-4255-9310-b9fce1b0860e"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJydZJBlaGJjoGqQamemaGJma6loaGxroJlmmJacaJhlYmBmkAgB7YRU4"*)(*]VB*)}(*||*),(*||*){(*VB[*)(FrontEndRef["c2acc47b-2c38-4311-aa65-0833de072324"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJxslJiebmCfpGiUbW+iaGBsa6iYmmpnqGlgYG6ekGpgbGRuZAACGCRUr"*)(*]VB*)}}(*]GB*)
The output result is a string, but quite predictable. We analyze all strings used in outputs and decompose them into numbers and string templates if possible. Then the numerical content is interpoalted as usual and the final string is composed back.
Better handling external windows
You can assign handlers to the events generated by projected cells
state = ""; TextView[state // Offload, "Label"->"State"] cell = CellPrint[Plot[x,{x,0,1}], "Target"->_]; EventHandler[cell, { "Mounted" -> Function[Null, state = "Mounted"], "Closed" -> Function[Null, state = "Closed"] }]
(*VB[*)(FrontEndRef["ed11ea2a-b91d-4a22-9a7e-eb547d1a1073"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKp6YYGqYmGiXqJlkapuiaJBoZ6VommqfqpiaZmpinGCYaGpgbAwCRzxXu"*)(*]VB*)
And manually close it if needed
Delete[cell]
Note that Mounted
event contains WindowObj
, which can be used together with FrontSubmit
and FrontFetch
to trigger actions there.
Let expression
We adopted Leonid Shifrin's library LetWL
Leonid Shifrin is a software developer (Wolfram Research), an enthusiast, and the author of the excellent work Mathematica Programming: An Advanced Introduction by Leonid Shifrin. Please read it here if you haven't!
Let[{a = 1, b = a * 2}, b ]
2
Code Freeze
We decided to disable automatic granular updates by default (except for the entire WLJS Notebook app), unless you explicitly request it from the launcher window.
We do not expect a demand for frequent updates, as our project is becoming more and more stable. We do this for your own safety, ensuring that you won't face a situation where there is a version mismatch between different subsystems. Additionally, it reduces loading time because it does not check versions by default.