Show More
@@ -1,319 +1,319 b'' | |||
|
1 | 1 | Migrating Widgets to IPython 3 |
|
2 | 2 | ============================== |
|
3 | 3 | |
|
4 | 4 | Upgrading Notebooks |
|
5 | 5 | ------------------- |
|
6 | 6 | |
|
7 | 7 | 1. The first thing you'll notice when upgrading an IPython 2.0 widget |
|
8 | 8 | notebook to IPython 3.0 is the "Notebook converted" dialog. Click |
|
9 | 9 | "ok". |
|
10 | 10 | 2. All of the widgets distributed with IPython have been renamed. The |
|
11 | 11 | "Widget" suffix was removed from the end of the class name. i.e. |
|
12 | 12 | ``ButtonWidget`` is now ``Button``. |
|
13 | 13 | 3. ``ContainerWidget`` was renamed to ``Box``. |
|
14 | 14 | 4. ``PopupWidget`` was removed from IPython. If you use the |
|
15 | 15 | ``PopupWidget``, try using a ``Box`` widget instead. If your notebook |
|
16 | 16 | can't live without the popup functionality, subclass the ``Box`` |
|
17 | 17 | widget (both in Python and JS) and use JQuery UI's ``draggable()`` |
|
18 | 18 | and ``resizable()`` methods to mimic the behavior. |
|
19 | 19 | 5. ``add_class`` and ``remove_class`` were removed. More often than not |
|
20 | 20 | a new attribute exists on the widget that allows you to achieve the |
|
21 | 21 | same explicitly. i.e. the ``Button`` widget now has a |
|
22 | 22 | ``button_style`` attribute which you can set to 'primary', 'success', |
|
23 | 23 | 'info', 'warning', 'danger', or '' instead of using ``add_class`` to |
|
24 | 24 | add the bootstrap class. ``VBox`` and ``HBox`` classes (flexible |
|
25 | 25 | ``Box`` subclasses) were added that allow you to avoid using |
|
26 | 26 | ``add_class`` and ``remove_class`` to make flexible box model |
|
27 | 27 | layouts. As a last resort, if you can't find a built in attribute for |
|
28 | 28 | the class you want to use, a new ``_dom_classes`` list trait was |
|
29 | 29 | added, which combines ``add_class`` and ``remove_class`` into one |
|
30 | 30 | stateful list. |
|
31 | 31 | 6. ``set_css`` and ``get_css`` were removed in favor of explicit style |
|
32 | 32 | attributes - ``visible``, ``width``, ``height``, ``padding``, |
|
33 | 33 | ``margin``, ``color``, ``background_color``, ``border_color``, |
|
34 | 34 | ``border_width``, ``border_radius``, ``border_style``, |
|
35 | 35 | ``font_style``, ``font_weight``, ``font_size``, and ``font_family`` |
|
36 | 36 | are a few. If you can't find a trait to see the css attribute you |
|
37 | 37 | need, you can, in order of preference, (A) subclass to create your |
|
38 | 38 | own custom widget, (B) use CSS and the ``_dom_classes`` trait to set |
|
39 | 39 | ``_dom_classes``, or (C) use the ``_css`` dictionary to set CSS |
|
40 | 40 | styling like ``set_css`` and ``get_css``. |
|
41 | 41 | |
|
42 | 42 | Upgrading Custom Widgets |
|
43 | 43 | ------------------------ |
|
44 | 44 | |
|
45 | 45 | Javascript |
|
46 | 46 | ~~~~~~~~~~ |
|
47 | 47 | |
|
48 | 48 | 1. If you are distributing your widget and decide to use the deferred |
|
49 | 49 | loading technique (preferred), you can remove all references to the |
|
50 | 50 | WidgetManager and the register model/view calls (see the Python |
|
51 | 51 | section below for more information). |
|
52 | 52 | 2. In 2.0 require.js was used incorrectly, that has been fixed and now |
|
53 | 53 | loading works more like Python's import. Requiring |
|
54 | 54 | ``widgets/js/widget`` doesn't import the ``WidgetManager`` class, |
|
55 | 55 | instead it imports a dictionary that exposes the classes within that |
|
56 | 56 | module: |
|
57 | 57 | |
|
58 | 58 | .. code:: javascript |
|
59 | 59 | |
|
60 | 60 | { |
|
61 | 61 | 'WidgetModel': WidgetModel, |
|
62 | 62 | 'WidgetView': WidgetView, |
|
63 | 63 | 'DOMWidgetView': DOMWidgetView, |
|
64 | 64 | 'ViewList': ViewList, |
|
65 | 65 | } |
|
66 | 66 | |
|
67 | 67 | If you decide to continue to use the widget registry (by registering |
|
68 | 68 | your widgets with the manager), you can import a dictionary with a |
|
69 | 69 | handle to the WidgetManager class by requiring |
|
70 | 70 | ``widgets/js/manager``. Doing so will import: |
|
71 | 71 | |
|
72 | 72 | .. code:: javascript |
|
73 | 73 | |
|
74 | 74 | {'WidgetManager': WidgetManager} |
|
75 | 75 | |
|
76 | 76 | 3. Don't rely on the ``IPython`` namespace for anything. To inherit from |
|
77 | 77 | the DOMWidgetView, WidgetView, or WidgetModel, require |
|
78 | 78 | ``widgets/js/widget`` as ``widget``. If you were inheriting from |
|
79 | 79 | DOMWidgetView, and the code looked like this: |
|
80 | 80 | |
|
81 | 81 | .. code:: javascript |
|
82 | 82 | |
|
83 | 83 | IPython.DOMWidgetView.extend({...}) |
|
84 | 84 | |
|
85 | 85 | It would become this: |
|
86 | 86 | |
|
87 | 87 | .. code:: javascript |
|
88 | 88 | |
|
89 | 89 | widget.DOMWidgetView.extend({...}) |
|
90 | 90 | |
|
91 | 91 | 4. Custom models are encouraged. When possible, it's recommended to move |
|
92 | 92 | your code into a custom model, so actions are performed 1 time, |
|
93 | 93 | instead of N times where N is the number of displayed views. |
|
94 | 94 | |
|
95 | 95 | Python |
|
96 | 96 | ~~~~~~ |
|
97 | 97 | |
|
98 | 98 | Generally, custom widget Python code can remain unchanged. If you |
|
99 | 99 | distribute your custom widget, you may be using ``display`` and |
|
100 | 100 | ``Javascript`` to publish the widget's Javascript to the front-end. That |
|
101 | 101 | is no longer the recommended way of distributing widget Javascript. |
|
102 | 102 | Instead have the user install the Javascript to his/her nbextension |
|
103 | 103 | directory or their profile's static directory. Then use the new |
|
104 | 104 | ``_view_module`` and ``_model_module`` traitlets in combination with |
|
105 | 105 | ``_view_name`` and ``_model_name`` to instruct require.js on how to load |
|
106 | 106 | the widget's Javascript. The Javascript is then loaded when the widget |
|
107 | 107 | is used for the first time. |
|
108 | 108 | |
|
109 | 109 | Details |
|
110 | 110 | ------- |
|
111 | 111 | |
|
112 | 112 | Asynchronous |
|
113 | 113 | ~~~~~~~~~~~~ |
|
114 | 114 | |
|
115 | 115 | In the IPython 2.x series the only way to register custom widget views |
|
116 | 116 | and models was to use the registry in the widget manager. Unfortunately, |
|
117 |
using this method made |
|
|
117 | using this method made distributing and running custom widgets difficult. The widget | |
|
118 | 118 | maintainer had to either use the rich display framework to push the |
|
119 | 119 | widget's Javascript to the notebook or instruct the users to install the |
|
120 | 120 | Javascript by hand in a custom profile. With the first method, the |
|
121 | 121 | maintainer would have to be careful about when the Javascript was pushed |
|
122 | to the font-end. If the Javascript was pushed on Python widget | |
|
122 | to the front-end. If the Javascript was pushed on Python widget | |
|
123 | 123 | ``import``, the widgets wouldn't work after page refresh. This is |
|
124 | 124 | because refreshing the page does not restart the kernel, and the Python |
|
125 | 125 | ``import`` statement only runs once in a given kernel instance (unless |
|
126 | 126 | you reload the Python modules, which isn't straight forward). This meant |
|
127 | 127 | the maintainer would have to have a separate ``push_js()`` method that |
|
128 | 128 | the user would have to call after importing the widget's Python code. |
|
129 | 129 | |
|
130 | 130 | Our solution was to add support for loading widget views and models |
|
131 | 131 | using require.js paths. Thus the comm and widget frameworks now support |
|
132 | 132 | lazy loading. To do so, everything had to be converted to asynchronous |
|
133 | 133 | code. HTML5 promises are used to accomplish that |
|
134 | 134 | (`#6818 <https://github.com/ipython/ipython/pull/6818>`__, |
|
135 | 135 | `#6914 <https://github.com/ipython/ipython/pull/6914>`__). |
|
136 | 136 | |
|
137 | 137 | Symmetry |
|
138 | 138 | ~~~~~~~~ |
|
139 | 139 | |
|
140 | 140 | In IPython 3.0, widgets can be instantiated from the front-end |
|
141 | 141 | (`#6664 <https://github.com/ipython/ipython/pull/6664>`__). On top of |
|
142 | 142 | this, a widget persistence API was added |
|
143 | 143 | (`#7163 <https://github.com/ipython/ipython/pull/7163>`__, |
|
144 | 144 | `#7227 <https://github.com/ipython/ipython/pull/7227>`__). With the |
|
145 | 145 | widget persistence API, you can persist your widget instances using |
|
146 | 146 | Javascript. This makes it easy to persist your widgets to your notebook |
|
147 | 147 | document (with a small amount of custom JS). By default, the widgets are |
|
148 | 148 | persisted to your web browsers local storage which makes them reappear |
|
149 | 149 | when your refresh the page. |
|
150 | 150 | |
|
151 | 151 | Smaller Changes |
|
152 | 152 | ~~~~~~~~~~~~~~~ |
|
153 | 153 | |
|
154 | 154 | - Latex math is supported in widget ``description``\ s |
|
155 | 155 | (`#5937 <https://github.com/ipython/ipython/pull/5937>`__). |
|
156 | 156 | - Widgets can be display more than once within a single container |
|
157 | 157 | widget (`#5963 <https://github.com/ipython/ipython/pull/5963>`__, |
|
158 | 158 | `#6990 <https://github.com/ipython/ipython/pull/6990>`__). |
|
159 | 159 | - ``FloatRangeSlider`` and ``IntRangeSlider`` were added |
|
160 | 160 | (`#6050 <https://github.com/ipython/ipython/pull/6050>`__). |
|
161 | 161 | - "Widget" was removed from the ends of all of the widget class names |
|
162 | 162 | (`#6125 <https://github.com/ipython/ipython/pull/6125>`__). |
|
163 | 163 | - ``ContainerWidget`` was renamed to ``Box`` |
|
164 | 164 | (`#6125 <https://github.com/ipython/ipython/pull/6125>`__). |
|
165 | 165 | - ``HBox`` and ``VBox`` widgets were added |
|
166 | 166 | (`#6125 <https://github.com/ipython/ipython/pull/6125>`__). |
|
167 | 167 | - ``add\_class`` and ``remove\_class`` were removed in favor of a |
|
168 | 168 | ``_dom_classes`` list |
|
169 | 169 | (`#6235 <https://github.com/ipython/ipython/pull/6235>`__). |
|
170 | 170 | - ``get\_css`` and ``set\_css`` were removed in favor of explicit |
|
171 | 171 | traits for widget styling |
|
172 | 172 | (`#6235 <https://github.com/ipython/ipython/pull/6235>`__). |
|
173 | 173 | - ``jslink`` and ``jsdlink`` were added |
|
174 | 174 | (`#6454 <https://github.com/ipython/ipython/pull/6454>`__, |
|
175 | 175 | `#7468 <https://github.com/ipython/ipython/pull/7468>`__). |
|
176 | 176 | - An ``Output`` widget was added, which allows you to ``print`` and |
|
177 | 177 | ``display`` within widgets |
|
178 | 178 | (`#6670 <https://github.com/ipython/ipython/pull/6670>`__). |
|
179 | 179 | - ``PopupWidget`` was removed |
|
180 | 180 | (`#7341 <https://github.com/ipython/ipython/pull/7341>`__). |
|
181 | 181 | - A visual cue was added for widgets with 'dead' comms |
|
182 | 182 | (`#7227 <https://github.com/ipython/ipython/pull/7227>`__). |
|
183 | 183 | - A ``SelectMultiple`` widget was added (a ``Select`` widget that |
|
184 | 184 | allows multiple things to be selected at once) |
|
185 | 185 | (`#6890 <https://github.com/ipython/ipython/pull/6890>`__). |
|
186 | 186 | - A class was added to help manage children views |
|
187 | 187 | (`#6990 <https://github.com/ipython/ipython/pull/6990>`__). |
|
188 | 188 | - A warning was added that shows on widget import because it's expected |
|
189 | 189 | that the API will change again by IPython 4.0. This warning can be |
|
190 | 190 | supressed (`#7107 <https://github.com/ipython/ipython/pull/7107>`__, |
|
191 | 191 | `#7200 <https://github.com/ipython/ipython/pull/7200>`__, |
|
192 | 192 | `#7201 <https://github.com/ipython/ipython/pull/7201>`__, |
|
193 | 193 | `#7204 <https://github.com/ipython/ipython/pull/7204>`__). |
|
194 | 194 | |
|
195 | 195 | Comm and Widget PR Index |
|
196 | 196 | ------------------------ |
|
197 | 197 | |
|
198 | 198 | Here is a chronological list of PRs affecting the widget and comm frameworks for IPython 3.0. Note that later PRs may revert changes |
|
199 | 199 | made in earlier PRs: |
|
200 | 200 | |
|
201 | 201 | - Add placeholder attribute to text widgets |
|
202 | 202 | `#5652 <https://github.com/ipython/ipython/pull/5652>`__ |
|
203 | 203 | - Add latex support in widget labels, |
|
204 | 204 | `#5937 <https://github.com/ipython/ipython/pull/5937>`__ |
|
205 | 205 | - Allow widgets to display more than once within container widgets. |
|
206 | 206 | `#5963 <https://github.com/ipython/ipython/pull/5963>`__ |
|
207 | 207 | - use require.js, |
|
208 | 208 | `#5980 <https://github.com/ipython/ipython/pull/5980>`__ |
|
209 | 209 | - Range widgets |
|
210 | 210 | `#6050 <https://github.com/ipython/ipython/pull/6050>`__ |
|
211 | 211 | - Interact on\_demand option |
|
212 | 212 | `#6051 <https://github.com/ipython/ipython/pull/6051>`__ |
|
213 | 213 | - Allow text input on slider widgets |
|
214 | 214 | `#6106 <https://github.com/ipython/ipython/pull/6106>`__ |
|
215 | 215 | - support binary buffers in comm messages |
|
216 | 216 | `#6110 <https://github.com/ipython/ipython/pull/6110>`__ |
|
217 | 217 | - Embrace the flexible box model in the widgets |
|
218 | 218 | `#6125 <https://github.com/ipython/ipython/pull/6125>`__ |
|
219 | 219 | - Widget trait serialization |
|
220 | 220 | `#6128 <https://github.com/ipython/ipython/pull/6128>`__ |
|
221 | 221 | - Make Container widgets take children as the first positional |
|
222 | 222 | argument `#6153 <https://github.com/ipython/ipython/pull/6153>`__ |
|
223 | 223 | - once-displayed |
|
224 | 224 | `#6168 <https://github.com/ipython/ipython/pull/6168>`__ |
|
225 | 225 | - Validate slider value, when limits change |
|
226 | 226 | `#6171 <https://github.com/ipython/ipython/pull/6171>`__ |
|
227 | 227 | - Unregistering comms in Comm Manager |
|
228 | 228 | `#6216 <https://github.com/ipython/ipython/pull/6216>`__ |
|
229 | 229 | - Add EventfulList and EventfulDict trait types. |
|
230 | 230 | `#6228 <https://github.com/ipython/ipython/pull/6228>`__ |
|
231 | 231 | - Remove add/remove\_class and set/get\_css. |
|
232 | 232 | `#6235 <https://github.com/ipython/ipython/pull/6235>`__ |
|
233 | 233 | - avoid unregistering widget model twice |
|
234 | 234 | `#6250 <https://github.com/ipython/ipython/pull/6250>`__ |
|
235 | 235 | - Widget property lock should compare json states, not python states |
|
236 | 236 | `#6332 <https://github.com/ipython/ipython/pull/6332>`__ |
|
237 | 237 | - Strip the IPY\_MODEL\_ prefix from widget IDs before referencing |
|
238 | 238 | them. `#6377 <https://github.com/ipython/ipython/pull/6377>`__ |
|
239 | 239 | - "event" is not defined error in Firefox |
|
240 | 240 | `#6437 <https://github.com/ipython/ipython/pull/6437>`__ |
|
241 | 241 | - Javascript link |
|
242 | 242 | `#6454 <https://github.com/ipython/ipython/pull/6454>`__ |
|
243 | 243 | - Bulk update of widget attributes |
|
244 | 244 | `#6463 <https://github.com/ipython/ipython/pull/6463>`__ |
|
245 | 245 | - Creating a widget registry on the Python side. |
|
246 | 246 | `#6493 <https://github.com/ipython/ipython/pull/6493>`__ |
|
247 | 247 | - Allow widget views to be loaded from require modules |
|
248 | 248 | `#6494 <https://github.com/ipython/ipython/pull/6494>`__ |
|
249 | 249 | - Fix Issue #6530 |
|
250 | 250 | `#6532 <https://github.com/ipython/ipython/pull/6532>`__ |
|
251 | 251 | - Make comm manager (mostly) independent of InteractiveShell |
|
252 | 252 | `#6540 <https://github.com/ipython/ipython/pull/6540>`__ |
|
253 | 253 | - Add semantic classes to top-level containers for single widgets |
|
254 | 254 | `#6609 <https://github.com/ipython/ipython/pull/6609>`__ |
|
255 | 255 | - Selection Widgets: forcing 'value' to be in 'values' |
|
256 | 256 | `#6617 <https://github.com/ipython/ipython/pull/6617>`__ |
|
257 | 257 | - Allow widgets to be constructed from Javascript |
|
258 | 258 | `#6664 <https://github.com/ipython/ipython/pull/6664>`__ |
|
259 | 259 | - Output widget |
|
260 | 260 | `#6670 <https://github.com/ipython/ipython/pull/6670>`__ |
|
261 | 261 | - Minor change in widgets.less to fix alignment issue |
|
262 | 262 | `#6681 <https://github.com/ipython/ipython/pull/6681>`__ |
|
263 | 263 | - Make Selection widgets respect values order. |
|
264 | 264 | `#6747 <https://github.com/ipython/ipython/pull/6747>`__ |
|
265 | 265 | - Widget persistence API |
|
266 | 266 | `#6789 <https://github.com/ipython/ipython/pull/6789>`__ |
|
267 | 267 | - Add promises to the widget framework. |
|
268 | 268 | `#6818 <https://github.com/ipython/ipython/pull/6818>`__ |
|
269 | 269 | - SelectMultiple widget |
|
270 | 270 | `#6890 <https://github.com/ipython/ipython/pull/6890>`__ |
|
271 | 271 | - Tooltip on toggle button |
|
272 | 272 | `#6923 <https://github.com/ipython/ipython/pull/6923>`__ |
|
273 | 273 | - Allow empty text box \*while typing\* for numeric widgets |
|
274 | 274 | `#6943 <https://github.com/ipython/ipython/pull/6943>`__ |
|
275 | 275 | - Ignore failure of widget MathJax typesetting |
|
276 | 276 | `#6948 <https://github.com/ipython/ipython/pull/6948>`__ |
|
277 | 277 | - Refactor the do\_diff and manual child view lists into a separate |
|
278 | 278 | ViewList object |
|
279 | 279 | `#6990 <https://github.com/ipython/ipython/pull/6990>`__ |
|
280 | 280 | - Add warning to widget namespace import. |
|
281 | 281 | `#7107 <https://github.com/ipython/ipython/pull/7107>`__ |
|
282 | 282 | - lazy load widgets |
|
283 | 283 | `#7120 <https://github.com/ipython/ipython/pull/7120>`__ |
|
284 | 284 | - Fix padding of widgets. |
|
285 | 285 | `#7139 <https://github.com/ipython/ipython/pull/7139>`__ |
|
286 | 286 | - Persist widgets across page refresh |
|
287 | 287 | `#7163 <https://github.com/ipython/ipython/pull/7163>`__ |
|
288 | 288 | - Make the widget experimental error a real python warning |
|
289 | 289 | `#7200 <https://github.com/ipython/ipython/pull/7200>`__ |
|
290 | 290 | - Make the widget error message shorter and more understandable. |
|
291 | 291 | `#7201 <https://github.com/ipython/ipython/pull/7201>`__ |
|
292 | 292 | - Make the widget warning brief and easy to filter |
|
293 | 293 | `#7204 <https://github.com/ipython/ipython/pull/7204>`__ |
|
294 | 294 | - Add visual cue for widgets with dead comms |
|
295 | 295 | `#7227 <https://github.com/ipython/ipython/pull/7227>`__ |
|
296 | 296 | - Widget values as positional arguments |
|
297 | 297 | `#7260 <https://github.com/ipython/ipython/pull/7260>`__ |
|
298 | 298 | - Remove the popup widget |
|
299 | 299 | `#7341 <https://github.com/ipython/ipython/pull/7341>`__ |
|
300 | 300 | - document and validate link, dlink |
|
301 | 301 | `#7468 <https://github.com/ipython/ipython/pull/7468>`__ |
|
302 | 302 | - Document interact 5637 |
|
303 | 303 | `#7525 <https://github.com/ipython/ipython/pull/7525>`__ |
|
304 | 304 | - Update some broken examples of using widgets |
|
305 | 305 | `#7547 <https://github.com/ipython/ipython/pull/7547>`__ |
|
306 | 306 | - Use Output widget with Interact |
|
307 | 307 | `#7554 <https://github.com/ipython/ipython/pull/7554>`__ |
|
308 | 308 | - don't send empty execute\_result messages |
|
309 | 309 | `#7560 <https://github.com/ipython/ipython/pull/7560>`__ |
|
310 | 310 | - Validation on the python side |
|
311 | 311 | `#7602 <https://github.com/ipython/ipython/pull/7602>`__ |
|
312 | 312 | - only show prompt overlay if there's a prompt |
|
313 | 313 | `#7661 <https://github.com/ipython/ipython/pull/7661>`__ |
|
314 | 314 | - Allow predictate to be used for comparison in selection widgets |
|
315 | 315 | `#7674 <https://github.com/ipython/ipython/pull/7674>`__ |
|
316 | 316 | - Fix widget view persistence. |
|
317 | 317 | `#7680 <https://github.com/ipython/ipython/pull/7680>`__ |
|
318 | 318 | - Revert "Use Output widget with Interact" |
|
319 | 319 | `#7703 <https://github.com/ipython/ipython/pull/7703>`__ |
General Comments 0
You need to be logged in to leave comments.
Login now