juliagizmos / interactbase.jl Goto Github PK
View Code? Open in Web Editor NEWBuild interactive HTML5 widgets in Julia
License: Other
Build interactive HTML5 widgets in Julia
License: Other
Restricting Colors
to 0.11
, restricts Plots ~1.0
down the line.
This is an issue to decide the InteractBase API. The current approach tries to be as compatible as possible with the Interact.jl API which in turn is not fully consistent.
In Interact.jl, almost all arguments can be used as keyword arguments and a "positional" version is provided, that can take as positional version the most "commonly used" keyword argument. It generally is value
, but sometimes is placeholder
and other times it's label
. Still, there is some logic: the positional argument is placeholder
for text input, value
for "type input" (meaning input of non text types, like Bool
, Date
, Color
,..) and label
for buttons. Here is the current API reference.
One alternative would be as follows:
options
or range
for a slider) and value
placeholder
, label
, multiple
, etc...)The "fly in the ointment" of this rewrite is button
as the HTML5 version of button
takes argument that are not "keyword" and are the content of the button (generally label
and icon
). In this case I see as sensible both signatures:
button(args...; value=0, kwargs...)
where args
would be the button content (icon and label)button(value = 0, label = "press me", icon = nothing, kwargs....)
What is the consensus? Is it preferred to:
And, in case of 2), what should the signature of button
be?
When trying out textbox (using the Bulma backend) in Juno, I found that some normal keyboard input is ignored. I cannot use backspace, nor can I use the arrow keys to navigate in the text. I can however drag and drop parts of the text, indicating that it is possible to edit it.
using WebIO
using InteractBulma
textbox()
This is not important to me, I just thought that I'd raise the issue.
I was trying to track some broken styling in inputs.jl, but the eval blocks make it a little hard to track what is happening! I'm wondering if it is worth having them at all, in terms of the obfuscation vs DRYness ratio they deliver.
You could get a lot off the way by just extracting a few shared functions, say in slider.jl
:
slider(WT::WidgetTheme, vals::AbstractArray, formatted_vals = format.(vec(vals)); value = medianelement(vals), kwargs...) =
build_slider(slider, WT, vals, formatted_vals, value)
rangeslider(WT::WidgetTheme, vals::AbstractArray, formatted_vals = format.(vec(vals)); value = medianelement(vals), kwargs...) =
build_slider(rangeslider, WT, vals, formatted_vals, value)
function build_slider(f, WT, vals, formatted_vals, value)
T = Observables._val(value) isa Vector ? Vector{eltype(vals)} : eltype(vals)
value isa AbstractObservable || (value = Observable{T}(value))
vals = vec(vals)
indices = axes(vals)[1]
f = x -> _map(t -> searchsortedfirst(vals, t), x)
g = x -> vals[Int.(x)]
ObservablePair(value, f = f, g = g).second
value = build_value(vals, value)
index = build_index(vals)
wdg = Widget(f(WT, indices, formatted_vals; value = index, kwargs...), output = value)
wdg["value"] = value
wdg
end
Anyway, that is just my 2 cents! And mostly because I imagine I'll be reading this code a lot more, because its so useful :)
I was thinking that a widget that can display some sort of message could be very useful in GUIs programming. In this sense it would be a text area that doesn't take input but only shows a string.
This issue is used to trigger TagBot; feel free to unsubscribe.
If you haven't already, you should update your TagBot.yml
to include issue comment triggers.
Please see this post on Discourse for instructions and more details.
If you'd like for me to do this for you, comment TagBot fix
on this issue.
I'll open a PR within a few hours, please be patient!
It only emits a signal when released.
Particularly tricky when a conversion is needed to get a pure Julia value that does not exist in javascript.
All widget arguments that are passed to Knockout (e.g. the list of options) should also accept Observables and when upgraded Knockout would automatically update only that part of the widget.
None of the modifiers in https://github.com/piever/InteractBase.jl/blob/master/src/modifiers.jl is documented.
Label could say i =123
for example, to avoid having the readout far away.
When I use the filepicker widget, I would like to get a response for a callback function even when I select the same same twice or more times. The current behavior just ignores the callback for the same file selection.
This is a minimal working example:
using Blink, Interact
w = Window();
picker = filepicker();
on((n) -> println(picker[]), picker);
body!(w, picker);
, after that, it is necessary to select the same file multiple times and check that the println() function is only called once.
Here is an screeshoot that shows the behavior more clearly:
I'm using the latests versions of Interact and InteractBase, 0.10.5 and 0.10.10 respectively.
Maybe, the filepicker widget was meant to behave like that, however I need to detect selections even though the same file is chosen. Any ideas to overcome this?
Describe the bug
Theme is undefined on this line in dialog
https://github.com/piever/InteractBase.jl/blob/0a91fe6d605cafcb27b1b9c15d5fea568fb187da/src/input.jl#L113
Original report here:
JuliaGizmos/Interact.jl#414
To Reproduce
See JuliaGizmos/Interact.jl#414
Expected behavior
theme
should be defined.
Screenshots
See JuliaGizmos/Interact.jl#414
Version info (please complete the following information):
versioninfo()
and Pkg.status()
Before opening an issue
Pkg.build("InteractBase")
If widgets do not appear
Pkg.build("WebIO")
using WebIO; display(Node(:input, attributes = Dict("type" => "range")))
Now a stack=true
option is provided but maybe one could allow the user to pass a layout function (see notifications
for example).
Now that this is released and I have Flatten.jl I don't need AutoInteract.jl anymore... I'll be directly using this packages for making UIs, so I was wondering how my efforts to polish project layouts could be contributed back where possible.
There are lots of small details like labels overlapping sliders when widgets are smaller that I need to tweak for two projects over the next week. It would be good to do those fixes in a generally useful way, if you have any pointers on that!
I also have some nice formatting helpers from AutoInteract such as column layouts for large groups of widgets, and those could be good to include in the Interact ecosystem somehow.
I tried installing and running this at work but it fails at the build step with Failed to connect to cdn.bootcss.com port 443: Operation timed out
. Upon investigation it turns out this is because bootcss.com is hosted in China and the office firewall blocks connections to Chinese websites.
This surprised me—isn't bootstrap hosted at maxcdn.bootstrapcdn.com? What is bootcss.com and why is it in China?
when trying one of the docs examples
using InteractBase, InteractUIkit, WebIO
width, height = 700, 300
colors = ["black", "gray", "silver", "maroon", "red", "olive", "yellow", "green", "lime", "teal", "aqua", "navy", "blue", "purple", "fuchsia"]
color(i) = colors[i%length(colors)+1]
ui = @manipulate for nsamples in 1:200,
sample_step in slider(0.01:0.01:1.0, value=0.1, label="sample step"),
phase in slider(0:0.1:2pi, value=0.0, label="phase"),
radii in 0.1:0.1:60
cxs_unscaled = [i*sample_step + phase for i in 1:nsamples]
cys = sin.(cxs_unscaled) .* height/3 .+ height/2
cxs = cxs_unscaled .* width/4pi
dom"svg:svg[width=$width, height=$height]"(
(dom"svg:circle[cx=$(cxs[i]), cy=$(cys[i]), r=$radii, fill=$(color(i))]"()
for i in 1:nsamples)...
)
end
display(ui)
the result is that it runs without error, but there is no output. The widget does not materialize.
julia> versioninfo()
Julia Version 0.6.4
Commit 9d11f62bcb (2018-07-09 19:09 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin14.5.0)
CPU: Intel(R) Core(TM) i5-5250U CPU @ 1.60GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell MAX_THREADS=16)
LAPACK: libopenblas64_
LIBM: libopenlibm
LLVM: libLLVM-3.9.1 (ORCJIT, broadwell)
Yesterday I stumbled across a stange misbehaviour of sliders with Integer
ranges.
slider(5:10)
will not evaluate correctly, whereas slider(collect(5:10))
does.
The reason is that the slider method from Widgets, which adds the backend, will directly jump to the slider method, which generates the ui. (Thanks to @tkoolen and @stevengj who helped me understand the issue!)
To prevent this, I propose to add another method
slider(vals::AbstractRange{<:Integer}, args... ; kwargs...) = slider(collect(vals), args... ; kwargs...)
One might add a hint somewhere that calling the backend directly would need a collect
for Integer ranges.
Describe the bug
A clear and concise description of what the bug is.
Sliders do not accept arrays containing negative numbers larger than -21 when a value keyword is used.
I couldn't track down exactly where this is happening.
To Reproduce
Steps to reproduce the behavior.
julia> InteractBase.slider(collect(0.0:-1.0:-25.0), value=-10.0)
ERROR: BoundsError: attempt to access 26-element Array{String,1} at index [27]
Stacktrace:
[1] ./array.jl:731
[2] /home/raf/.julia/dev/InteractBase/src/slider.jl:68
[3] ./none:0
[4] /home/raf/.julia/dev/InteractBase/src/slider.jl:24
[5] ./simdloop.jl:0 [inlined]
[6] ./none:0
[7] /home/raf/.julia/dev/InteractBase/src/defaults.jl:12
[8] ./none:0
[9] none:0
Expected behavior
A clear and concise description of what you expected to happen.
Return a slider! As with InteractBase.slider(collect(0.0:-1.0:-20.0), value=-10.0)
or any positive numbers.
Interestingly this works if the first number in the array is larger than some distance from the minimum negative val:
julia> InteractBase.slider(collect(2.0:-1.0:-24.0), value=-10.0)
ERROR: BoundsError: attempt to access 27-element Array{String,1} at index [28]
Stacktrace:
[1] getindex(::Array{String,1}, ::Int64) at ./array.jl:731
[2] #slider#75(::String, ::String, ::Observables.Observable{Any}, ::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::NativeHTML, ::Base.OneTo{Int64}, ::Array{String,1}) at /home/raf/.julia/dev/InteractBase/src/slider.jl:68
[3] (::getfield(InteractBase, Symbol("#kw##slider")))(::NamedTuple{(:value,),Tuple{Observables.Observable{Any}}}, ::typeof(slider), ::NativeHTML, ::Base.OneTo{Int64}, ::Array{String,1}) at ./none:0
[4] #slider#67(::Float64, ::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::NativeHTML, ::Array{Float64,1}, ::Array{String,1}) at /home/raf/.julia/dev/InteractBase/src/slider.jl:24
[5] #slider at ./simdloop.jl:0 [inlined]
[6] (::getfield(InteractBase, Symbol("#kw##slider")))(::NamedTuple{(:value,),Tuple{Float64}}, ::typeof(slider), ::NativeHTML, ::Array{Float64,1}) at ./none:0
[7] #slider#170(::Base.Iterators.Pairs{Symbol,Float64,Tuple{Symbol},NamedTuple{(:value,),Tuple{Float64}}}, ::Function, ::Array{Float64,1}) at /home/raf/.julia/dev/InteractBase/src/defaults.jl:12
[8] (::getfield(InteractBase, Symbol("#kw##slider")))(::NamedTuple{(:value,),Tuple{Float64}}, ::typeof(slider), ::Array{Float64,1}) at ./none:0
[9] top-level scope at none:0
But:
julia> InteractBase.slider(collect(3.0:-1.0:-24.0), value=-10.0)
Widget{:slider,Float64}(OrderedCollections.OrderedDict{Symbol,Any}(:changes=>Observable{Int64} with 1 listeners. Value:
0,:index=>Observable{Any} with 2 listeners. Value:
1,:formatted_vals=>Observable{Any} with 1 listeners. Value:
...
Screenshots
If applicable, add screenshots to help explain your problem.
Version info (please complete the following information):
versioninfo()
and Pkg.status()
Julia Version 1.0.2
Commit d789231e99 (2018-11-08 20:11 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.0 (ORCJIT, skylake)
Environment:
JULIA_NUM_THREADS = 5
julia> Pkg.status()
Status ~/.julia/environments/v1.0/Project.toml
[f5f396d3] ApproxBayes v0.3.0
[c9ce4bd3] ArchGDAL v0.2.0
[bf4720bc] AssetRegistry v0.1.0
[6e4b80f9] BenchmarkTools v0.4.2
[ad839575] Blink v0.9.0
[70588ee8] CSSUtil v0.1.0
[159f3aea] Cairo v0.5.6
[a5dba43e] Cellular v0.0.0 [~/julia/Cellular
]
[5ae59095] Colors v0.9.5
[a8cc5b0e] Crayons v1.0.0
[a93c6f00] DataFrames v0.17.0
[ab62b9b5] DeepDiffs v1.1.0
[0c46a032] DifferentialEquations v5.3.1
[72d8b834] Dispersal v0.0.0 [~/julia/Dispersal
]
[31c24e10] Distributions v0.16.4
[6ffd65d2] DynamicEnergyBudgets v0.0.0 [~/julia/DynamicEnergyBudgets
]
[49426c49] FieldDefaults v0.0.1+ [~/julia/FieldDefaults
]
[bf96fef3] FieldMetadata v0.0.3+ [~/julia/FieldMetadata
]
[4c728ea3] Flatten v0.1.0+ [~/julia/Flatten
]
[4c0ca9eb] Gtk v0.16.4
[f67ccb44] HDF5 v0.11.0
[6218d12a] ImageMagick v0.7.1
[916415d5] Images v0.17.0
[c601a237] Interact v0.9.0
[d3863d7c] InteractBase v0.8.2+ [~/.julia/dev/InteractBase
]
[7981ab7d] InteractBulma v0.4.2
[033835bb] JLD2 v0.1.2
[2ee39098] LabelledArrays v0.4.0+ [~/.julia/dev/LabelledArrays
]
[23fbe1c1] Latexify v0.6.0
[e0eb800d] Microclimate v0.0.0 [~/julia/Microclimate
]
[2a8e4939] Mixers v0.1.0+ [~/julia/Mixers
]
[a975b10e] Mux v0.5.3
[85f8d34a] NCDatasets v0.6.0
[30363a11] NetCDF v0.7.2
[f7c12bf4] NicheMap v0.0.0 [~/julia/NicheMap
]
[510215fc] Observables v0.2.3
[6fe1bfb0] OffsetArrays v0.9.1
[5fb14364] OhMyREPL v0.4.1
[429524aa] Optim v0.17.2
[1dea7af3] OrdinaryDiffEq v4.21.1
[d96e819e] Parameters v0.10.3
[5e10c064] Photosynthesis v0.0.0 [~/julia/Photosynthesis
]
[48f930ff] PlotNested v0.0.0 [~/julia/PlotNested
]
[91a5bcdd] Plots v0.23.0
[c46f51b8] ProfileView v0.4.0
[061b77f0] REPLGamesBase v0.1.0 #master (https://github.com/ChristianKurz/REPLGamesBase.jl)
[ae029012] Requires v0.5.2
[295af30f] Revise v1.0.2+ [~/.julia/dev/Revise
]
[eac7fb6e] ReviseTest v0.0.0 [~/.julia/dev/ReviseTest
]
[1bc83da4] SafeTestsets v0.0.1
[6accb78c] SimpleRoots v0.0.0 [~/julia/SimpleRoots
]
[90137ffa] StaticArrays v0.10.2
[f3b207a7] StatsPlots v0.10.0
[eb3e9d2b] StructuralInheritance v0.2.4
[a759f4b9] TimerOutputs v0.4.0
[9d95f2ec] TypedTables v1.1.0
[ebadf6b4] UnicodeGraphics v0.0.1+ [~/julia/UnicodeGraphics
]
[1986cc42] Unitful v0.14.0+ [~/.julia/dev/Unitful
]
[2a06ce6d] UnitfulPlots v0.0.0 [~/julia/UnitfulPlots
]
[03de777c] UnitlessFlatten v0.0.1+ [~/julia/UnitlessFlatten
]
[0f1e0344] WebIO v0.7.0
[104b5d7c] WebSockets v1.2.0
[cc8bc4a8] Widgets v0.4.4
Before opening an issue
Pkg.build("InteractBase")
If widgets do not appear
Pkg.build("WebIO")
using WebIO; display(Node(:input, attributes = Dict("type" => "range")))
When I was trying Vertical Range Slider
, I wrote next code.
using Interact, Blink
win = Window();
ui = rangeslider(0:100; value=[30, 80], orientation="vertical");
body!(win, ui)
But, this Range Slider
is ... the smaller value is upper, the bigger value is below.
It is not the result I expected.
I found the option Direction
at NoUiSlider site.
But, it is not selectable with Widgets.rangeslider()
.
I suggest that direction
option is selectable.
When next change,
diff --git a/src/slider.jl b/src/slider.jl
index dbc44c2..778a476 100644
--- a/src/slider.jl
+++ b/src/slider.jl
@@ -82,13 +82,14 @@ Pass a vector to `value` with two values if you want to select a range.
"""
function rangeslider(theme::WidgetTheme, vals::AbstractUnitRange{<:Integer}, formatted_vals = format.(vals);
style = Dict(), label = nothing, value = medianelement(vals), orientation = "horizontal", readout = true,
- className = "is-primary")
+ className = "is-primary", direction = "ltr")
T = Observables.to_value(value) isa Vector ? Vector{eltype(vals)} : eltype(vals)
value isa AbstractObservable || (value = Observable{T}(value))
index = value
orientation = string(orientation)
+ direction = string(direction)
preprocess = T<:Vector ? js"unencoded.map(Math.round)" : js"Math.round(unencoded[0])"
scp = Scope(imports = vcat([nouislider_min_js, nouislider_min_css], libraries(theme)))
@@ -122,6 +123,7 @@ function rangeslider(theme::WidgetTheme, vals::AbstractUnitRange{<:Integer}, for
tooltips: $tooltips,
connect: $connect,
orientation: $orientation,
+ direction: $direction,
format: {
to: function ( value ) {
var ind = Math.round(value-($min));
We'll get the Range Slider
the bigger value is upper, smaller value is lower, with direction="rtl"
option.
using Interact, Blink
win = Window();
ui = rangeslider(0:100; value=[30, 80], orientation="vertical", direction="rtl");
body!(win, ui)
Ref is simple, but not good for modularity.
If in my package I have a strong preference of using Material design, then I'm going to do setbackend(Material())
.
But once you use something from my package anything you do next will also be of Material theme!!
To bypass this I'd have to do something like, first reach into backend[]
ref, save the current value, do setbackend, then setbackend with the saved value to leave it in a previous state.
If we used stacks, I could use a push!
and pop!
, and in the middle call some other package which may change the theme too.
The dictionary should be overloadable by the WidgetTheme
: this should simplify creating a new backend drastically. It should also allow to customize a theme using user css code or a more low level framework (e.g. Tachyons).
On v0.10.2,
julia> versioninfo()
Julia Version 1.1.1
Commit 55e36cc308 (2019-05-16 04:10 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Core(TM) i7-5820K CPU @ 3.30GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.1 (ORCJIT, haswell)
Environment:
JULIA_EDITOR = emacsclient
(ConfabEnv) pkg> build InteractBase
Building WebIO ───────→ `~/ConfabDepot/packages/WebIO/Rk8wc/deps/build.log`
Building Knockout ────→ `~/ConfabDepot/packages/Knockout/JE2Yq/deps/build.log`
Building InteractBase → `~/ConfabDepot/packages/InteractBase/l8cEC/deps/build.log`
┌ Error: Error building `InteractBase`:
│ % Total % Received % Xferd Average Speed Time Time Time Current
│ Dload Upload Total Spent Left Speed
100 664k 100 664k 0 0 2712k 0 --:--:-- --:--:-- --:--:-- 2712k
│ % Total % Received % Xferd Average Speed Time Time Time Current
│ Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
│ curl: (22) The requested URL returned error: 500 Internal Server Error
│ ERROR: LoadError: failed process: Process(`curl -g -L -f -o /home/cst-jean/ConfabDepot/packages/InteractBase/l8cEC/assets/prism.css https://www.gitcdn.xyz/repo/piever/InteractResources/v0.1.0/highlight/prism.css`, ProcessExited(22)) [22]
│ Stacktrace:
│ [1] error(::String, ::Base.Process, ::String, ::Int64, ::String) at ./error.jl:42
│ [2] pipeline_error at ./process.jl:785 [inlined]
│ [3] #run#515(::Bool, ::Function, ::Cmd) at ./process.jl:726
│ [4] run at ./process.jl:724 [inlined]
│ [5] download(::String, ::String) at ./download.jl:27
│ [6] top-level scope at /home/cst-jean/ConfabDepot/packages/InteractBase/l8cEC/deps/build.jl:18 [inlined]
│ [7] top-level scope at ./none:0
│ [8] include at ./boot.jl:326 [inlined]
│ [9] include_relative(::Module, ::String) at ./loading.jl:1038
│ [10] include(::Module, ::String) at ./sysimg.jl:29
│ [11] include(::String) at ./client.jl:403
│ [12] top-level scope at none:0
│ in expression starting at /home/cst-jean/ConfabDepot/packages/InteractBase/l8cEC/deps/build.jl:17
└ @ Pkg.Operations /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/Operations.jl:1075
Pasting the link in the browser gives me a 500 - internal server error.
I find the slider really useful for exploring data graphically. However, at present when using @manipulate for plots, the slider sometimes feels a bit laggy: If you click somewhere on the slider, then that particular index value is quickly evaluated, giving a rapid display.
But if you actually try to slide the slider, the only practical option is to slide rather slowly. A rapid slide at any point will lead to a freeze, followed by display of the plot for the final index value.
Here is an example using PyPlot:
using PyPlot, InteractBase
t = linspace(0,1,100) |>collect
x = linspace(-10,10,100) |>collect
f1 = figure(figsize=(10,2))
@manipulate for j in eachindex(t)
withfig(f1,clear=true) do
plot(x,sin.(t[j]*x))
end
end
where the difference should be seen between moving the slider slowly, dragging rapidly to the end, and clicking to the end. Perhaps this is something to do with PyPlot or my laptop graphics, but at present the slider can feel quite clunky even for modest slide rates. I am curious as to whether others have this experience, especially if it persists on better hardware.
Would it be possible to change the behavior so that if the slide rate is faster than "slow" (whatever is continuously frame rendered), then the slider just serves up the final value, much like clicking on the slider would do. This would feel a lot more responsive to work with.
Describe the bug
Using Slider with a default value of median feels unnatural for me. Would it be better to use first value as default?
To Reproduce
using @manipulate
Expected behavior
Slider value defaults to first value
using CSSUtil
loadbutton = filepicker()
hellobutton = button("Hello!")
goodbyebutton = button("Good bye!")
ui = vbox( # put things one on top of the other
loadbutton,
hbox( # put things one next to the other
pad(1em, hellobutton), # to allow some white space around the widget
pad(1em, goodbyebutton),
)
)
display(ui)
Hi! I get an error using dropdown menus when trying to execute the example code from the API reference:
using InteractBulma, WebIO
options = Observable(["a", "b", "c"])
wdg = dropdown(options)
This gives the following error message and stacktrace:
ERROR: Function InteractBase.dropdown was about to overflow: check the signature
Stacktrace:
[1] #dropdown#106(::Array{Any,1}, ::Function, ::InteractBulma.Bulma, ::Vararg{Any,N} where N) at /Users/lackner/.julia/v0.6/InteractBase/src/defaults.jl:10
[2] dropdown(::InteractBulma.Bulma, ::Observables.Observable{Array{String,1}}) at /Users/lackner/.julia/v0.6/InteractBase/src/defaults.jl:10
[3] #dropdown#106(::Array{Any,1}, ::Function, ::Observables.Observable{Array{String,1}}, ::Vararg{Observables.Observable{Array{String,1}},N} where N) at /Users/lackner/.julia/v0.6/InteractBase/src/defaults.jl:12
[4] dropdown(::Observables.Observable{Array{String,1}}) at /Users/lackner/.julia/v0.6/InteractBase/src/defaults.jl:10
[5] eval(::Module, ::Any) at ./boot.jl:235
button(style = "width: 100px;")
does not pass the style to the html widget, whereas other widgets do (e.g. slider
).
In particular think what's the best way to support togglebuttons from InteractBase.
This is an issue to discuss the design of a "recipe" system for GUIs. What is necessary is a small light dependency package such that each package can define complex widgets to simplify usage (for example. GLM may add a way to select variables from a table with a dropdown, a modelling package could allow choosing some parameters with sliders / togglebuttons etc.). This implies (unless we recommend some other solution like Requires.jl) having a minimal package that is sufficient to define these complex widgets and is 100% reliable and solid dependency, tentatively called UIRecipesBase.
widget
, input
, slider
, checkbox
, etc...)kwargs2vueprops
, props2string
...)macro dom_str
, Node
, Observable
, observe
... (though actually Observables is so lightweight that maybe it can be included in the dependencies)Widget
type? this is actually a bit tricky, as the Widget
type requires Node
and Scope
to type the fields, so it may be better to have a function that returns a Widget
type and this function would have a placeholder in UIRecipesBaseI'm not very fond of this option as all JuliaGizmos packages would have to depend and extend this thing, which seems somewhat awkward.
This is quite interesting, and would correspond to transforming all widgets into something that can be obtained as widget(type,...)
. We already have a function widget
that allows to access most widgets (colorpicker, date picker, input, etc... The action plan would be as follows:
slider
, dropdown
, textbox
etc... define dispatches for widget(::Val{:slider}, ...)
and then define slider(args....; kwargs...) = widget(::Val{:slider}, args..., kwargs...)
. This could be done by a macro:@recipe function slider(args...; kwargs...)
# write function body here
end
that defines the dispatch and the shorthand slider
. Though actually in InteractBase there's a place where it's very easy to define all of this, which is where I define the method without the first type argument (for the backend) for all widgets, so I could simply add it there.
placeholder
approach where we add a function node end
placeholder (that WebIO extends to return Node
) that users can use to create layout with flexboxes. Otherwise, we could add some placeholders for CSSUtil functions (hbox, vbox, hskip, vskip, hpad
, etc...)For this macro to work, the user would have to return a tuple of two elements: a node and an observable (or three elements if they want a primary scope) and then the macro would take care of defining the function that actually returns a widget object.
Defining type recipes would simply involve overloading widget
with a custom type.
I'm personally in favor of option 2, but happy to discuss alternatives.
cc: @shashi
It would be great if widgets supported Unitful.jl, so e.g. sliders can be time values. It might be in an addon package, but this issue is just a reminder to think about that when designing types and methods.
I ordered them as they appear on the export lists
datepicker, timepicker, colorpicker, spinbox
input, textarea, togglecontent
tabs, checkboxes, toggles, tabulator
cheers
In Interact slider()
produces an Interact.Slider
.
InteractNext just outputs WebIO.Scope for every widget. If this is replacing InteractNext, what is the plan here?
Not having separate types means post-processing of widgets is difficult. I have a package that makes widgets and an interface from anything you throw at it, and reapplies signals back to the data, to save me rebuilding the interface every time I change my models:
https://github.com/rafaqz/AutoInteract.jl
But to make the layout passable you have to separate checkboxes/toggles from sliders etc somehow. In Interact that's easy, in InteractNext (and maybe this package?) it doesn't seem possible.
Using vbox
to set the label is problematic for the downward arrow. Maybe even easier to put the label as placeholder?
Hi - I'm having an installation problem with InteractBase
...
julia> versioninfo()
Julia Version 0.6.4
Commit 9d11f62bcb (2018-07-09 19:09 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin14.5.0)
CPU: Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell MAX_THREADS=16)
LAPACK: libopenblas64_
LIBM: libopenlibm
LLVM: libLLVM-3.9.1 (ORCJIT, haswell)
julia> Pkg.add("InteractBase")
< stuff above >
INFO: Building InteractBase
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 664k 100 664k 0 0 3631k 0 --:--:-- --:--:-- --:--:-- 3631k
npm ERR! code EISDIR
npm ERR! errno -21
npm ERR! syscall read
npm ERR! EISDIR: illegal operation on a directory, read
< Failure notices below >
I can see in .julia/v0.6/InteractBase/deps/build.jl
the failure happens at
run(`$npm install -y`)
and the failure happens when I run that by hand.
I tried adding --verbose
to the command and it didn't shed much additional information.
julia> run(`$npm install --verbose`)
npm info it worked if it ends with ok
npm verb cli [ '/Users/lyon/.julia/v0.6/NodeJS/deps/bin/node-v8.10.0-darwin-x64/bin/node',
npm verb cli '/Users/lyon/.julia/v0.6/NodeJS/deps/bin/node-v8.10.0-darwin-x64/lib/node_modules/npm/bin/npm-cli.js',
npm verb cli 'install',
npm verb cli '--verbose' ]
npm info using [email protected]
npm info using [email protected]
npm verb config Skipping project config: /Users/lyon/.npmrc. (matches userconfig)
npm verb npm-session e2bcfb757c16565d
npm verb stack Error: EISDIR: illegal operation on a directory, read
npm verb cwd /Users/lyon/.julia/v0.6/InteractBase/deps
npm verb Darwin 17.6.0
npm verb argv "/Users/lyon/.julia/v0.6/NodeJS/deps/bin/node-v8.10.0-darwin-x64/bin/node" "/Users/lyon/.julia/v0.6/NodeJS/deps/bin/node-v8.10.0-darwin-x64/lib/node_modules/npm/bin/npm-cli.js" "install" "--verbose"
npm verb node v8.10.0
npm verb npm v5.6.0
npm ERR! code EISDIR
npm ERR! errno -21
npm ERR! syscall read
npm ERR! EISDIR: illegal operation on a directory, read
npm verb exit [ -21, true ]
EISDIR
seems to mean that it's trying to read a file that is actually a directory. I can't tell what it is trying to read.
Have you seen this before? I have a home-brew installed node
and npm
on my machine, but I don't think there's interference (for fun I tried using the same command with /usr/local/bin/npm
and I get the same error).
Thanks in advance for any ideas! -- Adam
Hi,
In Interact.jl, I would often use something like selection_slider(logspace(-2,2,100))
to create appropriate ranges of values for my sliders. Could we implement that here too?
Same as filepicker
, to be used when the app runs in Blink, with Electron.
Setting a PlotlyJS private variable on loading to embed the javascript in the html feels wrong, there should be a simpler way: maybe load the Plotly javascript in slap_design!
?
This package is very cool!
I have some minor naming suggestions:
CSSFramework
-> something like WidgetTheme
? Because things like Material are not just CSS frameworks, they require some JS etc.setbackend
-> settheme!
-- daisy chains nicely with the "theme" above.InteractBase
-- let's makes Interact.jl depend on this and have a sensible default theme. InteractNext would become MaterialTheme.jl maybe, and then BulmaTheme.jl etc.The rangeslider
widget is super-pretty!
You know what would be even prettier? Having it in many colors! It would be awesome if a keyword argument could let you specify a color for the slider! This teal-like color is really good but a choice would be even better!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.