JuliaPluto / PlutoUI.jl

https://featured.plutojl.org/basic/plutoui.jl
The Unlicense
299 stars 54 forks source link

Can we format the string shown by the Slider? #245

Open FelixBenning opened 1 year ago

FelixBenning commented 1 year ago

I want to create a slider on a log scale. Of course I would also want the Slider to show the correct value then. Other use cases are Scientific Notation, etc.

Can we format the string shown? For example, scientific notation and number of digits. posted by @putianyi889 in https://github.com/JuliaPluto/PlutoUI.jl/issues/11#issuecomment-1132651993

The current Implementation looks like this:

<script>
    const input_el = currentScript.previousElementSibling
    const output_el = currentScript.nextElementSibling
    const displays = $(string.(slider.values))

    input_el.addEventListener("input", () => {
        output_el.value = displays[input_el.valueAsNumber - 1]
    })
</script>
<output style='
    font-family: system-ui;
        font-size: 15px;
        margin-left: 3px;
        transform: translateY(-4px);
        display: inline-block;
'>$(string(slider.default))</output>

Transform Approach

<script>
    const input_el = currentScript.previousElementSibling
    const output_el = currentScript.nextElementSibling
    const displays = $(string.(slider.values))

        // allow for custom transform (if slider.show_value is simply true, default to identity)
    const transform = $(slider.show_value isa String ? slider.show_value : "(val) => val")

    input_el.addEventListener("input", () => {
        output_el.value = transform(displays[input_el.valueAsNumber - 1])
    })
</script>
<output style='
    font-family: system-ui;
        font-size: 15px;
        margin-left: 3px;
        transform: translateY(-4px);
        display: inline-block;
'>$(string(slider.default))</output>

So one could do the following:


@bind x Slider(1:10, show_value="(x) => Math.exp(x)")
FelixBenning commented 1 year ago

Maybe this transform approach is a bad idea. Another idea could be, to let the Slider look for the nextElementSibling but do not define the Sibling itself. Or more generally look for a specific document.getElementById($(outputID)) and pass it the value.

Custom Output Elements

<script>
    const input_el = currentScript.previousElementSibling
    const output_el = document.getElementById($(slider.show_value))
    const displays = $(string.(slider.values))

    input_el.addEventListener("input", () => {
        output_el.value = displays[input_el.valueAsNumber - 1]
    })
</script>

Usage would be

@htl("$(@bind x Slider(1:10, show_value="my-output")) $(PlutoUI.outputs.log("my-output"))")

Then this output element could define a setter for its value and choose its own display style. So you could have a set of input elements seperated from a set of output elements and mix and match

Pro

Con

FelixBenning commented 1 year ago

I just realized that my use case is achieved by Slider(exp.(1:10), show_value) So only the formatting use case remains

fonsp commented 1 year ago

Good idea to make this customizable! What about an API like this?

Slider(1:10; show_value=true) # default

Slider(1:10; show_value=(x -> @sprintf("%.2f kN", 5))) # custom formatter

Allowing you to customize the position of the output is something we should look into in a separate issue perhaps?