<jupyter_start><jupyter_text>Low Level Widget Tutorial  How do they fit into the picture? One of the goals of the Jupyter Notebook is to minimize the “distance” the user is from their data.  This means allowing the user to quickly view and manipulate the data.   | ![](images/inputoutput.PNG)                                                                           | ![](images/widgets.PNG)                                                                                                                      ||-------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|| Before the widgets, this was just the segmentation of code and results from executing those segments. | Widgets further decrease the distance between the user and their data by allowing UI interactions to directly manipulate data in the kernel. |  How? Jupyter interactive widgets are interactive elements, think sliders, text boxes, buttons, that have representations both in the kernel (place where code is executed) and the front-end (the Notebook web interface).  To do this, a clean, well-abstracted communication layer must exist.  Comms This is where Jupyter notebook “comms” come into play.  The comm API is a symmetric, asynchronous, fire and forget style messaging API.  It allows the programmer to send JSON-able blobs between the front-end and the back-end.  The comm API hides the complexity of the webserver, ZMQ, and websockets. ![](images/transport.svg)  Synchronized state Using comms, the widget base layer is designed to keep state in sync.  In the kernel, a Widget instance exists.  This Widget instance has a corresponding WidgetModel instance in the front-end.  The Widget and WidgetModel store the same state.  The widget framework ensures both models are kept in sync with each other.  If the WidgetModel is changed in the front-end, the Widget receives the same change in the kernel.  Vice versa, if the Widget in the kernel is changed, the WidgetModel in the front-end receives the same change.  There is no single source of truth, both models have the same precedence.  Although a notebook has the notion of cells, neither Widget or WidgetModel are bound to any single cell. ![](images/state_sync.svg)  Models and Views In order for the user to interact with widgets on a cell by cell basis, the WidgetModels are represented by WidgetViews.  Any single WidgetView is bound to a single cell.  Multiple WidgetViews can be linked to a single WidgetModel.  This is how you can redisplay the same Widget multiple times and it still works.  To accomplish this, the widget framework uses Backbone.js.  In a traditional MVC framework, the WidgetModel is the (M)odel, and the WidgetView is both the (V)iew and (C)ontroller. Meaning that, the views both display the state of the model and manipulate it.  Think about a slider control, it both displays the value and allows the user to change the value by dragging the slide handle.<jupyter_code>from ipywidgets import *
from IPython.display import display
w = IntSlider()
display(w, w)
display(w)<jupyter_output><empty_output><jupyter_text>![](images/assoc.svg)  Code execution The user code required to display a simple FloatSlider widget is:```pythonfrom ipywidgets import FloatSliderfrom IPython.display import displayslider = FloatSlider()display(slider)```In order to understand how a widget is displayed, one must understand how code is executed in the Notebook.  Execution begins in the code cell.  A user event triggers the code cell to send an evaluate code message to the kernel, containing all of the code in the code cell.  This message is given a GUID, which the front-end associates to the code cell, and remembers it (**important**). ![](images/execute.svg) Once that message is received by the kernel, the kernel immediately sends the front-end an “I’m busy” status message.  The kernel then proceeds to execute the code. ![](images/busy.svg)  Model construction When a Widget is constructed in the kernel, the first thing that happens is that a comm is constructed and associated with the widget.  When the comm is constructed, it is given a GUID (globally unique identifier).  A comm-open message is sent to the front-end, with metadata stating that the comm is a widget comm and what the corresponding WidgetModel class is.   ![](images/widgetcomm.svg) The WidgetModel class is specified by module and name.  Require.js is then used to asynchronously load the WidgetModel class. The message triggers a comm to be created in the front-end with the same GUID as the back-end.  Then, the new comm gets passed into the WidgetManager in the front-end, which creates an instance of the WidgetModel class, linked to the comm.  Both the Widget and WidgetModel repurpose the comm GUID as their own. ![](images/widgetcomm2.svg) Asynchronously, the kernel sends an initial state push, containing the initial state of the Widget, to the front-end, immediately after the comm-open message.  This state message may or may not be received by the time the WidgetModel is constructed.  Regardless, the message is cached and gets processed once the WidgetModel has been constructed.  The initial state push is what causes the WidgetModel in the front-end to become in sync with the Widget in the kernel. ![](images/state.svg)  Displaying a view After the Widget has been constructed, it can be displayed.  Calling `display(widgetinstance)` causes a specially named repr method in the widget to run.  This method sends a message to the front-end that tells the front-end to construct and display a widget view.  The message is in response to the original code execution message, and the original message’s GUID is stored in the new message’s header.  When the front-end receives the message, it uses the original message’s GUID to determine what cell the new view should belong to.  Then, the view is created, using the WidgetView class specified in the WidgetModel’s state.  The same require.js method is used to load the view class.  Once the class is loaded, an instance of it is constructed, displayed in the right cell, and registers listeners for changes of the model. ![](images/display.svg)  Widget skeleton<jupyter_code>%%javascript
this.model.get('count');
this.model.set('count', 999);
this.touch();

/////////////////////////////////

this.colorpicker = document.createElement('input');
this.colorpicker.setAttribute('type', 'color');
this.el.appendChild(this.colorpicker);<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09182598223694115, 'fraction_numerical': 0.0006021375884389584, 'mean_word_length': 3.2754182754182755, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '33051', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 1530, 'n_tokens_neox': 1507, 'n_words': 909, 'path': 'docs/source/examples/Widget Low Level.ipynb', 'repo_name': 'afonit/ipywidgets', 'size': '6643'}