##// END OF EJS Templates
Cleanup examples...
Jonathan Frederic -
Show More
@@ -0,0 +1,70 b''
1 {
2 "metadata": {
3 "name": ""
4 },
5 "nbformat": 3,
6 "nbformat_minor": 0,
7 "worksheets": [
8 {
9 "cells": [
10 {
11 "cell_type": "heading",
12 "level": 1,
13 "metadata": {},
14 "source": [
15 "Widgets"
16 ]
17 },
18 {
19 "cell_type": "markdown",
20 "metadata": {},
21 "source": [
22 "This directory includes a tutorial and collection of examples related to the IPython notebook widget framework."
23 ]
24 },
25 {
26 "cell_type": "heading",
27 "level": 2,
28 "metadata": {},
29 "source": [
30 "Tutorial"
31 ]
32 },
33 {
34 "cell_type": "markdown",
35 "metadata": {},
36 "source": [
37 "- [Part 1 - Basics](Part 1 - Basics.ipynb) \n",
38 "- [Part 2 - Events](Part 2 - Events.ipynb) \n",
39 "- [Part 3 - Placement](Part 3 - Placement.ipynb) \n",
40 "- [Part 4 - Styles](Part 4 - Styles.ipynb) \n",
41 "- [Part 5 - Alignment](Part 5 - Alignment.ipynb) \n",
42 "- [Part 6 - Custom Widget](Part 6 - Custom Widget.ipynb) "
43 ]
44 },
45 {
46 "cell_type": "heading",
47 "level": 2,
48 "metadata": {},
49 "source": [
50 "Examples"
51 ]
52 },
53 {
54 "cell_type": "markdown",
55 "metadata": {},
56 "source": [
57 "- [Widget Tester](Widget Tester.ipynb) \n",
58 "- [Variable Inspector](Variable Inspector.ipynb) \n",
59 "- [Export As (nbconvert)](Export As (nbconvert%29.ipynb) \n",
60 "- [Nonblocking Console](Nonblocking Console.ipynb) \n",
61 "- [D3](D3.ipynb) \n",
62 "- [File Upload Widget](File Upload Widget.ipynb) \n",
63 "- [Dialogs](Dialogs.ipynb) "
64 ]
65 }
66 ],
67 "metadata": {}
68 }
69 ]
70 } No newline at end of file
@@ -17,7 +17,9 b''
17 "cell_type": "markdown",
17 "cell_type": "markdown",
18 "metadata": {},
18 "metadata": {},
19 "source": [
19 "source": [
20 "To use IPython widgets in the notebook, the widget namespace and optionally the display function need to be imported."
20 "[Index](index.ipynb)\n",
21 "\n",
22 "To use IPython widgets in the notebook, the widget namespace needs to be imported."
21 ]
23 ]
22 },
24 },
23 {
25 {
@@ -126,7 +128,7 b''
126 "cell_type": "markdown",
128 "cell_type": "markdown",
127 "metadata": {},
129 "metadata": {},
128 "source": [
130 "source": [
129 "The basic widgets can all be constructed without arguments. The following creates a FloatRangeWidget without displaying it"
131 "The basic widgets can all be constructed without arguments. The following creates a *FloatSliderWidget* without displaying it"
130 ]
132 ]
131 },
133 },
132 {
134 {
@@ -297,6 +299,13 b''
297 }
299 }
298 ],
300 ],
299 "prompt_number": 10
301 "prompt_number": 10
302 },
303 {
304 "cell_type": "markdown",
305 "metadata": {},
306 "source": [
307 "In [Part 2](Part 2 - Events.ipynb) of this [series](index.ipynb), you will learn about widget events."
308 ]
300 }
309 }
301 ],
310 ],
302 "metadata": {}
311 "metadata": {}
@@ -14,6 +14,13 b''
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "markdown",
18 "metadata": {},
19 "source": [
20 "[< Back to Part 1](Part 1 - Basics.ipynb) or [Index](index.ipynb)"
21 ]
22 },
23 {
17 "cell_type": "code",
24 "cell_type": "code",
18 "collapsed": false,
25 "collapsed": false,
19 "input": [
26 "input": [
@@ -39,7 +46,7 b''
39 "cell_type": "markdown",
46 "cell_type": "markdown",
40 "metadata": {},
47 "metadata": {},
41 "source": [
48 "source": [
42 "The widget properties are IPython traitlets. Traitlets are eventful. To handle property value changes, the `on_trait_change` method of the widget can be used to register an event handling callback. The doc string for `on_trait_change` can be seen below. Both the `name` and `remove` properties are optional."
49 "As mentioned in Part 1, the widget properties are IPython traitlets. Traitlets are eventful. To handle property value changes, the `on_trait_change` method of the widget can be used to register an event handling callback. The doc string for `on_trait_change` can be seen below. Both the `name` and `remove` properties are optional."
43 ]
50 ]
44 },
51 },
45 {
52 {
@@ -95,7 +102,7 b''
95 "- callback(trait_name, new_value)\n",
102 "- callback(trait_name, new_value)\n",
96 "- callback(trait_name, old_value, new_value)\n",
103 "- callback(trait_name, old_value, new_value)\n",
97 "\n",
104 "\n",
98 "An example of how to output an IntRangeWiget's value as it is changed can be seen below."
105 "Using this method, an example of how to output an IntSliderWiget's value as it is changed can be seen below."
99 ]
106 ]
100 },
107 },
101 {
108 {
@@ -157,7 +164,7 b''
157 "cell_type": "markdown",
164 "cell_type": "markdown",
158 "metadata": {},
165 "metadata": {},
159 "source": [
166 "source": [
160 "The `ButtonWidget` is a special widget, like the `ContainerWidget` and `MulticontainerWidget`, that isn't used to represent a data type. Instead the button widget is used to handle mouse clicks. The `on_click` method of the `ButtonWidget` can be used to register a click even handler. The doc string of the `on_click` can be seen below."
167 "The `ButtonWidget` is a special widget, like the `ContainerWidget` and `TabWidget`, that isn't used to represent a data type. Instead the button widget is used to handle mouse clicks. The `on_click` method of the `ButtonWidget` can be used to register a click even handler. The doc string of the `on_click` can be seen below."
161 ]
168 ]
162 },
169 },
163 {
170 {
@@ -264,6 +271,13 b''
264 "metadata": {},
271 "metadata": {},
265 "outputs": [],
272 "outputs": [],
266 "prompt_number": 6
273 "prompt_number": 6
274 },
275 {
276 "cell_type": "markdown",
277 "metadata": {},
278 "source": [
279 "In [Part 3](Part 3 - Placement.ipynb) of this [series](index.ipynb), you will learn about widget placement."
280 ]
267 }
281 }
268 ],
282 ],
269 "metadata": {}
283 "metadata": {}
@@ -14,6 +14,13 b''
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "markdown",
18 "metadata": {},
19 "source": [
20 "[< Back to Part 2](Part 2 - Events.ipynb) or [Index](index.ipynb)"
21 ]
22 },
23 {
17 "cell_type": "code",
24 "cell_type": "code",
18 "collapsed": false,
25 "collapsed": false,
19 "input": [
26 "input": [
@@ -37,7 +44,7 b''
37 "cell_type": "markdown",
44 "cell_type": "markdown",
38 "metadata": {},
45 "metadata": {},
39 "source": [
46 "source": [
40 "To display widget A inside widget B, widget A must be a child of widget B. With IPython widgets, the widgets are instances that live in the back-end (usally Python). There can be multiple views displayed in the front-end that represent one widget in the backend. Each view can be displayed at a different time. Only one instance of any particular model can be child of another. In other words, *widget A* cannot have *widget B* listed twice in it's children list.\n",
47 "To display widget A inside widget B, widget A must be a child of widget B. Only one instance of any particular model can be child of another. In other words, *widget A* cannot have *widget B* listed twice in it's children list.\n",
41 "\n",
48 "\n",
42 "Widgets that can contain other widgets have a `children` property. This property can be set via a kwarg in the widget's constructor or after construction. Calling display on an object with children automatically displays those children too (as seen below)."
49 "Widgets that can contain other widgets have a `children` property. This property can be set via a kwarg in the widget's constructor or after construction. Calling display on an object with children automatically displays those children too (as seen below)."
43 ]
50 ]
@@ -164,6 +171,13 b''
164 "metadata": {},
171 "metadata": {},
165 "outputs": [],
172 "outputs": [],
166 "prompt_number": 7
173 "prompt_number": 7
174 },
175 {
176 "cell_type": "markdown",
177 "metadata": {},
178 "source": [
179 "In [Part 4](Part 4 - Styles.ipynb) of this [series](index.ipynb), you will learn about widget styling."
180 ]
167 }
181 }
168 ],
182 ],
169 "metadata": {}
183 "metadata": {}
@@ -14,6 +14,13 b''
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "markdown",
18 "metadata": {},
19 "source": [
20 "[< Back to Part 3](Part 3 - Placement.ipynb) or [Index](index.ipynb)"
21 ]
22 },
23 {
17 "cell_type": "code",
24 "cell_type": "code",
18 "collapsed": false,
25 "collapsed": false,
19 "input": [
26 "input": [
@@ -37,7 +44,7 b''
37 "cell_type": "markdown",
44 "cell_type": "markdown",
38 "metadata": {},
45 "metadata": {},
39 "source": [
46 "source": [
40 "When trying to design an attractive widget GUI, styling becomes important. Widget views are DOM (document object model) elements that can be controlled with CSS. There are two helper methods defined on widget that allow the manipulation of the widget's CSS. The first is the `set_css` method, whos doc string is displayed below. This method allows one or more CSS attributes to be set at once. "
47 "When trying to design an attractive widget GUI, styling becomes important. Most Widgets views are DOM (document object model) elements that can be controlled with CSS. There are two helper methods defined on widget that allow the manipulation of the widget's CSS. The first is the `set_css` method, whos doc string is displayed below. This method allows one or more CSS attributes to be set at once. "
41 ]
48 ]
42 },
49 },
43 {
50 {
@@ -193,7 +200,7 b''
193 "cell_type": "markdown",
200 "cell_type": "markdown",
194 "metadata": {},
201 "metadata": {},
195 "source": [
202 "source": [
196 "Since `add_class` if a DOM operation, it will only affect widgets that have been displayed. `add_class` must be called after the widget has been displayed. Extending the example above, the corners of the container can be rounded by adding the `corner-all` notebook class to the container (as seen below). "
203 "Since `add_class` if a DOM operation, **it will only affect widgets that have already been displayed**. `add_class` must be called after the widget has been displayed. Extending the example above, the corners of the container can be rounded by adding the `corner-all` notebook class to the container (as seen below). "
197 ]
204 ]
198 },
205 },
199 {
206 {
@@ -272,7 +279,7 b''
272 "cell_type": "markdown",
279 "cell_type": "markdown",
273 "metadata": {},
280 "metadata": {},
274 "source": [
281 "source": [
275 "It's also useful to be able to remove DOM classes from widgets. The `remove_class` widget method allows you to remove classes from widgets that have been displayed. Like `add_widget`, it must be called after the widget has been displayed. The doc string of `remove_class` can be seen below."
282 "It's also useful to be able to remove DOM classes from widgets. The `remove_class` widget method allows you to remove classes from widgets that have been displayed. Like `add_class`, it must be called after the widget has been displayed. The doc string of `remove_class` can be seen below."
276 ]
283 ]
277 },
284 },
278 {
285 {
@@ -333,6 +340,13 b''
333 "metadata": {},
340 "metadata": {},
334 "outputs": [],
341 "outputs": [],
335 "prompt_number": 10
342 "prompt_number": 10
343 },
344 {
345 "cell_type": "markdown",
346 "metadata": {},
347 "source": [
348 "In [Part 5](Part 5 - Alignment.ipynb) of this [series](index.ipynb), you will learn about widget alignment."
349 ]
336 }
350 }
337 ],
351 ],
338 "metadata": {}
352 "metadata": {}
@@ -14,6 +14,13 b''
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "markdown",
18 "metadata": {},
19 "source": [
20 "[< Back to Part 4](Part 4 - Styles.ipynb) or [Index](index.ipynb)"
21 ]
22 },
23 {
17 "cell_type": "code",
24 "cell_type": "code",
18 "collapsed": false,
25 "collapsed": false,
19 "input": [
26 "input": [
@@ -107,7 +114,7 b''
107 "cell_type": "markdown",
114 "cell_type": "markdown",
108 "metadata": {},
115 "metadata": {},
109 "source": [
116 "source": [
110 "`ContainerWidget`s allow for custom alignment of widgets. The `hbox` and `vbox` methods (parameterless) cause the `ContainerWidget` to both horizontally and vertically align its children. The following example compares `vbox` to `hbox`."
117 "`ContainerWidget`s allow for custom alignment of widgets. The `hbox` and `vbox` DOM classes cause the `ContainerWidget` to both horizontally and vertically align its children. The following example compares `vbox` to `hbox`."
111 ]
118 ]
112 },
119 },
113 {
120 {
@@ -160,7 +167,7 b''
160 "cell_type": "markdown",
167 "cell_type": "markdown",
161 "metadata": {},
168 "metadata": {},
162 "source": [
169 "source": [
163 "The `ContainerWidget` `pack_start`, `pack_center`, and `pack_end` methods (parameterless) adjust the alignment of the widgets on the axis that they are being rendered on. Below is an example of the different alignments."
170 "The `start`, `center`, and `end` DOM classes adjust the alignment of the widgets on the axis that they are being rendered on. Below is an example of the different alignments."
164 ]
171 ]
165 },
172 },
166 {
173 {
@@ -191,7 +198,7 b''
191 "cell_type": "markdown",
198 "cell_type": "markdown",
192 "metadata": {},
199 "metadata": {},
193 "source": [
200 "source": [
194 "The `ContainerWidget` `flex0`, `flex1`, and `flex2` methods (parameterless) modify the containers flexibility. Changing a container flexibility affects how and if the container will occupy the remaining space. Setting `flex0` has the same result as setting no flex. Below is an example of different flex configurations. The number on the boxes correspond to the applied flex."
201 "The `box-flex0`, `box-flex1`, and `box-flex2` DOM classes modify the container's flexibility. Changing a container flexibility affects how and if the container will occupy the remaining space. Applying `box-flex0` has the same result as not applying flex. Below is an example of different flex configurations. The number on the boxes correspond to the applied flex."
195 ]
202 ]
196 },
203 },
197 {
204 {
@@ -249,7 +256,7 b''
249 "cell_type": "markdown",
256 "cell_type": "markdown",
250 "metadata": {},
257 "metadata": {},
251 "source": [
258 "source": [
252 "The `ContainerWidget` `align_start`, `align_center`, and `align_end` methods (parameterless) adjust the alignment of the widgets on the axis perpindicular to the one that they are being rendered on. Below is an example of the different alignments."
259 "The `align_start`, `align_center`, and `align_end` DOM classes adjust the alignment of the widgets on the axis perpindicular to the one that they are being rendered on. Below is an example of the different alignments."
253 ]
260 ]
254 },
261 },
255 {
262 {
@@ -305,6 +312,13 b''
305 "metadata": {},
312 "metadata": {},
306 "outputs": [],
313 "outputs": [],
307 "prompt_number": 9
314 "prompt_number": 9
315 },
316 {
317 "cell_type": "markdown",
318 "metadata": {},
319 "source": [
320 "In [Part 6](Part 6 - Custom Widget.ipynb) of this [series](index.ipynb), you will learn how to create your own custom widget."
321 ]
308 }
322 }
309 ],
323 ],
310 "metadata": {}
324 "metadata": {}
@@ -17,6 +17,8 b''
17 "cell_type": "markdown",
17 "cell_type": "markdown",
18 "metadata": {},
18 "metadata": {},
19 "source": [
19 "source": [
20 "[< Back to Part 5](Part 5 - Alignment.ipynb) or [Index](index.ipynb)\n",
21 "\n",
20 "Before reading, the author recommends the reader to review\n",
22 "Before reading, the author recommends the reader to review\n",
21 "\n",
23 "\n",
22 "- [MVC prgramming](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)\n",
24 "- [MVC prgramming](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)\n",
@@ -31,32 +33,14 b''
31 "input": [
33 "input": [
32 "from __future__ import print_function # For py 2.7 compat\n",
34 "from __future__ import print_function # For py 2.7 compat\n",
33 "\n",
35 "\n",
34 "from IPython.html import widgets # Widget definitions\n",
36 "from IPython.html import widgets # Widget definitions.\n",
35 "from IPython.display import display # Used to display widgets in the notebook"
37 "from IPython.display import display # Used to display widgets in the notebook.\n",
38 "from IPython.utils.traitlets import Unicode # Used to declare properties of our widget."
36 ],
39 ],
37 "language": "python",
40 "language": "python",
38 "metadata": {},
41 "metadata": {},
39 "outputs": [],
42 "outputs": [],
40 "prompt_number": 19
43 "prompt_number": 1
41 },
42 {
43 "cell_type": "markdown",
44 "metadata": {},
45 "source": [
46 "The 3 part of this tutorial requires the 3rd party `dateutil` library. https://pypi.python.org/pypi/python-dateutil"
47 ]
48 },
49 {
50 "cell_type": "code",
51 "collapsed": false,
52 "input": [
53 "# Import the dateutil library to parse date strings.\n",
54 "from dateutil import parser"
55 ],
56 "language": "python",
57 "metadata": {},
58 "outputs": [],
59 "prompt_number": 20
60 },
44 },
61 {
45 {
62 "cell_type": "heading",
46 "cell_type": "heading",
@@ -100,24 +84,19 b''
100 "cell_type": "code",
84 "cell_type": "code",
101 "collapsed": false,
85 "collapsed": false,
102 "input": [
86 "input": [
103 "# Import the base Widget class and the traitlets Unicode class.\n",
87 "class DateWidget(widgets.DOMWidget):\n",
104 "from IPython.html.widgets import DOMWidget\n",
105 "from IPython.utils.traitlets import Unicode\n",
106 "\n",
107 "# Define our DateWidget and its target model and default view.\n",
108 "class DateWidget(DOMWidget):\n",
109 " _view_name = Unicode('DatePickerView', sync=True)"
88 " _view_name = Unicode('DatePickerView', sync=True)"
110 ],
89 ],
111 "language": "python",
90 "language": "python",
112 "metadata": {},
91 "metadata": {},
113 "outputs": [],
92 "outputs": [],
114 "prompt_number": 21
93 "prompt_number": 2
115 },
94 },
116 {
95 {
117 "cell_type": "markdown",
96 "cell_type": "markdown",
118 "metadata": {},
97 "metadata": {},
119 "source": [
98 "source": [
120 "- **_view_name** is the default Backbone view to display when the user calls `display` to display an instance of this widget.\n"
99 "Our widget inherits from `widgets.DOMWidget` since it is intended that it will be displayed in the notebook directly. The `_view_name` trait is specially named, the widget framework will read the `_view_name` trait to determine what Backbone view the widget is associated with. **Using `sync=True` is very important** because it tells the widget framework that that specific traitlet should be synced between the front- and back-ends."
121 ]
100 ]
122 },
101 },
123 {
102 {
@@ -158,17 +137,17 b''
158 "metadata": {},
137 "metadata": {},
159 "output_type": "display_data",
138 "output_type": "display_data",
160 "text": [
139 "text": [
161 "<IPython.core.display.Javascript at 0x1e409d0>"
140 "<IPython.core.display.Javascript at 0x2a2e0d0>"
162 ]
141 ]
163 }
142 }
164 ],
143 ],
165 "prompt_number": 22
144 "prompt_number": 3
166 },
145 },
167 {
146 {
168 "cell_type": "markdown",
147 "cell_type": "markdown",
169 "metadata": {},
148 "metadata": {},
170 "source": [
149 "source": [
171 "Now we need to define a view that can be used to represent the model. To do this, the `IPython.DOMWidgetView` is extended. A render function must be defined. The render function is used to render a widget view instance to the DOM. For now the render function renders a div that contains the text *Hello World!* Lastly, the view needs to be registered with the widget manager like the model was.\n",
150 "Now we need to define a view that can be used to represent the model. To do this, the `IPython.DOMWidgetView` is extended. A render function must be defined. The render function is used to render a widget view instance to the DOM. For now the render function renders a div that contains the text *Hello World!* Lastly, the view needs to be registered with the widget manager.\n",
172 "\n",
151 "\n",
173 "**Final JavaScript code below:**"
152 "**Final JavaScript code below:**"
174 ]
153 ]
@@ -210,11 +189,11 b''
210 "metadata": {},
189 "metadata": {},
211 "output_type": "display_data",
190 "output_type": "display_data",
212 "text": [
191 "text": [
213 "<IPython.core.display.Javascript at 0x1e40a50>"
192 "<IPython.core.display.Javascript at 0x2a2e3d0>"
214 ]
193 ]
215 }
194 }
216 ],
195 ],
217 "prompt_number": 23
196 "prompt_number": 4
218 },
197 },
219 {
198 {
220 "cell_type": "heading",
199 "cell_type": "heading",
@@ -240,7 +219,7 b''
240 "language": "python",
219 "language": "python",
241 "metadata": {},
220 "metadata": {},
242 "outputs": [],
221 "outputs": [],
243 "prompt_number": 24
222 "prompt_number": 5
244 },
223 },
245 {
224 {
246 "cell_type": "heading",
225 "cell_type": "heading",
@@ -262,26 +241,21 b''
262 "cell_type": "markdown",
241 "cell_type": "markdown",
263 "metadata": {},
242 "metadata": {},
264 "source": [
243 "source": [
265 "In the last section we created a simple widget that displayed *Hello World!* To make an actual date widget, we need to add a property that will be synced between the Python model and the JavaScript model. The new property must be a traitlet property so the widget machinery can automatically handle it. The property needs to be constructed with a `sync=True` keyword argument so the widget machinery knows to syncronize it with the fron-end. Adding this to the code from the last section:"
244 "In the last section we created a simple widget that displayed *Hello World!* To make an actual date widget, we need to add a property that will be synced between the Python model and the JavaScript model. The new property must be a traitlet property so the widget machinery can automatically handle it. The property needs to be constructed with a `sync=True` keyword argument so the widget machinery knows to syncronize it with the front-end. Adding this to the code from the last section:"
266 ]
245 ]
267 },
246 },
268 {
247 {
269 "cell_type": "code",
248 "cell_type": "code",
270 "collapsed": false,
249 "collapsed": false,
271 "input": [
250 "input": [
272 "# Import the base Widget class and the traitlets Unicode class.\n",
251 "class DateWidget(widgets.DOMWidget):\n",
273 "from IPython.html.widgets import DOMWidget\n",
274 "from IPython.utils.traitlets import Unicode\n",
275 "\n",
276 "# Define our DateWidget and its target model and default view.\n",
277 "class DateWidget(DOMWidget):\n",
278 " _view_name = Unicode('DatePickerView', sync=True)\n",
252 " _view_name = Unicode('DatePickerView', sync=True)\n",
279 " value = Unicode(sync=True)"
253 " value = Unicode(sync=True)"
280 ],
254 ],
281 "language": "python",
255 "language": "python",
282 "metadata": {},
256 "metadata": {},
283 "outputs": [],
257 "outputs": [],
284 "prompt_number": 25
258 "prompt_number": 6
285 },
259 },
286 {
260 {
287 "cell_type": "heading",
261 "cell_type": "heading",
@@ -295,7 +269,7 b''
295 "cell_type": "markdown",
269 "cell_type": "markdown",
296 "metadata": {},
270 "metadata": {},
297 "source": [
271 "source": [
298 "In the JavaScript there is no need to define the same properties in the JavaScript model. When the JavaScript model is created for the first time, it copies all of the attributes from the Python model. We need to replace *Hello World!* with an actual HTML date picker widget."
272 "In the JavaScript there is no need to define counterparts to the traitlets. When the JavaScript model is created for the first time, it copies all of the traitlet `sync=True` attributes from the Python model. We need to replace *Hello World!* with an actual HTML date picker widget."
299 ]
273 ]
300 },
274 },
301 {
275 {
@@ -347,11 +321,11 b''
347 "metadata": {},
321 "metadata": {},
348 "output_type": "display_data",
322 "output_type": "display_data",
349 "text": [
323 "text": [
350 "<IPython.core.display.Javascript at 0x1e40810>"
324 "<IPython.core.display.Javascript at 0x2a2e6d0>"
351 ]
325 ]
352 }
326 }
353 ],
327 ],
354 "prompt_number": 26
328 "prompt_number": 7
355 },
329 },
356 {
330 {
357 "cell_type": "markdown",
331 "cell_type": "markdown",
@@ -423,11 +397,11 b''
423 "metadata": {},
397 "metadata": {},
424 "output_type": "display_data",
398 "output_type": "display_data",
425 "text": [
399 "text": [
426 "<IPython.core.display.Javascript at 0x1e40390>"
400 "<IPython.core.display.Javascript at 0x2a2e090>"
427 ]
401 ]
428 }
402 }
429 ],
403 ],
430 "prompt_number": 27
404 "prompt_number": 8
431 },
405 },
432 {
406 {
433 "cell_type": "markdown",
407 "cell_type": "markdown",
@@ -521,11 +495,11 b''
521 "metadata": {},
495 "metadata": {},
522 "output_type": "display_data",
496 "output_type": "display_data",
523 "text": [
497 "text": [
524 "<IPython.core.display.Javascript at 0x1e40890>"
498 "<IPython.core.display.Javascript at 0x2a2e750>"
525 ]
499 ]
526 }
500 }
527 ],
501 ],
528 "prompt_number": 28
502 "prompt_number": 9
529 },
503 },
530 {
504 {
531 "cell_type": "heading",
505 "cell_type": "heading",
@@ -552,7 +526,7 b''
552 "language": "python",
526 "language": "python",
553 "metadata": {},
527 "metadata": {},
554 "outputs": [],
528 "outputs": [],
555 "prompt_number": 29
529 "prompt_number": 10
556 },
530 },
557 {
531 {
558 "cell_type": "markdown",
532 "cell_type": "markdown",
@@ -570,7 +544,7 b''
570 "language": "python",
544 "language": "python",
571 "metadata": {},
545 "metadata": {},
572 "outputs": [],
546 "outputs": [],
573 "prompt_number": 30
547 "prompt_number": 11
574 },
548 },
575 {
549 {
576 "cell_type": "markdown",
550 "cell_type": "markdown",
@@ -591,13 +565,13 b''
591 {
565 {
592 "metadata": {},
566 "metadata": {},
593 "output_type": "pyout",
567 "output_type": "pyout",
594 "prompt_number": 31,
568 "prompt_number": 12,
595 "text": [
569 "text": [
596 "u''"
570 "u'2014-01-01'"
597 ]
571 ]
598 }
572 }
599 ],
573 ],
600 "prompt_number": 31
574 "prompt_number": 12
601 },
575 },
602 {
576 {
603 "cell_type": "markdown",
577 "cell_type": "markdown",
@@ -615,7 +589,7 b''
615 "language": "python",
589 "language": "python",
616 "metadata": {},
590 "metadata": {},
617 "outputs": [],
591 "outputs": [],
618 "prompt_number": 32
592 "prompt_number": 13
619 },
593 },
620 {
594 {
621 "cell_type": "heading",
595 "cell_type": "heading",
@@ -629,6 +603,25 b''
629 "cell_type": "markdown",
603 "cell_type": "markdown",
630 "metadata": {},
604 "metadata": {},
631 "source": [
605 "source": [
606 "The 3rd party `dateutil` library is required to continue. https://pypi.python.org/pypi/python-dateutil"
607 ]
608 },
609 {
610 "cell_type": "code",
611 "collapsed": false,
612 "input": [
613 "# Import the dateutil library to parse date strings.\n",
614 "from dateutil import parser"
615 ],
616 "language": "python",
617 "metadata": {},
618 "outputs": [],
619 "prompt_number": 14
620 },
621 {
622 "cell_type": "markdown",
623 "metadata": {},
624 "source": [
632 "In the last section we created a fully working date picker widget. Now we will add custom validation and support for labels. Currently only the ISO date format \"YYYY-MM-DD\" is supported. We will add support for all of the date formats recognized by the 3rd party Python dateutil library."
625 "In the last section we created a fully working date picker widget. Now we will add custom validation and support for labels. Currently only the ISO date format \"YYYY-MM-DD\" is supported. We will add support for all of the date formats recognized by the 3rd party Python dateutil library."
633 ]
626 ]
634 },
627 },
@@ -644,96 +637,61 b''
644 "cell_type": "markdown",
637 "cell_type": "markdown",
645 "metadata": {},
638 "metadata": {},
646 "source": [
639 "source": [
647 "The traitlet machinery searches the class that the trait is defined in for methods with \"`_changed`\" suffixed onto their names. Any method with the format \"`X_changed`\" will be called when \"`X`\" is modified. We can take advantage of this to perform validation and parsing of different date string formats. Below a method that listens to value has been added to the DateWidget."
640 "The standard property name used for widget labels is `description`. In the code block below, `description` has been added to the Python widget."
648 ]
641 ]
649 },
642 },
650 {
643 {
651 "cell_type": "code",
644 "cell_type": "code",
652 "collapsed": false,
645 "collapsed": false,
653 "input": [
646 "input": [
654 "# Import the base Widget class and the traitlets Unicode class.\n",
647 "class DateWidget(widgets.DOMWidget):\n",
655 "from IPython.html.widgets import DOMWidget\n",
656 "from IPython.utils.traitlets import Unicode\n",
657 "\n",
658 "# Define our DateWidget and its target model and default view.\n",
659 "class DateWidget(DOMWidget):\n",
660 " _view_name = Unicode('DatePickerView', sync=True)\n",
648 " _view_name = Unicode('DatePickerView', sync=True)\n",
661 " value = Unicode(sync=True)\n",
649 " value = Unicode(sync=True)\n",
662 " \n",
650 " description = Unicode(sync=True)"
663 " # This function automatically gets called by the traitlet machinery when\n",
664 " # value is modified because of this function's name.\n",
665 " def _value_changed(self, name, old_value, new_value):\n",
666 " pass\n",
667 " "
668 ],
651 ],
669 "language": "python",
652 "language": "python",
670 "metadata": {},
653 "metadata": {},
671 "outputs": [],
654 "outputs": [],
672 "prompt_number": 33
655 "prompt_number": 15
673 },
656 },
674 {
657 {
675 "cell_type": "markdown",
658 "cell_type": "markdown",
676 "metadata": {},
659 "metadata": {},
677 "source": [
660 "source": [
678 "Now the function that parses the date string and only sets it in the correct format can be added."
661 "The traitlet machinery searches the class that the trait is defined in for methods with \"`_changed`\" suffixed onto their names. Any method with the format \"`X_changed`\" will be called when \"`X`\" is modified. We can take advantage of this to perform validation and parsing of different date string formats. Below a method that listens to value has been added to the DateWidget."
679 ]
662 ]
680 },
663 },
681 {
664 {
682 "cell_type": "code",
665 "cell_type": "code",
683 "collapsed": false,
666 "collapsed": false,
684 "input": [
667 "input": [
685 "# Import the dateutil library to parse date strings.\n",
668 "class DateWidget(widgets.DOMWidget):\n",
686 "from dateutil import parser\n",
687 "\n",
688 "# Import the base Widget class and the traitlets Unicode class.\n",
689 "from IPython.html.widgets import DOMWidget\n",
690 "from IPython.utils.traitlets import Unicode\n",
691 "\n",
692 "# Define our DateWidget and its target model and default view.\n",
693 "class DateWidget(DOMWidget):\n",
694 " _view_name = Unicode('DatePickerView', sync=True)\n",
669 " _view_name = Unicode('DatePickerView', sync=True)\n",
695 " value = Unicode(sync=True)\n",
670 " value = Unicode(sync=True)\n",
696 " \n",
671 " description = Unicode(sync=True)\n",
672 "\n",
697 " # This function automatically gets called by the traitlet machinery when\n",
673 " # This function automatically gets called by the traitlet machinery when\n",
698 " # value is modified because of this function's name.\n",
674 " # value is modified because of this function's name.\n",
699 " def _value_changed(self, name, old_value, new_value):\n",
675 " def _value_changed(self, name, old_value, new_value):\n",
700 " \n",
676 " pass"
701 " # Parse the date time value.\n",
702 " try:\n",
703 " parsed_date = parser.parse(new_value)\n",
704 " parsed_date_string = parsed_date.strftime(\"%Y-%m-%d\")\n",
705 " except:\n",
706 " parsed_date_string = ''\n",
707 " \n",
708 " # Set the parsed date string if the current date string is different.\n",
709 " if self.value != parsed_date_string:\n",
710 " self.value = parsed_date_string"
711 ],
677 ],
712 "language": "python",
678 "language": "python",
713 "metadata": {},
679 "metadata": {},
714 "outputs": [],
680 "outputs": [],
715 "prompt_number": 34
681 "prompt_number": 16
716 },
682 },
717 {
683 {
718 "cell_type": "markdown",
684 "cell_type": "markdown",
719 "metadata": {},
685 "metadata": {},
720 "source": [
686 "source": [
721 "The standard property name used for widget labels is `description`. In the code block below, `description` has been added to the Python widget."
687 "Now the function that parses the date string and only sets it in the correct format can be added."
722 ]
688 ]
723 },
689 },
724 {
690 {
725 "cell_type": "code",
691 "cell_type": "code",
726 "collapsed": false,
692 "collapsed": false,
727 "input": [
693 "input": [
728 "# Import the dateutil library to parse date strings.\n",
694 "class DateWidget(widgets.DOMWidget):\n",
729 "from dateutil import parser\n",
730 "\n",
731 "# Import the base Widget class and the traitlets Unicode class.\n",
732 "from IPython.html.widgets import DOMWidget\n",
733 "from IPython.utils.traitlets import Unicode\n",
734 "\n",
735 "# Define our DateWidget and its target model and default view.\n",
736 "class DateWidget(DOMWidget):\n",
737 " _view_name = Unicode('DatePickerView', sync=True)\n",
695 " _view_name = Unicode('DatePickerView', sync=True)\n",
738 " value = Unicode(sync=True)\n",
696 " value = Unicode(sync=True)\n",
739 " description = Unicode(sync=True)\n",
697 " description = Unicode(sync=True)\n",
@@ -756,13 +714,13 b''
756 "language": "python",
714 "language": "python",
757 "metadata": {},
715 "metadata": {},
758 "outputs": [],
716 "outputs": [],
759 "prompt_number": 35
717 "prompt_number": 17
760 },
718 },
761 {
719 {
762 "cell_type": "markdown",
720 "cell_type": "markdown",
763 "metadata": {},
721 "metadata": {},
764 "source": [
722 "source": [
765 "Finally, a callback list is added so the user can perform custom validation. If any one of the callbacks returns False, the new date time is not set.\n",
723 "Finally, a `CallbackDispatcher` is added so the user can perform custom validation. If any one of the callbacks registered with the dispatcher returns False, the new date time is not set.\n",
766 "\n",
724 "\n",
767 "**Final Python code below:**"
725 "**Final Python code below:**"
768 ]
726 ]
@@ -771,15 +729,7 b''
771 "cell_type": "code",
729 "cell_type": "code",
772 "collapsed": false,
730 "collapsed": false,
773 "input": [
731 "input": [
774 "# Import the dateutil library to parse date strings.\n",
732 "class DateWidget(widgets.DOMWidget):\n",
775 "from dateutil import parser\n",
776 "\n",
777 "# Import the base Widget class and the traitlets Unicode class.\n",
778 "from IPython.html.widgets import DOMWidget, CallbackDispatcher\n",
779 "from IPython.utils.traitlets import Unicode\n",
780 "\n",
781 "# Define our DateWidget and its target model and default view.\n",
782 "class DateWidget(DOMWidget):\n",
783 " _view_name = Unicode('DatePickerView', sync=True)\n",
733 " _view_name = Unicode('DatePickerView', sync=True)\n",
784 " value = Unicode(sync=True)\n",
734 " value = Unicode(sync=True)\n",
785 " description = Unicode(sync=True)\n",
735 " description = Unicode(sync=True)\n",
@@ -790,7 +740,7 b''
790 " # Specify the number of positional arguments supported. For \n",
740 " # Specify the number of positional arguments supported. For \n",
791 " # validation we only are worried about one parameter, the\n",
741 " # validation we only are worried about one parameter, the\n",
792 " # new value that should be validated.\n",
742 " # new value that should be validated.\n",
793 " self.validation = CallbackDispatcher(acceptable_nargs=[1])\n",
743 " self.validation = widgets.CallbackDispatcher(acceptable_nargs=[1])\n",
794 " \n",
744 " \n",
795 " # This function automatically gets called by the traitlet machinery when\n",
745 " # This function automatically gets called by the traitlet machinery when\n",
796 " # value is modified because of this function's name.\n",
746 " # value is modified because of this function's name.\n",
@@ -817,7 +767,7 b''
817 "language": "python",
767 "language": "python",
818 "metadata": {},
768 "metadata": {},
819 "outputs": [],
769 "outputs": [],
820 "prompt_number": 45
770 "prompt_number": 18
821 },
771 },
822 {
772 {
823 "cell_type": "heading",
773 "cell_type": "heading",
@@ -953,11 +903,11 b''
953 "metadata": {},
903 "metadata": {},
954 "output_type": "display_data",
904 "output_type": "display_data",
955 "text": [
905 "text": [
956 "<IPython.core.display.Javascript at 0x1efe210>"
906 "<IPython.core.display.Javascript at 0x2a5a6d0>"
957 ]
907 ]
958 }
908 }
959 ],
909 ],
960 "prompt_number": 40
910 "prompt_number": 19
961 },
911 },
962 {
912 {
963 "cell_type": "heading",
913 "cell_type": "heading",
@@ -989,7 +939,7 b''
989 "language": "python",
939 "language": "python",
990 "metadata": {},
940 "metadata": {},
991 "outputs": [],
941 "outputs": [],
992 "prompt_number": 46
942 "prompt_number": 20
993 },
943 },
994 {
944 {
995 "cell_type": "markdown",
945 "cell_type": "markdown",
@@ -1012,7 +962,7 b''
1012 "language": "python",
962 "language": "python",
1013 "metadata": {},
963 "metadata": {},
1014 "outputs": [],
964 "outputs": [],
1015 "prompt_number": 47
965 "prompt_number": 21
1016 },
966 },
1017 {
967 {
1018 "cell_type": "code",
968 "cell_type": "code",
@@ -1024,7 +974,7 b''
1024 "language": "python",
974 "language": "python",
1025 "metadata": {},
975 "metadata": {},
1026 "outputs": [],
976 "outputs": [],
1027 "prompt_number": 48
977 "prompt_number": 22
1028 },
978 },
1029 {
979 {
1030 "cell_type": "code",
980 "cell_type": "code",
@@ -1036,7 +986,7 b''
1036 "language": "python",
986 "language": "python",
1037 "metadata": {},
987 "metadata": {},
1038 "outputs": [],
988 "outputs": [],
1039 "prompt_number": 49
989 "prompt_number": 23
1040 },
990 },
1041 {
991 {
1042 "cell_type": "code",
992 "cell_type": "code",
@@ -1050,13 +1000,20 b''
1050 {
1000 {
1051 "metadata": {},
1001 "metadata": {},
1052 "output_type": "pyout",
1002 "output_type": "pyout",
1053 "prompt_number": 50,
1003 "prompt_number": 24,
1054 "text": [
1004 "text": [
1055 "u'2014-12-02'"
1005 "u'2014-12-02'"
1056 ]
1006 ]
1057 }
1007 }
1058 ],
1008 ],
1059 "prompt_number": 50
1009 "prompt_number": 24
1010 },
1011 {
1012 "cell_type": "markdown",
1013 "metadata": {},
1014 "source": [
1015 "This concludes Part 6 of the [series](index.ipynb)."
1016 ]
1060 }
1017 }
1061 ],
1018 ],
1062 "metadata": {}
1019 "metadata": {}
General Comments 0
You need to be logged in to leave comments. Login now