Last active
April 22, 2021 08:22
-
-
Save bvdmitri/5523d1c7ffa13b5a54e0235dd037c4b0 to your computer and use it in GitHub Desktop.
Throttled slider for Pluto.jl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export ThrottledSlider | |
struct ThrottledSlider | |
range :: AbstractRange | |
default :: Number | |
throttle :: Number | |
show_value :: Bool | |
end | |
"""A Slider on the given `range`. | |
## Examples | |
`@bind x ThrottledSlider(1:10)` | |
`@bind x ThrottledSlider(0.00 : 0.01 : 0.30)` | |
`@bind x ThrottledSlider(1:10; default=8, show_value=true)` | |
`@bind x ThrottledSlider(1:10; default=8, show_value=true, throttle = 50)` | |
""" | |
function ThrottledSlider(range::AbstractRange; default=missing, show_value=true, throttle = 32) | |
return ThrottledSlider(range, (default === missing) ? first(range) : default, throttle, show_value) | |
end | |
function Base.show(io::IO, ::MIME"text/html", slider::ThrottledSlider) | |
sid = string(join(rand('a':'z', 10))); | |
id = string(join(rand('a':'z', 10))); | |
print(io, "<span id='$(sid)'></span>") | |
print(io, """<input id='$(id)' | |
type="range" | |
min="$(first(slider.range))" | |
step="$(step(slider.range))" | |
max="$(last(slider.range))" | |
value="$(slider.default)" | |
>""") | |
if slider.show_value | |
print(io, """<output>$(typeof(slider.default) <: Float64 ? round(slider.default, digits = 3) : slider.default)</output>""") | |
end | |
script = """ | |
<script> | |
(function() { | |
const sp = document.getElementById('$(sid)') | |
const el = document.getElementById('$(id)') | |
const _ = window._ | |
const c = window.console | |
let value = null | |
const dispatchEvent = () => { | |
sp.value = value | |
sp.dispatchEvent(new CustomEvent("input", {})) | |
$(slider.show_value ? "el.nextElementSibling.value = Number.isInteger(value) ? value : value.toPrecision(2)" : "") | |
} | |
const debouncedEvent = _.throttle(dispatchEvent, $(slider.throttle)) | |
el.addEventListener("input", (event) => { | |
value = event.target.valueAsNumber; | |
debouncedEvent(event); | |
event.stopImmediatePropagation(); | |
event.preventDefault(); | |
}) | |
}()) | |
</script> | |
""" | |
print(io, script) | |
end | |
Base.get(slider::ThrottledSlider) = slider.default |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment