##// END OF EJS Templates
Clear output
Jonathan Frederic -
Show More
@@ -1,1011 +1,796 b''
1 1 {
2 2 "metadata": {
3 3 "celltoolbar": "Slideshow",
4 4 "name": "",
5 "signature": "sha256:4fc2f8717ea4752070ed0e10a8997c2a5f45851ba9b20293339335894264021c"
5 "signature": "sha256:32ada55b57f8674a38435bae581b0f53caefd829dca5c5a7931ab3d04a7d86bb"
6 6 },
7 7 "nbformat": 3,
8 8 "nbformat_minor": 0,
9 9 "worksheets": [
10 10 {
11 11 "cells": [
12 12 {
13 13 "cell_type": "markdown",
14 14 "metadata": {},
15 15 "source": [
16 16 "[Index](Index.ipynb) - [Back](Widget Styling.ipynb)"
17 17 ]
18 18 },
19 19 {
20 20 "cell_type": "code",
21 21 "collapsed": false,
22 22 "input": [
23 23 "from __future__ import print_function # For py 2.7 compat"
24 24 ],
25 25 "language": "python",
26 26 "metadata": {},
27 "outputs": [],
28 "prompt_number": 3
27 "outputs": []
29 28 },
30 29 {
31 30 "cell_type": "heading",
32 31 "level": 1,
33 32 "metadata": {
34 33 "slideshow": {
35 34 "slide_type": "slide"
36 35 }
37 36 },
38 37 "source": [
39 38 "Building a Custom Widget"
40 39 ]
41 40 },
42 41 {
43 42 "cell_type": "markdown",
44 43 "metadata": {},
45 44 "source": [
46 45 "The widget framework is built **on top of the Comm framework** (short for communication). The Comm framework is a framework that **allows you send/receive JSON messages** to/from the front-end (as seen below).\n",
47 46 "\n",
48 47 "![Widget layer](images/WidgetArch.png)\n",
49 48 "\n",
50 49 "To create a custom widget, you need to **define the widget both in the back-end and in the front-end**. "
51 50 ]
52 51 },
53 52 {
54 53 "cell_type": "heading",
55 54 "level": 1,
56 55 "metadata": {
57 56 "slideshow": {
58 57 "slide_type": "slide"
59 58 }
60 59 },
61 60 "source": [
62 61 "Building a Custom Widget"
63 62 ]
64 63 },
65 64 {
66 65 "cell_type": "markdown",
67 66 "metadata": {},
68 67 "source": [
69 68 "To get started, you'll create a **simple hello world widget**. Later you'll build on this foundation to make more complex widgets."
70 69 ]
71 70 },
72 71 {
73 72 "cell_type": "heading",
74 73 "level": 2,
75 74 "metadata": {
76 75 "slideshow": {
77 76 "slide_type": "slide"
78 77 }
79 78 },
80 79 "source": [
81 80 "Back-end (Python)"
82 81 ]
83 82 },
84 83 {
85 84 "cell_type": "heading",
86 85 "level": 3,
87 86 "metadata": {},
88 87 "source": [
89 88 "DOMWidget and Widget"
90 89 ]
91 90 },
92 91 {
93 92 "cell_type": "markdown",
94 93 "metadata": {},
95 94 "source": [
96 95 "To define a widget, you must inherit from the **Widget or DOMWidget** base class. If you intend for your widget to be **displayed in the IPython notebook**, you'll need to **inherit from the DOMWidget**. The DOMWidget class itself inherits from the Widget class. The Widget class is useful for cases in which the **Widget is not meant to be displayed directly in the notebook**, but **instead as a child of another rendering environment**. For example, if you wanted to create a three.js widget (a popular WebGL library), you would implement the rendering window as a DOMWidget and any 3D objects or lights meant to be rendered in that window as Widgets."
97 96 ]
98 97 },
99 98 {
100 99 "cell_type": "heading",
101 100 "level": 3,
102 101 "metadata": {
103 102 "slideshow": {
104 103 "slide_type": "slide"
105 104 }
106 105 },
107 106 "source": [
108 107 "_view_name"
109 108 ]
110 109 },
111 110 {
112 111 "cell_type": "markdown",
113 112 "metadata": {},
114 113 "source": [
115 114 "Inheriting from the DOMWidget does not tell the widget framework what front-end widget to associate with your back-end widget. Instead, you must tell it yourself by defining a **specially named Traitlet, `_view_name`** (as seen below)."
116 115 ]
117 116 },
118 117 {
119 118 "cell_type": "code",
120 119 "collapsed": false,
121 120 "input": [
122 121 "from IPython.html import widgets\n",
123 122 "from IPython.utils.traitlets import Unicode\n",
124 123 "\n",
125 124 "class HelloWidget(widgets.DOMWidget):\n",
126 125 " _view_name = Unicode('HelloView', sync=True)"
127 126 ],
128 127 "language": "python",
129 128 "metadata": {},
130 "outputs": [],
131 "prompt_number": 1
129 "outputs": []
132 130 },
133 131 {
134 132 "cell_type": "heading",
135 133 "level": 3,
136 134 "metadata": {
137 135 "slideshow": {
138 136 "slide_type": "slide"
139 137 }
140 138 },
141 139 "source": [
142 140 "sync=True traitlets"
143 141 ]
144 142 },
145 143 {
146 144 "cell_type": "markdown",
147 145 "metadata": {},
148 146 "source": [
149 147 "**Traitlets is** an IPython library for defining **type-safe properties** on configurable objects. For this tutorial you do not need to worry about the *configurable* piece of the traitlets machinery. The **`sync=True` keyword argument** tells the widget framework to **handle synchronizing that value to the front-end**. Without `sync=True`, the front-end would have no knowledge of `_view_name`."
150 148 ]
151 149 },
152 150 {
153 151 "cell_type": "heading",
154 152 "level": 3,
155 153 "metadata": {
156 154 "slideshow": {
157 155 "slide_type": "slide"
158 156 }
159 157 },
160 158 "source": [
161 159 "Other traitlet types"
162 160 ]
163 161 },
164 162 {
165 163 "cell_type": "markdown",
166 164 "metadata": {},
167 165 "source": [
168 166 "Unicode, used for _view_name, is not the only Traitlet type, there are many more some of which are listed below: \n",
169 167 "\n",
170 168 "- Any\n",
171 169 "- Bool\n",
172 170 "- Bytes\n",
173 171 "- CBool\n",
174 172 "- CBytes\n",
175 173 "- CComplex\n",
176 174 "- CFloat\n",
177 175 "- CInt\n",
178 176 "- CLong\n",
179 177 "- CRegExp\n",
180 178 "- CUnicode\n",
181 179 "- CaselessStrEnum\n",
182 180 "- Complex\n",
183 181 "- Dict\n",
184 182 "- DottedObjectName\n",
185 183 "- Enum\n",
186 184 "- Float\n",
187 185 "- FunctionType\n",
188 186 "- Instance\n",
189 187 "- InstanceType\n",
190 188 "- Int\n",
191 189 "- List\n",
192 190 "- Long\n",
193 191 "- Set\n",
194 192 "- TCPAddress\n",
195 193 "- Tuple\n",
196 194 "- Type\n",
197 195 "- Unicode\n",
198 196 "\n",
199 197 "**Not all of these traitlets can be synchronized** across the network, **only the JSON-able** traits and **Widget instances** will be synchronized."
200 198 ]
201 199 },
202 200 {
203 201 "cell_type": "heading",
204 202 "level": 2,
205 203 "metadata": {
206 204 "slideshow": {
207 205 "slide_type": "slide"
208 206 }
209 207 },
210 208 "source": [
211 209 "Front-end (JavaScript)"
212 210 ]
213 211 },
214 212 {
215 213 "cell_type": "heading",
216 214 "level": 3,
217 215 "metadata": {},
218 216 "source": [
219 217 "Models and views"
220 218 ]
221 219 },
222 220 {
223 221 "cell_type": "markdown",
224 222 "metadata": {},
225 223 "source": [
226 224 "The IPython widget framework front-end relies heavily on [Backbone.js](http://backbonejs.org/). **Backbone.js is an MVC (model view controller) framework**. Widgets defined in the back-end are automatically **synchronized with generic Backbone.js models** in the front-end. The traitlets are added to the front-end instance **automatically on first state push**. The **`_view_name` trait** that you defined earlier is used by the widget framework to create the corresponding Backbone.js view and **link that view to the model**."
227 225 ]
228 226 },
229 227 {
230 228 "cell_type": "heading",
231 229 "level": 3,
232 230 "metadata": {
233 231 "slideshow": {
234 232 "slide_type": "slide"
235 233 }
236 234 },
237 235 "source": [
238 236 "Import the WidgetManager"
239 237 ]
240 238 },
241 239 {
242 240 "cell_type": "markdown",
243 241 "metadata": {},
244 242 "source": [
245 243 "You first need to **import the WidgetManager**. You will use it later to register your view by name (the same name you used in the back-end). To import the widget manager, use the `require` method of [require.js](http://requirejs.org/) (as seen below)."
246 244 ]
247 245 },
248 246 {
249 247 "cell_type": "code",
250 248 "collapsed": false,
251 249 "input": [
252 250 "%%javascript\n",
253 251 "\n",
254 252 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
255 253 " \n",
256 254 "});"
257 255 ],
258 256 "language": "python",
259 257 "metadata": {},
260 "outputs": [
261 {
262 "javascript": [
263 "\n",
264 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
265 " \n",
266 "});"
267 ],
268 "metadata": {},
269 "output_type": "display_data",
270 "text": [
271 "<IPython.core.display.Javascript object>"
272 ]
273 }
274 ],
275 "prompt_number": 2
258 "outputs": []
276 259 },
277 260 {
278 261 "cell_type": "heading",
279 262 "level": 3,
280 263 "metadata": {
281 264 "slideshow": {
282 265 "slide_type": "slide"
283 266 }
284 267 },
285 268 "source": [
286 269 "Define the view"
287 270 ]
288 271 },
289 272 {
290 273 "cell_type": "markdown",
291 274 "metadata": {},
292 275 "source": [
293 276 "Next define your widget view class. **Inherit from the `DOMWidgetView`** by using the `.extend` method. Register the view class with the widget manager by calling **`.register_widget_view`**. The **first parameter is the widget view name** (`_view_name` that you defined earlier in Python) and the **second is a handle to the class type**."
294 277 ]
295 278 },
296 279 {
297 280 "cell_type": "code",
298 281 "collapsed": false,
299 282 "input": [
300 283 "%%javascript\n",
301 284 "\n",
302 285 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
303 286 " \n",
304 287 " // Define the HelloView\n",
305 288 " var HelloView = IPython.DOMWidgetView.extend({\n",
306 289 " \n",
307 290 " });\n",
308 291 " \n",
309 292 " // Register the HelloView with the widget manager.\n",
310 293 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
311 294 "});"
312 295 ],
313 296 "language": "python",
314 297 "metadata": {},
315 "outputs": [
316 {
317 "javascript": [
318 "\n",
319 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
320 " \n",
321 " // Define the HelloView\n",
322 " var HelloView = IPython.DOMWidgetView.extend({\n",
323 " \n",
324 " });\n",
325 " \n",
326 " // Register the HelloView with the widget manager.\n",
327 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
328 "});"
329 ],
330 "metadata": {},
331 "output_type": "display_data",
332 "text": [
333 "<IPython.core.display.Javascript object>"
334 ]
335 }
336 ],
337 "prompt_number": 3
298 "outputs": []
338 299 },
339 300 {
340 301 "cell_type": "heading",
341 302 "level": 3,
342 303 "metadata": {
343 304 "slideshow": {
344 305 "slide_type": "slide"
345 306 }
346 307 },
347 308 "source": [
348 309 "Render method"
349 310 ]
350 311 },
351 312 {
352 313 "cell_type": "markdown",
353 314 "metadata": {},
354 315 "source": [
355 316 "Lastly, **override the base `render` method** of the view to define custom rendering logic. A handle to the widget's default div element can be acquired via **`this.$el`**. The `$el` property is a **[jQuery](http://jquery.com/) object handle** (which can be thought of as a supercharged version of the normal DOM element's handle)."
356 317 ]
357 318 },
358 319 {
359 320 "cell_type": "code",
360 321 "collapsed": false,
361 322 "input": [
362 323 "%%javascript\n",
363 324 "\n",
364 325 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
365 326 " \n",
366 327 " var HelloView = IPython.DOMWidgetView.extend({\n",
367 328 " \n",
368 329 " // Render the view.\n",
369 330 " render: function(){ \n",
370 331 " this.$el.text('Hello World!'); \n",
371 332 " },\n",
372 333 " });\n",
373 334 " \n",
374 335 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
375 336 "});"
376 337 ],
377 338 "language": "python",
378 339 "metadata": {},
379 "outputs": [
380 {
381 "javascript": [
382 "\n",
383 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
384 " \n",
385 " var HelloView = IPython.DOMWidgetView.extend({\n",
386 " \n",
387 " // Render the view.\n",
388 " render: function(){ \n",
389 " this.$el.text('Hello World!'); \n",
390 " },\n",
391 " });\n",
392 " \n",
393 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
394 "});"
395 ],
396 "metadata": {},
397 "output_type": "display_data",
398 "text": [
399 "<IPython.core.display.Javascript object>"
400 ]
401 }
402 ],
403 "prompt_number": 4
340 "outputs": []
404 341 },
405 342 {
406 343 "cell_type": "heading",
407 344 "level": 2,
408 345 "metadata": {
409 346 "slideshow": {
410 347 "slide_type": "slide"
411 348 }
412 349 },
413 350 "source": [
414 351 "Test"
415 352 ]
416 353 },
417 354 {
418 355 "cell_type": "markdown",
419 356 "metadata": {},
420 357 "source": [
421 358 "You should be able to display your widget just like any other widget now."
422 359 ]
423 360 },
424 361 {
425 362 "cell_type": "code",
426 363 "collapsed": false,
427 364 "input": [
428 365 "HelloWidget()"
429 366 ],
430 367 "language": "python",
431 368 "metadata": {},
432 "outputs": [],
433 "prompt_number": 5
369 "outputs": []
434 370 },
435 371 {
436 372 "cell_type": "heading",
437 373 "level": 2,
438 374 "metadata": {
439 375 "slideshow": {
440 376 "slide_type": "slide"
441 377 }
442 378 },
443 379 "source": [
444 380 "Making the widget stateful"
445 381 ]
446 382 },
447 383 {
448 384 "cell_type": "markdown",
449 385 "metadata": {},
450 386 "source": [
451 387 "There is not much that you can do with the above example that you can't do with the IPython display framework. To change this, you will make the widget stateful. Instead of displaying a static \"hello world\" message, it will **display a string set by the back-end**. First you need to **add a traitlet in the back-end**. Use the name of **`value` to stay consistent** with the rest of the widget framework and to **allow your widget to be used with interact**."
452 388 ]
453 389 },
454 390 {
455 391 "cell_type": "code",
456 392 "collapsed": false,
457 393 "input": [
458 394 "class HelloWidget(widgets.DOMWidget):\n",
459 395 " _view_name = Unicode('HelloView', sync=True)\n",
460 396 " value = Unicode('Hello World!', sync=True)"
461 397 ],
462 398 "language": "python",
463 399 "metadata": {},
464 "outputs": [],
465 "prompt_number": 6
400 "outputs": []
466 401 },
467 402 {
468 403 "cell_type": "heading",
469 404 "level": 3,
470 405 "metadata": {
471 406 "slideshow": {
472 407 "slide_type": "slide"
473 408 }
474 409 },
475 410 "source": [
476 411 "Accessing the model from the view"
477 412 ]
478 413 },
479 414 {
480 415 "cell_type": "markdown",
481 416 "metadata": {},
482 417 "source": [
483 418 "To access the model associate with a view instance, use the **`model` property** of the view. **`get` and `set`** methods are used to interact with the Backbone model. **`get` is trivial**, however you have to **be careful when using `set`**. **After calling the model `set`** you need call the **view's `touch` method**. This associates the `set` operation with a particular view so **output will be routed to the correct cell**. The model also has a **`on` method** which allows you to listen to events triggered by the model (like value changes)."
484 419 ]
485 420 },
486 421 {
487 422 "cell_type": "heading",
488 423 "level": 3,
489 424 "metadata": {
490 425 "slideshow": {
491 426 "slide_type": "slide"
492 427 }
493 428 },
494 429 "source": [
495 430 "Rendering model contents"
496 431 ]
497 432 },
498 433 {
499 434 "cell_type": "markdown",
500 435 "metadata": {},
501 436 "source": [
502 437 "By **replacing the string literal with a call to `model.get`**, the view will now display the **value of the back-end upon display**. However, it will not update itself to a new value when the value changes."
503 438 ]
504 439 },
505 440 {
506 441 "cell_type": "code",
507 442 "collapsed": false,
508 443 "input": [
509 444 "%%javascript\n",
510 445 "\n",
511 446 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
512 447 " \n",
513 448 " var HelloView = IPython.DOMWidgetView.extend({\n",
514 449 " \n",
515 450 " render: function(){ \n",
516 451 " this.$el.text(this.model.get('value')); \n",
517 452 " },\n",
518 453 " });\n",
519 454 " \n",
520 455 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
521 456 "});"
522 457 ],
523 458 "language": "python",
524 459 "metadata": {},
525 "outputs": [
526 {
527 "javascript": [
528 "\n",
529 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
530 " \n",
531 " var HelloView = IPython.DOMWidgetView.extend({\n",
532 " \n",
533 " render: function(){ \n",
534 " this.$el.text(this.model.get('value')); \n",
535 " },\n",
536 " });\n",
537 " \n",
538 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
539 "});"
540 ],
541 "metadata": {},
542 "output_type": "display_data",
543 "text": [
544 "<IPython.core.display.Javascript object>"
545 ]
546 }
547 ],
548 "prompt_number": 7
460 "outputs": []
549 461 },
550 462 {
551 463 "cell_type": "heading",
552 464 "level": 3,
553 465 "metadata": {
554 466 "slideshow": {
555 467 "slide_type": "slide"
556 468 }
557 469 },
558 470 "source": [
559 471 "Dynamic updates"
560 472 ]
561 473 },
562 474 {
563 475 "cell_type": "markdown",
564 476 "metadata": {},
565 477 "source": [
566 478 "To get the view to **update itself dynamically**, register a function to update the view's value when the model's `value` property changes. This can be done using the **`model.on` method**. The `on` method takes three parameters, an event name, callback handle, and callback context. The Backbone **event named `change`** will fire whenever the model changes. By **appending `:value`** to it, you tell Backbone to only listen to the change event of the `value` property (as seen below)."
567 479 ]
568 480 },
569 481 {
570 482 "cell_type": "code",
571 483 "collapsed": false,
572 484 "input": [
573 485 "%%javascript\n",
574 486 "\n",
575 487 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
576 488 " \n",
577 489 " var HelloView = IPython.DOMWidgetView.extend({\n",
578 490 " \n",
579 491 " \n",
580 492 " render: function(){ \n",
581 493 " this.value_changed();\n",
582 494 " this.model.on('change:value', this.value_changed, this);\n",
583 495 " },\n",
584 496 " \n",
585 497 " value_changed: function() {\n",
586 498 " this.$el.text(this.model.get('value')); \n",
587 499 " },\n",
588 500 " });\n",
589 501 " \n",
590 502 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
591 503 "});"
592 504 ],
593 505 "language": "python",
594 506 "metadata": {},
595 "outputs": [
596 {
597 "javascript": [
598 "\n",
599 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
600 " \n",
601 " var HelloView = IPython.DOMWidgetView.extend({\n",
602 " \n",
603 " \n",
604 " render: function(){ \n",
605 " this.value_changed();\n",
606 " this.model.on('change:value', this.value_changed, this);\n",
607 " },\n",
608 " \n",
609 " value_changed: function() {\n",
610 " this.$el.text(this.model.get('value')); \n",
611 " },\n",
612 " });\n",
613 " \n",
614 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
615 "});"
616 ],
617 "metadata": {},
618 "output_type": "display_data",
619 "text": [
620 "<IPython.core.display.Javascript object>"
621 ]
622 }
623 ],
624 "prompt_number": 8
507 "outputs": []
625 508 },
626 509 {
627 510 "cell_type": "heading",
628 511 "level": 2,
629 512 "metadata": {
630 513 "slideshow": {
631 514 "slide_type": "slide"
632 515 }
633 516 },
634 517 "source": [
635 518 "Test"
636 519 ]
637 520 },
638 521 {
639 522 "cell_type": "code",
640 523 "collapsed": false,
641 524 "input": [
642 525 "w = HelloWidget()\n",
643 526 "w"
644 527 ],
645 528 "language": "python",
646 529 "metadata": {},
647 "outputs": [],
648 "prompt_number": 9
530 "outputs": []
649 531 },
650 532 {
651 533 "cell_type": "code",
652 534 "collapsed": false,
653 535 "input": [
654 536 "w.value = 'test'"
655 537 ],
656 538 "language": "python",
657 539 "metadata": {},
658 "outputs": [],
659 "prompt_number": 10
540 "outputs": []
660 541 },
661 542 {
662 543 "cell_type": "heading",
663 544 "level": 1,
664 545 "metadata": {
665 546 "slideshow": {
666 547 "slide_type": "slide"
667 548 }
668 549 },
669 550 "source": [
670 551 "Finishing"
671 552 ]
672 553 },
673 554 {
674 555 "cell_type": "heading",
675 556 "level": 2,
676 557 "metadata": {},
677 558 "source": [
678 559 "Bidirectional communication"
679 560 ]
680 561 },
681 562 {
682 563 "cell_type": "markdown",
683 564 "metadata": {},
684 565 "source": [
685 566 "The examples above dump the value directly into the DOM. There is no way for you to interact with this dumped data in the front-end. To create an example that **accepts input**, you will have to do something more than blindly dumping the contents of value into the DOM. In this part of the tutorial, you will **use a jQuery spinner** to display and accept input in the front-end. IPython currently lacks a spinner implementation so this widget will be unique."
686 567 ]
687 568 },
688 569 {
689 570 "cell_type": "heading",
690 571 "level": 3,
691 572 "metadata": {
692 573 "slideshow": {
693 574 "slide_type": "slide"
694 575 }
695 576 },
696 577 "source": [
697 578 "Update the Python code"
698 579 ]
699 580 },
700 581 {
701 582 "cell_type": "markdown",
702 583 "metadata": {},
703 584 "source": [
704 585 "You will need to change the type of the **value traitlet to `Int`**. It also makes sense to **change the name of the widget** to something more appropriate, like `SpinnerWidget`."
705 586 ]
706 587 },
707 588 {
708 589 "cell_type": "code",
709 590 "collapsed": false,
710 591 "input": [
711 592 "from IPython.utils.traitlets import CInt\n",
712 593 "class SpinnerWidget(widgets.DOMWidget):\n",
713 594 " _view_name = Unicode('SpinnerView', sync=True)\n",
714 595 " value = CInt(0, sync=True)"
715 596 ],
716 597 "language": "python",
717 598 "metadata": {},
718 "outputs": [],
719 "prompt_number": 11
599 "outputs": []
720 600 },
721 601 {
722 602 "cell_type": "heading",
723 603 "level": 3,
724 604 "metadata": {
725 605 "slideshow": {
726 606 "slide_type": "slide"
727 607 }
728 608 },
729 609 "source": [
730 610 "Updating the Javascript code"
731 611 ]
732 612 },
733 613 {
734 614 "cell_type": "markdown",
735 615 "metadata": {},
736 616 "source": [
737 617 "The [jQuery docs for the spinner control](https://jqueryui.com/spinner/) say to use **`.spinner` to create a spinner** in an element. Calling **`.spinner` on `$el` will create a spinner inside `$el`**. Make sure to **update the widget name here too** so it's the same as `_view_name` in the back-end."
738 618 ]
739 619 },
740 620 {
741 621 "cell_type": "code",
742 622 "collapsed": false,
743 623 "input": [
744 624 "%%javascript\n",
745 625 "\n",
746 626 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
747 627 " \n",
748 628 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
749 629 " \n",
750 630 " render: function(){ \n",
751 631 " \n",
752 632 " // jQuery code to create a spinner and append it to $el\n",
753 633 " this.$input = $('<input />');\n",
754 634 " this.$el.append(this.$input);\n",
755 635 " this.$spinner = this.$input.spinner({\n",
756 636 " change: function( event, ui ) {}\n",
757 637 " });\n",
758 638 " \n",
759 639 " this.value_changed();\n",
760 640 " this.model.on('change:value', this.value_changed, this);\n",
761 641 " },\n",
762 642 " \n",
763 643 " value_changed: function() {\n",
764 644 " \n",
765 645 " },\n",
766 646 " });\n",
767 647 " \n",
768 648 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
769 649 "});"
770 650 ],
771 651 "language": "python",
772 652 "metadata": {},
773 "outputs": [
774 {
775 "javascript": [
776 "\n",
777 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
778 " \n",
779 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
780 " \n",
781 " render: function(){ \n",
782 " \n",
783 " // jQuery code to create a spinner and append it to $el\n",
784 " this.$input = $('<input />');\n",
785 " this.$el.append(this.$input);\n",
786 " this.$spinner = this.$input.spinner({\n",
787 " change: function( event, ui ) {}\n",
788 " });\n",
789 " \n",
790 " this.value_changed();\n",
791 " this.model.on('change:value', this.value_changed, this);\n",
792 " },\n",
793 " \n",
794 " value_changed: function() {\n",
795 " \n",
796 " },\n",
797 " });\n",
798 " \n",
799 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
800 "});"
801 ],
802 "metadata": {},
803 "output_type": "display_data",
804 "text": [
805 "<IPython.core.display.Javascript object>"
806 ]
807 }
808 ],
809 "prompt_number": 12
653 "outputs": []
810 654 },
811 655 {
812 656 "cell_type": "heading",
813 657 "level": 3,
814 658 "metadata": {
815 659 "slideshow": {
816 660 "slide_type": "slide"
817 661 }
818 662 },
819 663 "source": [
820 664 "Getting and setting the value"
821 665 ]
822 666 },
823 667 {
824 668 "cell_type": "markdown",
825 669 "metadata": {},
826 670 "source": [
827 671 "To **set the value of the spinner on update from the back-end**, you need to use **jQuery's `spinner` API**. `spinner.spinner('value', new)` will set the value of the spinner. Add that code to the **`value_changed` method** to make the spinner **update with the value stored in the back-end((. Using jQuery's spinner API, you can add a function to handle the **spinner `change` event** by passing it in when constructing the spinner. Inside the `change` event, call **`model.set`** to set the value and then **`touch`** to inform the framework that this view was the view that caused the change to the model. **Note: The `var that = this;` is a JavaScript trick to pass the current context into closures.**"
828 672 ]
829 673 },
830 674 {
831 675 "cell_type": "code",
832 676 "collapsed": false,
833 677 "input": [
834 678 "%%javascript\n",
835 679 "\n",
836 680 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
837 681 " \n",
838 682 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
839 683 " \n",
840 684 " render: function(){ \n",
841 685 "\n",
842 686 " var that = this;\n",
843 687 " this.$input = $('<input />');\n",
844 688 " this.$el.append(this.$input);\n",
845 689 " this.$spinner = this.$input.spinner({\n",
846 690 " change: function( event, ui ) {\n",
847 691 " that.handle_spin();\n",
848 692 " },\n",
849 693 " spin: function( event, ui ) {\n",
850 694 " that.handle_spin();\n",
851 695 " }\n",
852 696 " });\n",
853 697 " \n",
854 698 " this.value_changed();\n",
855 699 " this.model.on('change:value', this.value_changed, this);\n",
856 700 " },\n",
857 701 " \n",
858 702 " value_changed: function() {\n",
859 703 " this.$spinner.spinner('value', this.model.get('value'));\n",
860 704 " },\n",
861 705 " \n",
862 706 " handle_spin: function() {\n",
863 707 " this.model.set('value', this.$spinner.spinner('value'));\n",
864 708 " this.touch();\n",
865 709 " },\n",
866 710 " });\n",
867 711 " \n",
868 712 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
869 713 "});"
870 714 ],
871 715 "language": "python",
872 716 "metadata": {},
873 "outputs": [
874 {
875 "javascript": [
876 "\n",
877 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
878 " \n",
879 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
880 " \n",
881 " render: function(){ \n",
882 "\n",
883 " var that = this;\n",
884 " this.$input = $('<input />');\n",
885 " this.$el.append(this.$input);\n",
886 " this.$spinner = this.$input.spinner({\n",
887 " change: function( event, ui ) {\n",
888 " that.handle_spin();\n",
889 " },\n",
890 " spin: function( event, ui ) {\n",
891 " that.handle_spin();\n",
892 " }\n",
893 " });\n",
894 " \n",
895 " this.value_changed();\n",
896 " this.model.on('change:value', this.value_changed, this);\n",
897 " },\n",
898 " \n",
899 " value_changed: function() {\n",
900 " this.$spinner.spinner('value', this.model.get('value'));\n",
901 " },\n",
902 " \n",
903 " handle_spin: function() {\n",
904 " this.model.set('value', this.$spinner.spinner('value'));\n",
905 " this.touch();\n",
906 " },\n",
907 " });\n",
908 " \n",
909 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
910 "});"
911 ],
912 "metadata": {},
913 "output_type": "display_data",
914 "text": [
915 "<IPython.core.display.Javascript object>"
916 ]
917 }
918 ],
919 "prompt_number": 13
717 "outputs": []
920 718 },
921 719 {
922 720 "cell_type": "heading",
923 721 "level": 2,
924 722 "metadata": {
925 723 "slideshow": {
926 724 "slide_type": "slide"
927 725 }
928 726 },
929 727 "source": [
930 728 "Test"
931 729 ]
932 730 },
933 731 {
934 732 "cell_type": "code",
935 733 "collapsed": false,
936 734 "input": [
937 735 "w = SpinnerWidget(value=5)\n",
938 736 "w"
939 737 ],
940 738 "language": "python",
941 739 "metadata": {},
942 "outputs": [],
943 "prompt_number": 15
740 "outputs": []
944 741 },
945 742 {
946 743 "cell_type": "code",
947 744 "collapsed": false,
948 745 "input": [
949 746 "w.value"
950 747 ],
951 748 "language": "python",
952 749 "metadata": {},
953 "outputs": [
954 {
955 "metadata": {},
956 "output_type": "pyout",
957 "prompt_number": 16,
958 "text": [
959 "5"
960 ]
961 }
962 ],
963 "prompt_number": 16
750 "outputs": []
964 751 },
965 752 {
966 753 "cell_type": "code",
967 754 "collapsed": false,
968 755 "input": [
969 756 "w.value = 20"
970 757 ],
971 758 "language": "python",
972 759 "metadata": {},
973 "outputs": [],
974 "prompt_number": 17
760 "outputs": []
975 761 },
976 762 {
977 763 "cell_type": "markdown",
978 764 "metadata": {},
979 765 "source": [
980 766 "Trying to **use the spinner with another widget**."
981 767 ]
982 768 },
983 769 {
984 770 "cell_type": "code",
985 771 "collapsed": false,
986 772 "input": [
987 773 "from IPython.display import display\n",
988 774 "w1 = SpinnerWidget(value=0)\n",
989 775 "w2 = widgets.IntSliderWidget()\n",
990 776 "display(w1,w2)\n",
991 777 "\n",
992 778 "from IPython.utils.traitlets import link\n",
993 779 "mylink = link((w1, 'value'), (w2, 'value'))"
994 780 ],
995 781 "language": "python",
996 782 "metadata": {},
997 "outputs": [],
998 "prompt_number": 18
783 "outputs": []
999 784 },
1000 785 {
1001 786 "cell_type": "markdown",
1002 787 "metadata": {},
1003 788 "source": [
1004 789 "[Index](Index.ipynb) - [Back](Widget Styling.ipynb)"
1005 790 ]
1006 791 }
1007 792 ],
1008 793 "metadata": {}
1009 794 }
1010 795 ]
1011 796 } No newline at end of file
@@ -1,478 +1,437 b''
1 1 {
2 2 "metadata": {
3 3 "celltoolbar": "Slideshow",
4 4 "name": "",
5 "signature": "sha256:4ca68d6f219809b3b1c4e84665384a4069dbc1c8496fdbdcba1508bbe1266b44"
5 "signature": "sha256:916b80c91b959f78d7e5a9d5c9c7d371d3aa2b4476fdb19a7cb5cf9666d68d5b"
6 6 },
7 7 "nbformat": 3,
8 8 "nbformat_minor": 0,
9 9 "worksheets": [
10 10 {
11 11 "cells": [
12 12 {
13 13 "cell_type": "markdown",
14 14 "metadata": {},
15 15 "source": [
16 16 "[Index](Index.ipynb) - [Next](Widget List.ipynb)"
17 17 ]
18 18 },
19 19 {
20 20 "cell_type": "heading",
21 21 "level": 1,
22 22 "metadata": {},
23 23 "source": [
24 24 "Simple Widget Introduction"
25 25 ]
26 26 },
27 27 {
28 28 "cell_type": "heading",
29 29 "level": 2,
30 30 "metadata": {},
31 31 "source": [
32 32 "What are widgets?"
33 33 ]
34 34 },
35 35 {
36 36 "cell_type": "markdown",
37 37 "metadata": {
38 38 "slideshow": {
39 39 "slide_type": "slide"
40 40 }
41 41 },
42 42 "source": [
43 43 "Widgets are elements that exists in both the front-end and the back-end.\n",
44 44 "\n",
45 45 "![Kernel & front-end diagram](../images/FrontendKernel.png)"
46 46 ]
47 47 },
48 48 {
49 49 "cell_type": "heading",
50 50 "level": 2,
51 51 "metadata": {},
52 52 "source": [
53 53 "What can they be used for?"
54 54 ]
55 55 },
56 56 {
57 57 "cell_type": "markdown",
58 58 "metadata": {
59 59 "slideshow": {
60 60 "slide_type": "slide"
61 61 }
62 62 },
63 63 "source": [
64 64 "You can use widgets to build **interactive GUIs** for your notebooks. \n",
65 65 "You can also use widgets to **synchronize stateful and stateless information** between Python and JavaScript."
66 66 ]
67 67 },
68 68 {
69 69 "cell_type": "heading",
70 70 "level": 2,
71 71 "metadata": {},
72 72 "source": [
73 73 "Using widgets "
74 74 ]
75 75 },
76 76 {
77 77 "cell_type": "markdown",
78 78 "metadata": {
79 79 "slideshow": {
80 80 "slide_type": "slide"
81 81 }
82 82 },
83 83 "source": [
84 84 "To use the widget framework, you need to **import `IPython.html.widgets`**."
85 85 ]
86 86 },
87 87 {
88 88 "cell_type": "code",
89 89 "collapsed": false,
90 90 "input": [
91 91 "from IPython.html.widgets import *"
92 92 ],
93 93 "language": "python",
94 94 "metadata": {},
95 "outputs": [],
96 "prompt_number": 1
95 "outputs": []
97 96 },
98 97 {
99 98 "cell_type": "heading",
100 99 "level": 3,
101 100 "metadata": {
102 101 "slideshow": {
103 102 "slide_type": "slide"
104 103 }
105 104 },
106 105 "source": [
107 106 "repr"
108 107 ]
109 108 },
110 109 {
111 110 "cell_type": "markdown",
112 111 "metadata": {},
113 112 "source": [
114 113 "Widgets have their own display `repr` which allows them to be displayed using IPython's display framework. Constructing and returning an `IntSliderWidget` automatically displays the widget (as seen below). Widgets are **displayed inside the `widget area`**, which sits between the code cell and output. **You can hide all of the widgets** in the `widget area` by clicking the grey *x* in the margin."
115 114 ]
116 115 },
117 116 {
118 117 "cell_type": "code",
119 118 "collapsed": false,
120 119 "input": [
121 120 "IntSliderWidget()"
122 121 ],
123 122 "language": "python",
124 123 "metadata": {},
125 "outputs": [],
126 "prompt_number": 2
124 "outputs": []
127 125 },
128 126 {
129 127 "cell_type": "heading",
130 128 "level": 3,
131 129 "metadata": {
132 130 "slideshow": {
133 131 "slide_type": "slide"
134 132 }
135 133 },
136 134 "source": [
137 135 "display()"
138 136 ]
139 137 },
140 138 {
141 139 "cell_type": "markdown",
142 140 "metadata": {},
143 141 "source": [
144 142 "You can also explicitly display the widget using `display(...)`."
145 143 ]
146 144 },
147 145 {
148 146 "cell_type": "code",
149 147 "collapsed": false,
150 148 "input": [
151 149 "from IPython.display import display\n",
152 150 "w = IntSliderWidget()\n",
153 151 "display(w)"
154 152 ],
155 153 "language": "python",
156 154 "metadata": {},
157 "outputs": [],
158 "prompt_number": 3
155 "outputs": []
159 156 },
160 157 {
161 158 "cell_type": "heading",
162 159 "level": 3,
163 160 "metadata": {
164 161 "slideshow": {
165 162 "slide_type": "slide"
166 163 }
167 164 },
168 165 "source": [
169 166 "Multiple display() calls"
170 167 ]
171 168 },
172 169 {
173 170 "cell_type": "markdown",
174 171 "metadata": {},
175 172 "source": [
176 173 "If you display the same widget twice, the displayed instances in the front-end **will remain in sync** with each other."
177 174 ]
178 175 },
179 176 {
180 177 "cell_type": "code",
181 178 "collapsed": false,
182 179 "input": [
183 180 "display(w)"
184 181 ],
185 182 "language": "python",
186 183 "metadata": {},
187 "outputs": [],
188 "prompt_number": 4
184 "outputs": []
189 185 },
190 186 {
191 187 "cell_type": "heading",
192 188 "level": 2,
193 189 "metadata": {},
194 190 "source": [
195 191 "Why does displaying the same widget twice work?"
196 192 ]
197 193 },
198 194 {
199 195 "cell_type": "markdown",
200 196 "metadata": {
201 197 "slideshow": {
202 198 "slide_type": "slide"
203 199 }
204 200 },
205 201 "source": [
206 202 "Widgets are **represented in the back-end by a single object**. Each time a widget is displayed, **a new representation** of that same object is created in the front-end. These representations are called **views**.\n",
207 203 "\n",
208 204 "![Kernel & front-end diagram](images/WidgetModelView.png)"
209 205 ]
210 206 },
211 207 {
212 208 "cell_type": "heading",
213 209 "level": 3,
214 210 "metadata": {
215 211 "slideshow": {
216 212 "slide_type": "slide"
217 213 }
218 214 },
219 215 "source": [
220 216 "Closing widgets"
221 217 ]
222 218 },
223 219 {
224 220 "cell_type": "markdown",
225 221 "metadata": {},
226 222 "source": [
227 223 "You can close a widget by calling its `close()` method."
228 224 ]
229 225 },
230 226 {
231 227 "cell_type": "code",
232 228 "collapsed": false,
233 229 "input": [
234 230 "display(w)"
235 231 ],
236 232 "language": "python",
237 233 "metadata": {},
238 234 "outputs": []
239 235 },
240 236 {
241 237 "cell_type": "code",
242 238 "collapsed": false,
243 239 "input": [
244 240 "w.close()"
245 241 ],
246 242 "language": "python",
247 243 "metadata": {},
248 "outputs": [],
249 "prompt_number": 5
244 "outputs": []
250 245 },
251 246 {
252 247 "cell_type": "heading",
253 248 "level": 2,
254 249 "metadata": {},
255 250 "source": [
256 251 "Widget properties"
257 252 ]
258 253 },
259 254 {
260 255 "cell_type": "markdown",
261 256 "metadata": {
262 257 "slideshow": {
263 258 "slide_type": "slide"
264 259 }
265 260 },
266 261 "source": [
267 262 "All of the IPython widgets **share a similar naming scheme**. To read the value of a widget, you can query its `value` property."
268 263 ]
269 264 },
270 265 {
271 266 "cell_type": "code",
272 267 "collapsed": false,
273 268 "input": [
274 269 "w = IntSliderWidget()\n",
275 270 "display(w)"
276 271 ],
277 272 "language": "python",
278 273 "metadata": {},
279 "outputs": [],
280 "prompt_number": 9
274 "outputs": []
281 275 },
282 276 {
283 277 "cell_type": "code",
284 278 "collapsed": false,
285 279 "input": [
286 280 "w.value"
287 281 ],
288 282 "language": "python",
289 283 "metadata": {},
290 "outputs": [
291 {
292 "metadata": {},
293 "output_type": "pyout",
294 "prompt_number": 11,
295 "text": [
296 "40"
297 ]
298 }
299 ],
300 "prompt_number": 11
284 "outputs": []
301 285 },
302 286 {
303 287 "cell_type": "markdown",
304 288 "metadata": {},
305 289 "source": [
306 290 "Similarly, to set a widget's value, you can set its `value` property."
307 291 ]
308 292 },
309 293 {
310 294 "cell_type": "code",
311 295 "collapsed": false,
312 296 "input": [
313 297 "w.value = 100"
314 298 ],
315 299 "language": "python",
316 300 "metadata": {},
317 "outputs": [],
318 "prompt_number": 12
301 "outputs": []
319 302 },
320 303 {
321 304 "cell_type": "heading",
322 305 "level": 3,
323 306 "metadata": {
324 307 "slideshow": {
325 308 "slide_type": "slide"
326 309 }
327 310 },
328 311 "source": [
329 312 "Keys"
330 313 ]
331 314 },
332 315 {
333 316 "cell_type": "markdown",
334 317 "metadata": {},
335 318 "source": [
336 319 "In addition to `value`, most widgets share `keys`, `description`, `disabled`, and `visible`. To see the entire list of synchronized, stateful properties, of any specific widget, you can **query the `keys` property**."
337 320 ]
338 321 },
339 322 {
340 323 "cell_type": "code",
341 324 "collapsed": false,
342 325 "input": [
343 326 "w.keys"
344 327 ],
345 328 "language": "python",
346 329 "metadata": {},
347 "outputs": [
348 {
349 "metadata": {},
350 "output_type": "pyout",
351 "prompt_number": 13,
352 "text": [
353 "['_view_name',\n",
354 " 'orientation',\n",
355 " 'msg_throttle',\n",
356 " 'min',\n",
357 " 'max',\n",
358 " '_css',\n",
359 " 'value',\n",
360 " 'readout',\n",
361 " 'disabled',\n",
362 " 'visible',\n",
363 " 'step',\n",
364 " 'description']"
365 ]
366 }
367 ],
368 "prompt_number": 13
330 "outputs": []
369 331 },
370 332 {
371 333 "cell_type": "heading",
372 334 "level": 3,
373 335 "metadata": {},
374 336 "source": [
375 337 "Shorthand for setting the initial values of widget properties"
376 338 ]
377 339 },
378 340 {
379 341 "cell_type": "markdown",
380 342 "metadata": {
381 343 "slideshow": {
382 344 "slide_type": "slide"
383 345 }
384 346 },
385 347 "source": [
386 348 "While creating a widget, you can set some or all of the initial values of that widget by **defining them as keyword arguments in the widget's constructor** (as seen below)."
387 349 ]
388 350 },
389 351 {
390 352 "cell_type": "code",
391 353 "collapsed": false,
392 354 "input": [
393 355 "TextWidget(value='Hello World!', disabled=True)"
394 356 ],
395 357 "language": "python",
396 358 "metadata": {},
397 "outputs": [],
398 "prompt_number": 14
359 "outputs": []
399 360 },
400 361 {
401 362 "cell_type": "heading",
402 363 "level": 2,
403 364 "metadata": {},
404 365 "source": [
405 366 "Linking two similar widgets"
406 367 ]
407 368 },
408 369 {
409 370 "cell_type": "markdown",
410 371 "metadata": {
411 372 "slideshow": {
412 373 "slide_type": "slide"
413 374 }
414 375 },
415 376 "source": [
416 377 "If you need to display the same value two different ways, you'll have to use two different widgets. Instead of **attempting to manually synchronize the values** of the two widgets, you can use the `traitlet` `link` function **to link two properties together**. Below, the values of three widgets are linked together."
417 378 ]
418 379 },
419 380 {
420 381 "cell_type": "code",
421 382 "collapsed": false,
422 383 "input": [
423 384 "from IPython.utils.traitlets import link\n",
424 385 "a = FloatTextWidget()\n",
425 386 "b = FloatSliderWidget()\n",
426 387 "c = FloatProgressWidget()\n",
427 388 "display(a,b,c)\n",
428 389 "\n",
429 390 "\n",
430 391 "mylink = link((a, 'value'), (b, 'value'), (c, 'value'))"
431 392 ],
432 393 "language": "python",
433 394 "metadata": {},
434 "outputs": [],
435 "prompt_number": 15
395 "outputs": []
436 396 },
437 397 {
438 398 "cell_type": "heading",
439 399 "level": 3,
440 400 "metadata": {},
441 401 "source": [
442 402 "Unlinking widgets"
443 403 ]
444 404 },
445 405 {
446 406 "cell_type": "markdown",
447 407 "metadata": {
448 408 "slideshow": {
449 409 "slide_type": "slide"
450 410 }
451 411 },
452 412 "source": [
453 413 "Unlinking the widgets is simple. All you have to do is call `.unlink` on the link object."
454 414 ]
455 415 },
456 416 {
457 417 "cell_type": "code",
458 418 "collapsed": false,
459 419 "input": [
460 420 "mylink.unlink()"
461 421 ],
462 422 "language": "python",
463 423 "metadata": {},
464 "outputs": [],
465 "prompt_number": 16
424 "outputs": []
466 425 },
467 426 {
468 427 "cell_type": "markdown",
469 428 "metadata": {},
470 429 "source": [
471 430 "[Index](Index.ipynb) - [Next](Widget List.ipynb)"
472 431 ]
473 432 }
474 433 ],
475 434 "metadata": {}
476 435 }
477 436 ]
478 437 } No newline at end of file
@@ -1,352 +1,226 b''
1 1 {
2 2 "metadata": {
3 3 "cell_tags": [
4 4 [
5 5 "<None>",
6 6 null
7 7 ]
8 8 ],
9 9 "celltoolbar": "Slideshow",
10 10 "name": "",
11 "signature": "sha256:00bfd86bbcdbb8dcaea27753885c4ee4727c9b56bd460c3ee0595641e4afe21f"
11 "signature": "sha256:43e4910dd01111e1206f4f7940a201d6d5e69485df79de96e0ad927eb0046226"
12 12 },
13 13 "nbformat": 3,
14 14 "nbformat_minor": 0,
15 15 "worksheets": [
16 16 {
17 17 "cells": [
18 18 {
19 19 "cell_type": "markdown",
20 20 "metadata": {},
21 21 "source": [
22 22 "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)"
23 23 ]
24 24 },
25 25 {
26 26 "cell_type": "heading",
27 27 "level": 1,
28 28 "metadata": {
29 29 "slideshow": {
30 30 "slide_type": "slide"
31 31 }
32 32 },
33 33 "source": [
34 34 "Widget Events"
35 35 ]
36 36 },
37 37 {
38 38 "cell_type": "heading",
39 39 "level": 2,
40 40 "metadata": {},
41 41 "source": [
42 42 "Special events"
43 43 ]
44 44 },
45 45 {
46 46 "cell_type": "code",
47 47 "collapsed": false,
48 48 "input": [
49 49 "from __future__ import print_function"
50 50 ],
51 51 "language": "python",
52 52 "metadata": {},
53 "outputs": [],
54 "prompt_number": 1
53 "outputs": []
55 54 },
56 55 {
57 56 "cell_type": "markdown",
58 57 "metadata": {},
59 58 "source": [
60 59 "The `ButtonWidget` is not 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 function to be called when the button is clicked. The doc string of the `on_click` can be seen below."
61 60 ]
62 61 },
63 62 {
64 63 "cell_type": "code",
65 64 "collapsed": false,
66 65 "input": [
67 66 "from IPython.html import widgets\n",
68 67 "print(widgets.ButtonWidget.on_click.__doc__)"
69 68 ],
70 69 "language": "python",
71 70 "metadata": {},
72 "outputs": [
73 {
74 "output_type": "stream",
75 "stream": "stdout",
76 "text": [
77 "Register a callback to execute when the button is clicked.\n",
78 "\n",
79 " The callback will be called with one argument,\n",
80 " the clicked button widget instance.\n",
81 "\n",
82 " Parameters\n",
83 " ----------\n",
84 " remove : bool (optional)\n",
85 " Set to true to remove the callback from the list of callbacks.\n"
86 ]
87 }
88 ],
89 "prompt_number": 2
71 "outputs": []
90 72 },
91 73 {
92 74 "cell_type": "heading",
93 75 "level": 3,
94 76 "metadata": {
95 77 "slideshow": {
96 78 "slide_type": "slide"
97 79 }
98 80 },
99 81 "source": [
100 82 "Example"
101 83 ]
102 84 },
103 85 {
104 86 "cell_type": "markdown",
105 87 "metadata": {},
106 88 "source": [
107 89 "Since button clicks are **stateless**, they are **transmitted from the front-end to the back-end using custom messages**. By using the `on_click` method, a button that prints a message when it has been clicked is shown below."
108 90 ]
109 91 },
110 92 {
111 93 "cell_type": "code",
112 94 "collapsed": false,
113 95 "input": [
114 96 "from IPython.display import display\n",
115 97 "button = widgets.ButtonWidget(description=\"Click Me!\")\n",
116 98 "display(button)\n",
117 99 "\n",
118 100 "def on_button_clicked(b):\n",
119 101 " print(\"Button clicked.\")\n",
120 102 "\n",
121 103 "button.on_click(on_button_clicked)"
122 104 ],
123 105 "language": "python",
124 106 "metadata": {},
125 "outputs": [
126 {
127 "output_type": "stream",
128 "stream": "stdout",
129 "text": [
130 "Button clicked.\n"
131 ]
132 },
133 {
134 "output_type": "stream",
135 "stream": "stdout",
136 "text": [
137 "Button clicked.\n"
138 ]
139 },
140 {
141 "output_type": "stream",
142 "stream": "stdout",
143 "text": [
144 "Button clicked.\n"
145 ]
146 }
147 ],
148 "prompt_number": 3
107 "outputs": []
149 108 },
150 109 {
151 110 "cell_type": "heading",
152 111 "level": 3,
153 112 "metadata": {
154 113 "slideshow": {
155 114 "slide_type": "slide"
156 115 }
157 116 },
158 117 "source": [
159 118 "on_sumbit"
160 119 ]
161 120 },
162 121 {
163 122 "cell_type": "markdown",
164 123 "metadata": {},
165 124 "source": [
166 125 "The **`TextWidget`** also has a special **`on_submit` event**. The `on_submit` event **fires when the user hits return**."
167 126 ]
168 127 },
169 128 {
170 129 "cell_type": "code",
171 130 "collapsed": false,
172 131 "input": [
173 132 "text = widgets.TextWidget()\n",
174 133 "display(text)\n",
175 134 "\n",
176 135 "def handle_submit(sender):\n",
177 136 " print(text.value)\n",
178 137 "\n",
179 138 "text.on_submit(handle_submit)"
180 139 ],
181 140 "language": "python",
182 141 "metadata": {},
183 "outputs": [
184 {
185 "output_type": "stream",
186 "stream": "stdout",
187 "text": [
188 "adsfasdf\n"
189 ]
190 }
191 ],
192 "prompt_number": 4
142 "outputs": []
193 143 },
194 144 {
195 145 "cell_type": "heading",
196 146 "level": 2,
197 147 "metadata": {
198 148 "slideshow": {
199 149 "slide_type": "slide"
200 150 }
201 151 },
202 152 "source": [
203 153 "Traitlet events"
204 154 ]
205 155 },
206 156 {
207 157 "cell_type": "markdown",
208 158 "metadata": {},
209 159 "source": [
210 160 "**Widget properties are IPython traitlets** and **traitlets are eventful**. To handle changes, the **`on_trait_change` method** of the widget can be used to **register a callback**. The doc string for `on_trait_change` can be seen below."
211 161 ]
212 162 },
213 163 {
214 164 "cell_type": "code",
215 165 "collapsed": false,
216 166 "input": [
217 167 "print(widgets.Widget.on_trait_change.__doc__)"
218 168 ],
219 169 "language": "python",
220 170 "metadata": {},
221 "outputs": [
222 {
223 "output_type": "stream",
224 "stream": "stdout",
225 "text": [
226 "Setup a handler to be called when a trait changes.\n",
227 "\n",
228 " This is used to setup dynamic notifications of trait changes.\n",
229 "\n",
230 " Static handlers can be created by creating methods on a HasTraits\n",
231 " subclass with the naming convention '_[traitname]_changed'. Thus,\n",
232 " to create static handler for the trait 'a', create the method\n",
233 " _a_changed(self, name, old, new) (fewer arguments can be used, see\n",
234 " below).\n",
235 "\n",
236 " Parameters\n",
237 " ----------\n",
238 " handler : callable\n",
239 " A callable that is called when a trait changes. Its\n",
240 " signature can be handler(), handler(name), handler(name, new)\n",
241 " or handler(name, old, new).\n",
242 " name : list, str, None\n",
243 " If None, the handler will apply to all traits. If a list\n",
244 " of str, handler will apply to all names in the list. If a\n",
245 " str, the handler will apply just to that name.\n",
246 " remove : bool\n",
247 " If False (the default), then install the handler. If True\n",
248 " then unintall it.\n",
249 " \n"
250 ]
251 }
252 ],
253 "prompt_number": 5
171 "outputs": []
254 172 },
255 173 {
256 174 "cell_type": "heading",
257 175 "level": 3,
258 176 "metadata": {
259 177 "slideshow": {
260 178 "slide_type": "slide"
261 179 }
262 180 },
263 181 "source": [
264 182 "Signatures"
265 183 ]
266 184 },
267 185 {
268 186 "cell_type": "markdown",
269 187 "metadata": {},
270 188 "source": [
271 189 "Mentioned in the doc string, the callback registered can have **4 possible signatures**:\n",
272 190 "\n",
273 191 "- callback()\n",
274 192 "- callback(trait_name)\n",
275 193 "- callback(trait_name, new_value)\n",
276 194 "- callback(trait_name, old_value, new_value)\n",
277 195 "\n",
278 196 "Using this method, an example of how to output an IntSliderWiget's value as it is changed can be seen below."
279 197 ]
280 198 },
281 199 {
282 200 "cell_type": "code",
283 201 "collapsed": false,
284 202 "input": [
285 203 "int_range = widgets.IntSliderWidget()\n",
286 204 "display(int_range)\n",
287 205 "\n",
288 206 "def on_value_change(name, value):\n",
289 207 " print(value)\n",
290 208 "\n",
291 209 "int_range.on_trait_change(on_value_change, 'value')"
292 210 ],
293 211 "language": "python",
294 212 "metadata": {},
295 "outputs": [
296 {
297 "output_type": "stream",
298 "stream": "stdout",
299 "text": [
300 "1\n"
301 ]
302 },
303 {
304 "output_type": "stream",
305 "stream": "stdout",
306 "text": [
307 "4\n"
308 ]
309 },
310 {
311 "output_type": "stream",
312 "stream": "stdout",
313 "text": [
314 "13\n"
315 ]
316 },
317 {
318 "output_type": "stream",
319 "stream": "stdout",
320 "text": [
321 "26\n"
322 ]
323 },
324 {
325 "output_type": "stream",
326 "stream": "stdout",
327 "text": [
328 "31\n"
329 ]
330 },
331 {
332 "output_type": "stream",
333 "stream": "stdout",
334 "text": [
335 "34\n"
336 ]
337 }
338 ],
339 "prompt_number": 6
213 "outputs": []
340 214 },
341 215 {
342 216 "cell_type": "markdown",
343 217 "metadata": {},
344 218 "source": [
345 219 "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)"
346 220 ]
347 221 }
348 222 ],
349 223 "metadata": {}
350 224 }
351 225 ]
352 226 } No newline at end of file
@@ -1,651 +1,579 b''
1 1 {
2 2 "metadata": {
3 3 "celltoolbar": "Slideshow",
4 4 "name": "",
5 "signature": "sha256:5ded7796417476da43feb6a52919043719f504bd72c145163e3e8a1105c5b642"
5 "signature": "sha256:f8284581eb29fde72c434a9a414fcb60837302177ebaa4af6ff219dd2b726381"
6 6 },
7 7 "nbformat": 3,
8 8 "nbformat_minor": 0,
9 9 "worksheets": [
10 10 {
11 11 "cells": [
12 12 {
13 13 "cell_type": "markdown",
14 14 "metadata": {},
15 15 "source": [
16 16 "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)"
17 17 ]
18 18 },
19 19 {
20 20 "cell_type": "heading",
21 21 "level": 1,
22 22 "metadata": {},
23 23 "source": [
24 24 "Widget List"
25 25 ]
26 26 },
27 27 {
28 28 "cell_type": "heading",
29 29 "level": 2,
30 30 "metadata": {},
31 31 "source": [
32 32 "Complete list"
33 33 ]
34 34 },
35 35 {
36 36 "cell_type": "markdown",
37 37 "metadata": {
38 38 "slideshow": {
39 39 "slide_type": "slide"
40 40 }
41 41 },
42 42 "source": [
43 43 "For a complete list of the widgets available to you, you can list the classes in the widget namespace (as seen below). Classes with the suffix `Widget` are widgets. `Widget` and `DOMWidget` are base classes."
44 44 ]
45 45 },
46 46 {
47 47 "cell_type": "code",
48 48 "collapsed": false,
49 49 "input": [
50 50 "from IPython.html import widgets\n",
51 51 "[w for w in dir(widgets) if w.endswith('Widget')]"
52 52 ],
53 53 "language": "python",
54 54 "metadata": {},
55 "outputs": [
56 {
57 "metadata": {},
58 "output_type": "pyout",
59 "prompt_number": 1,
60 "text": [
61 "['AccordionWidget',\n",
62 " 'BoundedFloatTextWidget',\n",
63 " 'BoundedIntTextWidget',\n",
64 " 'ButtonWidget',\n",
65 " 'CheckboxWidget',\n",
66 " 'ContainerWidget',\n",
67 " 'DOMWidget',\n",
68 " 'DropdownWidget',\n",
69 " 'FloatProgressWidget',\n",
70 " 'FloatSliderWidget',\n",
71 " 'FloatTextWidget',\n",
72 " 'HTMLWidget',\n",
73 " 'ImageWidget',\n",
74 " 'IntProgressWidget',\n",
75 " 'IntSliderWidget',\n",
76 " 'IntTextWidget',\n",
77 " 'LatexWidget',\n",
78 " 'PopupWidget',\n",
79 " 'RadioButtonsWidget',\n",
80 " 'SelectWidget',\n",
81 " 'TabWidget',\n",
82 " 'TextWidget',\n",
83 " 'TextareaWidget',\n",
84 " 'ToggleButtonWidget',\n",
85 " 'ToggleButtonsWidget',\n",
86 " 'Widget']"
87 ]
88 }
89 ],
90 "prompt_number": 1
55 "outputs": []
91 56 },
92 57 {
93 58 "cell_type": "heading",
94 59 "level": 2,
95 60 "metadata": {
96 61 "slideshow": {
97 62 "slide_type": "slide"
98 63 }
99 64 },
100 65 "source": [
101 66 "Numeric widgets"
102 67 ]
103 68 },
104 69 {
105 70 "cell_type": "markdown",
106 71 "metadata": {},
107 72 "source": [
108 73 "There are 8 widgets distributed with IPython that are designed to display numeric values. Widgets exist for displaying integers and floats, both bounded and unbounded. The integer widgets share a similar naming scheme to their floating point counterparts. By replacing `Float` with `Int` in the widget name, you can find the Integer equivalent."
109 74 ]
110 75 },
111 76 {
112 77 "cell_type": "heading",
113 78 "level": 3,
114 79 "metadata": {
115 80 "slideshow": {
116 81 "slide_type": "slide"
117 82 }
118 83 },
119 84 "source": [
120 85 "FloatSliderWidget"
121 86 ]
122 87 },
123 88 {
124 89 "cell_type": "code",
125 90 "collapsed": false,
126 91 "input": [
127 92 "widgets.FloatSliderWidget(\n",
128 93 " value=7.5,\n",
129 94 " min=5.0,\n",
130 95 " max=10.0,\n",
131 96 " step=0.1,\n",
132 97 " description='Test:',\n",
133 98 ")"
134 99 ],
135 100 "language": "python",
136 101 "metadata": {},
137 "outputs": [],
138 "prompt_number": 2
102 "outputs": []
139 103 },
140 104 {
141 105 "cell_type": "markdown",
142 106 "metadata": {},
143 107 "source": [
144 108 "Sliders can also be **displayed vertically**."
145 109 ]
146 110 },
147 111 {
148 112 "cell_type": "code",
149 113 "collapsed": false,
150 114 "input": [
151 115 "widgets.FloatSliderWidget(\n",
152 116 " value=7.5,\n",
153 117 " min=5.0,\n",
154 118 " max=10.0,\n",
155 119 " step=0.1,\n",
156 120 " description='Test',\n",
157 121 " orientation='vertical',\n",
158 122 ")"
159 123 ],
160 124 "language": "python",
161 125 "metadata": {},
162 "outputs": [],
163 "prompt_number": 3
126 "outputs": []
164 127 },
165 128 {
166 129 "cell_type": "heading",
167 130 "level": 3,
168 131 "metadata": {
169 132 "slideshow": {
170 133 "slide_type": "slide"
171 134 }
172 135 },
173 136 "source": [
174 137 "FloatProgressWidget"
175 138 ]
176 139 },
177 140 {
178 141 "cell_type": "code",
179 142 "collapsed": false,
180 143 "input": [
181 144 "widgets.FloatProgressWidget(\n",
182 145 " value=7.5,\n",
183 146 " min=5.0,\n",
184 147 " max=10.0,\n",
185 148 " step=0.1,\n",
186 149 " description='Loading:',\n",
187 150 ")"
188 151 ],
189 152 "language": "python",
190 153 "metadata": {},
191 "outputs": [],
192 "prompt_number": 4
154 "outputs": []
193 155 },
194 156 {
195 157 "cell_type": "heading",
196 158 "level": 3,
197 159 "metadata": {
198 160 "slideshow": {
199 161 "slide_type": "slide"
200 162 }
201 163 },
202 164 "source": [
203 165 "BoundedFloatTextWidget"
204 166 ]
205 167 },
206 168 {
207 169 "cell_type": "code",
208 170 "collapsed": false,
209 171 "input": [
210 172 "widgets.BoundedFloatTextWidget(\n",
211 173 " value=7.5,\n",
212 174 " min=5.0,\n",
213 175 " max=10.0,\n",
214 176 " description='Text:',\n",
215 177 ")"
216 178 ],
217 179 "language": "python",
218 180 "metadata": {},
219 "outputs": [],
220 "prompt_number": 5
181 "outputs": []
221 182 },
222 183 {
223 184 "cell_type": "heading",
224 185 "level": 3,
225 186 "metadata": {
226 187 "slideshow": {
227 188 "slide_type": "slide"
228 189 }
229 190 },
230 191 "source": [
231 192 "FloatTextWidget"
232 193 ]
233 194 },
234 195 {
235 196 "cell_type": "code",
236 197 "collapsed": false,
237 198 "input": [
238 199 "widgets.FloatTextWidget(\n",
239 200 " value=7.5,\n",
240 201 " description='Any:',\n",
241 202 ")"
242 203 ],
243 204 "language": "python",
244 205 "metadata": {},
245 "outputs": [],
246 "prompt_number": 6
206 "outputs": []
247 207 },
248 208 {
249 209 "cell_type": "heading",
250 210 "level": 2,
251 211 "metadata": {
252 212 "slideshow": {
253 213 "slide_type": "slide"
254 214 }
255 215 },
256 216 "source": [
257 217 "Boolean widgets"
258 218 ]
259 219 },
260 220 {
261 221 "cell_type": "markdown",
262 222 "metadata": {},
263 223 "source": [
264 224 "There are two widgets that are designed to display a boolean value."
265 225 ]
266 226 },
267 227 {
268 228 "cell_type": "heading",
269 229 "level": 3,
270 230 "metadata": {},
271 231 "source": [
272 232 "ToggleButtonWidget"
273 233 ]
274 234 },
275 235 {
276 236 "cell_type": "code",
277 237 "collapsed": false,
278 238 "input": [
279 239 "widgets.ToggleButtonWidget(\n",
280 240 " description='Click me',\n",
281 241 " value=False,\n",
282 242 ")"
283 243 ],
284 244 "language": "python",
285 245 "metadata": {},
286 "outputs": [],
287 "prompt_number": 7
246 "outputs": []
288 247 },
289 248 {
290 249 "cell_type": "heading",
291 250 "level": 3,
292 251 "metadata": {
293 252 "slideshow": {
294 253 "slide_type": "slide"
295 254 }
296 255 },
297 256 "source": [
298 257 "CheckboxWidget"
299 258 ]
300 259 },
301 260 {
302 261 "cell_type": "code",
303 262 "collapsed": false,
304 263 "input": [
305 264 "widgets.CheckboxWidget(\n",
306 265 " description='Check me',\n",
307 266 " value=True,\n",
308 267 ")"
309 268 ],
310 269 "language": "python",
311 270 "metadata": {},
312 "outputs": [],
313 "prompt_number": 8
271 "outputs": []
314 272 },
315 273 {
316 274 "cell_type": "heading",
317 275 "level": 2,
318 276 "metadata": {
319 277 "slideshow": {
320 278 "slide_type": "slide"
321 279 }
322 280 },
323 281 "source": [
324 282 "Selection widgets"
325 283 ]
326 284 },
327 285 {
328 286 "cell_type": "markdown",
329 287 "metadata": {},
330 288 "source": [
331 289 "There are four widgets that can be used to display single selection lists. All four inherit from the same base class. You can specify the **enumeration of selectables by passing a list**. You can **also specify the enumeration as a dictionary**, in which case the **keys will be used as the item displayed** in the list and the corresponding **value will be returned** when an item is selected."
332 290 ]
333 291 },
334 292 {
335 293 "cell_type": "heading",
336 294 "level": 3,
337 295 "metadata": {
338 296 "slideshow": {
339 297 "slide_type": "slide"
340 298 }
341 299 },
342 300 "source": [
343 301 "DropdownWidget"
344 302 ]
345 303 },
346 304 {
347 305 "cell_type": "code",
348 306 "collapsed": false,
349 307 "input": [
350 308 "from IPython.display import display\n",
351 309 "w = widgets.DropdownWidget(\n",
352 310 " values=[1, 2, 3],\n",
353 311 " value=2,\n",
354 312 " description='Number:',\n",
355 313 ")\n",
356 314 "display(w)"
357 315 ],
358 316 "language": "python",
359 317 "metadata": {},
360 "outputs": [],
361 "prompt_number": 9
318 "outputs": []
362 319 },
363 320 {
364 321 "cell_type": "code",
365 322 "collapsed": false,
366 323 "input": [
367 324 "w.value"
368 325 ],
369 326 "language": "python",
370 327 "metadata": {},
371 "outputs": [
372 {
373 "metadata": {},
374 "output_type": "pyout",
375 "prompt_number": 10,
376 "text": [
377 "2"
378 ]
379 }
380 ],
381 "prompt_number": 10
328 "outputs": []
382 329 },
383 330 {
384 331 "cell_type": "markdown",
385 332 "metadata": {},
386 333 "source": [
387 334 "The following is also valid:"
388 335 ]
389 336 },
390 337 {
391 338 "cell_type": "code",
392 339 "collapsed": false,
393 340 "input": [
394 341 "w = widgets.DropdownWidget(\n",
395 342 " values={'One': 1, 'Two': 2, 'Three': 3},\n",
396 343 " value=2,\n",
397 344 " description='Number:',\n",
398 345 ")\n",
399 346 "display(w)"
400 347 ],
401 348 "language": "python",
402 349 "metadata": {},
403 "outputs": [],
404 "prompt_number": 11
350 "outputs": []
405 351 },
406 352 {
407 353 "cell_type": "code",
408 354 "collapsed": false,
409 355 "input": [
410 356 "w.value"
411 357 ],
412 358 "language": "python",
413 359 "metadata": {},
414 "outputs": [
415 {
416 "metadata": {},
417 "output_type": "pyout",
418 "prompt_number": 12,
419 "text": [
420 "2"
421 ]
422 }
423 ],
424 "prompt_number": 12
360 "outputs": []
425 361 },
426 362 {
427 363 "cell_type": "heading",
428 364 "level": 3,
429 365 "metadata": {
430 366 "slideshow": {
431 367 "slide_type": "slide"
432 368 }
433 369 },
434 370 "source": [
435 371 "RadioButtonsWidget"
436 372 ]
437 373 },
438 374 {
439 375 "cell_type": "code",
440 376 "collapsed": false,
441 377 "input": [
442 378 "widgets.RadioButtonsWidget(\n",
443 379 " description='Pizza topping:',\n",
444 380 " values=['pepperoni', 'pineapple', 'anchovies'],\n",
445 381 ")"
446 382 ],
447 383 "language": "python",
448 384 "metadata": {},
449 "outputs": [],
450 "prompt_number": 13
385 "outputs": []
451 386 },
452 387 {
453 388 "cell_type": "heading",
454 389 "level": 3,
455 390 "metadata": {
456 391 "slideshow": {
457 392 "slide_type": "slide"
458 393 }
459 394 },
460 395 "source": [
461 396 "SelectWidget"
462 397 ]
463 398 },
464 399 {
465 400 "cell_type": "code",
466 401 "collapsed": false,
467 402 "input": [
468 403 "widgets.SelectWidget(\n",
469 404 " description='OS:',\n",
470 405 " values=['Linux', 'Windows', 'OSX'],\n",
471 406 ")"
472 407 ],
473 408 "language": "python",
474 409 "metadata": {},
475 "outputs": [],
476 "prompt_number": 14
410 "outputs": []
477 411 },
478 412 {
479 413 "cell_type": "heading",
480 414 "level": 3,
481 415 "metadata": {
482 416 "slideshow": {
483 417 "slide_type": "slide"
484 418 }
485 419 },
486 420 "source": [
487 421 "ToggleButtonsWidget"
488 422 ]
489 423 },
490 424 {
491 425 "cell_type": "code",
492 426 "collapsed": false,
493 427 "input": [
494 428 "widgets.ToggleButtonsWidget(\n",
495 429 " description='Speed:',\n",
496 430 " values=['Slow', 'Regular', 'Fast'],\n",
497 431 ")"
498 432 ],
499 433 "language": "python",
500 434 "metadata": {},
501 "outputs": [],
502 "prompt_number": 15
435 "outputs": []
503 436 },
504 437 {
505 438 "cell_type": "heading",
506 439 "level": 2,
507 440 "metadata": {
508 441 "slideshow": {
509 442 "slide_type": "slide"
510 443 }
511 444 },
512 445 "source": [
513 446 "String widgets"
514 447 ]
515 448 },
516 449 {
517 450 "cell_type": "markdown",
518 451 "metadata": {},
519 452 "source": [
520 453 "There are 4 widgets that can be used to display a string value. Of those, the **`TextWidget` and `TextareaWidget` accept input**. The **`LatexWidget` and `HTMLWidget` display the string** as either Latex or HTML respectively, but **do not accept input**."
521 454 ]
522 455 },
523 456 {
524 457 "cell_type": "heading",
525 458 "level": 3,
526 459 "metadata": {
527 460 "slideshow": {
528 461 "slide_type": "slide"
529 462 }
530 463 },
531 464 "source": [
532 465 "TextWidget"
533 466 ]
534 467 },
535 468 {
536 469 "cell_type": "code",
537 470 "collapsed": false,
538 471 "input": [
539 472 "widgets.TextWidget(\n",
540 473 " description='String:',\n",
541 474 " value='Hello World',\n",
542 475 ")"
543 476 ],
544 477 "language": "python",
545 478 "metadata": {},
546 "outputs": [],
547 "prompt_number": 16
479 "outputs": []
548 480 },
549 481 {
550 482 "cell_type": "heading",
551 483 "level": 3,
552 484 "metadata": {},
553 485 "source": [
554 486 "TextareaWidget"
555 487 ]
556 488 },
557 489 {
558 490 "cell_type": "code",
559 491 "collapsed": false,
560 492 "input": [
561 493 "widgets.TextareaWidget(\n",
562 494 " description='String:',\n",
563 495 " value='Hello World',\n",
564 496 ")"
565 497 ],
566 498 "language": "python",
567 499 "metadata": {},
568 "outputs": [],
569 "prompt_number": 17
500 "outputs": []
570 501 },
571 502 {
572 503 "cell_type": "heading",
573 504 "level": 3,
574 505 "metadata": {
575 506 "slideshow": {
576 507 "slide_type": "slide"
577 508 }
578 509 },
579 510 "source": [
580 511 "LatexWidget"
581 512 ]
582 513 },
583 514 {
584 515 "cell_type": "code",
585 516 "collapsed": false,
586 517 "input": [
587 518 "widgets.LatexWidget(\n",
588 519 " value=\"$$\\\\frac{n!}{k!(n-k)!} = \\\\binom{n}{k}$$\",\n",
589 520 ")"
590 521 ],
591 522 "language": "python",
592 523 "metadata": {},
593 "outputs": [],
594 "prompt_number": 18
524 "outputs": []
595 525 },
596 526 {
597 527 "cell_type": "heading",
598 528 "level": 3,
599 529 "metadata": {},
600 530 "source": [
601 531 "HTMLWidget"
602 532 ]
603 533 },
604 534 {
605 535 "cell_type": "code",
606 536 "collapsed": false,
607 537 "input": [
608 538 "widgets.HTMLWidget(\n",
609 539 " value=\"Hello <b>World</b>\"\n",
610 540 ")"
611 541 ],
612 542 "language": "python",
613 543 "metadata": {},
614 "outputs": [],
615 "prompt_number": 19
544 "outputs": []
616 545 },
617 546 {
618 547 "cell_type": "heading",
619 548 "level": 2,
620 549 "metadata": {
621 550 "slideshow": {
622 551 "slide_type": "slide"
623 552 }
624 553 },
625 554 "source": [
626 555 "ButtonWidget"
627 556 ]
628 557 },
629 558 {
630 559 "cell_type": "code",
631 560 "collapsed": false,
632 561 "input": [
633 562 "widgets.ButtonWidget(description='Click me')"
634 563 ],
635 564 "language": "python",
636 565 "metadata": {},
637 "outputs": [],
638 "prompt_number": 20
566 "outputs": []
639 567 },
640 568 {
641 569 "cell_type": "markdown",
642 570 "metadata": {},
643 571 "source": [
644 572 "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)"
645 573 ]
646 574 }
647 575 ],
648 576 "metadata": {}
649 577 }
650 578 ]
651 579 } No newline at end of file
@@ -1,1464 +1,1387 b''
1 1 {
2 2 "metadata": {
3 3 "cell_tags": [
4 4 [
5 5 "<None>",
6 6 null
7 7 ]
8 8 ],
9 9 "celltoolbar": "Slideshow",
10 10 "name": "",
11 "signature": "sha256:25ac05059b7d8d60e6ff6a9098db0fb06a6c0b0e67c457b1d362f34d9cecef18"
11 "signature": "sha256:b5501a34b2148c57201625da06989ae31e2d22f429b786170c96fb703e08bc58"
12 12 },
13 13 "nbformat": 3,
14 14 "nbformat_minor": 0,
15 15 "worksheets": [
16 16 {
17 17 "cells": [
18 18 {
19 19 "cell_type": "markdown",
20 20 "metadata": {},
21 21 "source": [
22 22 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
23 23 ]
24 24 },
25 25 {
26 26 "cell_type": "code",
27 27 "collapsed": false,
28 28 "input": [
29 29 "%%html\n",
30 30 "<style>\n",
31 31 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
32 32 ".example-container.sm { min-height: 50px; }\n",
33 33 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
34 34 ".example-box.med { width: 65px; height: 65px; } \n",
35 35 ".example-box.lrg { width: 80px; height: 80px; } \n",
36 36 "</style>"
37 37 ],
38 38 "language": "python",
39 39 "metadata": {},
40 "outputs": [
41 {
42 "html": [
43 "<style>\n",
44 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
45 ".example-container.sm { min-height: 50px; }\n",
46 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
47 ".example-box.med { width: 65px; height: 65px; } \n",
48 ".example-box.lrg { width: 80px; height: 80px; } \n",
49 "</style>"
50 ],
51 "metadata": {},
52 "output_type": "display_data",
53 "text": [
54 "<IPython.core.display.HTML object>"
55 ]
56 }
57 ],
58 "prompt_number": 1
40 "outputs": []
59 41 },
60 42 {
61 43 "cell_type": "heading",
62 44 "level": 1,
63 45 "metadata": {
64 46 "slideshow": {
65 47 "slide_type": "slide"
66 48 }
67 49 },
68 50 "source": [
69 51 "Widget Styling"
70 52 ]
71 53 },
72 54 {
73 55 "cell_type": "heading",
74 56 "level": 2,
75 57 "metadata": {},
76 58 "source": [
77 59 "CSS"
78 60 ]
79 61 },
80 62 {
81 63 "cell_type": "markdown",
82 64 "metadata": {},
83 65 "source": [
84 66 "Since the representation of the widget you see is a **browser element**, **Cascading Style Sheets (CSS)** are used for styling. Widgets have a **`set_css` method** that allows you to **add and remove CSS properties** from your elements. The following example shows had `set_css` **can be used to set the background color** of a `TextWidget`."
85 67 ]
86 68 },
87 69 {
88 70 "cell_type": "code",
89 71 "collapsed": false,
90 72 "input": [
91 73 "from IPython.html import widgets\n",
92 74 "text = widgets.TextWidget(value=\"Hello World!\")\n",
93 75 "text.set_css('background', 'lime')\n",
94 76 "text "
95 77 ],
96 78 "language": "python",
97 79 "metadata": {},
98 "outputs": [],
99 "prompt_number": 5
80 "outputs": []
100 81 },
101 82 {
102 83 "cell_type": "heading",
103 84 "level": 3,
104 85 "metadata": {
105 86 "slideshow": {
106 87 "slide_type": "slide"
107 88 }
108 89 },
109 90 "source": [
110 91 "Color codes"
111 92 ]
112 93 },
113 94 {
114 95 "cell_type": "markdown",
115 96 "metadata": {},
116 97 "source": [
117 98 "In the example above, **the color `lime` is specified by name**. CSS also supports specifying colors by a **3 byte hexadecimal string**. The first byte is red, second green, and third blue (**RGB**). The following example sets the `TextWidget`'s background to blue."
118 99 ]
119 100 },
120 101 {
121 102 "cell_type": "code",
122 103 "collapsed": false,
123 104 "input": [
124 105 "text.set_css('background', '#0000FF')"
125 106 ],
126 107 "language": "python",
127 108 "metadata": {},
128 "outputs": [],
129 "prompt_number": 6
109 "outputs": []
130 110 },
131 111 {
132 112 "cell_type": "heading",
133 113 "level": 3,
134 114 "metadata": {
135 115 "slideshow": {
136 116 "slide_type": "slide"
137 117 }
138 118 },
139 119 "source": [
140 120 "Forecolor"
141 121 ]
142 122 },
143 123 {
144 124 "cell_type": "markdown",
145 125 "metadata": {},
146 126 "source": [
147 127 "In CSS the **font color is `color`.**"
148 128 ]
149 129 },
150 130 {
151 131 "cell_type": "code",
152 132 "collapsed": false,
153 133 "input": [
154 134 "text.set_css('color', '#FFFFFF')"
155 135 ],
156 136 "language": "python",
157 137 "metadata": {},
158 "outputs": [],
159 "prompt_number": 7
138 "outputs": []
160 139 },
161 140 {
162 141 "cell_type": "heading",
163 142 "level": 3,
164 143 "metadata": {
165 144 "slideshow": {
166 145 "slide_type": "slide"
167 146 }
168 147 },
169 148 "source": [
170 149 "Size"
171 150 ]
172 151 },
173 152 {
174 153 "cell_type": "markdown",
175 154 "metadata": {},
176 155 "source": [
177 156 "CSS is also used to set the **height and width** of controls. The `set_css` method also **can accept a single dictionary with multiple CSS properties** (as seen below)."
178 157 ]
179 158 },
180 159 {
181 160 "cell_type": "code",
182 161 "collapsed": false,
183 162 "input": [
184 163 "btn = widgets.ButtonWidget()\n",
185 164 "btn.set_css({\n",
186 165 " 'width': '100px',\n",
187 166 " 'height': '100px',\n",
188 167 " 'background': 'red',\n",
189 168 "})\n",
190 169 "btn"
191 170 ],
192 171 "language": "python",
193 172 "metadata": {},
194 "outputs": [],
195 "prompt_number": 8
173 "outputs": []
196 174 },
197 175 {
198 176 "cell_type": "heading",
199 177 "level": 3,
200 178 "metadata": {
201 179 "slideshow": {
202 180 "slide_type": "slide"
203 181 }
204 182 },
205 183 "source": [
206 184 "Removing"
207 185 ]
208 186 },
209 187 {
210 188 "cell_type": "markdown",
211 189 "metadata": {},
212 190 "source": [
213 191 "To remove the styling, you can call `set_css` again, but use an empty string instead of a color value."
214 192 ]
215 193 },
216 194 {
217 195 "cell_type": "code",
218 196 "collapsed": false,
219 197 "input": [
220 198 "btn.set_css('background', '')"
221 199 ],
222 200 "language": "python",
223 201 "metadata": {},
224 "outputs": [],
225 "prompt_number": 9
202 "outputs": []
226 203 },
227 204 {
228 205 "cell_type": "markdown",
229 206 "metadata": {},
230 207 "source": [
231 208 "For more information about what can be done with CSS, please refer to the [Mozilla Developer Network's series on it](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started).\n"
232 209 ]
233 210 },
234 211 {
235 212 "cell_type": "heading",
236 213 "level": 2,
237 214 "metadata": {
238 215 "slideshow": {
239 216 "slide_type": "slide"
240 217 }
241 218 },
242 219 "source": [
243 220 "Parent/child relationships"
244 221 ]
245 222 },
246 223 {
247 224 "cell_type": "markdown",
248 225 "metadata": {},
249 226 "source": [
250 227 "To display widget A inside widget B, widget A must be a child of widget B. **Only one instance of any particular widget can be child of another (this limitation will be removed in IPython 3.0).** In other words, *widget A* cannot have *widget B* listed twice in it's list of children.\n",
251 228 "\n",
252 229 "Widgets that can contain other widgets have a **`children` attribute**. This attribute can be **set via a keyword argument** in the widget's constructor **or after construction**. Calling display on an **object with children automatically displays those children**, too."
253 230 ]
254 231 },
255 232 {
256 233 "cell_type": "code",
257 234 "collapsed": false,
258 235 "input": [
259 236 "from IPython.display import display\n",
260 237 "\n",
261 238 "float_range = widgets.FloatSliderWidget()\n",
262 239 "string = widgets.TextWidget(value='hi')\n",
263 240 "container = widgets.ContainerWidget(children=[float_range, string])\n",
264 241 "\n",
265 242 "container.set_css('border', '3px dotted red')\n",
266 243 "display(container) # Displays the `container` and all of it's children."
267 244 ],
268 245 "language": "python",
269 246 "metadata": {},
270 "outputs": [],
271 "prompt_number": 10
247 "outputs": []
272 248 },
273 249 {
274 250 "cell_type": "heading",
275 251 "level": 3,
276 252 "metadata": {},
277 253 "source": [
278 254 "After the parent is displayed"
279 255 ]
280 256 },
281 257 {
282 258 "cell_type": "markdown",
283 259 "metadata": {
284 260 "slideshow": {
285 261 "slide_type": "slide"
286 262 }
287 263 },
288 264 "source": [
289 265 "Children **can be added to parents** after the parent has been displayed. The **parent is responsible for rendering its children**."
290 266 ]
291 267 },
292 268 {
293 269 "cell_type": "code",
294 270 "collapsed": false,
295 271 "input": [
296 272 "container = widgets.ContainerWidget()\n",
297 273 "container.set_css('border', '3px dotted red')\n",
298 274 "display(container)\n",
299 275 "\n",
300 276 "int_range = widgets.IntSliderWidget()\n",
301 277 "container.children=[int_range]"
302 278 ],
303 279 "language": "python",
304 280 "metadata": {},
305 "outputs": [],
306 "prompt_number": 11
281 "outputs": []
307 282 },
308 283 {
309 284 "cell_type": "heading",
310 285 "level": 2,
311 286 "metadata": {
312 287 "slideshow": {
313 288 "slide_type": "slide"
314 289 }
315 290 },
316 291 "source": [
317 292 "Fancy containers"
318 293 ]
319 294 },
320 295 {
321 296 "cell_type": "markdown",
322 297 "metadata": {},
323 298 "source": [
324 299 "If you need to display a more complicated set of widgets, there are **specialized containers** that you can use. To display **multiple sets of widgets**, you can use an **`AccordionWidget` or a `TabWidget` in combination with one `ContainerWidget` per set of widgets** (as seen below). The \"pages\" of these widgets are their children. To set the titles of the pages, one must **call `set_title` after the widget has been displayed**."
325 300 ]
326 301 },
327 302 {
328 303 "cell_type": "heading",
329 304 "level": 3,
330 305 "metadata": {},
331 306 "source": [
332 307 "AccordionWidget"
333 308 ]
334 309 },
335 310 {
336 311 "cell_type": "code",
337 312 "collapsed": false,
338 313 "input": [
339 314 "name1 = widgets.TextWidget(description='Location:')\n",
340 315 "zip1 = widgets.BoundedIntTextWidget(description='Zip:', min=0, max=99999)\n",
341 316 "page1 = widgets.ContainerWidget(children=[name1, zip1])\n",
342 317 "\n",
343 318 "name2 = widgets.TextWidget(description='Location:')\n",
344 319 "zip2 = widgets.BoundedIntTextWidget(description='Zip:', min=0, max=99999)\n",
345 320 "page2 = widgets.ContainerWidget(children=[name2, zip2])\n",
346 321 "\n",
347 322 "accord = widgets.AccordionWidget(children=[page1, page2])\n",
348 323 "display(accord)\n",
349 324 "\n",
350 325 "accord.set_title(0, 'From')\n",
351 326 "accord.set_title(1, 'To')"
352 327 ],
353 328 "language": "python",
354 329 "metadata": {},
355 "outputs": [],
356 "prompt_number": 12
330 "outputs": []
357 331 },
358 332 {
359 333 "cell_type": "heading",
360 334 "level": 3,
361 335 "metadata": {
362 336 "slideshow": {
363 337 "slide_type": "slide"
364 338 }
365 339 },
366 340 "source": [
367 341 "TabWidget"
368 342 ]
369 343 },
370 344 {
371 345 "cell_type": "code",
372 346 "collapsed": false,
373 347 "input": [
374 348 "name = widgets.TextWidget(description='Name:')\n",
375 349 "color = widgets.DropdownWidget(description='Color:', values=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n",
376 350 "page1 = widgets.ContainerWidget(children=[name, color])\n",
377 351 "\n",
378 352 "age = widgets.IntSliderWidget(description='Age:', min=0, max=120, value=50)\n",
379 353 "gender = widgets.RadioButtonsWidget(description='Gender:', values=['male', 'female'])\n",
380 354 "page2 = widgets.ContainerWidget(children=[age, gender])\n",
381 355 "\n",
382 356 "tabs = widgets.TabWidget(children=[page1, page2])\n",
383 357 "display(tabs)\n",
384 358 "\n",
385 359 "tabs.set_title(0, 'Name')\n",
386 360 "tabs.set_title(1, 'Details')"
387 361 ],
388 362 "language": "python",
389 363 "metadata": {},
390 "outputs": [],
391 "prompt_number": 13
364 "outputs": []
392 365 },
393 366 {
394 367 "cell_type": "heading",
395 368 "level": 3,
396 369 "metadata": {
397 370 "slideshow": {
398 371 "slide_type": "slide"
399 372 }
400 373 },
401 374 "source": [
402 375 "PopupWidget"
403 376 ]
404 377 },
405 378 {
406 379 "cell_type": "markdown",
407 380 "metadata": {},
408 381 "source": [
409 382 "Unlike the other two special containers, the `PopupWidget` is only **designed to display one set of widgets**. The `PopupWidget` can be used to **display widgets outside of the widget area**. "
410 383 ]
411 384 },
412 385 {
413 386 "cell_type": "code",
414 387 "collapsed": false,
415 388 "input": [
416 389 "counter = widgets.IntTextWidget(description='Counter:')\n",
417 390 "popup = widgets.PopupWidget(children=[counter], description='Popup Demo', button_text='Popup Button')\n",
418 391 "display(popup)"
419 392 ],
420 393 "language": "python",
421 394 "metadata": {},
422 "outputs": [],
423 "prompt_number": 14
395 "outputs": []
424 396 },
425 397 {
426 398 "cell_type": "code",
427 399 "collapsed": false,
428 400 "input": [
429 401 "counter.value += 1"
430 402 ],
431 403 "language": "python",
432 404 "metadata": {},
433 "outputs": [],
434 "prompt_number": 15
405 "outputs": []
435 406 },
436 407 {
437 408 "cell_type": "code",
438 409 "collapsed": false,
439 410 "input": [],
440 411 "language": "python",
441 412 "metadata": {},
442 "outputs": [],
443 "prompt_number": 15
413 "outputs": []
444 414 },
445 415 {
446 416 "cell_type": "code",
447 417 "collapsed": false,
448 418 "input": [],
449 419 "language": "python",
450 420 "metadata": {},
451 "outputs": [],
452 "prompt_number": 15
421 "outputs": []
453 422 },
454 423 {
455 424 "cell_type": "code",
456 425 "collapsed": false,
457 426 "input": [],
458 427 "language": "python",
459 428 "metadata": {},
460 "outputs": [],
461 "prompt_number": 15
429 "outputs": []
462 430 },
463 431 {
464 432 "cell_type": "code",
465 433 "collapsed": false,
466 434 "input": [],
467 435 "language": "python",
468 436 "metadata": {},
469 "outputs": [],
470 "prompt_number": 15
437 "outputs": []
471 438 },
472 439 {
473 440 "cell_type": "code",
474 441 "collapsed": false,
475 442 "input": [],
476 443 "language": "python",
477 444 "metadata": {},
478 "outputs": [],
479 "prompt_number": 15
445 "outputs": []
480 446 },
481 447 {
482 448 "cell_type": "code",
483 449 "collapsed": false,
484 450 "input": [],
485 451 "language": "python",
486 452 "metadata": {},
487 "outputs": [],
488 "prompt_number": 15
453 "outputs": []
489 454 },
490 455 {
491 456 "cell_type": "code",
492 457 "collapsed": false,
493 458 "input": [],
494 459 "language": "python",
495 460 "metadata": {},
496 "outputs": [],
497 "prompt_number": 15
461 "outputs": []
498 462 },
499 463 {
500 464 "cell_type": "code",
501 465 "collapsed": false,
502 466 "input": [],
503 467 "language": "python",
504 468 "metadata": {},
505 "outputs": [],
506 "prompt_number": 15
469 "outputs": []
507 470 },
508 471 {
509 472 "cell_type": "code",
510 473 "collapsed": false,
511 474 "input": [],
512 475 "language": "python",
513 476 "metadata": {},
514 "outputs": [],
515 "prompt_number": 15
477 "outputs": []
516 478 },
517 479 {
518 480 "cell_type": "code",
519 481 "collapsed": false,
520 482 "input": [],
521 483 "language": "python",
522 484 "metadata": {},
523 "outputs": [],
524 "prompt_number": 15
485 "outputs": []
525 486 },
526 487 {
527 488 "cell_type": "code",
528 489 "collapsed": false,
529 490 "input": [],
530 491 "language": "python",
531 492 "metadata": {},
532 "outputs": [],
533 "prompt_number": 15
493 "outputs": []
534 494 },
535 495 {
536 496 "cell_type": "code",
537 497 "collapsed": false,
538 498 "input": [],
539 499 "language": "python",
540 500 "metadata": {},
541 "outputs": [],
542 "prompt_number": 15
501 "outputs": []
543 502 },
544 503 {
545 504 "cell_type": "code",
546 505 "collapsed": false,
547 506 "input": [],
548 507 "language": "python",
549 508 "metadata": {},
550 "outputs": [],
551 "prompt_number": 15
509 "outputs": []
552 510 },
553 511 {
554 512 "cell_type": "code",
555 513 "collapsed": false,
556 514 "input": [],
557 515 "language": "python",
558 516 "metadata": {},
559 "outputs": [],
560 "prompt_number": 15
517 "outputs": []
561 518 },
562 519 {
563 520 "cell_type": "code",
564 521 "collapsed": false,
565 522 "input": [
566 523 "counter.value += 1"
567 524 ],
568 525 "language": "python",
569 526 "metadata": {},
570 "outputs": [],
571 "prompt_number": 16
527 "outputs": []
572 528 },
573 529 {
574 530 "cell_type": "code",
575 531 "collapsed": false,
576 532 "input": [
577 533 "popup.close()"
578 534 ],
579 535 "language": "python",
580 536 "metadata": {},
581 "outputs": [],
582 "prompt_number": 17
537 "outputs": []
583 538 },
584 539 {
585 540 "cell_type": "heading",
586 541 "level": 1,
587 542 "metadata": {
588 543 "slideshow": {
589 544 "slide_type": "slide"
590 545 }
591 546 },
592 547 "source": [
593 548 "Alignment"
594 549 ]
595 550 },
596 551 {
597 552 "cell_type": "markdown",
598 553 "metadata": {},
599 554 "source": [
600 555 "Most widgets have a **`description` attribute**, which allows a label for the widget to be defined.\n",
601 556 "The label of the widget **has a fixed minimum width**.\n",
602 557 "The text of the label is **always right aligned and the widget is left aligned**:"
603 558 ]
604 559 },
605 560 {
606 561 "cell_type": "code",
607 562 "collapsed": false,
608 563 "input": [
609 564 "display(widgets.TextWidget(description=\"a:\"))\n",
610 565 "display(widgets.TextWidget(description=\"aa:\"))\n",
611 566 "display(widgets.TextWidget(description=\"aaa:\"))"
612 567 ],
613 568 "language": "python",
614 569 "metadata": {},
615 "outputs": [],
616 "prompt_number": 18
570 "outputs": []
617 571 },
618 572 {
619 573 "cell_type": "markdown",
620 574 "metadata": {
621 575 "slideshow": {
622 576 "slide_type": "slide"
623 577 }
624 578 },
625 579 "source": [
626 580 "If a **label is longer** than the minimum width, the **widget is shifted to the right**:"
627 581 ]
628 582 },
629 583 {
630 584 "cell_type": "code",
631 585 "collapsed": false,
632 586 "input": [
633 587 "display(widgets.TextWidget(description=\"a:\"))\n",
634 588 "display(widgets.TextWidget(description=\"aa:\"))\n",
635 589 "display(widgets.TextWidget(description=\"aaa:\"))\n",
636 590 "display(widgets.TextWidget(description=\"aaaaaaaaaaaaaaaaaa:\"))"
637 591 ],
638 592 "language": "python",
639 593 "metadata": {},
640 "outputs": [],
641 "prompt_number": 19
594 "outputs": []
642 595 },
643 596 {
644 597 "cell_type": "markdown",
645 598 "metadata": {
646 599 "slideshow": {
647 600 "slide_type": "slide"
648 601 }
649 602 },
650 603 "source": [
651 604 "If a `description` is **not set** for the widget, the **label is not displayed**:"
652 605 ]
653 606 },
654 607 {
655 608 "cell_type": "code",
656 609 "collapsed": false,
657 610 "input": [
658 611 "display(widgets.TextWidget(description=\"a:\"))\n",
659 612 "display(widgets.TextWidget(description=\"aa:\"))\n",
660 613 "display(widgets.TextWidget(description=\"aaa:\"))\n",
661 614 "display(widgets.TextWidget())"
662 615 ],
663 616 "language": "python",
664 617 "metadata": {},
665 "outputs": [],
666 "prompt_number": 20
618 "outputs": []
667 619 },
668 620 {
669 621 "cell_type": "heading",
670 622 "level": 1,
671 623 "metadata": {
672 624 "slideshow": {
673 625 "slide_type": "slide"
674 626 }
675 627 },
676 628 "source": [
677 629 "DOM Classes"
678 630 ]
679 631 },
680 632 {
681 633 "cell_type": "markdown",
682 634 "metadata": {},
683 635 "source": [
684 636 "IPython defines a large number of **DOM (document object model) classes** that you can apply to your widgets. Applying a DOM class causes all of the **CSS associated with that class** to be applied to the element. Classes can be applied and removed using the **`add_class` and `remove_class`** methods **after a widget has been displayed**. The majority of DOM classes defined by IPython are actually **Bootstrap classes**. For more information on Bootstrap classes and CSS, please refer to [Bootstrap's website](http://getbootstrap.com/2.3.2/)."
685 637 ]
686 638 },
687 639 {
688 640 "cell_type": "heading",
689 641 "level": 2,
690 642 "metadata": {
691 643 "slideshow": {
692 644 "slide_type": "slide"
693 645 }
694 646 },
695 647 "source": [
696 648 "Path dependent"
697 649 ]
698 650 },
699 651 {
700 652 "cell_type": "markdown",
701 653 "metadata": {},
702 654 "source": [
703 655 "Both `add_class` and `remove_class` allow you to use **CSS selectors** to pick which sub elements of your widget get styled. Because of this, the `add_class` and `remove_class` methods are **path dependent (order specific)**. The following example shows the **same three calls** made in three **different orders** and the resulting output. **All three differ.**"
704 656 ]
705 657 },
706 658 {
707 659 "cell_type": "code",
708 660 "collapsed": false,
709 661 "input": [
710 662 "%%html\n",
711 663 "<style>\n",
712 664 " div.cube { display: inline; padding: 5px; }\n",
713 665 " div.red { background: red; }\n",
714 666 " div.blue { background: blue; }\n",
715 667 "</style>"
716 668 ],
717 669 "language": "python",
718 670 "metadata": {},
719 "outputs": [
720 {
721 "html": [
722 "<style>\n",
723 " div.cube { display: inline; padding: 5px; }\n",
724 " div.red { background: red; }\n",
725 " div.blue { background: blue; }\n",
726 "</style>"
727 ],
728 "metadata": {},
729 "output_type": "display_data",
730 "text": [
731 "<IPython.core.display.HTML object>"
732 ]
733 }
734 ],
735 "prompt_number": 21
671 "outputs": []
736 672 },
737 673 {
738 674 "cell_type": "code",
739 675 "collapsed": false,
740 676 "input": [
741 677 "from IPython.html import widgets\n",
742 678 "from IPython.display import display\n",
743 679 "html = '<br />'.join([''.join(['<div class=\"cube\">x</div>' for i in range(8)]) for j in range(8)])\n",
744 680 "widget = [widgets.HTMLWidget(value=html) for i in range(3)]\n",
745 681 "\n",
746 682 "display(widget[0])\n",
747 683 "widget[0].add_class('red', 'div.cube:nth-child(even)')\n",
748 684 "widget[0].remove_class('red', 'div.red:nth-child(7n+1)')\n",
749 685 "widget[0].add_class('blue', 'div.red:nth-child(3n+1)')"
750 686 ],
751 687 "language": "python",
752 688 "metadata": {},
753 "outputs": [],
754 "prompt_number": 22
689 "outputs": []
755 690 },
756 691 {
757 692 "cell_type": "code",
758 693 "collapsed": false,
759 694 "input": [
760 695 "display(widget[1])\n",
761 696 "widget[1].remove_class('red', 'div.red:nth-child(7n+1)')\n",
762 697 "widget[1].add_class('blue', 'div.red:nth-child(3n+1)')\n",
763 698 "widget[1].add_class('red', 'div.cube:nth-child(even)')"
764 699 ],
765 700 "language": "python",
766 701 "metadata": {},
767 "outputs": [],
768 "prompt_number": 23
702 "outputs": []
769 703 },
770 704 {
771 705 "cell_type": "code",
772 706 "collapsed": false,
773 707 "input": [
774 708 "display(widget[2])\n",
775 709 "widget[2].add_class('red', 'div.cube:nth-child(even)')\n",
776 710 "widget[2].add_class('blue', 'div.red:nth-child(3n+1)')\n",
777 711 "widget[2].remove_class('red', 'div.red:nth-child(7n+1)')"
778 712 ],
779 713 "language": "python",
780 714 "metadata": {},
781 "outputs": [],
782 "prompt_number": 24
715 "outputs": []
783 716 },
784 717 {
785 718 "cell_type": "heading",
786 719 "level": 2,
787 720 "metadata": {
788 721 "slideshow": {
789 722 "slide_type": "slide"
790 723 }
791 724 },
792 725 "source": [
793 726 "Alignment classes"
794 727 ]
795 728 },
796 729 {
797 730 "cell_type": "markdown",
798 731 "metadata": {},
799 732 "source": [
800 733 "Widgets can be aligned using IPython **alignment classes**. These classes should work with most widgets, but were **designed to be applied to `ContainerWidget`s**. Examples of these classes follow:"
801 734 ]
802 735 },
803 736 {
804 737 "cell_type": "heading",
805 738 "level": 3,
806 739 "metadata": {},
807 740 "source": [
808 741 "Orientation classes"
809 742 ]
810 743 },
811 744 {
812 745 "cell_type": "heading",
813 746 "level": 4,
814 747 "metadata": {},
815 748 "source": [
816 749 "\"vbox\""
817 750 ]
818 751 },
819 752 {
820 753 "cell_type": "markdown",
821 754 "metadata": {},
822 755 "source": [
823 756 "Widget containers default to this orientation.\n",
824 757 "<div class=\"example-container vbox\">\n",
825 758 "<div class=\"example-box\">A</div>\n",
826 759 "<div class=\"example-box med\">B</div>\n",
827 760 "<div class=\"example-box lrg\">C</div>\n",
828 761 "</div>"
829 762 ]
830 763 },
831 764 {
832 765 "cell_type": "heading",
833 766 "level": 4,
834 767 "metadata": {},
835 768 "source": [
836 769 "\"hbox\""
837 770 ]
838 771 },
839 772 {
840 773 "cell_type": "markdown",
841 774 "metadata": {},
842 775 "source": [
843 776 "<div class=\"example-container hbox\">\n",
844 777 "<div class=\"example-box\">A</div>\n",
845 778 "<div class=\"example-box med\">B</div>\n",
846 779 "<div class=\"example-box lrg\">C</div>\n",
847 780 "</div>"
848 781 ]
849 782 },
850 783 {
851 784 "cell_type": "heading",
852 785 "level": 3,
853 786 "metadata": {},
854 787 "source": [
855 788 "Packing classes"
856 789 ]
857 790 },
858 791 {
859 792 "cell_type": "markdown",
860 793 "metadata": {},
861 794 "source": [
862 795 "These examples use the **hbox layout** to show packing. Packing is the alignment of the widgets along the the **axis that they are displayed on**."
863 796 ]
864 797 },
865 798 {
866 799 "cell_type": "heading",
867 800 "level": 4,
868 801 "metadata": {},
869 802 "source": [
870 803 "\"start\""
871 804 ]
872 805 },
873 806 {
874 807 "cell_type": "markdown",
875 808 "metadata": {},
876 809 "source": [
877 810 "<div class=\"example-container hbox start\">\n",
878 811 "<div class=\"example-box\">A</div>\n",
879 812 "<div class=\"example-box med\">B</div>\n",
880 813 "<div class=\"example-box lrg\">C</div>\n",
881 814 "</div>"
882 815 ]
883 816 },
884 817 {
885 818 "cell_type": "heading",
886 819 "level": 4,
887 820 "metadata": {},
888 821 "source": [
889 822 "\"center\""
890 823 ]
891 824 },
892 825 {
893 826 "cell_type": "markdown",
894 827 "metadata": {},
895 828 "source": [
896 829 "<div class=\"example-container hbox center\">\n",
897 830 "<div class=\"example-box\">A</div>\n",
898 831 "<div class=\"example-box med\">B</div>\n",
899 832 "<div class=\"example-box lrg\">C</div>\n",
900 833 "</div>"
901 834 ]
902 835 },
903 836 {
904 837 "cell_type": "heading",
905 838 "level": 4,
906 839 "metadata": {},
907 840 "source": [
908 841 "\"end\""
909 842 ]
910 843 },
911 844 {
912 845 "cell_type": "markdown",
913 846 "metadata": {
914 847 "slideshow": {
915 848 "slide_type": "slide"
916 849 }
917 850 },
918 851 "source": [
919 852 "<div class=\"example-container hbox end\">\n",
920 853 "<div class=\"example-box\">A</div>\n",
921 854 "<div class=\"example-box med\">B</div>\n",
922 855 "<div class=\"example-box lrg\">C</div>\n",
923 856 "</div>"
924 857 ]
925 858 },
926 859 {
927 860 "cell_type": "heading",
928 861 "level": 3,
929 862 "metadata": {},
930 863 "source": [
931 864 "Aligning classes"
932 865 ]
933 866 },
934 867 {
935 868 "cell_type": "markdown",
936 869 "metadata": {},
937 870 "source": [
938 871 "These examples use the **hbox layout** to show alignment. Packing is the alignment of the widgets along the the **axis perpendicular to the one that they are displayed on**."
939 872 ]
940 873 },
941 874 {
942 875 "cell_type": "heading",
943 876 "level": 4,
944 877 "metadata": {},
945 878 "source": [
946 879 "\"align-start\""
947 880 ]
948 881 },
949 882 {
950 883 "cell_type": "markdown",
951 884 "metadata": {},
952 885 "source": [
953 886 "<div class=\"example-container hbox align-start\">\n",
954 887 "<div class=\"example-box\">A</div>\n",
955 888 "<div class=\"example-box med\">B</div>\n",
956 889 "<div class=\"example-box lrg\">C</div>\n",
957 890 "</div>"
958 891 ]
959 892 },
960 893 {
961 894 "cell_type": "heading",
962 895 "level": 4,
963 896 "metadata": {},
964 897 "source": [
965 898 "\"align-center\""
966 899 ]
967 900 },
968 901 {
969 902 "cell_type": "markdown",
970 903 "metadata": {},
971 904 "source": [
972 905 "<div class=\"example-container hbox align-center\">\n",
973 906 "<div class=\"example-box\">A</div>\n",
974 907 "<div class=\"example-box med\">B</div>\n",
975 908 "<div class=\"example-box lrg\">C</div>\n",
976 909 "</div>"
977 910 ]
978 911 },
979 912 {
980 913 "cell_type": "heading",
981 914 "level": 4,
982 915 "metadata": {},
983 916 "source": [
984 917 "\"align-end\""
985 918 ]
986 919 },
987 920 {
988 921 "cell_type": "markdown",
989 922 "metadata": {
990 923 "slideshow": {
991 924 "slide_type": "slide"
992 925 }
993 926 },
994 927 "source": [
995 928 "<div class=\"example-container hbox align-end\">\n",
996 929 "<div class=\"example-box\">A</div>\n",
997 930 "<div class=\"example-box med\">B</div>\n",
998 931 "<div class=\"example-box lrg\">C</div>\n",
999 932 "</div>"
1000 933 ]
1001 934 },
1002 935 {
1003 936 "cell_type": "heading",
1004 937 "level": 3,
1005 938 "metadata": {},
1006 939 "source": [
1007 940 "Flex classes"
1008 941 ]
1009 942 },
1010 943 {
1011 944 "cell_type": "markdown",
1012 945 "metadata": {},
1013 946 "source": [
1014 947 "To specify **how \"greedy\" a container is** when filling in the remaining space of its parent, the **`box-flexN`** classes are used (where N is 0, 1, or 2). The **higher the value of N, the more greedy** the child is. **`box-flex0` is the default behavior**, which is to not fill the parent."
1015 948 ]
1016 949 },
1017 950 {
1018 951 "cell_type": "heading",
1019 952 "level": 4,
1020 953 "metadata": {},
1021 954 "source": [
1022 955 "Example 1"
1023 956 ]
1024 957 },
1025 958 {
1026 959 "cell_type": "markdown",
1027 960 "metadata": {},
1028 961 "source": [
1029 962 "<div class=\"example-container sm hbox center\">\n",
1030 963 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
1031 964 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
1032 965 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
1033 966 "</div>"
1034 967 ]
1035 968 },
1036 969 {
1037 970 "cell_type": "heading",
1038 971 "level": 4,
1039 972 "metadata": {},
1040 973 "source": [
1041 974 "Example 2"
1042 975 ]
1043 976 },
1044 977 {
1045 978 "cell_type": "markdown",
1046 979 "metadata": {},
1047 980 "source": [
1048 981 "<div class=\"example-container sm hbox center\">\n",
1049 982 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
1050 983 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1051 984 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
1052 985 "</div>"
1053 986 ]
1054 987 },
1055 988 {
1056 989 "cell_type": "heading",
1057 990 "level": 4,
1058 991 "metadata": {},
1059 992 "source": [
1060 993 "Example 3"
1061 994 ]
1062 995 },
1063 996 {
1064 997 "cell_type": "markdown",
1065 998 "metadata": {},
1066 999 "source": [
1067 1000 "<div class=\"example-container sm hbox center\">\n",
1068 1001 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
1069 1002 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1070 1003 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1071 1004 "</div>"
1072 1005 ]
1073 1006 },
1074 1007 {
1075 1008 "cell_type": "heading",
1076 1009 "level": 4,
1077 1010 "metadata": {},
1078 1011 "source": [
1079 1012 "Example 4"
1080 1013 ]
1081 1014 },
1082 1015 {
1083 1016 "cell_type": "markdown",
1084 1017 "metadata": {},
1085 1018 "source": [
1086 1019 "<div class=\"example-container sm hbox center\">\n",
1087 1020 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1088 1021 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1089 1022 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1090 1023 "</div>"
1091 1024 ]
1092 1025 },
1093 1026 {
1094 1027 "cell_type": "heading",
1095 1028 "level": 4,
1096 1029 "metadata": {},
1097 1030 "source": [
1098 1031 "Example 5"
1099 1032 ]
1100 1033 },
1101 1034 {
1102 1035 "cell_type": "markdown",
1103 1036 "metadata": {},
1104 1037 "source": [
1105 1038 "<div class=\"example-container sm hbox center\">\n",
1106 1039 "<div class=\"example-box box-flex2\">box-flex2</div>\n",
1107 1040 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1108 1041 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1109 1042 "</div>"
1110 1043 ]
1111 1044 },
1112 1045 {
1113 1046 "cell_type": "heading",
1114 1047 "level": 4,
1115 1048 "metadata": {},
1116 1049 "source": [
1117 1050 "Example 6"
1118 1051 ]
1119 1052 },
1120 1053 {
1121 1054 "cell_type": "markdown",
1122 1055 "metadata": {
1123 1056 "slideshow": {
1124 1057 "slide_type": "slide"
1125 1058 }
1126 1059 },
1127 1060 "source": [
1128 1061 "<div class=\"example-container sm hbox center\">\n",
1129 1062 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
1130 1063 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
1131 1064 "<div class=\"example-box box-flex2\">box-flex2</div>\n",
1132 1065 "</div>"
1133 1066 ]
1134 1067 },
1135 1068 {
1136 1069 "cell_type": "heading",
1137 1070 "level": 3,
1138 1071 "metadata": {
1139 1072 "slideshow": {
1140 1073 "slide_type": "slide"
1141 1074 }
1142 1075 },
1143 1076 "source": [
1144 1077 "Application to widgets"
1145 1078 ]
1146 1079 },
1147 1080 {
1148 1081 "cell_type": "markdown",
1149 1082 "metadata": {},
1150 1083 "source": [
1151 1084 "Widget containers **default to vbox** alignment."
1152 1085 ]
1153 1086 },
1154 1087 {
1155 1088 "cell_type": "code",
1156 1089 "collapsed": false,
1157 1090 "input": [
1158 1091 "buttons = [widgets.ButtonWidget(description=str(i)) for i in range(3)]\n",
1159 1092 "\n",
1160 1093 "container = widgets.ContainerWidget(children=buttons)\n",
1161 1094 "display(container)"
1162 1095 ],
1163 1096 "language": "python",
1164 1097 "metadata": {},
1165 "outputs": [],
1166 "prompt_number": 25
1098 "outputs": []
1167 1099 },
1168 1100 {
1169 1101 "cell_type": "heading",
1170 1102 "level": 3,
1171 1103 "metadata": {
1172 1104 "slideshow": {
1173 1105 "slide_type": "slide"
1174 1106 }
1175 1107 },
1176 1108 "source": [
1177 1109 "Using hbox"
1178 1110 ]
1179 1111 },
1180 1112 {
1181 1113 "cell_type": "markdown",
1182 1114 "metadata": {},
1183 1115 "source": [
1184 1116 "To make a widget container display its widgets horizontally, you need to **remove the `vbox` class** from the container and **add the `hbox` class** in its place."
1185 1117 ]
1186 1118 },
1187 1119 {
1188 1120 "cell_type": "code",
1189 1121 "collapsed": false,
1190 1122 "input": [
1191 1123 "container = widgets.ContainerWidget(children=buttons)\n",
1192 1124 "display(container)\n",
1193 1125 "container.remove_class('vbox')\n",
1194 1126 "container.add_class('hbox')"
1195 1127 ],
1196 1128 "language": "python",
1197 1129 "metadata": {},
1198 "outputs": [],
1199 "prompt_number": 26
1130 "outputs": []
1200 1131 },
1201 1132 {
1202 1133 "cell_type": "markdown",
1203 1134 "metadata": {},
1204 1135 "source": [
1205 1136 "By setting the width of the container to 100% and adding the `center` class to it, you can center the buttons."
1206 1137 ]
1207 1138 },
1208 1139 {
1209 1140 "cell_type": "code",
1210 1141 "collapsed": false,
1211 1142 "input": [
1212 1143 "container.set_css('width', '100%')\n",
1213 1144 "container.add_class('center')"
1214 1145 ],
1215 1146 "language": "python",
1216 1147 "metadata": {},
1217 "outputs": [],
1218 "prompt_number": 27
1148 "outputs": []
1219 1149 },
1220 1150 {
1221 1151 "cell_type": "heading",
1222 1152 "level": 2,
1223 1153 "metadata": {
1224 1154 "slideshow": {
1225 1155 "slide_type": "slide"
1226 1156 }
1227 1157 },
1228 1158 "source": [
1229 1159 "Style classes"
1230 1160 ]
1231 1161 },
1232 1162 {
1233 1163 "cell_type": "markdown",
1234 1164 "metadata": {},
1235 1165 "source": [
1236 1166 "In addition to alignment classes, the classes defined by Bootstrap can also be used. This tutorial will only cover a few of the most common classes. For a full list of Bootstrap classes, please refer to [Bootstrap's website](http://getbootstrap.com/2.3.2/)."
1237 1167 ]
1238 1168 },
1239 1169 {
1240 1170 "cell_type": "heading",
1241 1171 "level": 3,
1242 1172 "metadata": {},
1243 1173 "source": [
1244 1174 "ButtonWidgets"
1245 1175 ]
1246 1176 },
1247 1177 {
1248 1178 "cell_type": "code",
1249 1179 "collapsed": false,
1250 1180 "input": [
1251 1181 "# List of the bootstrap button styles\n",
1252 1182 "classes = [\n",
1253 1183 " 'btn', \n",
1254 1184 " 'btn-primary', \n",
1255 1185 " 'btn-info', \n",
1256 1186 " 'btn-success', \n",
1257 1187 " 'btn-warning', \n",
1258 1188 " 'btn-danger', \n",
1259 1189 " 'btn-inverse', \n",
1260 1190 " 'btn-link'\n",
1261 1191 "]\n",
1262 1192 "\n",
1263 1193 "# Display the buttons in a hbox\n",
1264 1194 "container = widgets.ContainerWidget(children=[widgets.ButtonWidget(description=c) for c in classes])\n",
1265 1195 "display(container)\n",
1266 1196 "\n",
1267 1197 "# Apply classes after display\n",
1268 1198 "container.remove_class('vbox')\n",
1269 1199 "container.add_class('hbox')\n",
1270 1200 "ret = [container.children[i].add_class(c) for i, c in enumerate(classes)]"
1271 1201 ],
1272 1202 "language": "python",
1273 1203 "metadata": {},
1274 "outputs": [],
1275 "prompt_number": 28
1204 "outputs": []
1276 1205 },
1277 1206 {
1278 1207 "cell_type": "heading",
1279 1208 "level": 3,
1280 1209 "metadata": {
1281 1210 "slideshow": {
1282 1211 "slide_type": "slide"
1283 1212 }
1284 1213 },
1285 1214 "source": [
1286 1215 "ContainerWidgets"
1287 1216 ]
1288 1217 },
1289 1218 {
1290 1219 "cell_type": "code",
1291 1220 "collapsed": false,
1292 1221 "input": [
1293 1222 "def create_label(cls):\n",
1294 1223 " class_name = widgets.HTMLWidget(value=cls)\n",
1295 1224 " container = widgets.ContainerWidget(children=[class_name])\n",
1296 1225 " display(container)\n",
1297 1226 " container.add_class(cls)\n",
1298 1227 "\n",
1299 1228 "ret = [create_label(c) for c in [\n",
1300 1229 " 'alert', \n",
1301 1230 " 'alert alert-error', \n",
1302 1231 " 'alert alert-success', \n",
1303 1232 " 'alert alert-info'\n",
1304 1233 "]]"
1305 1234 ],
1306 1235 "language": "python",
1307 1236 "metadata": {},
1308 "outputs": [],
1309 "prompt_number": 29
1237 "outputs": []
1310 1238 },
1311 1239 {
1312 1240 "cell_type": "heading",
1313 1241 "level": 3,
1314 1242 "metadata": {
1315 1243 "slideshow": {
1316 1244 "slide_type": "slide"
1317 1245 }
1318 1246 },
1319 1247 "source": [
1320 1248 "ProgressWidgets"
1321 1249 ]
1322 1250 },
1323 1251 {
1324 1252 "cell_type": "code",
1325 1253 "collapsed": false,
1326 1254 "input": [
1327 1255 "classes = [\n",
1328 1256 " 'progress-info', \n",
1329 1257 " 'progress-success', \n",
1330 1258 " 'progress-warning', \n",
1331 1259 " 'progress-danger',\n",
1332 1260 " 'progress-info progress-striped', \n",
1333 1261 " 'progress-success progress-striped', \n",
1334 1262 " 'progress-warning progress-striped', \n",
1335 1263 " 'progress-danger progress-striped',\n",
1336 1264 " 'active progress-info progress-striped', \n",
1337 1265 " 'active progress-success progress-striped', \n",
1338 1266 " 'active progress-warning progress-striped', \n",
1339 1267 " 'active progress-danger progress-striped',\n",
1340 1268 "]\n",
1341 1269 "ws = [widgets.IntProgressWidget(value=50, description=c) for c in classes]\n",
1342 1270 "ret = [display(w) for w in ws]\n",
1343 1271 "ret = [ws[i].add_class(c) for i, cs in enumerate(classes) for c in cs.split(' ')]"
1344 1272 ],
1345 1273 "language": "python",
1346 1274 "metadata": {},
1347 "outputs": [],
1348 "prompt_number": 31
1275 "outputs": []
1349 1276 },
1350 1277 {
1351 1278 "cell_type": "heading",
1352 1279 "level": 2,
1353 1280 "metadata": {
1354 1281 "slideshow": {
1355 1282 "slide_type": "slide"
1356 1283 }
1357 1284 },
1358 1285 "source": [
1359 1286 "Visibility"
1360 1287 ]
1361 1288 },
1362 1289 {
1363 1290 "cell_type": "markdown",
1364 1291 "metadata": {},
1365 1292 "source": [
1366 1293 "Sometimes it is necessary to **hide or show widgets** in place, **without having to re-display** the widget.\n",
1367 1294 "The `visibility` property of widgets can be used to hide or show **widgets that have already been displayed** (as seen below)."
1368 1295 ]
1369 1296 },
1370 1297 {
1371 1298 "cell_type": "code",
1372 1299 "collapsed": false,
1373 1300 "input": [
1374 1301 "string = widgets.LatexWidget(value=\"Hello World!\")\n",
1375 1302 "display(string) "
1376 1303 ],
1377 1304 "language": "python",
1378 1305 "metadata": {},
1379 "outputs": [],
1380 "prompt_number": 32
1306 "outputs": []
1381 1307 },
1382 1308 {
1383 1309 "cell_type": "code",
1384 1310 "collapsed": false,
1385 1311 "input": [
1386 1312 "string.visible=False"
1387 1313 ],
1388 1314 "language": "python",
1389 1315 "metadata": {},
1390 "outputs": [],
1391 "prompt_number": 33
1316 "outputs": []
1392 1317 },
1393 1318 {
1394 1319 "cell_type": "code",
1395 1320 "collapsed": false,
1396 1321 "input": [
1397 1322 "string.visible=True"
1398 1323 ],
1399 1324 "language": "python",
1400 1325 "metadata": {},
1401 "outputs": [],
1402 "prompt_number": 34
1326 "outputs": []
1403 1327 },
1404 1328 {
1405 1329 "cell_type": "heading",
1406 1330 "level": 3,
1407 1331 "metadata": {
1408 1332 "slideshow": {
1409 1333 "slide_type": "slide"
1410 1334 }
1411 1335 },
1412 1336 "source": [
1413 1337 "Another example"
1414 1338 ]
1415 1339 },
1416 1340 {
1417 1341 "cell_type": "markdown",
1418 1342 "metadata": {},
1419 1343 "source": [
1420 1344 "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox."
1421 1345 ]
1422 1346 },
1423 1347 {
1424 1348 "cell_type": "code",
1425 1349 "collapsed": false,
1426 1350 "input": [
1427 1351 "form = widgets.ContainerWidget()\n",
1428 1352 "first = widgets.TextWidget(description=\"First Name:\")\n",
1429 1353 "last = widgets.TextWidget(description=\"Last Name:\")\n",
1430 1354 "\n",
1431 1355 "student = widgets.CheckboxWidget(description=\"Student:\", value=False)\n",
1432 1356 "school_info = widgets.ContainerWidget(visible=False, children=[\n",
1433 1357 " widgets.TextWidget(description=\"School:\"),\n",
1434 1358 " widgets.IntTextWidget(description=\"Grade:\", min=0, max=12)\n",
1435 1359 " ])\n",
1436 1360 "\n",
1437 1361 "pet = widgets.TextWidget(description=\"Pet's Name:\")\n",
1438 1362 "form.children = [first, last, student, school_info, pet]\n",
1439 1363 "display(form)\n",
1440 1364 "\n",
1441 1365 "def on_student_toggle(name, value):\n",
1442 1366 " if value:\n",
1443 1367 " school_info.visible = True\n",
1444 1368 " else:\n",
1445 1369 " school_info.visible = False\n",
1446 1370 "student.on_trait_change(on_student_toggle, 'value')\n"
1447 1371 ],
1448 1372 "language": "python",
1449 1373 "metadata": {},
1450 "outputs": [],
1451 "prompt_number": 35
1374 "outputs": []
1452 1375 },
1453 1376 {
1454 1377 "cell_type": "markdown",
1455 1378 "metadata": {},
1456 1379 "source": [
1457 1380 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
1458 1381 ]
1459 1382 }
1460 1383 ],
1461 1384 "metadata": {}
1462 1385 }
1463 1386 ]
1464 1387 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now