Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 45900
Kernel: Python 3
import vcsn import ipywidgets as widgets from IPython.display import display

Widgets wrapper

The ipywidgets package provides a good interface to create widgets wrappers in Python, and interact between them.

def on_update(disp, change): try: svg = vcsn.B.expression(change['owner'].value).automaton().SVG() disp.value = ''' <p>{} was {}, now is {}.</p> {} '''.format(change['name'], change['old'], change['new'], svg) except Exception as e: disp.value = vcsn.ipython.formatError(e) # input widget input1 = widgets.Text(value='\e', description='expr:') # output widget disp1 = widgets.HTML() # what happens when input changes input1.observe(lambda change: on_update(disp1, change), 'value') display(input1, disp1)

Some widgets can be used for layout.

label = widgets.Label(value='Expression:') input2 = widgets.Text(value='\e') disp2 = widgets.HTML() input2.observe(lambda change: on_update(disp2, change), 'value') layout = widgets.HBox(children=[label, input2, disp2]) display(layout)

Some CSS properties can even be set.

Beware: widgets are unique, so editing them after displaying will change what has been displayed previously. Don't display them twice, or you will duplicate them!

label.padding = '5px 5px 0 0' label.border = 'solid 3px red' display(input2)

Custom widget

Sometimes you may want to create a custom Widget, with a custom Javascript.

Python back-end

In the Python back-end, we will define a class and some attributes so that Jupyter can link it with the Javascript front-end.

import traitlets class MyCustomWidget(widgets.DOMWidget): # The name of the view between Javascript and Python # tag(sync=True) means it will be the same in Python and the notebook _view_name = traitlets.Unicode('MyCustomView').tag(sync=True) # The name of the RequireJS module _view_module = traitlets.Unicode('MyCustomModule').tag(sync=True) # Some attribute that I want to interact with value = traitlets.CUnicode('').tag(sync=True)

Javascript front-end

In the Javascript front end we define what we need, and create a module to match our Python.

%%javascript // What I need in my module require.config({paths: {d3: "http://d3js.org/d3.v3.min"}}); // Just in case Jupyter has a old version require.undef('MyCustomModule'); // Define a new RequireJS module whose name matches Python define('MyCustomModule', ['jupyter-js-widgets', 'd3'], function(widgets, d3) { var MyCustomView = widgets.DOMWidgetView.extend({ // Called once, on rendering the widget render: function() { //this.value_changed(); this.$el.text("I am a custom widget with d3 v" + d3.version); this.model.on('change:value', this.value_changed, this); }, value_changed: function() { this.$el.text(this.model.get('value')); }, }); return { MyCustomView: MyCustomView }; } );
<IPython.core.display.Javascript object>

Now we just have to instanciate it in Python.

my_widget = MyCustomWidget() display(my_widget)

Now the Python is linked to the Javascript:

my_widget.value = '3'

We can even link it with other widgets:

def my_widget_update(to, change): to.value = change['owner'].value mw = MyCustomWidget() tw = widgets.Text() mw.observe(lambda change: my_widget_update(tw, change), 'value') tw.observe(lambda change: my_widget_update(mw, change), 'value') display(mw, tw)
from time import sleep for i in range(11): sleep(1) mw.value = i

A note about Javascript

Javascript can be executed by using the magic %%javascript or the Javascript display:

%%javascript alert(1)
<IPython.core.display.Javascript object>
from IPython.display import Javascript display(Javascript('''alert(2)'''))
<IPython.core.display.Javascript object>
from IPython.display import display_javascript display_javascript('''alert(3)''', raw=True)
MIME type unknown not supported

The current node output is designated by element:

%%javascript element.append("<h1 style='color: purple;'>This output is inside the node.</h1>");
<IPython.core.display.Javascript object>