version3_widget_migration.rst
322 lines
| 15.0 KiB
| text/x-rst
|
RstLexer
Jonathan Frederic
|
r20512 | Migrating Widgets to IPython 3 | ||
============================== | ||||
Jonathan Frederic
|
r20503 | Upgrading Notebooks | ||
------------------- | ||||
1. The first thing you'll notice when upgrading an IPython 2.0 widget | ||||
notebook to IPython 3.0 is the "Notebook converted" dialog. Click | ||||
"ok". | ||||
2. All of the widgets distributed with IPython have been renamed. The | ||||
"Widget" suffix was removed from the end of the class name. i.e. | ||||
``ButtonWidget`` is now ``Button``. | ||||
3. ``ContainerWidget`` was renamed to ``Box``. | ||||
Fermi paradox
|
r22909 | 4. ``PopupWidget`` was removed from IPython, because bootstrapjs was | ||
problematic (creates global variables, etc.). If you use the | ||||
Jonathan Frederic
|
r20503 | ``PopupWidget``, try using a ``Box`` widget instead. If your notebook | ||
can't live without the popup functionality, subclass the ``Box`` | ||||
widget (both in Python and JS) and use JQuery UI's ``draggable()`` | ||||
and ``resizable()`` methods to mimic the behavior. | ||||
5. ``add_class`` and ``remove_class`` were removed. More often than not | ||||
a new attribute exists on the widget that allows you to achieve the | ||||
same explicitly. i.e. the ``Button`` widget now has a | ||||
``button_style`` attribute which you can set to 'primary', 'success', | ||||
'info', 'warning', 'danger', or '' instead of using ``add_class`` to | ||||
add the bootstrap class. ``VBox`` and ``HBox`` classes (flexible | ||||
``Box`` subclasses) were added that allow you to avoid using | ||||
``add_class`` and ``remove_class`` to make flexible box model | ||||
layouts. As a last resort, if you can't find a built in attribute for | ||||
the class you want to use, a new ``_dom_classes`` list trait was | ||||
added, which combines ``add_class`` and ``remove_class`` into one | ||||
stateful list. | ||||
6. ``set_css`` and ``get_css`` were removed in favor of explicit style | ||||
attributes - ``visible``, ``width``, ``height``, ``padding``, | ||||
``margin``, ``color``, ``background_color``, ``border_color``, | ||||
``border_width``, ``border_radius``, ``border_style``, | ||||
``font_style``, ``font_weight``, ``font_size``, and ``font_family`` | ||||
are a few. If you can't find a trait to see the css attribute you | ||||
need, you can, in order of preference, (A) subclass to create your | ||||
own custom widget, (B) use CSS and the ``_dom_classes`` trait to set | ||||
``_dom_classes``, or (C) use the ``_css`` dictionary to set CSS | ||||
styling like ``set_css`` and ``get_css``. | ||||
Patrick Snape
|
r20634 | 7. For selection widgets, such as ``Dropdown``, the ``values`` argument | ||
has been renamed to ``options``. | ||||
Jonathan Frederic
|
r20503 | |||
Upgrading Custom Widgets | ||||
------------------------ | ||||
Javascript | ||||
~~~~~~~~~~ | ||||
1. If you are distributing your widget and decide to use the deferred | ||||
loading technique (preferred), you can remove all references to the | ||||
WidgetManager and the register model/view calls (see the Python | ||||
section below for more information). | ||||
2. In 2.0 require.js was used incorrectly, that has been fixed and now | ||||
loading works more like Python's import. Requiring | ||||
``widgets/js/widget`` doesn't import the ``WidgetManager`` class, | ||||
instead it imports a dictionary that exposes the classes within that | ||||
module: | ||||
.. code:: javascript | ||||
{ | ||||
'WidgetModel': WidgetModel, | ||||
'WidgetView': WidgetView, | ||||
'DOMWidgetView': DOMWidgetView, | ||||
'ViewList': ViewList, | ||||
} | ||||
If you decide to continue to use the widget registry (by registering | ||||
your widgets with the manager), you can import a dictionary with a | ||||
handle to the WidgetManager class by requiring | ||||
``widgets/js/manager``. Doing so will import: | ||||
.. code:: javascript | ||||
{'WidgetManager': WidgetManager} | ||||
3. Don't rely on the ``IPython`` namespace for anything. To inherit from | ||||
the DOMWidgetView, WidgetView, or WidgetModel, require | ||||
``widgets/js/widget`` as ``widget``. If you were inheriting from | ||||
DOMWidgetView, and the code looked like this: | ||||
.. code:: javascript | ||||
IPython.DOMWidgetView.extend({...}) | ||||
It would become this: | ||||
.. code:: javascript | ||||
widget.DOMWidgetView.extend({...}) | ||||
4. Custom models are encouraged. When possible, it's recommended to move | ||||
your code into a custom model, so actions are performed 1 time, | ||||
instead of N times where N is the number of displayed views. | ||||
Python | ||||
~~~~~~ | ||||
Generally, custom widget Python code can remain unchanged. If you | ||||
distribute your custom widget, you may be using ``display`` and | ||||
``Javascript`` to publish the widget's Javascript to the front-end. That | ||||
is no longer the recommended way of distributing widget Javascript. | ||||
Instead have the user install the Javascript to his/her nbextension | ||||
directory or their profile's static directory. Then use the new | ||||
``_view_module`` and ``_model_module`` traitlets in combination with | ||||
``_view_name`` and ``_model_name`` to instruct require.js on how to load | ||||
the widget's Javascript. The Javascript is then loaded when the widget | ||||
is used for the first time. | ||||
Details | ||||
------- | ||||
Asynchronous | ||||
~~~~~~~~~~~~ | ||||
In the IPython 2.x series the only way to register custom widget views | ||||
and models was to use the registry in the widget manager. Unfortunately, | ||||
Jonathan Frederic
|
r20545 | using this method made distributing and running custom widgets difficult. The widget | ||
Jonathan Frederic
|
r20503 | maintainer had to either use the rich display framework to push the | ||
widget's Javascript to the notebook or instruct the users to install the | ||||
Javascript by hand in a custom profile. With the first method, the | ||||
maintainer would have to be careful about when the Javascript was pushed | ||||
Jonathan Frederic
|
r20545 | to the front-end. If the Javascript was pushed on Python widget | ||
Jonathan Frederic
|
r20503 | ``import``, the widgets wouldn't work after page refresh. This is | ||
because refreshing the page does not restart the kernel, and the Python | ||||
``import`` statement only runs once in a given kernel instance (unless | ||||
you reload the Python modules, which isn't straight forward). This meant | ||||
the maintainer would have to have a separate ``push_js()`` method that | ||||
the user would have to call after importing the widget's Python code. | ||||
Our solution was to add support for loading widget views and models | ||||
using require.js paths. Thus the comm and widget frameworks now support | ||||
lazy loading. To do so, everything had to be converted to asynchronous | ||||
code. HTML5 promises are used to accomplish that | ||||
(`#6818 <https://github.com/ipython/ipython/pull/6818>`__, | ||||
`#6914 <https://github.com/ipython/ipython/pull/6914>`__). | ||||
Symmetry | ||||
~~~~~~~~ | ||||
In IPython 3.0, widgets can be instantiated from the front-end | ||||
(`#6664 <https://github.com/ipython/ipython/pull/6664>`__). On top of | ||||
this, a widget persistence API was added | ||||
(`#7163 <https://github.com/ipython/ipython/pull/7163>`__, | ||||
`#7227 <https://github.com/ipython/ipython/pull/7227>`__). With the | ||||
widget persistence API, you can persist your widget instances using | ||||
Javascript. This makes it easy to persist your widgets to your notebook | ||||
document (with a small amount of custom JS). By default, the widgets are | ||||
persisted to your web browsers local storage which makes them reappear | ||||
when your refresh the page. | ||||
Smaller Changes | ||||
~~~~~~~~~~~~~~~ | ||||
- Latex math is supported in widget ``description``\ s | ||||
(`#5937 <https://github.com/ipython/ipython/pull/5937>`__). | ||||
- Widgets can be display more than once within a single container | ||||
widget (`#5963 <https://github.com/ipython/ipython/pull/5963>`__, | ||||
`#6990 <https://github.com/ipython/ipython/pull/6990>`__). | ||||
- ``FloatRangeSlider`` and ``IntRangeSlider`` were added | ||||
(`#6050 <https://github.com/ipython/ipython/pull/6050>`__). | ||||
- "Widget" was removed from the ends of all of the widget class names | ||||
(`#6125 <https://github.com/ipython/ipython/pull/6125>`__). | ||||
- ``ContainerWidget`` was renamed to ``Box`` | ||||
(`#6125 <https://github.com/ipython/ipython/pull/6125>`__). | ||||
- ``HBox`` and ``VBox`` widgets were added | ||||
(`#6125 <https://github.com/ipython/ipython/pull/6125>`__). | ||||
- ``add\_class`` and ``remove\_class`` were removed in favor of a | ||||
``_dom_classes`` list | ||||
(`#6235 <https://github.com/ipython/ipython/pull/6235>`__). | ||||
- ``get\_css`` and ``set\_css`` were removed in favor of explicit | ||||
traits for widget styling | ||||
(`#6235 <https://github.com/ipython/ipython/pull/6235>`__). | ||||
- ``jslink`` and ``jsdlink`` were added | ||||
(`#6454 <https://github.com/ipython/ipython/pull/6454>`__, | ||||
`#7468 <https://github.com/ipython/ipython/pull/7468>`__). | ||||
- An ``Output`` widget was added, which allows you to ``print`` and | ||||
``display`` within widgets | ||||
(`#6670 <https://github.com/ipython/ipython/pull/6670>`__). | ||||
- ``PopupWidget`` was removed | ||||
(`#7341 <https://github.com/ipython/ipython/pull/7341>`__). | ||||
- A visual cue was added for widgets with 'dead' comms | ||||
(`#7227 <https://github.com/ipython/ipython/pull/7227>`__). | ||||
- A ``SelectMultiple`` widget was added (a ``Select`` widget that | ||||
allows multiple things to be selected at once) | ||||
(`#6890 <https://github.com/ipython/ipython/pull/6890>`__). | ||||
- A class was added to help manage children views | ||||
(`#6990 <https://github.com/ipython/ipython/pull/6990>`__). | ||||
- A warning was added that shows on widget import because it's expected | ||||
that the API will change again by IPython 4.0. This warning can be | ||||
luzpaz
|
r24084 | suppressed (`#7107 <https://github.com/ipython/ipython/pull/7107>`__, | ||
Jonathan Frederic
|
r20503 | `#7200 <https://github.com/ipython/ipython/pull/7200>`__, | ||
`#7201 <https://github.com/ipython/ipython/pull/7201>`__, | ||||
`#7204 <https://github.com/ipython/ipython/pull/7204>`__). | ||||
Comm and Widget PR Index | ||||
------------------------ | ||||
Jonathan Frederic
|
r20514 | Here is a chronological list of PRs affecting the widget and comm frameworks for IPython 3.0. Note that later PRs may revert changes | ||
Thomas Kluyver
|
r20515 | made in earlier PRs: | ||
- Add placeholder attribute to text widgets | ||||
Jonathan Frederic
|
r20503 | `#5652 <https://github.com/ipython/ipython/pull/5652>`__ | ||
Thomas Kluyver
|
r20515 | - Add latex support in widget labels, | ||
Jonathan Frederic
|
r20503 | `#5937 <https://github.com/ipython/ipython/pull/5937>`__ | ||
Thomas Kluyver
|
r20515 | - Allow widgets to display more than once within container widgets. | ||
Jonathan Frederic
|
r20503 | `#5963 <https://github.com/ipython/ipython/pull/5963>`__ | ||
Thomas Kluyver
|
r20515 | - use require.js, | ||
Jonathan Frederic
|
r20503 | `#5980 <https://github.com/ipython/ipython/pull/5980>`__ | ||
Thomas Kluyver
|
r20515 | - Range widgets | ||
Jonathan Frederic
|
r20503 | `#6050 <https://github.com/ipython/ipython/pull/6050>`__ | ||
Thomas Kluyver
|
r20515 | - Interact on\_demand option | ||
Jonathan Frederic
|
r20503 | `#6051 <https://github.com/ipython/ipython/pull/6051>`__ | ||
Thomas Kluyver
|
r20515 | - Allow text input on slider widgets | ||
Jonathan Frederic
|
r20503 | `#6106 <https://github.com/ipython/ipython/pull/6106>`__ | ||
Thomas Kluyver
|
r20515 | - support binary buffers in comm messages | ||
Jonathan Frederic
|
r20503 | `#6110 <https://github.com/ipython/ipython/pull/6110>`__ | ||
Thomas Kluyver
|
r20515 | - Embrace the flexible box model in the widgets | ||
Jonathan Frederic
|
r20503 | `#6125 <https://github.com/ipython/ipython/pull/6125>`__ | ||
Thomas Kluyver
|
r20515 | - Widget trait serialization | ||
Jonathan Frederic
|
r20503 | `#6128 <https://github.com/ipython/ipython/pull/6128>`__ | ||
Thomas Kluyver
|
r20515 | - Make Container widgets take children as the first positional | ||
Jonathan Frederic
|
r20503 | argument `#6153 <https://github.com/ipython/ipython/pull/6153>`__ | ||
Thomas Kluyver
|
r20515 | - once-displayed | ||
Jonathan Frederic
|
r20503 | `#6168 <https://github.com/ipython/ipython/pull/6168>`__ | ||
Thomas Kluyver
|
r20515 | - Validate slider value, when limits change | ||
Jonathan Frederic
|
r20503 | `#6171 <https://github.com/ipython/ipython/pull/6171>`__ | ||
Thomas Kluyver
|
r20515 | - Unregistering comms in Comm Manager | ||
Jonathan Frederic
|
r20503 | `#6216 <https://github.com/ipython/ipython/pull/6216>`__ | ||
Thomas Kluyver
|
r20515 | - Add EventfulList and EventfulDict trait types. | ||
Jonathan Frederic
|
r20503 | `#6228 <https://github.com/ipython/ipython/pull/6228>`__ | ||
Thomas Kluyver
|
r20515 | - Remove add/remove\_class and set/get\_css. | ||
Jonathan Frederic
|
r20503 | `#6235 <https://github.com/ipython/ipython/pull/6235>`__ | ||
Thomas Kluyver
|
r20515 | - avoid unregistering widget model twice | ||
Jonathan Frederic
|
r20503 | `#6250 <https://github.com/ipython/ipython/pull/6250>`__ | ||
Thomas Kluyver
|
r20515 | - Widget property lock should compare json states, not python states | ||
Jonathan Frederic
|
r20503 | `#6332 <https://github.com/ipython/ipython/pull/6332>`__ | ||
Thomas Kluyver
|
r20515 | - Strip the IPY\_MODEL\_ prefix from widget IDs before referencing | ||
Jonathan Frederic
|
r20503 | them. `#6377 <https://github.com/ipython/ipython/pull/6377>`__ | ||
Thomas Kluyver
|
r20515 | - "event" is not defined error in Firefox | ||
Jonathan Frederic
|
r20503 | `#6437 <https://github.com/ipython/ipython/pull/6437>`__ | ||
Thomas Kluyver
|
r20515 | - Javascript link | ||
Jonathan Frederic
|
r20503 | `#6454 <https://github.com/ipython/ipython/pull/6454>`__ | ||
Thomas Kluyver
|
r20515 | - Bulk update of widget attributes | ||
Jonathan Frederic
|
r20503 | `#6463 <https://github.com/ipython/ipython/pull/6463>`__ | ||
Thomas Kluyver
|
r20515 | - Creating a widget registry on the Python side. | ||
Jonathan Frederic
|
r20503 | `#6493 <https://github.com/ipython/ipython/pull/6493>`__ | ||
Thomas Kluyver
|
r20515 | - Allow widget views to be loaded from require modules | ||
Jonathan Frederic
|
r20503 | `#6494 <https://github.com/ipython/ipython/pull/6494>`__ | ||
Thomas Kluyver
|
r20515 | - Fix Issue #6530 | ||
Jonathan Frederic
|
r20503 | `#6532 <https://github.com/ipython/ipython/pull/6532>`__ | ||
Thomas Kluyver
|
r20515 | - Make comm manager (mostly) independent of InteractiveShell | ||
Jonathan Frederic
|
r20503 | `#6540 <https://github.com/ipython/ipython/pull/6540>`__ | ||
Thomas Kluyver
|
r20515 | - Add semantic classes to top-level containers for single widgets | ||
Jonathan Frederic
|
r20503 | `#6609 <https://github.com/ipython/ipython/pull/6609>`__ | ||
Thomas Kluyver
|
r20515 | - Selection Widgets: forcing 'value' to be in 'values' | ||
Jonathan Frederic
|
r20503 | `#6617 <https://github.com/ipython/ipython/pull/6617>`__ | ||
Thomas Kluyver
|
r20515 | - Allow widgets to be constructed from Javascript | ||
Jonathan Frederic
|
r20503 | `#6664 <https://github.com/ipython/ipython/pull/6664>`__ | ||
Thomas Kluyver
|
r20515 | - Output widget | ||
Jonathan Frederic
|
r20503 | `#6670 <https://github.com/ipython/ipython/pull/6670>`__ | ||
Thomas Kluyver
|
r20515 | - Minor change in widgets.less to fix alignment issue | ||
Jonathan Frederic
|
r20503 | `#6681 <https://github.com/ipython/ipython/pull/6681>`__ | ||
Thomas Kluyver
|
r20515 | - Make Selection widgets respect values order. | ||
Jonathan Frederic
|
r20503 | `#6747 <https://github.com/ipython/ipython/pull/6747>`__ | ||
Thomas Kluyver
|
r20515 | - Widget persistence API | ||
Jonathan Frederic
|
r20503 | `#6789 <https://github.com/ipython/ipython/pull/6789>`__ | ||
Thomas Kluyver
|
r20515 | - Add promises to the widget framework. | ||
Jonathan Frederic
|
r20503 | `#6818 <https://github.com/ipython/ipython/pull/6818>`__ | ||
Thomas Kluyver
|
r20515 | - SelectMultiple widget | ||
Jonathan Frederic
|
r20503 | `#6890 <https://github.com/ipython/ipython/pull/6890>`__ | ||
Thomas Kluyver
|
r20515 | - Tooltip on toggle button | ||
Jonathan Frederic
|
r20503 | `#6923 <https://github.com/ipython/ipython/pull/6923>`__ | ||
Thomas Kluyver
|
r20515 | - Allow empty text box \*while typing\* for numeric widgets | ||
Jonathan Frederic
|
r20503 | `#6943 <https://github.com/ipython/ipython/pull/6943>`__ | ||
Thomas Kluyver
|
r20515 | - Ignore failure of widget MathJax typesetting | ||
Jonathan Frederic
|
r20503 | `#6948 <https://github.com/ipython/ipython/pull/6948>`__ | ||
Thomas Kluyver
|
r20515 | - Refactor the do\_diff and manual child view lists into a separate | ||
Jonathan Frederic
|
r20503 | ViewList object | ||
`#6990 <https://github.com/ipython/ipython/pull/6990>`__ | ||||
Thomas Kluyver
|
r20515 | - Add warning to widget namespace import. | ||
Jonathan Frederic
|
r20503 | `#7107 <https://github.com/ipython/ipython/pull/7107>`__ | ||
Thomas Kluyver
|
r20515 | - lazy load widgets | ||
Jonathan Frederic
|
r20503 | `#7120 <https://github.com/ipython/ipython/pull/7120>`__ | ||
Thomas Kluyver
|
r20515 | - Fix padding of widgets. | ||
Jonathan Frederic
|
r20503 | `#7139 <https://github.com/ipython/ipython/pull/7139>`__ | ||
Thomas Kluyver
|
r20515 | - Persist widgets across page refresh | ||
Jonathan Frederic
|
r20503 | `#7163 <https://github.com/ipython/ipython/pull/7163>`__ | ||
Thomas Kluyver
|
r20515 | - Make the widget experimental error a real python warning | ||
Jonathan Frederic
|
r20503 | `#7200 <https://github.com/ipython/ipython/pull/7200>`__ | ||
Thomas Kluyver
|
r20515 | - Make the widget error message shorter and more understandable. | ||
Jonathan Frederic
|
r20503 | `#7201 <https://github.com/ipython/ipython/pull/7201>`__ | ||
Thomas Kluyver
|
r20515 | - Make the widget warning brief and easy to filter | ||
Jonathan Frederic
|
r20503 | `#7204 <https://github.com/ipython/ipython/pull/7204>`__ | ||
Thomas Kluyver
|
r20515 | - Add visual cue for widgets with dead comms | ||
Jonathan Frederic
|
r20503 | `#7227 <https://github.com/ipython/ipython/pull/7227>`__ | ||
Thomas Kluyver
|
r20515 | - Widget values as positional arguments | ||
Jonathan Frederic
|
r20503 | `#7260 <https://github.com/ipython/ipython/pull/7260>`__ | ||
Thomas Kluyver
|
r20515 | - Remove the popup widget | ||
Jonathan Frederic
|
r20503 | `#7341 <https://github.com/ipython/ipython/pull/7341>`__ | ||
Thomas Kluyver
|
r20515 | - document and validate link, dlink | ||
Jonathan Frederic
|
r20503 | `#7468 <https://github.com/ipython/ipython/pull/7468>`__ | ||
Thomas Kluyver
|
r20515 | - Document interact 5637 | ||
Jonathan Frederic
|
r20503 | `#7525 <https://github.com/ipython/ipython/pull/7525>`__ | ||
Thomas Kluyver
|
r20515 | - Update some broken examples of using widgets | ||
Jonathan Frederic
|
r20503 | `#7547 <https://github.com/ipython/ipython/pull/7547>`__ | ||
Thomas Kluyver
|
r20515 | - Use Output widget with Interact | ||
Jonathan Frederic
|
r20503 | `#7554 <https://github.com/ipython/ipython/pull/7554>`__ | ||
Thomas Kluyver
|
r20515 | - don't send empty execute\_result messages | ||
Jonathan Frederic
|
r20503 | `#7560 <https://github.com/ipython/ipython/pull/7560>`__ | ||
Thomas Kluyver
|
r20515 | - Validation on the python side | ||
Jonathan Frederic
|
r20503 | `#7602 <https://github.com/ipython/ipython/pull/7602>`__ | ||
Thomas Kluyver
|
r20515 | - only show prompt overlay if there's a prompt | ||
Jonathan Frederic
|
r20503 | `#7661 <https://github.com/ipython/ipython/pull/7661>`__ | ||
Thomas Kluyver
|
r20515 | - Allow predictate to be used for comparison in selection widgets | ||
Jonathan Frederic
|
r20503 | `#7674 <https://github.com/ipython/ipython/pull/7674>`__ | ||
Thomas Kluyver
|
r20515 | - Fix widget view persistence. | ||
Jonathan Frederic
|
r20503 | `#7680 <https://github.com/ipython/ipython/pull/7680>`__ | ||
Thomas Kluyver
|
r20515 | - Revert "Use Output widget with Interact" | ||
Jonathan Frederic
|
r20503 | `#7703 <https://github.com/ipython/ipython/pull/7703>`__ | ||