GithubHelp home page GithubHelp logo

juliapluto / plutoui.jl Goto Github PK

View Code? Open in Web Editor NEW
300.0 7.0 54.0 3.64 MB

Home Page: https://featured.plutojl.org/basic/plutoui.jl

License: The Unlicense

Julia 98.67% CSS 0.63% JavaScript 0.70%
pluto-notebooks julia interactive written-in-pluto javascript

plutoui.jl's Introduction

PlutoUI.jl

Documentation Run with binder

A small package with interactive elements to be used in Pluto.jl.

@bind x PlutoUI.Slider(1:100)
repeat("Hello ", x)

For documentation, read the PlutoUI.jl featured notebook.

plutoui.jl's People

Contributors

barucden avatar c42f avatar ctrekker avatar disberd avatar dralletje avatar ericphanson avatar feanor12 avatar firionus avatar fonsp avatar genericallyterrible avatar ghaetinger avatar iboss-ptk avatar icweaver avatar j-fu avatar jerlich avatar jin-park avatar jveres avatar karlwessel avatar loganwalls avatar lucaferranti avatar lukavdplas avatar masonprotter avatar michaelhatherly avatar mossr avatar mthelm85 avatar pangoraw avatar pankgeorg avatar shashankp avatar wilsongoode avatar yha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

plutoui.jl's Issues

Feature request: Date and time widget

A date and time selection widget that returns a DateTime would be nice.

I can already get a string of the date and time with

@bind dateandtime html"""<input type="datetime-local">"""

which i can convert to DateTime with

parse(DateTime, date)

It would be nice to have a ready made widget that does this all in one step.

Mismatch when default is out of range

Hi, small issue which confused me for a while, is that the value shown might not match the value of the bound variable.

Here's a basic reproduction in Pluto.jl:

begin
	using Pkg
	Pkg.activate(mktempdir())
end
begin
	Pkg.add(["PlutoUI",])
	using PlutoUI
end
@bind someval Slider(0.01:0.001:1, default=0.002, show_value=true)

Note that someval now shows 0.002 near the Slider. Also note that 0.002 is outside of the provided slider range.

someval

Note that someval is actual equal to 0.01 (i.e. it really is clamped to the slider range).

Thanks,

Roman

Clock limit

I like the Clock feature a lot. But is there a possibility to set an end point? Now, when I let the clock run, it will eventually error, given that it tries to go on even when there are no more data to plot. Looping back would be an alternative.

Animation example

Nice work on fonsp/Pluto.jl#17, design looks nice and works like a charm.

How would you recommend doing animations? One can now drive animations from javascript by doing something along the lines of:

@bind t html"""
<div id='time'>
	<input id='speed' type='range' min='-1' max='1'/>
	<label id='time' for='speed'/>
	<script>
		const time  = document.querySelector("div#time")
		const label = document.querySelector("label#time")
		const speed = document.querySelector("input#speed")
		let t = 0;
		setInterval(dt, 10);
		function dt()
		{
      	   t = t + speed.valueAsNumber * 0.01;
		   time.value = t;
		   label.innerHTML = t.toFixed(2);
		   time.dispatchEvent(new CustomEvent("input"))
		}
	</script>
</div>
"""

and then using t to animate other cells.

@fonsp is there a better / simpler way you'd recommend?

I also tried driving an animation from julia, using @async or @spawn to increment a global time variable in the background. The time variable does get updated, but the asynchronous updates do not trigger reactive evaluation of dependent cells. Is there is a way to trigger reactive eval from asynchronous blocks of code?

Radio button not binding values on Windows 10, Julia 1.5.2

The code @bind temp Radio(["neat", "drop"], default="neat") correctly creates radio buttons in the UI, and defaults to "neat". However, any click of the radio buttons leads to the bound value temp being set to nothing.

I double-checked the javascript and on cell initialization do get this error:

"CellOutput.js:200 TypeError: Cannot read property 'querySelector' of undefined"

This line being suspect: const form = this.querySelector('#jqeekved'). On JavaScript's strict mode, isn't a global invocation of this supposed to be undefined? As this is a top-level script block, it to mean would make sense if the script fails to execute for this reason; replacing this with window may solve the issue.

I disabled my popup blocker. Let me know if you need me to check anything else. Thanks!

Slider2D

Like a slider, but for tracking scroll in x & y direction

@bind x, y Slider2D(1:50, 1:100)

to create a canvas with given ranges

#9 (comment)

[Feature request] Slider with custom Vector (instead of range)

How can one create a slider that is indexed onto an array but that binds to the values of the array?

E.g., say I have an array of values with a custom type, e.g.,

using Unitful: m
my_array = [0.0, 1.0, 3.0, 5.0, 10.0, 30.0, 50.0]m

I would like a slider to pick one of these values.

Ideally, it'd be great to be able to create that slider with just

Slider(my_array)

Make Select return arbitrary values instead of strings

I would like to use the Select element to select different matrices with different names in the select combobox. I want the name to be displayed in the combobox and the matrix bound to the variable I @bind the Select to. So

@bind M Select([M1 => "Diagonal Matrix", M2 => "Symmetric Matrix"])

This currently does not work since Select binds the keys (which currently have to be strings) of the passed dict to the variable and displays the values.

Can we just change Select to support arbitrary keys instead just Strings?

Instability in return type of PlutoUI.Slider

issue description:
The return type of PlutoUI.Slider is Int64 in few instances and Float64 in few instances

image-1603965448996

expected behavior:
the return type must be stable

remarks
right now, the possible workaround is using Float64(var) or Int64(var) where ever required. But, it is not ideal to explicitly type Float64 everywhere.

Add radio buttons

Hi Fons,

I attempted to add radio buttons but I don't believe it's possible to get the value without some JavaScript. Is this correct? Here's what I have so far:

struct Radio
    options::Array{Pair{AbstractString,Any},1}
    groupname::AbstractString
    checked::AbstractString
end
Radio(options::Array{<:AbstractString,1}, groupname::AbstractString, checked::AbstractString="") = Radio([o => o for o in options], groupname, checked)

function show(io::IO, ::MIME"text/html", radio::Radio)
    for o in radio.options
        println(io, """<input type="radio" id="$(htmlesc(o.first))" name="$(radio.groupname)" value="$(htmlesc(o.first))" $(htmlesc(radio.checked) == htmlesc(o.first) ? "checked" : "")>""")
        println(io, """<label for=$(htmlesc(o.first))>""")
        if showable(MIME("text/html"), o.second)
            show(io, MIME("text/html"), o.second)
        else
            print(io, o.second)
        end
        print(io, """</option>""")
        println(io, """</label><br>""")
    end
end

get(radio::Radio) = first(radio.options).first

This produces the following:

radio_button_test

As you can see, the value of the checked button is not bound to the variable. Do you know the best way to make this work? If you can point me in the right direction I'll keep chipping away at it. : )

Paste screenshot from clipboard

A feature that I love in Jupyter is the ability to take a screenshot of the task at hand (especially in a school setting, as is the case for me), and paste it directly into the notebook, so that you have it right there as you solve the task. This is a fast and easy fix to the problem of having to tab back and forth from the problem to the notebook.

When I tried to paste a picture from my clipboard into a pluto notebook, nothing happened. I don't know if I am doing it wrong, but I am unable to find a way to paste a picture, so I guess it is not a feature yet. Would it be possible to make this a thing in Pluto?

I am imagining that the data for the screenshot could be put into an array of the type that holds RGB data and printed directly, as demonstrated by Grant Sanderson in some detail in the "Computational thinking" series. This would also maintain the ideal of reproducibility, and "everything needed is right there in the notebook".

Are there others that would like this feature?
Would something like this be hard to implement?

Feature request: playback controls

Bumping from #1 (comment)

Basically the clock widget, but bound to a slider-like range of times. It'd be extra nice to provide an enumerate-like interface returning both the index and value of the range:

@bind (i, val) Playback(range(0, 1, length=100); rate = 30) # playback at 30 fps

Grabbing and reloading values from/to `html"<input>"`s

Feature idea (soft request)...

Having made a big table of parameter values for my notebook, I found myself wanting to capture ("grab") and reload ("load") the values. This provides a means for a notebook user to save the parameters for a later analysis, or send them to other users or the developer to share their experience.

Being a neophyte JS programmer, I hacked it into existence, It looks like this:

image

The section of the notebook that makes this is here

This is all ok, but it sure would be easier if there were PlutoUI features to attach an id to an input, build a table or layout of inputs, and provide a function to grab/load inputs based on the ids. Bonus points on integrating this with Julia code somehow... that was a bridge too far for me. The string syntax was also a bit of a hack, json would be nicer, but that would be easier on the Julia side.

Counters

It would be nice to provide a way of creating and using counters within notebooks. (These maybe most commonly interpolated into Markdown).

The basic idea is that there is a global dictionary of counters, and they are incremented as they appear in the notebook, and not as they get evaluated. Then we can use these to number sections, exercises ;), figures, or LaTeX snippets, or footnotes.

Section 2.1 of the LaTeX doc https://www.ntg.nl/doc/lamport/latex2e.pdf describes how to create and use counters in LaTeX. This is a good starting point!

Webcam capture

A widget that shows a little preview of the (webcam) camera and sends an image to the bound variable when you click it.

Rewrite to use Hyperscript.jl

Because it makes this package more stable because we will never have HTML errors. The other option is to use a HTML parser in our testing to verify the output, but using Hyperscript is much nicer.

Also it's a nice package to work with!

Show value of slider next to it

Is it possible to show the value of the slider in the same cell in Pluto? I think not from

Separate definition and reference

If you put a bond and a reference to the same variable together, it will keep evaluating in a loop.

So do not write

md""\"$(@bind r html"<input type='range'>")  $(r^2)""\"

Instead, create two cells:

md""\"$(@bind r html"<input type='range'>")""\"
r^2

but maybe I missed something? I would like something like

begin
	r_slider = @bind r html"<input type='range'>"
	md"""
	r = $r $r_slider
	"""
end

Slideshow + frame animation

A widget (does not @bind anything) that takes an array of objects and displays them in a slideshow:

Slideshow([md"# Hey!", image_1, image_2])

with extra options to auto-advance (setting it to delay = 1/30 will make it an animation :)).

For example:

functions = [sin, cos, tan]
map(plot, functions)

gives an array of three plots, but it would be cool of you could do

Slideshow(map(plot, functions))

and click through the plots using buttons.

These should also work in the exported HTML.

Sizing of the slideshow box might be tricky

Shorthand to make a cell sticky or fixed

I would like to see a shorthand to make some cell fixed or sticky, this will be very convenient for cells that have boxes or input fields of parameters that affect many cells.

Up to this moment my solution is making a cell that contains custom styles, and searching the id of the target cell in the DOM to make it sticky or fixed.

Filepicker can not reload a file

Sometimes I need to reload a configuration file from my disk. An intuitive approach is to pick the same file. It would be nice to refresh the value automatically.

TagBot trigger issue

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.

Default value for date widget not recognized

Using the Date widget with a default value like

begin
using Dates
using PlutoUI
@bind date PlutoUI.DateField(Date(2020, 1,1))
end

does not display the default value on startup.

This is because html expects the date format to be Y-mm-dd but PlutoUI uses Y-m-d.

The same goes for TimeField:

@bind date2 PlutoUI.TimeField(Time(1,1,1))

does not work while

@bind date2 PlutoUI.TimeField(Time(10,10,10))

does.

Also DateField and TimeField are not exported.

I can provide a PR to fix this later.

Button should return number of clicks?

Right now the Button always returns the same: the label of the button (String). This is fine, you can use the button to "trigger reactivity" just by referencing the bound variable somewhere:

https://github.com/fonsp/PlutoUI.jl/blob/v0.6.1/src/Builtins.jl#L64-L86

But if you only want to do something after the button is clicked, you need to write that logic yourself:

begin
    clicked_ref = Ref(false)
	@bind click Button("Do it!")
end
begin
	if clicked_ref[]
		something()
	end
    clicked_ref[] = true
end

Instead we could have the bound value be the number of times it was clicked:

@bind click Button("Do it!")
if click > 0
	something()
end

Text selection wrapper

An object that you can put something else inside (like an markdown text) that sends the currently selected text to the bound variable.

A Pluto version warning

Use like:

PlutoUI.PlutoVersionWarning(v"0.12.1")

will output nothing when the version is higher than 0.12.1, and output a big warning when it is not.

I already wrote this, it just needs to be polished up and put into this package

html"""
<script>
const warning = html`
<h2 style="color: #800">Oopsie! You need to update Pluto to the latest version</h2>
<p>Close Pluto, go to the REPL, and type:
<pre><code>julia> import Pkg
julia> Pkg.update("Pluto")
</code></pre>
`

// this needs some work: in Pluto 0.12.0 you get Pluto's version number as:
// window.version_info_pluto

// in Pluto <0.12 it is:
// window.pluto_version

// I THINK but you should check
// https://github.com/fonsp/Pluto.jl/blob/master/CONTRIBUTING.md#how-to-run-specific-version-of-pluto

// for this code, I just wanted to warn for <0.12.1, but you should make it more general
const super_old = window.version_info == null || window.version_info.pluto == null
if(super_old) {
	return warning
}
const version_str = window.version_info.pluto.substring(1)
const numbers = version_str.split(".").map(Number)
console.log(numbers)

if(numbers[0] > 0 || numbers[1] > 12 || numbers[2] > 1) {
	
} else {
	return warning
}

</script>

"""

Syntax to set width of number fields

In practice generally we don't want a number field larger than 2-3 digits, so I think it would be interesting to add the possibility to setup the width of the number fields to avoid using CSS. By example you can setup the width of all number fields in the whole notebook with pluto-output input[type=number] { width: ... ; }, or for some specific cell using it id instead of the pluto-output tag.

Canvas to draw on

This can be based on the rectangle drawing demo in the Interactivity sample notebook inside Pluto.

Speed might not be great yet, but this should improve a lot once Pluto uses MsgPack instead of JSON.

Clock's Stop button not working in Pluto v0.12.3

Running the PlutoUI demo, you can see the Stop buttons for both Clock() examples are not working.

This problem may be related to this Pluto issue

I am seeing the same issue in my custom HTML & JS code, which contains buttons that don't seem to get their click events.

Platform: macOS, Julia 1.5.2, latest release Chrome & Safari both

Mouse coordinates wrapper

An object that you can put something else inside (like an image or a plot) that sends the mouse coordinates on click to the bound variable.

Memoized evaluation for sliders

Most often sliders are used to evaluate something at different values. Can we implement a macro/function that takes some function f(t) to be evaluated, and a range.

Internally, it

  1. binds a variable t to a slider on the range range
  2. Creates an empty array of size range and type as the return type of f
  3. Creates a callable MemoizedFunction object, which has the slider, the function and t as objects

When the MemoizedFunction object is called, it evaluates f(t) and stores it in the array. At the next call, it checks whether f(t) had been evaled and returns that value, else evaluates and returns.

It also returns the slider.

I'm not sure whether this idea will work with Pluto's reactivity, but I'd be super happy if we could make it work!

Usage of Button?

Hi,

can you please tell me how to use the Button? It always seems to have the value given as argument "label" to the constructor.

Thank you!, z.

Hide all codes and make the UI feel real

I had so much fun playing with PlutoUI, thank the developers.
In order to make the Web UI feel real, I made some widgets here
https://gist.github.com/GiggleLiu/aff2af66a896cf8a05310b8ba66f540f

Two issues are addressed in this gist to make the UI real

  1. hide all code editing features,
  2. run a piece of code if and only if a "run" button is clicked.

However, both are not yet perfectly resolved.

  1. I don't know how to completely eliminate spaces of empty cells. It revives every time when there is a new output, or a cell being selected., which makes the UI looks cheap.

plutoui-issue

  1. In order to prevent the code block running repeatedly, I have to use some ugly design in the code. I wish there can be a "real" button that deterministically control the execution of a code block.

Possible bug in Select?

I have the impression that with the following PR a bug has been introduced into the Select function.

https://github.com/fonsp/PlutoUI.jl/pull/15/files

function show(io::IO, ::MIME"text/html", select::Select)
    withtag(io, :select) do
        for o in select.options

# this print opens an `option` tag and fills its value property, but not its content 
            print(io, """<option value="$(htmlesc(o.first))"$(select.default === o.first ? " selected" : "")>""")
# here, a new `option` tag is created, with content (but without default selection). This results in duplicate entries in the selector.
            withtag(io, :option, :value=>o.first) do
                if showable(MIME"text/html"(), o.second)
                    show(io, MIME"text/html"(), o.second)
                else
                    print(io, o.second)
                end
            end
            print(io, "</option>")
        end
    end
end

Removing the withtag(io, :option, :value=>o.first) do line (and the corresponding end) fixes this issue for me.

Input Labels

It would be nice to pass a label to the input so that you don't need to use a different cell to display the value. Maybe as an optional keyword arg?

Something like:

@bind balloons Slider(1:100; label = "Number of Balloons")

?

Real-time printing using `with_terminal`

Not sure if this is being discussed elsewhere, but I would be important to have with_terminal (or a macro version) that could print out in real-time (instead of all at once after execution).

E.g.

with_terminal() do
    for i in 1:10
        println(i)
        sleep(0.1)
    end
end

We'd want this to print 1 2 etc. every 10th of a second and not all at once.

Missing dependency Random in Project.toml

When using PlutoUI, I get the following warning message:

julia> Pluto.run(1234)
Go to http://localhost:1234/ to start writing ~ have fun!

Press Ctrl+C in this terminal to stop Pluto

      From worker 2:    ┌ Warning: Package PlutoUI does not have Random in its dependencies:
      From worker 2:    │ - If you have PlutoUI checked out for development and have
      From worker 2:    │   added Random as a dependency but haven't updated your primary
      From worker 2:    │   environment's manifest file, try `Pkg.resolve()`.
      From worker 2:    │ - Otherwise you may need to report an issue with PlutoUI
      From worker 2:    └ Loading Random into PlutoUI from project dependency, future warnings for PlutoUI are suppressed.

The issue seems to be that Random is used in Builtins.jl, but not defined as a dependency in the Project.toml.

Debouncer

I wrote a debouncer! Let's put it into PlutoUI

begin
	struct Debounced
		x::Any
		wait::Real
	end
	debounced(x, wait=1000) = Debounced(x, wait)
	
	function Base.show(io::IO, m::MIME"text/html", d::Debounced)
		id = String(rand('a':'z',10))
		
		print(io, "<span id=$(id)></span>")
		show(io, m, d.x)
		
		print(io, """
			<script>
			const span = document.querySelector('#$(id)')
			const el = span.nextElementSibling
			
			const _ = window._
			
			el.addEventListener("input", (e) => {
				e.stopPropagation()
			})
			
			var value = null
			
			const debounced_setter = _.debounce(() => {
				span.value = value
				span.dispatchEvent(new CustomEvent("input", {}))
			}, $(d.wait))
			
			const dothing = async () => {
				for(const value_promise of Generators.input(el)) {
					value = await value_promise
					debounced_setter()
				}
			}
			dothing()

			
			</script>
			""")
	end
	
	Base.get(d::Debounced) = try
		Base.get(d.x)
	catch
		missing
	end
end

[Feature Request] Range or multi-handle Slider

Would it be possible to have "range" sliders that bind two values (or a tuple?) and looks like

PS: I thought I saw this issue before but could not find it again. Please close if this is a duplicate.

`@animate` API

It would be nice to say

@animate fps=20 for n=1:100, m=1:100
     <expr>
end

And have Pluto

  • run and record the repr of expr for all values of n, then send them all to the UI.
  • show a play/pause button with a repeat toggle and play the animation by running over all the repr(expr)s it has stored.
  • allow you to pause the animation and use sliders to tweak n and m.

Select for elements other than AbstractStrings

It would be awesome if one could use Select on arbitrary key => value pairs:

names = ["Hamburg", "Berlin", "Magdeburg"]
populations = [1_900_000, 3_700_000, 240_000]

@bind city Select(pairs(names))

@show populations[k]
name = Dict(:hr => "Human Resources",
            :x => "Research & Development")
manager = Dict(:hr => "Jane Doe",
               :x => "Max Mustermann")

@bind division Select(name) # pairs(name) === name

@show manager[division]

I assume allowing Int and Symbol should cover most use cases.

Implementation Proposal

I don't know JavaScript, so I would try to manage the state mostly in Julia. One could split the internal representation of value => representation into seperate arrays, so that the only exchange with the frontend would be index::Int corresponding to the selection (and a handle to the s::Select object itself, maybe its hash(s)::UInt64). set_bond would then have to be adjusted to ask the Select object, what the actual new value should be.

The benefit of this approach is that we don't need to deal with conversions/representations of Julia types from and to JavaScript.

A big downside of this that this would introduce a new global Dict{UInt64,Select} object of sorts.

Table of contents / Automatic enumeration of Markdown headers?

Hi there,

I use Jupyter (specifically Jupyter Lab) to make project reports every 3 months or so. As a result, the reports get quite large. I structure them in detail with markdown headers and sections. Jupyter provides an excellent extension, called simply "table of contents" that does two things:

  1. Enables a table of contents sidebar that is clickable and brings you to the markdown header that you clicked (very useful)
  2. Optionally enumerates all markdown headers with 1., 1.1, 1.2.1, etc. (nice to have, but not as crucial as the above).

Example:

image

Is this possible to be done in Pluto.jl? Is it planned?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.